├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ └── swift.yml ├── .gitignore ├── .npmignore ├── .spi.yml ├── .swiftpm └── xcode │ ├── package.xcworkspace │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ └── xcschemes │ ├── SpotifyAPI-Package.xcscheme │ └── SpotifyAPI.xcscheme ├── CHANGELOG.md ├── LICENSE.txt ├── Package.swift ├── README.md ├── Sources ├── SpotifyAPITestUtilities │ ├── Authorization │ │ ├── AuthorizationConstants.swift │ │ ├── RedirectListener.swift │ │ ├── SeleniumBrowserAuthorizer.swift │ │ ├── WebKitBrowserAuthorizer.swift │ │ └── openAuthorizationURL.swift │ ├── CodingExtensions.swift │ ├── CombineTestUtilities.swift │ ├── DistributedLock.swift │ ├── MiscellaneousUtilities.swift │ ├── NetworkAdaptor.swift │ ├── README.md │ ├── Resources │ │ ├── requirements.txt │ │ └── spotify_api_authorizer.py │ ├── SpotifyAPI Utilities │ │ ├── AuthorizationCodeFlowExtensions.swift │ │ ├── AuthorizationCodeFlowPKCEExtensions.swift │ │ ├── ClientCredentialsFlowExtensions.swift │ │ ├── SpotifyAPIClientBaseTestClasses.swift │ │ ├── SpotifyAPIExtensions.swift │ │ ├── SpotifyAPIProxyBaseTestClasses.swift │ │ └── SpotifyAPITests.swift │ ├── SpotifyAPITestCase.swift │ └── SpotifyAPITestUtilities.docc │ │ └── SpotifyAPITestUtilities.md ├── SpotifyExampleContent │ ├── ExampleAlbums.swift │ ├── ExampleArtists.swift │ ├── ExampleAudioAnalysis.swift │ ├── ExampleAudioFeatures.swift │ ├── ExampleAudiobooks.swift │ ├── ExampleBrowse.swift │ ├── ExampleEpisodes.swift │ ├── ExampleLibrary.swift │ ├── ExamplePlayer.swift │ ├── ExamplePlaylistItems.swift │ ├── ExamplePlaylists.swift │ ├── ExampleSearch.swift │ ├── ExampleShows.swift │ ├── ExampleTracks.swift │ ├── ExampleUserProfile.swift │ ├── ImageAssets.swift │ ├── README.md │ ├── Resources │ │ ├── Albums │ │ │ ├── Abbey Road - Album.json │ │ │ ├── Dark Side Of The Moon - Album.json │ │ │ ├── In Rainbows - Album.json │ │ │ ├── Jinx - Album.json │ │ │ ├── Jinx - PagingObject.json │ │ │ ├── Meddle - Album.json │ │ │ └── Skiptracing - Album.json │ │ ├── Artists │ │ │ ├── Crumb - Artist.json │ │ │ ├── Levitation Room - Artist.json │ │ │ ├── Pink Floyd - Artist.json │ │ │ ├── Radiohead - Artist.json │ │ │ ├── Skinshape - Artist.json │ │ │ └── The Beatles - Artist.json │ │ ├── Audiobooks │ │ │ ├── Enlightenment Now - Audiobook.json │ │ │ ├── Enlightenment Now Chapter 3 - AudiobookChapter.json │ │ │ ├── Free Will - Audiobook.json │ │ │ ├── Free Will Chapter 1 - AudiobookChapter.json │ │ │ ├── Harry Potter and the Sorcerer's Stone - Audiobook.json │ │ │ └── Steve Jobs Chapter 1 - AudiobookChapter.json │ │ ├── Audo Analysis │ │ │ ├── Any Colour You Like - AudioAnalysis.json │ │ │ └── Fearless - AudioFeatures.json │ │ ├── Browse │ │ │ ├── Category Playlists - PagingObject>.json │ │ │ ├── Featured Playlists - FeaturedPlaylists.json │ │ │ └── categories - SpotifyCategory.json │ │ ├── Episodes │ │ │ ├── Sam Harris 213 - Episode.json │ │ │ ├── Sam Harris 214 - Episode.json │ │ │ ├── Sam Harris 215 - Episode.json │ │ │ ├── Sean Carroll 111 - Episode.json │ │ │ └── Sean Carroll 112 - Episode.json │ │ ├── Images │ │ │ ├── Annabelle Compressed.jpeg │ │ │ └── Annabelle Large.jpeg │ │ ├── Library │ │ │ └── Current User Saved Albums - PagingObject>.json │ │ ├── Player │ │ │ ├── Current Playback - CurrentlyPlayingContext.json │ │ │ ├── Queue - SpotifyQueue.json │ │ │ └── Recently Played - CursorPagingObject.json │ │ ├── PlaylistItems │ │ │ ├── #1536 - Edward Snowden - PlaylistItem.json │ │ │ ├── #1537 - Lex Fridman - PlaylistItem.json │ │ │ ├── #216 — September 3, 2020 - PlaylistItem.json │ │ │ ├── #217 — The New Religion of Anti-Racism - PlaylistItem.json │ │ │ ├── Echoes - Acoustic Version - PlaylistItem.json │ │ │ ├── Hans Zimmer & Radiohead - Ocean Bloom (full song HQ) - PlaylistItem.json │ │ │ └── Killshot - PlaylistItem.json │ │ ├── Playlists │ │ │ ├── Blues Classics - PagingObject>.json │ │ │ ├── Crumb - Playlist>>.json │ │ │ ├── Local Songs - Playlist>>.json │ │ │ ├── Lucy in the sky with diamonds - Playlist.json │ │ │ ├── Men I Trust - Playlist.json │ │ │ ├── Modern Psychedelia - Playlist.json │ │ │ ├── Rock Classics - Playlist.json │ │ │ ├── This Is King Gizzard & The Lizard Wizard - Playlist.json │ │ │ ├── This Is MF DOOM - Playlist.json │ │ │ ├── This Is Mild High Club - Playlist.json │ │ │ ├── This Is Radiohead - Playlist.json │ │ │ ├── This Is Sonic Youth - Playlist.json │ │ │ ├── This Is Spoon - PagingObject>.json │ │ │ ├── This is Jimi Hendrix - PagingObject>.json │ │ │ ├── This is Mac DeMarco - PagingObject>.json │ │ │ ├── This is Pink Floyd - PagingObject>.json │ │ │ ├── This is Skinshape - Playlist.json │ │ │ └── This is Stevie Ray Vaughan - PagingObject>.json │ │ ├── Search │ │ │ └── Search for 'Crumb' - SearchResult.json │ │ ├── Shows │ │ │ ├── Joe Rogan - Show.json │ │ │ ├── Sam Harris - Show.json │ │ │ └── Sean Carroll - Show.json │ │ ├── Tracks │ │ │ ├── Because - Track.json │ │ │ ├── Come Together - Track.json │ │ │ ├── Faces - Track.json │ │ │ ├── Ill Wind - Track.json │ │ │ ├── Ode To Viceroy - Track.json │ │ │ ├── Reckoner - Track.json │ │ │ ├── The End - Track.json │ │ │ └── Time - Track.json │ │ └── User Profile │ │ │ └── Current User Profile - SpotifyUser.json │ ├── SpotifyExampleContent.docc │ │ ├── Object Model Samples.md │ │ └── SpotifyExampleContent.md │ ├── URIs.swift │ └── Utilities.swift └── SpotifyWebAPI │ ├── API │ ├── SpotifyAPI+Albums.swift │ ├── SpotifyAPI+Artists.swift │ ├── SpotifyAPI+Audiobooks.swift │ ├── SpotifyAPI+Browse.swift │ ├── SpotifyAPI+Episodes.swift │ ├── SpotifyAPI+Follow.swift │ ├── SpotifyAPI+Library.swift │ ├── SpotifyAPI+Markets.swift │ ├── SpotifyAPI+Personalization.swift │ ├── SpotifyAPI+Player.swift │ ├── SpotifyAPI+Playlists.swift │ ├── SpotifyAPI+Search.swift │ ├── SpotifyAPI+Shows.swift │ ├── SpotifyAPI+Tracks.swift │ ├── SpotifyAPI+UserProfile.swift │ ├── SpotifyAPI+Utilities.swift │ ├── SpotifyAPI+Wrappers.swift │ └── SpotifyAPI.swift │ ├── Authorization │ ├── AuthorizationCodeFlowManager.swift │ ├── AuthorizationCodeFlowManagerBase.swift │ ├── AuthorizationCodeFlowPKCEManager.swift │ ├── AuthorizationScopes.swift │ ├── Backends │ │ ├── AuthorizationBackends.swift │ │ ├── AuthorizationCodeFlowClientBackend.swift │ │ ├── AuthorizationCodeFlowPKCEClientBackend.swift │ │ ├── AuthorizationCodeFlowPKCEProxyBackend.swift │ │ ├── AuthorizationCodeFlowProxyBackend.swift │ │ ├── ClientCredentialsFlowClientBackend.swift │ │ └── ClientCredentialsFlowProxyBackend.swift │ ├── ClientCredentialsFlowManager.swift │ ├── SpotifyAuthorizationManager.swift │ └── SpotifyScopeAuthorizationManager.swift │ ├── Errors │ ├── RateLimitedError.swift │ ├── SpotifyAuthenticationError.swift │ ├── SpotifyAuthorizationError.swift │ ├── SpotifyDecodingError.swift │ ├── SpotifyError.swift │ ├── SpotifyGeneralError.swift │ └── SpotifyPlayerError.swift │ ├── Object Model │ ├── Audio Analysis Objects │ │ ├── AudioAnalysis.swift │ │ ├── AudioFeatures.swift │ │ ├── Section.swift │ │ ├── Segment.swift │ │ └── SpotifyTimeInterval.swift │ ├── Audiobook Objects │ │ ├── Audiobook.swift │ │ ├── AudiobookAuthor.swift │ │ └── AudiobookChapter.swift │ ├── Authorization Objects │ │ ├── AuthInfo.swift │ │ ├── ClientCredentialsTokensRequest.swift │ │ ├── PKCERefreshTokensRequest.swift │ │ ├── PKCETokensRequest.swift │ │ ├── ProxyPKCERefreshTokensRequest.swift │ │ ├── ProxyPKCETokensRequest.swift │ │ ├── ProxyTokensRequest.swift │ │ ├── RefreshTokensRequest.swift │ │ └── TokensRequest.swift │ ├── Browse Objects │ │ ├── RecommendationSeed.swift │ │ └── RecommendationsResponse.swift │ ├── Music Objects │ │ ├── Album.swift │ │ ├── Artist.swift │ │ └── Track.swift │ ├── Other Spotify Objects │ │ ├── AlbumType.swift │ │ ├── Copyright.swift │ │ ├── CursorPagingObject.swift │ │ ├── FeaturedPlaylists.swift │ │ ├── Followers.swift │ │ ├── NewAlbumReleases.swift │ │ ├── PagingObject.swift │ │ ├── SavedItem.swift │ │ ├── SearchResult.swift │ │ ├── SpotifyCategory.swift │ │ ├── SpotifyCursor.swift │ │ ├── SpotifyImage.swift │ │ ├── SpotifyUser.swift │ │ └── TrackLink.swift │ ├── Player Objects │ │ ├── CurrentlyPlayingContext.swift │ │ ├── Device.swift │ │ ├── DeviceType.swift │ │ ├── PlayHistory.swift │ │ ├── PlaybackActions.swift │ │ ├── RepeatMode.swift │ │ ├── ResumePoint.swift │ │ ├── SpotifyContext.swift │ │ └── SpotifyQueue.swift │ ├── Playlist Objects │ │ ├── Playlist.swift │ │ ├── PlaylistItem.swift │ │ ├── PlaylistItemContainer.swift │ │ └── PlaylistItemsReference.swift │ ├── Podcast Objects │ │ ├── Episode.swift │ │ └── Show.swift │ ├── Post Request Objects │ │ ├── Other Objects │ │ │ ├── AttributeRange.swift │ │ │ ├── TimeRange.swift │ │ │ └── TrackAttributes.swift │ │ ├── Player Objects │ │ │ ├── PlaybackRequest+Context.swift │ │ │ ├── PlaybackRequest+Offset.swift │ │ │ ├── PlaybackRequest.swift │ │ │ ├── TimeReference.swift │ │ │ └── TransferPlaybackRequest.swift │ │ └── Playlist Objects │ │ │ ├── PlaylistDetails.swift │ │ │ ├── ReorderPlaylistItems.swift │ │ │ ├── URIsContainer.swift │ │ │ └── URIsDictWithInsertionIndex.swift │ └── TypeAliases.swift │ ├── Other │ ├── ApproximateEquality.swift │ ├── ApproximatelyEquatable.swift │ ├── AuthorizationManagerLoggers.swift │ ├── CodingExtensions.swift │ ├── DataExtensions.swift │ ├── DateExtensions.swift │ ├── DateFormatterExtensions.swift │ ├── DebugHooks.swift │ ├── Endpoints.swift │ ├── Headers.swift │ ├── IDCategory.swift │ ├── LogHandler.swift │ ├── MiscellaneousUtilities.swift │ ├── Paginated.swift │ ├── SpotifyIdentifier.swift │ ├── SpotifyURIConvertible.swift │ └── StringExtensions.swift │ ├── Publisher Extensions │ ├── DelayedConditionalRetryPublisher.swift │ ├── OtherPublisherExtensions.swift │ └── SpotifyObjectDecoding.swift │ ├── README.md │ ├── SpotifyWebAPI.docc │ ├── Articles │ │ ├── Authorization │ │ │ ├── Additional Authorization Methods.md │ │ │ ├── Authorizing with the Authorization Code Flow with Proof Key for Code Exchange.md │ │ │ ├── Authorizing with the Authorization Code Flow.md │ │ │ └── Authorizing with the Client Credentials Flow.md │ │ ├── Debugging.md │ │ ├── Running the Unit Tests.md │ │ ├── Saving the Authorization Information to Persistent Storage.md │ │ ├── Using the Player Endpoints.md │ │ └── Working with Paginated Results.md │ ├── Collections │ │ └── Object Model │ │ │ ├── Audio Analysis Objects.md │ │ │ ├── Audiobook Objects.md │ │ │ ├── Media Objects.md │ │ │ ├── Other Objects.md │ │ │ ├── Player Objects.md │ │ │ └── Playlist Objects.md │ ├── Resources │ │ ├── Change_Test_Plan.png │ │ ├── JSON_Viewer.png │ │ └── SpotifyAPIMainTestPlan.png │ ├── SpotifyWebAPI.md │ ├── Symbols │ │ ├── Authorization │ │ │ ├── AuthorizationCodeFlowBackendManager.md │ │ │ ├── AuthorizationCodeFlowManager.md │ │ │ ├── AuthorizationCodeFlowManagerBase.md │ │ │ ├── AuthorizationCodeFlowPKCEBackendManager.md │ │ │ ├── AuthorizationCodeFlowPKCEManager.md │ │ │ ├── ClientCredentialsFlowBackendManager.md │ │ │ ├── ClientCredentialsFlowManager.md │ │ │ └── Scope.md │ │ └── SpotifyAPI.md │ └── theme-settings.json │ └── URLExtensions │ ├── URLComponentsExtensions.swift │ ├── URLExtensions.swift │ ├── URLQueryItemExtensions.swift │ └── URLSessionWrappers.swift ├── Tests ├── SpotifyAPIMainTestPlan.xctestplan ├── SpotifyAPIMainTests │ ├── API Tests │ │ ├── SpoifyAPIArtistTests.swift │ │ ├── SpotifyAPIAlbumsTests.swift │ │ ├── SpotifyAPIAudiobookTests.swift │ │ ├── SpotifyAPIBrowseTests.swift │ │ ├── SpotifyAPIEpisodeTests.swift │ │ ├── SpotifyAPIErrorTests.swift │ │ ├── SpotifyAPIFollowTests.swift │ │ ├── SpotifyAPILibraryTests.swift │ │ ├── SpotifyAPIMarketTests.swift │ │ ├── SpotifyAPIPersonalizationTests.swift │ │ ├── SpotifyAPIPlayerTests.swift │ │ ├── SpotifyAPIPlaylistsTests.swift │ │ ├── SpotifyAPISearchTests.swift │ │ ├── SpotifyAPIShowTests.swift │ │ ├── SpotifyAPITrackTests.swift │ │ └── SpotifyAPIUserProfileTests.swift │ ├── Authorization Tests │ │ ├── SpotifyAPIAuthorizationCodeFlowAuthorizationTests.swift │ │ ├── SpotifyAPIAuthorizationCodeFlowPKCEAuthorizationTests.swift │ │ ├── SpotifyAPIAuthorizationTests.swift │ │ ├── SpotifyAPIClientCredentialsFlowAuthorizationTests.swift │ │ ├── SpotifyAPIInsufficientScopeTests.swift │ │ └── SpotifyAPIRefreshTokensConcurrentTests.swift │ ├── Coding Tests │ │ ├── Authorization Objects │ │ │ ├── CodingAuthInfoTests.swift │ │ │ ├── CodingAuthorizationCodeFlowManagerTests.swift │ │ │ ├── CodingAuthorizationCodeFlowPKCEManagerTests.swift │ │ │ └── CodingClientCredentialsFlowManagerTests.swift │ │ ├── CodingCurrentlyPlayingContextTests.swift │ │ ├── CodingPlaybackRequestTests.swift │ │ ├── CodingSpotifyUserTests.swift │ │ ├── CodingTimeReferenceTests.swift │ │ ├── CodingTrackAttributesTests.swift │ │ ├── CursorPagingObjectPlayHistoryCodingTests.swift │ │ └── SpotifyPlayerErrorCodingTests.swift │ ├── Documentation Tests │ │ ├── GetAvailableDeviceThenPlayDocumentationTest.swift │ │ ├── MiscellaneousDocumentationTests.swift │ │ ├── PaginationArticleCompilationTests.swift │ │ ├── PlaylistMappingDocumentationCompilationTests.swift │ │ ├── READMEExamplesCompilationTests.swift │ │ └── SpotifyObservableCompilationTests.swift │ ├── Other Tests │ │ ├── AuthorizationScopesTests.swift │ │ ├── ExampleContentTests.swift │ │ ├── RepeatModeTests.swift │ │ └── SpotifyIdentifierTests.swift │ └── Test Utilities │ │ ├── FilteredPlaylist.swift │ │ └── FilteredPlaylistItems.swift └── SpotifyAPIProxyServer.xctestplan ├── build_documentation.sh ├── docker_linux.sh ├── docs ├── css │ ├── 866.60f074fd.css │ ├── 989.4f123103.css │ ├── documentation-topic.91c07ba9.css │ ├── index.3a335429.css │ ├── topic.4be8f56d.css │ └── tutorials-overview.7942d777.css ├── data │ └── documentation │ │ ├── spotifywebapi.json │ │ └── spotifywebapi │ │ ├── additional-authorization-methods.json │ │ ├── album.json │ │ ├── album │ │ ├── !=(_:_:).json │ │ ├── albumgroup.json │ │ ├── albumtype.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── artists.json │ │ ├── availablemarkets.json │ │ ├── copyrights.json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── externalids.json │ │ ├── externalurls.json │ │ ├── genres.json │ │ ├── href.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(from:).json │ │ ├── init(name:tracks:artists:releasedate:uri:id:images:popularity:label:genres:totaltracks:href:externalurls:externalids:albumtype:albumgroup:availablemarkets:copyrights:releasedateprecision:restrictions:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── label.json │ │ ├── name.json │ │ ├── popularity.json │ │ ├── releasedate.json │ │ ├── releasedateprecision.json │ │ ├── restrictions.json │ │ ├── totaltracks.json │ │ ├── tracks.json │ │ ├── type.json │ │ └── uri.json │ │ ├── albumtype.json │ │ ├── albumtype │ │ ├── !=(_:_:).json │ │ ├── album.json │ │ ├── appearson.json │ │ ├── compilation.json │ │ ├── encode(to:).json │ │ ├── ep.json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashvalue.json │ │ ├── init(from:).json │ │ ├── init(rawvalue:).json │ │ ├── other.json │ │ ├── rawrepresentable-implementations.json │ │ └── single.json │ │ ├── approximatelyequatable.json │ │ ├── approximatelyequatable │ │ └── isapproximatelyequal(to:).json │ │ ├── artist.json │ │ ├── artist │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── followers.json │ │ ├── genres.json │ │ ├── href.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(from:).json │ │ ├── init(name:uri:id:images:popularity:externalurls:followers:genres:href:).json │ │ ├── name.json │ │ ├── popularity.json │ │ ├── type.json │ │ └── uri.json │ │ ├── attributerange.json │ │ ├── attributerange │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(min:target:max:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── max.json │ │ ├── min.json │ │ ├── querydictionary(attributename:).json │ │ └── target.json │ │ ├── audio-analysis-objects.json │ │ ├── audioanalysis.json │ │ ├── audioanalysis │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── bars.json │ │ ├── beats.json │ │ ├── equatable-implementations.json │ │ ├── init(bars:beats:tatums:sections:segments:).json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── sections.json │ │ ├── segments.json │ │ └── tatums.json │ │ ├── audiobook-objects.json │ │ ├── audiobook.json │ │ ├── audiobook │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── authors.json │ │ ├── availablemarkets.json │ │ ├── chapters.json │ │ ├── copyrights.json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── edition.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── htmldescription.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(from:).json │ │ ├── init(name:authors:narrators:publisher:description:htmldescription:chapters:totalchapters:isexplicit:uri:id:images:availablemarkets:href:externalurls:languages:copyrights:mediatype:edition:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── isexplicit.json │ │ ├── languages.json │ │ ├── mediatype.json │ │ ├── name.json │ │ ├── narrators.json │ │ ├── publisher.json │ │ ├── totalchapters.json │ │ ├── type.json │ │ └── uri.json │ │ ├── audiobookauthor.json │ │ ├── audiobookauthor │ │ ├── !=(_:_:).json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(name:).json │ │ └── name.json │ │ ├── audiobookchapter.json │ │ ├── audiobookchapter │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── audiobook.json │ │ ├── audiopreviewurl.json │ │ ├── availablemarkets.json │ │ ├── chapternumber.json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── durationms.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── htmldescription.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(from:).json │ │ ├── init(name:audiobook:chapternumber:audiopreviewurl:description:htmldescription:resumepoint:durationms:isexplicit:releasedate:uri:id:images:availablemarkets:href:isplayable:externalurls:languages:restrictions:releasedateprecision:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── isexplicit.json │ │ ├── isplayable.json │ │ ├── languages.json │ │ ├── name.json │ │ ├── releasedate.json │ │ ├── releasedateprecision.json │ │ ├── restrictions.json │ │ ├── resumepoint.json │ │ ├── type.json │ │ └── uri.json │ │ ├── audiofeatures.json │ │ ├── audiofeatures │ │ ├── !=(_:_:).json │ │ ├── acousticness.json │ │ ├── analysisurl.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── danceability.json │ │ ├── durationms.json │ │ ├── energy.json │ │ ├── equatable-implementations.json │ │ ├── id.json │ │ ├── init(from:).json │ │ ├── init(key:mode:timesignature:acousticness:danceability:energy:instrumentalness:liveness:loudness:speechiness:valence:tempo:uri:id:trackhref:analysisurl:durationms:type:).json │ │ ├── instrumentalness.json │ │ ├── isapproximatelyequal(to:).json │ │ ├── key.json │ │ ├── liveness.json │ │ ├── loudness.json │ │ ├── mode.json │ │ ├── speechiness.json │ │ ├── tempo.json │ │ ├── timesignature.json │ │ ├── trackhref.json │ │ ├── type.json │ │ ├── uri.json │ │ └── valence.json │ │ ├── authinfo.json │ │ ├── authinfo │ │ ├── !=(_:_:).json │ │ ├── accesstoken.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── codingkeys.json │ │ ├── codingkeys │ │ │ ├── !=(_:_:).json │ │ │ ├── accesstoken.json │ │ │ ├── backend.json │ │ │ ├── clientid.json │ │ │ ├── clientsecret.json │ │ │ ├── codingkey-implementations.json │ │ │ ├── debugdescription.json │ │ │ ├── description.json │ │ │ ├── equatable-implementations.json │ │ │ ├── expirationdate.json │ │ │ ├── expiresinseconds.json │ │ │ ├── hash(into:).json │ │ │ ├── hashvalue.json │ │ │ ├── init(intvalue:).json │ │ │ ├── init(rawvalue:).json │ │ │ ├── init(stringvalue:).json │ │ │ ├── rawrepresentable-implementations.json │ │ │ ├── refreshtoken.json │ │ │ └── scopes.json │ │ ├── customstringconvertible-implementations.json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── expirationdate.json │ │ ├── init(accesstoken:refreshtoken:expirationdate:scopes:).json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── refreshtoken.json │ │ └── scopes.json │ │ ├── authorizationcodeflowbackend.json │ │ ├── authorizationcodeflowbackend │ │ ├── clientid.json │ │ ├── refreshtokens(refreshtoken:).json │ │ └── requestaccessandrefreshtokens(code:redirecturiwithquery:).json │ │ ├── authorizationcodeflowbackendmanager.json │ │ ├── authorizationcodeflowbackendmanager │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── description.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── init(backend:).json │ │ ├── init(backend:accesstoken:expirationdate:refreshtoken:scopes:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ ├── makeauthorizationurl(redirecturi:showdialog:state:scopes:).json │ │ ├── refreshtokens(onlyifexpired:tolerance:).json │ │ ├── requestaccessandrefreshtokens(redirecturiwithquery:state:).json │ │ └── spotifyauthorizationmanager-implementations.json │ │ ├── authorizationcodeflowclientbackend.json │ │ ├── authorizationcodeflowclientbackend │ │ ├── !=(_:_:).json │ │ ├── clientid.json │ │ ├── clientsecret.json │ │ ├── customstringconvertible-implementations.json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── init(clientid:clientsecret:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ ├── refreshtokens(refreshtoken:).json │ │ └── requestaccessandrefreshtokens(code:redirecturiwithquery:).json │ │ ├── authorizationcodeflowmanager.json │ │ ├── authorizationcodeflowmanager │ │ ├── clientid.json │ │ ├── clientsecret.json │ │ ├── description.json │ │ ├── init(clientid:clientsecret:).json │ │ └── init(clientid:clientsecret:accesstoken:expirationdate:refreshtoken:scopes:).json │ │ ├── authorizationcodeflowmanagerbase.json │ │ ├── authorizationcodeflowmanagerbase │ │ ├── accesstoken.json │ │ ├── accesstokenisexpired(tolerance:).json │ │ ├── backend.json │ │ ├── baselogger.json │ │ ├── deauthorize().json │ │ ├── didchange.json │ │ ├── diddeauthorize.json │ │ ├── expirationdate.json │ │ ├── isauthorized(for:).json │ │ ├── makecopy().json │ │ ├── refreshtoken.json │ │ ├── scopes.json │ │ └── setexpirationdate(to:).json │ │ ├── authorizationcodeflowpkcebackend.json │ │ ├── authorizationcodeflowpkcebackend │ │ ├── clientid.json │ │ ├── refreshtokens(refreshtoken:).json │ │ └── requestaccessandrefreshtokens(code:codeverifier:redirecturiwithquery:).json │ │ ├── authorizationcodeflowpkcebackendmanager.json │ │ ├── authorizationcodeflowpkcebackendmanager │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── description.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── init(backend:).json │ │ ├── init(backend:accesstoken:expirationdate:refreshtoken:scopes:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ ├── makeauthorizationurl(redirecturi:codechallenge:state:scopes:).json │ │ ├── refreshtokens(onlyifexpired:tolerance:).json │ │ ├── requestaccessandrefreshtokens(redirecturiwithquery:codeverifier:state:).json │ │ └── spotifyauthorizationmanager-implementations.json │ │ ├── authorizationcodeflowpkceclientbackend.json │ │ ├── authorizationcodeflowpkceclientbackend │ │ ├── !=(_:_:).json │ │ ├── clientid.json │ │ ├── customstringconvertible-implementations.json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── equatable-implementations.json │ │ ├── init(clientid:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ ├── refreshtokens(refreshtoken:).json │ │ └── requestaccessandrefreshtokens(code:codeverifier:redirecturiwithquery:).json │ │ ├── authorizationcodeflowpkcemanager.json │ │ ├── authorizationcodeflowpkcemanager │ │ ├── clientid.json │ │ ├── description.json │ │ ├── init(clientid:).json │ │ └── init(clientid:accesstoken:expirationdate:refreshtoken:scopes:).json │ │ ├── authorizationcodeflowpkceproxybackend.json │ │ ├── authorizationcodeflowpkceproxybackend │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── clientid.json │ │ ├── customstringconvertible-implementations.json │ │ ├── decodable-implementations.json │ │ ├── decodeservererror.json │ │ ├── description.json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashable-implementations.json │ │ ├── init(clientid:tokensurl:tokenrefreshurl:decodeservererror:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ ├── refreshtokens(refreshtoken:).json │ │ ├── requestaccessandrefreshtokens(code:codeverifier:redirecturiwithquery:).json │ │ ├── tokenrefreshurl.json │ │ └── tokensurl.json │ │ ├── authorizationcodeflowproxybackend.json │ │ ├── authorizationcodeflowproxybackend │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── clientid.json │ │ ├── customstringconvertible-implementations.json │ │ ├── decodable-implementations.json │ │ ├── decodeservererror.json │ │ ├── description.json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashable-implementations.json │ │ ├── init(clientid:tokensurl:tokenrefreshurl:decodeservererror:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ ├── refreshtokens(refreshtoken:).json │ │ ├── requestaccessandrefreshtokens(code:redirecturiwithquery:).json │ │ ├── tokenrefreshurl.json │ │ └── tokensurl.json │ │ ├── authorizing-with-the-authorization-code-flow-with-proof-key-for-code-exchange.json │ │ ├── authorizing-with-the-authorization-code-flow.json │ │ ├── authorizing-with-the-client-credentials-flow.json │ │ ├── clientcredentialsflowbackend.json │ │ ├── clientcredentialsflowbackend │ │ └── makeclientcredentialstokensrequest().json │ │ ├── clientcredentialsflowbackendmanager.json │ │ ├── clientcredentialsflowbackendmanager │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── accesstoken.json │ │ ├── accesstokenisexpired(tolerance:).json │ │ ├── authorize().json │ │ ├── backend.json │ │ ├── deauthorize().json │ │ ├── description.json │ │ ├── didchange.json │ │ ├── diddeauthorize.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── expirationdate.json │ │ ├── hash(into:).json │ │ ├── init(backend:).json │ │ ├── init(backend:accesstoken:expirationdate:).json │ │ ├── init(from:).json │ │ ├── isauthorized(for:).json │ │ ├── logger.json │ │ ├── makecopy().json │ │ ├── refreshtokens(onlyifexpired:tolerance:).json │ │ ├── scopes.json │ │ ├── setexpirationdate(to:).json │ │ └── spotifyauthorizationmanager-implementations.json │ │ ├── clientcredentialsflowclientbackend.json │ │ ├── clientcredentialsflowclientbackend │ │ ├── !=(_:_:).json │ │ ├── clientid.json │ │ ├── clientsecret.json │ │ ├── customstringconvertible-implementations.json │ │ ├── description.json │ │ ├── equatable-implementations.json │ │ ├── init(clientid:clientsecret:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ └── makeclientcredentialstokensrequest().json │ │ ├── clientcredentialsflowmanager.json │ │ ├── clientcredentialsflowmanager │ │ ├── clientid.json │ │ ├── clientsecret.json │ │ ├── description.json │ │ ├── init(clientid:clientsecret:).json │ │ └── init(clientid:clientsecret:accesstoken:expirationdate:).json │ │ ├── clientcredentialsflowproxybackend.json │ │ ├── clientcredentialsflowproxybackend │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── customstringconvertible-implementations.json │ │ ├── decodable-implementations.json │ │ ├── decodeservererror.json │ │ ├── description.json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashable-implementations.json │ │ ├── init(from:).json │ │ ├── init(tokensurl:decodeservererror:).json │ │ ├── logger.json │ │ ├── makeclientcredentialstokensrequest().json │ │ └── tokensurl.json │ │ ├── clientcredentialstokensrequest.json │ │ ├── clientcredentialstokensrequest │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init().json │ │ └── init(from:).json │ │ ├── combine.json │ │ ├── combine │ │ ├── publisher.json │ │ └── publisher │ │ │ ├── collectandsortbyoffset().json │ │ │ ├── decodeoptionalspotifyobject(_:maxretrydelay:).json │ │ │ ├── decodespotifyerrors(maxretrydelay:).json │ │ │ ├── decodespotifyobject(_:maxretrydelay:).json │ │ │ ├── extendpages(_:maxextrapages:).json │ │ │ ├── extendpagesconcurrently(_:maxextrapages:).json │ │ │ └── sink(receivecompletion:).json │ │ ├── currentlyplayingcontext.json │ │ ├── currentlyplayingcontext │ │ ├── !=(_:_:).json │ │ ├── allowedactions.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── context.json │ │ ├── decodable-implementations.json │ │ ├── device.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── init(device:repeatstate:shuffleison:context:timestamp:progressms:isplaying:item:itemtype:allowedactions:).json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── isplaying.json │ │ ├── item.json │ │ ├── itemtype.json │ │ ├── logger.json │ │ ├── progressms.json │ │ ├── repeatstate.json │ │ ├── shuffleison.json │ │ └── timestamp.json │ │ ├── cursorpagingobject.json │ │ ├── cursorpagingobject │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── cursors.json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── href.json │ │ ├── init(from:).json │ │ ├── init(href:items:limit:next:cursors:total:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── items.json │ │ ├── limit.json │ │ ├── next.json │ │ └── total.json │ │ ├── debugging.json │ │ ├── decodespotifyerrors(data:httpurlresponse:).json │ │ ├── decodespotifyobject(data:httpurlresponse:responsetype:).json │ │ ├── device.json │ │ ├── device │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── id.json │ │ ├── init(from:).json │ │ ├── init(id:isactive:isprivatesession:isrestricted:name:type:volumepercent:).json │ │ ├── isactive.json │ │ ├── isprivatesession.json │ │ ├── isrestricted.json │ │ ├── name.json │ │ ├── type.json │ │ └── volumepercent.json │ │ ├── devicetype.json │ │ ├── devicetype │ │ ├── !=(_:_:).json │ │ ├── audiodongle.json │ │ ├── automobile.json │ │ ├── avr.json │ │ ├── castaudio.json │ │ ├── castvideo.json │ │ ├── computer.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── gameconsole.json │ │ ├── hash(into:).json │ │ ├── hashvalue.json │ │ ├── init(from:).json │ │ ├── init(rawvalue:).json │ │ ├── rawrepresentable-implementations.json │ │ ├── smartphone.json │ │ ├── speaker.json │ │ ├── stb.json │ │ ├── tablet.json │ │ ├── tv.json │ │ └── unknown.json │ │ ├── endpoints.json │ │ ├── endpoints │ │ ├── accountsbase.json │ │ ├── apibase.json │ │ ├── apiendpoint(_:queryitems:).json │ │ ├── apiversion1.json │ │ ├── authorize.json │ │ ├── gettokens.json │ │ └── token.json │ │ ├── episode.json │ │ ├── episode │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── audiopreviewurl.json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── durationms.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── htmldescription.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(from:).json │ │ ├── init(name:show:audiopreviewurl:description:htmldescription:resumepoint:durationms:isexplicit:releasedate:uri:id:images:href:isplayable:externalurls:isexternallyhosted:languages:releasedateprecision:restrictions:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── isexplicit.json │ │ ├── isexternallyhosted.json │ │ ├── isplayable.json │ │ ├── languages.json │ │ ├── name.json │ │ ├── releasedate.json │ │ ├── releasedateprecision.json │ │ ├── restrictions.json │ │ ├── resumepoint.json │ │ ├── show.json │ │ ├── type.json │ │ └── uri.json │ │ ├── featuredplaylists.json │ │ ├── featuredplaylists │ │ ├── !=(_:_:).json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(message:playlists:).json │ │ ├── message.json │ │ └── playlists.json │ │ ├── followers.json │ │ ├── followers │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── href.json │ │ ├── init(from:).json │ │ ├── init(href:total:).json │ │ └── total.json │ │ ├── foundation.json │ │ ├── foundation │ │ ├── characterset.json │ │ ├── characterset │ │ │ └── urlqueryandpathallowed.json │ │ ├── data.json │ │ ├── data │ │ │ ├── base64urlencodedstring(options:).json │ │ │ └── init(base64urlencoded:options:).json │ │ ├── date.json │ │ ├── date │ │ │ ├── approximatelyequatable-implementations.json │ │ │ ├── init(millisecondssince1970:).json │ │ │ ├── isapproximatelyequal(to:).json │ │ │ └── millisecondssince1970.json │ │ ├── dateformatter.json │ │ ├── dateformatter │ │ │ ├── featuredplaylists.json │ │ │ ├── millisecondstime.json │ │ │ ├── spotifyalbumlong.json │ │ │ ├── spotifyalbummedium.json │ │ │ └── spotifyalbumshort.json │ │ ├── url.json │ │ ├── url │ │ │ ├── appending(queryitems:)-4id6o.json │ │ │ ├── appending(queryitems:)-fcfy.json │ │ │ ├── components.json │ │ │ ├── queryitems.json │ │ │ ├── queryitemsdict.json │ │ │ ├── removequeryitems().json │ │ │ ├── removetrailingslashinpath().json │ │ │ ├── removingqueryitems().json │ │ │ ├── removingtrailingslashinpath().json │ │ │ ├── sortedqueryitems().json │ │ │ └── sortqueryitems().json │ │ ├── urlcomponents.json │ │ ├── urlcomponents │ │ │ ├── queryitemsdict.json │ │ │ ├── removetrailingslashinpath().json │ │ │ └── removingtrailingslashinpath().json │ │ ├── urlsession.json │ │ └── urlsession │ │ │ └── defaultnetworkadaptor(request:).json │ │ ├── generatepageoffsets(_:maxextrapages:).json │ │ ├── headers.json │ │ ├── headers │ │ ├── basicbase64encoded(clientid:clientsecret:).json │ │ ├── bearerauthorization(_:).json │ │ ├── bearerauthorizationandcontenttypejson(_:).json │ │ ├── contenttypeimagejpeg.json │ │ ├── contenttypejson.json │ │ └── formurlencoded.json │ │ ├── idcategory.json │ │ ├── idcategory │ │ ├── !=(_:_:).json │ │ ├── ad.json │ │ ├── album.json │ │ ├── artist.json │ │ ├── audiobook.json │ │ ├── chapter.json │ │ ├── collection.json │ │ ├── encode(to:).json │ │ ├── episode.json │ │ ├── equatable-implementations.json │ │ ├── genre.json │ │ ├── hash(into:).json │ │ ├── hashvalue.json │ │ ├── init(from:).json │ │ ├── init(rawvalue:).json │ │ ├── local.json │ │ ├── playlist.json │ │ ├── rawrepresentable-implementations.json │ │ ├── show.json │ │ ├── track.json │ │ ├── unknown.json │ │ └── user.json │ │ ├── logging.json │ │ ├── logging │ │ ├── logger.json │ │ └── logger │ │ │ ├── init(label:level:).json │ │ │ └── init(label:level:factory:).json │ │ ├── media-objects.json │ │ ├── newalbumreleases.json │ │ ├── newalbumreleases │ │ ├── !=(_:_:).json │ │ ├── albums.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(message:albums:).json │ │ ├── isapproximatelyequal(to:).json │ │ └── message.json │ │ ├── other-objects.json │ │ ├── paginated.json │ │ ├── paginated │ │ └── next.json │ │ ├── pagingobject.json │ │ ├── pagingobject │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── estimatedindex.json │ │ ├── estimatedtotalpages.json │ │ ├── hash(into:).json │ │ ├── hashable-implementations.json │ │ ├── href.json │ │ ├── init(from:).json │ │ ├── init(href:items:limit:next:previous:offset:total:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── items.json │ │ ├── limit.json │ │ ├── next.json │ │ ├── offset.json │ │ ├── previous.json │ │ └── total.json │ │ ├── pagingobjectprotocol.json │ │ ├── pagingobjectprotocol │ │ ├── href.json │ │ ├── item.json │ │ ├── items.json │ │ ├── limit.json │ │ ├── next.json │ │ ├── offset.json │ │ ├── previous.json │ │ └── total.json │ │ ├── pkcerefreshtokensrequest.json │ │ ├── pkcerefreshtokensrequest │ │ ├── !=(_:_:).json │ │ ├── clientid.json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init(from:).json │ │ ├── init(refreshtoken:clientid:).json │ │ └── refreshtoken.json │ │ ├── pkcetokensrequest.json │ │ ├── pkcetokensrequest │ │ ├── !=(_:_:).json │ │ ├── clientid.json │ │ ├── code.json │ │ ├── codeverifier.json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init(code:codeverifier:redirecturi:clientid:).json │ │ ├── init(from:).json │ │ └── redirecturi.json │ │ ├── playbackactions.json │ │ ├── playbackactions │ │ ├── !=(_:_:).json │ │ ├── allcases-swift.type.property.json │ │ ├── allcases-swift.typealias.json │ │ ├── caseiterable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashvalue.json │ │ ├── init(from:).json │ │ ├── init(rawvalue:).json │ │ ├── interruptplayback.json │ │ ├── pause.json │ │ ├── rawrepresentable-implementations.json │ │ ├── resume.json │ │ ├── seek.json │ │ ├── skiptonext.json │ │ ├── skiptoprevious.json │ │ ├── togglerepeatcontext.json │ │ ├── togglerepeattrack.json │ │ ├── toggleshuffle.json │ │ └── transferplayback.json │ │ ├── playbackrequest.json │ │ ├── playbackrequest │ │ ├── !=(_:_:).json │ │ ├── context-swift.enum.json │ │ ├── context-swift.enum │ │ │ ├── !=(_:_:).json │ │ │ ├── ==(_:_:).json │ │ │ ├── contexturi(_:).json │ │ │ ├── decodable-implementations.json │ │ │ ├── encodable-implementations.json │ │ │ ├── encode(to:).json │ │ │ ├── equatable-implementations.json │ │ │ ├── hash(into:).json │ │ │ ├── hashable-implementations.json │ │ │ ├── init(from:).json │ │ │ └── uris(_:).json │ │ ├── context-swift.property.json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── init(_:positionms:).json │ │ ├── init(context:offset:positionms:).json │ │ ├── init(from:).json │ │ ├── offset-swift.enum.json │ │ ├── offset-swift.enum │ │ │ ├── !=(_:_:).json │ │ │ ├── ==(_:_:).json │ │ │ ├── decodable-implementations.json │ │ │ ├── encodable-implementations.json │ │ │ ├── encode(to:).json │ │ │ ├── equatable-implementations.json │ │ │ ├── hash(into:).json │ │ │ ├── hashable-implementations.json │ │ │ ├── init(from:).json │ │ │ ├── position(_:).json │ │ │ └── uri(_:).json │ │ ├── offset-swift.property.json │ │ └── positionms.json │ │ ├── player-objects.json │ │ ├── playhistory.json │ │ ├── playhistory │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── context.json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(track:playedat:context:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── playedat.json │ │ └── track.json │ │ ├── playlist-objects.json │ │ ├── playlist.json │ │ ├── playlist │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── followers.json │ │ ├── href.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(from:).json │ │ ├── init(name:items:owner:ispublic:iscollaborative:description:snapshotid:externalurls:followers:href:id:uri:images:).json │ │ ├── iscollaborative.json │ │ ├── ispublic.json │ │ ├── items.json │ │ ├── name.json │ │ ├── owner.json │ │ ├── snapshotid.json │ │ ├── type.json │ │ └── uri.json │ │ ├── playlistdetails.json │ │ ├── playlistdetails │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(name:ispublic:iscollaborative:description:).json │ │ ├── iscollaborative.json │ │ ├── ispublic.json │ │ └── name.json │ │ ├── playlistitem.json │ │ ├── playlistitem │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── decodable-implementations.json │ │ ├── durationms.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── episode(_:).json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── id.json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── isexplicit.json │ │ ├── isplayable.json │ │ ├── name.json │ │ ├── track(_:).json │ │ ├── type.json │ │ └── uri.json │ │ ├── playlistitemcontainer.json │ │ ├── playlistitemcontainer │ │ ├── !=(_:_:).json │ │ ├── addedat.json │ │ ├── addedby.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── init(addedat:addedby:islocal:item:).json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── islocal.json │ │ └── item.json │ │ ├── playlistitems.json │ │ ├── playlistitemsreference.json │ │ ├── playlistitemsreference │ │ ├── !=(_:_:).json │ │ ├── equatable-implementations.json │ │ ├── href.json │ │ ├── init(from:).json │ │ ├── init(href:total:).json │ │ └── total.json │ │ ├── playlisttracks.json │ │ ├── proxypkcerefreshtokensrequest.json │ │ ├── proxypkcerefreshtokensrequest │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init(from:).json │ │ ├── init(refreshtoken:).json │ │ ├── method.json │ │ └── refreshtoken.json │ │ ├── proxypkcetokensrequest.json │ │ ├── proxypkcetokensrequest │ │ ├── !=(_:_:).json │ │ ├── code.json │ │ ├── codeverifier.json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init(code:codeverifier:redirecturi:).json │ │ ├── init(from:).json │ │ └── redirecturi.json │ │ ├── proxytokensrequest.json │ │ ├── proxytokensrequest │ │ ├── !=(_:_:).json │ │ ├── code.json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init(code:redirecturi:).json │ │ ├── init(from:).json │ │ └── redirecturi.json │ │ ├── ratelimitederror.json │ │ ├── ratelimitederror │ │ ├── !=(_:_:).json │ │ ├── anyfailingpublisher(_:).json │ │ ├── equatable-implementations.json │ │ ├── error-implementations.json │ │ ├── errordescription.json │ │ ├── failurereason.json │ │ ├── helpanchor.json │ │ ├── init(from:).json │ │ ├── localizeddescription.json │ │ ├── localizederror-implementations.json │ │ ├── recoverysuggestion.json │ │ └── retryafter.json │ │ ├── recommendationseed.json │ │ ├── recommendationseed │ │ ├── !=(_:_:).json │ │ ├── afterfilteringsize.json │ │ ├── afterrelinkingsize.json │ │ ├── equatable-implementations.json │ │ ├── href.json │ │ ├── id.json │ │ ├── init(afterfilteringsize:afterrelinkingsize:href:id:initialpoolsize:type:).json │ │ ├── init(from:).json │ │ ├── initialpoolsize.json │ │ └── type.json │ │ ├── recommendationsresponse.json │ │ ├── recommendationsresponse │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(seeds:tracks:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── seedartists.json │ │ ├── seedgenres.json │ │ ├── seeds.json │ │ ├── seedtracks.json │ │ └── tracks.json │ │ ├── refreshtokensrequest.json │ │ ├── refreshtokensrequest │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init(from:).json │ │ ├── init(refreshtoken:).json │ │ └── refreshtoken.json │ │ ├── reorderplaylistitems.json │ │ ├── reorderplaylistitems │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(rangestart:rangelength:insertbefore:snapshotid:).json │ │ ├── insertbefore.json │ │ ├── rangelength.json │ │ ├── rangestart.json │ │ └── snapshotid.json │ │ ├── repeatmode.json │ │ ├── repeatmode │ │ ├── !=(_:_:).json │ │ ├── context.json │ │ ├── cycle().json │ │ ├── cycled().json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashvalue.json │ │ ├── init(from:).json │ │ ├── init(rawvalue:).json │ │ ├── off.json │ │ ├── rawrepresentable-implementations.json │ │ └── track.json │ │ ├── resumepoint.json │ │ ├── resumepoint │ │ ├── !=(_:_:).json │ │ ├── equatable-implementations.json │ │ ├── fullyplayed.json │ │ ├── init(from:).json │ │ ├── init(fullyplayed:resumepositionms:).json │ │ └── resumepositionms.json │ │ ├── running-the-unit-tests.json │ │ ├── savedalbum.json │ │ ├── savedaudiobook.json │ │ ├── savedepisode.json │ │ ├── saveditem.json │ │ ├── saveditem │ │ ├── !=(_:_:).json │ │ ├── addedat.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── init(addedat:item:type:).json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── item.json │ │ └── type.json │ │ ├── savedshow.json │ │ ├── savedtrack.json │ │ ├── saving-the-authorization-information-to-persistent-storage.json │ │ ├── scope.json │ │ ├── scope │ │ ├── !=(_:_:).json │ │ ├── allcases-swift.type.property.json │ │ ├── allcases-swift.typealias.json │ │ ├── appremotecontrol.json │ │ ├── caseiterable-implementations.json │ │ ├── contains(_:).json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashvalue.json │ │ ├── init(from:).json │ │ ├── init(rawvalue:).json │ │ ├── makeset(_:).json │ │ ├── makestring(_:)-7pkz7.json │ │ ├── makestring(_:)-7y7yy.json │ │ ├── playlistmodifyprivate.json │ │ ├── playlistmodifypublic.json │ │ ├── playlistreadcollaborative.json │ │ ├── playlistreadprivate.json │ │ ├── rawrepresentable-implementations.json │ │ ├── streaming.json │ │ ├── ugcimageupload.json │ │ ├── userfollowmodify.json │ │ ├── userfollowread.json │ │ ├── userlibrarymodify.json │ │ ├── userlibraryread.json │ │ ├── usermodifyplaybackstate.json │ │ ├── userreadcurrentlyplaying.json │ │ ├── userreademail.json │ │ ├── userreadplaybackposition.json │ │ ├── userreadplaybackstate.json │ │ ├── userreadprivate.json │ │ ├── userreadrecentlyplayed.json │ │ └── usertopread.json │ │ ├── searchresult.json │ │ ├── searchresult │ │ ├── !=(_:_:).json │ │ ├── albums.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── artists.json │ │ ├── audiobooks.json │ │ ├── decodable-implementations.json │ │ ├── episodes.json │ │ ├── equatable-implementations.json │ │ ├── init(artists:albums:tracks:playlists:episodes:shows:audiobooks:).json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── playlists.json │ │ ├── shows.json │ │ └── tracks.json │ │ ├── section.json │ │ ├── section │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── confidence.json │ │ ├── decodable-implementations.json │ │ ├── duration.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(start:duration:confidence:loudness:tempo:tempoconfidence:key:keyconfidence:mode:modeconfidence:timesignature:timesignatureconfidence:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── key.json │ │ ├── keyconfidence.json │ │ ├── loudness.json │ │ ├── mode.json │ │ ├── modeconfidence.json │ │ ├── start.json │ │ ├── tempo.json │ │ ├── tempoconfidence.json │ │ ├── timesignature.json │ │ └── timesignatureconfidence.json │ │ ├── segment.json │ │ ├── segment │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── confidence.json │ │ ├── decodable-implementations.json │ │ ├── duration.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(start:duration:confidence:loudnessstart:loudnessmax:loudnessmaxtime:pitches:timbre:loudnessend:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── loudnessend.json │ │ ├── loudnessmax.json │ │ ├── loudnessmaxtime.json │ │ ├── loudnessstart.json │ │ ├── pitches.json │ │ ├── start.json │ │ └── timbre.json │ │ ├── show.json │ │ ├── show │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── availablemarkets.json │ │ ├── copyrights.json │ │ ├── decodable-implementations.json │ │ ├── description.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── episodes.json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── htmldescription.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(from:).json │ │ ├── init(name:description:htmldescription:episodes:totalepisodes:isexplicit:uri:id:images:availablemarkets:href:externalurls:isexternallyhosted:languages:copyrights:mediatype:publisher:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── isexplicit.json │ │ ├── isexternallyhosted.json │ │ ├── languages.json │ │ ├── mediatype.json │ │ ├── name.json │ │ ├── publisher.json │ │ ├── totalepisodes.json │ │ ├── type.json │ │ └── uri.json │ │ ├── spotifyapi.json │ │ ├── spotifyapi │ │ ├── addtoplaylist(_:uris:position:).json │ │ ├── addtoqueue(_:deviceid:).json │ │ ├── album(_:market:).json │ │ ├── albums(_:market:).json │ │ ├── albumtracks(_:market:limit:offset:).json │ │ ├── apirequestlogger.json │ │ ├── artist(_:).json │ │ ├── artistalbums(_:groups:country:limit:offset:).json │ │ ├── artists(_:).json │ │ ├── artisttoptracks(_:country:).json │ │ ├── audiobook(_:market:).json │ │ ├── audiobookchapters(_:market:limit:offset:).json │ │ ├── audiobooks(_:market:).json │ │ ├── authdidchangelogger.json │ │ ├── authorizationmanager.json │ │ ├── authorizationmanagerdidchange.json │ │ ├── authorizationmanagerdiddeauthorize.json │ │ ├── availabledevices().json │ │ ├── availablemarkets().json │ │ ├── categories(country:locale:limit:offset:).json │ │ ├── category(_:country:locale:).json │ │ ├── categoryplaylists(_:country:limit:offset:).json │ │ ├── changeplaylistdetails(_:to:).json │ │ ├── chapter(_:market:).json │ │ ├── chapters(_:market:).json │ │ ├── createplaylist(for:_:).json │ │ ├── currentplayback(market:).json │ │ ├── currentuserfollowedartists(after:limit:).json │ │ ├── currentuserfollowsartists(_:).json │ │ ├── currentuserfollowsplaylist(_:).json │ │ ├── currentuserfollowsusers(_:).json │ │ ├── currentuserplaylists(limit:offset:).json │ │ ├── currentuserprofile().json │ │ ├── currentusersavedalbums(limit:offset:market:).json │ │ ├── currentusersavedalbumscontains(_:).json │ │ ├── currentusersavedaudiobooks(limit:offset:).json │ │ ├── currentusersavedaudiobookscontains(_:).json │ │ ├── currentusersavedepisodes(limit:offset:market:).json │ │ ├── currentusersavedepisodescontains(_:).json │ │ ├── currentusersavedshows(limit:offset:).json │ │ ├── currentusersavedshowscontains(_:).json │ │ ├── currentusersavedtracks(limit:offset:market:).json │ │ ├── currentusersavedtrackscontains(_:).json │ │ ├── currentusertopartists(_:offset:limit:).json │ │ ├── currentusertoptracks(_:offset:limit:).json │ │ ├── customstringconvertible-implementations.json │ │ ├── description.json │ │ ├── encode(to:).json │ │ ├── episode(_:market:).json │ │ ├── episodes(_:market:).json │ │ ├── extendpages(_:maxextrapages:).json │ │ ├── extendpagesconcurrently(_:maxextrapages:).json │ │ ├── featuredplaylists(locale:country:timestamp:limit:offset:).json │ │ ├── filteredplaylist(_:filters:additionaltypes:market:).json │ │ ├── filteredplaylistitems(_:filters:additionaltypes:limit:offset:market:).json │ │ ├── followartistsforcurrentuser(_:).json │ │ ├── followplaylistforcurrentuser(_:publicly:).json │ │ ├── followusersforcurrentuser(_:).json │ │ ├── getfromhref(_:responsetype:).json │ │ ├── init(authorizationmanager:maxretrydelay:networkadaptor:).json │ │ ├── init(from:).json │ │ ├── logger.json │ │ ├── maxretrydelay.json │ │ ├── networkadaptor.json │ │ ├── newalbumreleases(country:limit:offset:).json │ │ ├── pauseplayback(deviceid:).json │ │ ├── play(_:deviceid:).json │ │ ├── playlist(_:market:).json │ │ ├── playlistimage(_:).json │ │ ├── playlistitems(_:limit:offset:market:).json │ │ ├── playlisttracks(_:limit:offset:market:).json │ │ ├── queue().json │ │ ├── recentlyplayed(_:limit:).json │ │ ├── recommendationgenres().json │ │ ├── recommendations(_:limit:market:).json │ │ ├── relatedartists(_:).json │ │ ├── removealloccurrencesfromplaylist(_:of:snapshotid:).json │ │ ├── removesavedalbumsforcurrentuser(_:).json │ │ ├── removesavedaudiobooksforcurrentuser(_:).json │ │ ├── removesavedepisodesforcurrentuser(_:).json │ │ ├── removesavedshowsforcurrentuser(_:market:).json │ │ ├── removesavedtracksforcurrentuser(_:).json │ │ ├── reorderplaylistitems(_:body:).json │ │ ├── replaceallplaylistitems(_:with:).json │ │ ├── resumeplayback(deviceid:).json │ │ ├── savealbumsforcurrentuser(_:).json │ │ ├── saveaudiobooksforcurrentuser(_:).json │ │ ├── saveepisodesforcurrentuser(_:).json │ │ ├── saveshowsforcurrentuser(_:).json │ │ ├── savetracksforcurrentuser(_:).json │ │ ├── search(query:categories:market:limit:offset:includeexternal:).json │ │ ├── seektoposition(_:deviceid:).json │ │ ├── setrepeatmode(to:deviceid:).json │ │ ├── setshuffle(to:deviceid:).json │ │ ├── setupdebugging().json │ │ ├── setvolume(to:deviceid:).json │ │ ├── show(_:market:).json │ │ ├── showepisodes(_:market:offset:limit:).json │ │ ├── shows(_:market:).json │ │ ├── skiptonext(deviceid:).json │ │ ├── skiptoprevious(deviceid:).json │ │ ├── track(_:market:).json │ │ ├── trackaudioanalysis(_:).json │ │ ├── trackaudiofeatures(_:).json │ │ ├── tracks(_:market:).json │ │ ├── tracksaudiofeatures(_:).json │ │ ├── transferplayback(to:play:).json │ │ ├── unfollowartistsforcurrentuser(_:).json │ │ ├── unfollowplaylistforcurrentuser(_:).json │ │ ├── unfollowusersforcurrentuser(_:).json │ │ ├── uploadplaylistimage(_:imagedata:).json │ │ ├── userplaylists(for:limit:offset:).json │ │ └── userprofile(_:).json │ │ ├── spotifyapiloghandler.json │ │ ├── spotifyapiloghandler │ │ ├── bootstrap().json │ │ ├── init(label:loglevel:metadata:).json │ │ ├── label.json │ │ ├── log(level:message:metadata:file:function:line:).json │ │ ├── log(level:message:metadata:source:file:function:line:).json │ │ ├── loghandler-implementations.json │ │ ├── loglevel.json │ │ ├── metadata.json │ │ └── subscript(metadatakey:).json │ │ ├── spotifyauthenticationerror.json │ │ ├── spotifyauthenticationerror │ │ ├── !=(_:_:).json │ │ ├── anyfailingpublisher(_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── error-implementations.json │ │ ├── error.json │ │ ├── errordescription.json │ │ ├── failurereason.json │ │ ├── helpanchor.json │ │ ├── init(from:).json │ │ ├── localizeddescription.json │ │ ├── localizederror-implementations.json │ │ └── recoverysuggestion.json │ │ ├── spotifyauthorizationerror.json │ │ ├── spotifyauthorizationerror │ │ ├── !=(_:_:).json │ │ ├── accesswasdenied.json │ │ ├── anyfailingpublisher(_:).json │ │ ├── equatable-implementations.json │ │ ├── error-implementations.json │ │ ├── error.json │ │ ├── errordescription.json │ │ ├── failurereason.json │ │ ├── helpanchor.json │ │ ├── init(from:).json │ │ ├── localizeddescription.json │ │ ├── localizederror-implementations.json │ │ ├── recoverysuggestion.json │ │ └── state.json │ │ ├── spotifyauthorizationmanager.json │ │ ├── spotifyauthorizationmanager │ │ ├── accesstoken.json │ │ ├── accesstokenisexpired(tolerance:).json │ │ ├── deauthorize().json │ │ ├── didchange.json │ │ ├── diddeauthorize.json │ │ ├── expirationdate.json │ │ ├── isauthorized(for:).json │ │ ├── refreshtokens(onlyifexpired:tolerance:).json │ │ └── scopes.json │ │ ├── spotifycategory.json │ │ ├── spotifycategory │ │ ├── !=(_:_:).json │ │ ├── equatable-implementations.json │ │ ├── href.json │ │ ├── icons.json │ │ ├── id.json │ │ ├── init(from:).json │ │ ├── init(name:id:href:icons:).json │ │ └── name.json │ │ ├── spotifycontext.json │ │ ├── spotifycontext │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── init(from:).json │ │ ├── init(uri:href:externalurls:type:).json │ │ ├── type.json │ │ └── uri.json │ │ ├── spotifycopyright.json │ │ ├── spotifycopyright │ │ ├── !=(_:_:).json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(text:type:).json │ │ ├── text.json │ │ └── type.json │ │ ├── spotifycursor.json │ │ ├── spotifycursor │ │ ├── !=(_:_:).json │ │ ├── after.json │ │ ├── before.json │ │ ├── equatable-implementations.json │ │ ├── init(before:after:).json │ │ └── init(from:).json │ │ ├── spotifydecodelogger.json │ │ ├── spotifydecodingerror.json │ │ ├── spotifydecodingerror │ │ ├── anyfailingpublisher(_:).json │ │ ├── datadumpfolder.json │ │ ├── debugerrordescription.json │ │ ├── description.json │ │ ├── error-implementations.json │ │ ├── errordescription.json │ │ ├── expectedresponsetype.json │ │ ├── failurereason.json │ │ ├── helpanchor.json │ │ ├── init(url:rawdata:responsetype:statuscode:underlyingerror:).json │ │ ├── localizeddescription.json │ │ ├── localizederror-implementations.json │ │ ├── prettycodingpath.json │ │ ├── rawdata.json │ │ ├── recoverysuggestion.json │ │ ├── statuscode.json │ │ ├── underlyingerror.json │ │ ├── url.json │ │ └── writetofolder(_:).json │ │ ├── spotifyerror.json │ │ ├── spotifyerror │ │ ├── !=(_:_:).json │ │ ├── anyfailingpublisher(_:).json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── error-implementations.json │ │ ├── errordescription.json │ │ ├── failurereason.json │ │ ├── helpanchor.json │ │ ├── init(from:).json │ │ ├── localizeddescription.json │ │ ├── localizederror-implementations.json │ │ ├── message.json │ │ ├── recoverysuggestion.json │ │ └── statuscode.json │ │ ├── spotifygeneralerror.json │ │ ├── spotifygeneralerror │ │ ├── anyfailingpublisher(_:).json │ │ ├── customstringconvertible-implementations.json │ │ ├── description.json │ │ ├── error-implementations.json │ │ ├── errordescription.json │ │ ├── failurereason.json │ │ ├── helpanchor.json │ │ ├── httperror(_:_:).json │ │ ├── identifierparsingerror(message:).json │ │ ├── insufficientscope(requiredscopes:authorizedscopes:).json │ │ ├── invalididcategory(expected:received:).json │ │ ├── invalidstate(supplied:received:).json │ │ ├── localizeddescription.json │ │ ├── localizederror-implementations.json │ │ ├── other(_:localizeddescription:).json │ │ ├── recoverysuggestion.json │ │ ├── toplevelkeynotfound(key:dict:).json │ │ └── unauthorized(_:).json │ │ ├── spotifyidentifier.json │ │ ├── spotifyidentifier │ │ ├── !=(_:_:).json │ │ ├── commaseparatedidsstring(_:ensurecategorymatches:).json │ │ ├── equatable-implementations.json │ │ ├── id.json │ │ ├── idcategory.json │ │ ├── idsarray(_:ensurecategorymatches:).json │ │ ├── init(from:).json │ │ ├── init(id:idcategory:).json │ │ ├── init(uri:ensurecategorymatches:).json │ │ ├── init(url:).json │ │ ├── uri.json │ │ └── url.json │ │ ├── spotifyimage.json │ │ ├── spotifyimage │ │ ├── !=(_:_:).json │ │ ├── equatable-implementations.json │ │ ├── height.json │ │ ├── init(from:).json │ │ ├── init(height:width:url:).json │ │ ├── load().json │ │ ├── url.json │ │ └── width.json │ │ ├── spotifyplayererror.json │ │ ├── spotifyplayererror │ │ ├── !=(_:_:).json │ │ ├── anyfailingpublisher(_:).json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── error-implementations.json │ │ ├── errordescription.json │ │ ├── errorreason.json │ │ ├── errorreason │ │ │ ├── !=(_:_:).json │ │ │ ├── alreadypaused.json │ │ │ ├── alreadyplaying.json │ │ │ ├── contextdisallow.json │ │ │ ├── devicenotcontrollable.json │ │ │ ├── encode(to:).json │ │ │ ├── endlesscontext.json │ │ │ ├── equatable-implementations.json │ │ │ ├── hash(into:).json │ │ │ ├── hashvalue.json │ │ │ ├── init(from:).json │ │ │ ├── init(rawvalue:).json │ │ │ ├── noactivedevice.json │ │ │ ├── nonexttrack.json │ │ │ ├── noprevioustrack.json │ │ │ ├── nospecifictrack.json │ │ │ ├── notpaused.json │ │ │ ├── notplayingcontext.json │ │ │ ├── notplayinglocally.json │ │ │ ├── notplayingtrack.json │ │ │ ├── premiumrequired.json │ │ │ ├── ratelimited.json │ │ │ ├── rawrepresentable-implementations.json │ │ │ ├── remotecontroldisallow.json │ │ │ ├── unknown.json │ │ │ └── volumecontroldisallow.json │ │ ├── failurereason.json │ │ ├── helpanchor.json │ │ ├── init(from:).json │ │ ├── localizeddescription.json │ │ ├── localizederror-implementations.json │ │ ├── message.json │ │ ├── reason.json │ │ ├── recoverysuggestion.json │ │ └── statuscode.json │ │ ├── spotifyqueue.json │ │ ├── spotifyqueue │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── currentlyplaying.json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── init(currentlyplaying:queue:).json │ │ ├── init(from:).json │ │ ├── isapproximatelyequal(to:).json │ │ └── queue.json │ │ ├── spotifyscopeauthorizationmanager.json │ │ ├── spotifytimeinterval.json │ │ ├── spotifytimeinterval │ │ ├── !=(_:_:).json │ │ ├── approximatelyequatable-implementations.json │ │ ├── confidence.json │ │ ├── duration.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(start:duration:confidence:).json │ │ ├── isapproximatelyequal(to:).json │ │ └── start.json │ │ ├── spotifytimestampformatter.json │ │ ├── spotifytimestampformatter │ │ ├── date(from:).json │ │ ├── millisecondsformatter.json │ │ ├── secondsformatter.json │ │ ├── shared.json │ │ └── string(from:).json │ │ ├── spotifyuriconvertible.json │ │ ├── spotifyuriconvertible │ │ └── uri.json │ │ ├── spotifyuser.json │ │ ├── spotifyuser │ │ ├── !=(_:_:).json │ │ ├── allowsexplicitcontent.json │ │ ├── country.json │ │ ├── decodable-implementations.json │ │ ├── displayname.json │ │ ├── email.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── explicitcontentsettingislocked.json │ │ ├── externalurls.json │ │ ├── followers.json │ │ ├── href.json │ │ ├── id.json │ │ ├── images.json │ │ ├── init(displayname:uri:id:images:href:allowsexplicitcontent:explicitcontentsettingislocked:followers:country:email:product:externalurls:).json │ │ ├── init(from:).json │ │ ├── product.json │ │ ├── type.json │ │ └── uri.json │ │ ├── swift.json │ │ ├── swift │ │ ├── additivearithmetic.json │ │ ├── additivearithmetic │ │ │ └── isapproximatelyequal(to:absolutetolerance:relativetolerance:norm:).json │ │ ├── collection.json │ │ ├── collection │ │ │ └── chunked(size:).json │ │ ├── decodingerror.json │ │ ├── decodingerror │ │ │ ├── context.json │ │ │ └── prettycodingpath.json │ │ ├── dictionary.json │ │ ├── dictionary │ │ │ └── formurlencoded().json │ │ ├── error.json │ │ ├── error │ │ │ └── anyfailingpublisher(_:).json │ │ ├── keyeddecodingcontainer.json │ │ ├── keyeddecodingcontainer │ │ │ ├── decodeandunwraparray(forkey:).json │ │ │ ├── decodedatefromexpiresinseconds(forkey:).json │ │ │ ├── decodedatefromexpiresinsecondsifpresent(forkey:).json │ │ │ ├── decodemillisecondssince1970(forkey:).json │ │ │ ├── decodemillisecondssince1970ifpresent(forkey:).json │ │ │ ├── decodespotifydate(forkey:).json │ │ │ ├── decodespotifydateifpresent(forkey:).json │ │ │ ├── decodespotifyimages(forkey:).json │ │ │ ├── decodespotifyscopesifpresent(forkey:).json │ │ │ ├── decodespotifytimestamp(forkey:).json │ │ │ ├── decodespotifytimestampifpresent(forkey:).json │ │ │ └── decodeuseruri(forkey:).json │ │ ├── keyedencodingcontainer.json │ │ ├── keyedencodingcontainer │ │ │ ├── encodemillisecondssince1970(_:forkey:).json │ │ │ ├── encodemillisecondssince1970ifpresent(_:forkey:).json │ │ │ ├── encodespotifydate(_:dateprecision:forkey:).json │ │ │ ├── encodespotifydateifpresent(_:dateprecision:forkey:).json │ │ │ ├── encodespotifyscopesifpresent(_:forkey:).json │ │ │ ├── encodespotifytimestamp(_:forkey:).json │ │ │ ├── encodespotifytimestampifpresent(_:forkey:).json │ │ │ └── encodeuseruri(_:forkey:).json │ │ ├── numeric.json │ │ ├── numeric │ │ │ ├── isapproximatelyequal(to:absolutetolerance:relativetolerance:).json │ │ │ └── isapproximatelyequal(to:relativetolerance:norm:).json │ │ ├── optional.json │ │ ├── optional │ │ │ ├── approximatelyequatable-implementations.json │ │ │ └── isapproximatelyequal(to:).json │ │ ├── randomaccesscollection.json │ │ ├── randomaccesscollection │ │ │ └── isapproximatelyequal(to:).json │ │ ├── sequence.json │ │ ├── sequence │ │ │ ├── commaseparatedstring().json │ │ │ ├── isapproximatelyequal(to:).json │ │ │ ├── largest.json │ │ │ └── removingduplicates().json │ │ ├── set.json │ │ ├── set │ │ │ ├── approximatelyequatable-implementations.json │ │ │ └── isapproximatelyequal(to:).json │ │ ├── string.json │ │ ├── string │ │ │ ├── base64decoded(encoding:options:).json │ │ │ ├── base64encoded(_:).json │ │ │ ├── makecodechallenge(codeverifier:).json │ │ │ ├── randomurlsafe(length:).json │ │ │ ├── randomurlsafe(length:using:).json │ │ │ ├── spotifyuriconvertible-implementations.json │ │ │ ├── strip(_:).json │ │ │ ├── uri.json │ │ │ └── urlsafecharacters.json │ │ ├── substring.json │ │ └── substring │ │ │ ├── spotifyuriconvertible-implementations.json │ │ │ └── uri.json │ │ ├── timerange.json │ │ ├── timerange │ │ ├── !=(_:_:).json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashvalue.json │ │ ├── init(from:).json │ │ ├── init(rawvalue:).json │ │ ├── longterm.json │ │ ├── mediumterm.json │ │ ├── rawrepresentable-implementations.json │ │ └── shortterm.json │ │ ├── timereference.json │ │ ├── timereference │ │ ├── !=(_:_:).json │ │ ├── after(_:)-swift.enum.case.json │ │ ├── after(_:)-swift.type.method.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── asqueryitem().json │ │ ├── before(_:)-swift.enum.case.json │ │ ├── before(_:)-swift.type.method.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ └── isapproximatelyequal(to:).json │ │ ├── tokensrequest.json │ │ ├── tokensrequest │ │ ├── !=(_:_:).json │ │ ├── clientid.json │ │ ├── clientsecret.json │ │ ├── code.json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── formurlencoded().json │ │ ├── granttype.json │ │ ├── init(code:redirecturi:clientid:clientsecret:).json │ │ ├── init(from:).json │ │ └── redirecturi.json │ │ ├── track.json │ │ ├── track │ │ ├── !=(_:_:).json │ │ ├── album.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── artists.json │ │ ├── availablemarkets.json │ │ ├── decodable-implementations.json │ │ ├── discnumber.json │ │ ├── durationms.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── externalids.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── id.json │ │ ├── init(from:).json │ │ ├── init(name:album:artists:uri:id:islocal:popularity:durationms:tracknumber:isexplicit:isplayable:href:previewurl:externalurls:externalids:availablemarkets:linkedfrom:restrictions:discnumber:type:).json │ │ ├── isapproximatelyequal(to:).json │ │ ├── isexplicit.json │ │ ├── islocal.json │ │ ├── isplayable.json │ │ ├── linkedfrom.json │ │ ├── name.json │ │ ├── popularity.json │ │ ├── previewurl.json │ │ ├── restrictions.json │ │ ├── tracknumber.json │ │ ├── type.json │ │ └── uri.json │ │ ├── trackattributes.json │ │ ├── trackattributes │ │ ├── !=(_:_:).json │ │ ├── acousticness.json │ │ ├── approximatelyequatable-implementations.json │ │ ├── danceability.json │ │ ├── decodable-implementations.json │ │ ├── durationms.json │ │ ├── energy.json │ │ ├── equatable-implementations.json │ │ ├── init(from:).json │ │ ├── init(seedartists:seedtracks:seedgenres:acousticness:danceability:durationms:energy:instrumentalness:key:liveness:loudness:mode:popularity:speechiness:tempo:timesignature:valence:).json │ │ ├── instrumentalness.json │ │ ├── isapproximatelyequal(to:).json │ │ ├── key.json │ │ ├── liveness.json │ │ ├── loudness.json │ │ ├── mode.json │ │ ├── popularity.json │ │ ├── querydictionary().json │ │ ├── seedartists.json │ │ ├── seedgenres.json │ │ ├── seedtracks.json │ │ ├── speechiness.json │ │ ├── tempo.json │ │ ├── timesignature.json │ │ └── valence.json │ │ ├── tracklink.json │ │ ├── tracklink │ │ ├── !=(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── equatable-implementations.json │ │ ├── externalurls.json │ │ ├── href.json │ │ ├── id.json │ │ ├── init(externalurls:href:uri:id:).json │ │ ├── init(from:).json │ │ ├── type.json │ │ └── uri.json │ │ ├── uriscontainer.json │ │ ├── uriscontainer │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashable-implementations.json │ │ ├── init(_:snapshotid:).json │ │ ├── init(from:).json │ │ ├── items.json │ │ └── snapshotid.json │ │ ├── urisdictwithinsertionindex.json │ │ ├── urisdictwithinsertionindex │ │ ├── !=(_:_:).json │ │ ├── ==(_:_:).json │ │ ├── decodable-implementations.json │ │ ├── encodable-implementations.json │ │ ├── encode(to:).json │ │ ├── equatable-implementations.json │ │ ├── hash(into:).json │ │ ├── hashable-implementations.json │ │ ├── init(from:).json │ │ ├── init(uris:position:).json │ │ ├── position.json │ │ └── uris.json │ │ ├── urlquerydictionary(_:).json │ │ ├── using-the-player-endpoints.json │ │ └── working-with-paginated-results.json ├── developer-og-twitter.jpg ├── developer-og.jpg ├── documentation │ └── spotifywebapi │ │ ├── additional-authorization-methods │ │ └── index.html │ │ ├── album │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── albumgroup │ │ │ └── index.html │ │ ├── albumtype │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── artists │ │ │ └── index.html │ │ ├── availablemarkets │ │ │ └── index.html │ │ ├── copyrights │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalids │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── genres │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:tracks:artists:releasedate:uri:id:images:popularity:label:genres:totaltracks:href:externalurls:externalids:albumtype:albumgroup:availablemarkets:copyrights:releasedateprecision:restrictions:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── label │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── popularity │ │ │ └── index.html │ │ ├── releasedate │ │ │ └── index.html │ │ ├── releasedateprecision │ │ │ └── index.html │ │ ├── restrictions │ │ │ └── index.html │ │ ├── totaltracks │ │ │ └── index.html │ │ ├── tracks │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── albumtype │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── album │ │ │ └── index.html │ │ ├── appearson │ │ │ └── index.html │ │ ├── compilation │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── ep │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashvalue │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rawvalue:) │ │ │ └── index.html │ │ ├── other │ │ │ └── index.html │ │ ├── rawrepresentable-implementations │ │ │ └── index.html │ │ └── single │ │ │ └── index.html │ │ ├── approximatelyequatable │ │ ├── index.html │ │ └── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── artist │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── followers │ │ │ └── index.html │ │ ├── genres │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:uri:id:images:popularity:externalurls:followers:genres:href:) │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── popularity │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── attributerange │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(min:target:max:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── max │ │ │ └── index.html │ │ ├── min │ │ │ └── index.html │ │ ├── querydictionary(attributename:) │ │ │ └── index.html │ │ └── target │ │ │ └── index.html │ │ ├── audio-analysis-objects │ │ └── index.html │ │ ├── audioanalysis │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── bars │ │ │ └── index.html │ │ ├── beats │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(bars:beats:tatums:sections:segments:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── sections │ │ │ └── index.html │ │ ├── segments │ │ │ └── index.html │ │ └── tatums │ │ │ └── index.html │ │ ├── audiobook-objects │ │ └── index.html │ │ ├── audiobook │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── authors │ │ │ └── index.html │ │ ├── availablemarkets │ │ │ └── index.html │ │ ├── chapters │ │ │ └── index.html │ │ ├── copyrights │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── edition │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── htmldescription │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:authors:narrators:publisher:description:htmldescription:chapters:totalchapters:isexplicit:uri:id:images:availablemarkets:href:externalurls:languages:copyrights:mediatype:edition:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── isexplicit │ │ │ └── index.html │ │ ├── languages │ │ │ └── index.html │ │ ├── mediatype │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── narrators │ │ │ └── index.html │ │ ├── publisher │ │ │ └── index.html │ │ ├── totalchapters │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── audiobookauthor │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:) │ │ │ └── index.html │ │ └── name │ │ │ └── index.html │ │ ├── audiobookchapter │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── audiobook │ │ │ └── index.html │ │ ├── audiopreviewurl │ │ │ └── index.html │ │ ├── availablemarkets │ │ │ └── index.html │ │ ├── chapternumber │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── durationms │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── htmldescription │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:audiobook:chapternumber:audiopreviewurl:description:htmldescription:resumepoint:durationms:isexplicit:releasedate:uri:id:images:availablemarkets:href:isplayable:externalurls:languages:restrictions:releasedateprecision:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── isexplicit │ │ │ └── index.html │ │ ├── isplayable │ │ │ └── index.html │ │ ├── languages │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── releasedate │ │ │ └── index.html │ │ ├── releasedateprecision │ │ │ └── index.html │ │ ├── restrictions │ │ │ └── index.html │ │ ├── resumepoint │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── audiofeatures │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── acousticness │ │ │ └── index.html │ │ ├── analysisurl │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── danceability │ │ │ └── index.html │ │ ├── durationms │ │ │ └── index.html │ │ ├── energy │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(key:mode:timesignature:acousticness:danceability:energy:instrumentalness:liveness:loudness:speechiness:valence:tempo:uri:id:trackhref:analysisurl:durationms:type:) │ │ │ └── index.html │ │ ├── instrumentalness │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── key │ │ │ └── index.html │ │ ├── liveness │ │ │ └── index.html │ │ ├── loudness │ │ │ └── index.html │ │ ├── mode │ │ │ └── index.html │ │ ├── speechiness │ │ │ └── index.html │ │ ├── tempo │ │ │ └── index.html │ │ ├── timesignature │ │ │ └── index.html │ │ ├── trackhref │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ ├── uri │ │ │ └── index.html │ │ └── valence │ │ │ └── index.html │ │ ├── authinfo │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── accesstoken │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── codingkeys │ │ │ ├── !=(_:_:) │ │ │ │ └── index.html │ │ │ ├── accesstoken │ │ │ │ └── index.html │ │ │ ├── backend │ │ │ │ └── index.html │ │ │ ├── clientid │ │ │ │ └── index.html │ │ │ ├── clientsecret │ │ │ │ └── index.html │ │ │ ├── codingkey-implementations │ │ │ │ └── index.html │ │ │ ├── debugdescription │ │ │ │ └── index.html │ │ │ ├── description │ │ │ │ └── index.html │ │ │ ├── equatable-implementations │ │ │ │ └── index.html │ │ │ ├── expirationdate │ │ │ │ └── index.html │ │ │ ├── expiresinseconds │ │ │ │ └── index.html │ │ │ ├── hash(into:) │ │ │ │ └── index.html │ │ │ ├── hashvalue │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── init(intvalue:) │ │ │ │ └── index.html │ │ │ ├── init(rawvalue:) │ │ │ │ └── index.html │ │ │ ├── init(stringvalue:) │ │ │ │ └── index.html │ │ │ ├── rawrepresentable-implementations │ │ │ │ └── index.html │ │ │ ├── refreshtoken │ │ │ │ └── index.html │ │ │ └── scopes │ │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── expirationdate │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(accesstoken:refreshtoken:expirationdate:scopes:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── refreshtoken │ │ │ └── index.html │ │ └── scopes │ │ │ └── index.html │ │ ├── authorizationcodeflowbackend │ │ ├── clientid │ │ │ └── index.html │ │ ├── index.html │ │ ├── refreshtokens(refreshtoken:) │ │ │ └── index.html │ │ └── requestaccessandrefreshtokens(code:redirecturiwithquery:) │ │ │ └── index.html │ │ ├── authorizationcodeflowbackendmanager │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(backend:) │ │ │ └── index.html │ │ ├── init(backend:accesstoken:expirationdate:refreshtoken:scopes:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── makeauthorizationurl(redirecturi:showdialog:state:scopes:) │ │ │ └── index.html │ │ ├── refreshtokens(onlyifexpired:tolerance:) │ │ │ └── index.html │ │ ├── requestaccessandrefreshtokens(redirecturiwithquery:state:) │ │ │ └── index.html │ │ └── spotifyauthorizationmanager-implementations │ │ │ └── index.html │ │ ├── authorizationcodeflowclientbackend │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── clientsecret │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:clientsecret:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── refreshtokens(refreshtoken:) │ │ │ └── index.html │ │ └── requestaccessandrefreshtokens(code:redirecturiwithquery:) │ │ │ └── index.html │ │ ├── authorizationcodeflowmanager │ │ ├── clientid │ │ │ └── index.html │ │ ├── clientsecret │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:clientsecret:) │ │ │ └── index.html │ │ └── init(clientid:clientsecret:accesstoken:expirationdate:refreshtoken:scopes:) │ │ │ └── index.html │ │ ├── authorizationcodeflowmanagerbase │ │ ├── accesstoken │ │ │ └── index.html │ │ ├── accesstokenisexpired(tolerance:) │ │ │ └── index.html │ │ ├── backend │ │ │ └── index.html │ │ ├── baselogger │ │ │ └── index.html │ │ ├── deauthorize() │ │ │ └── index.html │ │ ├── didchange │ │ │ └── index.html │ │ ├── diddeauthorize │ │ │ └── index.html │ │ ├── expirationdate │ │ │ └── index.html │ │ ├── index.html │ │ ├── isauthorized(for:) │ │ │ └── index.html │ │ ├── makecopy() │ │ │ └── index.html │ │ ├── refreshtoken │ │ │ └── index.html │ │ ├── scopes │ │ │ └── index.html │ │ └── setexpirationdate(to:) │ │ │ └── index.html │ │ ├── authorizationcodeflowpkcebackend │ │ ├── clientid │ │ │ └── index.html │ │ ├── index.html │ │ ├── refreshtokens(refreshtoken:) │ │ │ └── index.html │ │ └── requestaccessandrefreshtokens(code:codeverifier:redirecturiwithquery:) │ │ │ └── index.html │ │ ├── authorizationcodeflowpkcebackendmanager │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(backend:) │ │ │ └── index.html │ │ ├── init(backend:accesstoken:expirationdate:refreshtoken:scopes:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── makeauthorizationurl(redirecturi:codechallenge:state:scopes:) │ │ │ └── index.html │ │ ├── refreshtokens(onlyifexpired:tolerance:) │ │ │ └── index.html │ │ ├── requestaccessandrefreshtokens(redirecturiwithquery:codeverifier:state:) │ │ │ └── index.html │ │ └── spotifyauthorizationmanager-implementations │ │ │ └── index.html │ │ ├── authorizationcodeflowpkceclientbackend │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── refreshtokens(refreshtoken:) │ │ │ └── index.html │ │ └── requestaccessandrefreshtokens(code:codeverifier:redirecturiwithquery:) │ │ │ └── index.html │ │ ├── authorizationcodeflowpkcemanager │ │ ├── clientid │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:) │ │ │ └── index.html │ │ └── init(clientid:accesstoken:expirationdate:refreshtoken:scopes:) │ │ │ └── index.html │ │ ├── authorizationcodeflowpkceproxybackend │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── decodeservererror │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:tokensurl:tokenrefreshurl:decodeservererror:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── refreshtokens(refreshtoken:) │ │ │ └── index.html │ │ ├── requestaccessandrefreshtokens(code:codeverifier:redirecturiwithquery:) │ │ │ └── index.html │ │ ├── tokenrefreshurl │ │ │ └── index.html │ │ └── tokensurl │ │ │ └── index.html │ │ ├── authorizationcodeflowproxybackend │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── decodeservererror │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:tokensurl:tokenrefreshurl:decodeservererror:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── refreshtokens(refreshtoken:) │ │ │ └── index.html │ │ ├── requestaccessandrefreshtokens(code:redirecturiwithquery:) │ │ │ └── index.html │ │ ├── tokenrefreshurl │ │ │ └── index.html │ │ └── tokensurl │ │ │ └── index.html │ │ ├── authorizing-with-the-authorization-code-flow-with-proof-key-for-code-exchange │ │ └── index.html │ │ ├── authorizing-with-the-authorization-code-flow │ │ └── index.html │ │ ├── authorizing-with-the-client-credentials-flow │ │ └── index.html │ │ ├── clientcredentialsflowbackend │ │ ├── index.html │ │ └── makeclientcredentialstokensrequest() │ │ │ └── index.html │ │ ├── clientcredentialsflowbackendmanager │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── accesstoken │ │ │ └── index.html │ │ ├── accesstokenisexpired(tolerance:) │ │ │ └── index.html │ │ ├── authorize() │ │ │ └── index.html │ │ ├── backend │ │ │ └── index.html │ │ ├── deauthorize() │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── didchange │ │ │ └── index.html │ │ ├── diddeauthorize │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── expirationdate │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(backend:) │ │ │ └── index.html │ │ ├── init(backend:accesstoken:expirationdate:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isauthorized(for:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── makecopy() │ │ │ └── index.html │ │ ├── refreshtokens(onlyifexpired:tolerance:) │ │ │ └── index.html │ │ ├── scopes │ │ │ └── index.html │ │ ├── setexpirationdate(to:) │ │ │ └── index.html │ │ └── spotifyauthorizationmanager-implementations │ │ │ └── index.html │ │ ├── clientcredentialsflowclientbackend │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── clientsecret │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:clientsecret:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ └── makeclientcredentialstokensrequest() │ │ │ └── index.html │ │ ├── clientcredentialsflowmanager │ │ ├── clientid │ │ │ └── index.html │ │ ├── clientsecret │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(clientid:clientsecret:) │ │ │ └── index.html │ │ └── init(clientid:clientsecret:accesstoken:expirationdate:) │ │ │ └── index.html │ │ ├── clientcredentialsflowproxybackend │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── decodeservererror │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(tokensurl:decodeservererror:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── makeclientcredentialstokensrequest() │ │ │ └── index.html │ │ └── tokensurl │ │ │ └── index.html │ │ ├── clientcredentialstokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init() │ │ │ └── index.html │ │ └── init(from:) │ │ │ └── index.html │ │ ├── combine │ │ ├── index.html │ │ └── publisher │ │ │ ├── collectandsortbyoffset() │ │ │ └── index.html │ │ │ ├── decodeoptionalspotifyobject(_:maxretrydelay:) │ │ │ └── index.html │ │ │ ├── decodespotifyerrors(maxretrydelay:) │ │ │ └── index.html │ │ │ ├── decodespotifyobject(_:maxretrydelay:) │ │ │ └── index.html │ │ │ ├── extendpages(_:maxextrapages:) │ │ │ └── index.html │ │ │ ├── extendpagesconcurrently(_:maxextrapages:) │ │ │ └── index.html │ │ │ ├── index.html │ │ │ └── sink(receivecompletion:) │ │ │ └── index.html │ │ ├── currentlyplayingcontext │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── allowedactions │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── context │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── device │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(device:repeatstate:shuffleison:context:timestamp:progressms:isplaying:item:itemtype:allowedactions:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── isplaying │ │ │ └── index.html │ │ ├── item │ │ │ └── index.html │ │ ├── itemtype │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── progressms │ │ │ └── index.html │ │ ├── repeatstate │ │ │ └── index.html │ │ ├── shuffleison │ │ │ └── index.html │ │ └── timestamp │ │ │ └── index.html │ │ ├── cursorpagingobject │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── cursors │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(href:items:limit:next:cursors:total:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── items │ │ │ └── index.html │ │ ├── limit │ │ │ └── index.html │ │ ├── next │ │ │ └── index.html │ │ └── total │ │ │ └── index.html │ │ ├── debugging │ │ └── index.html │ │ ├── decodespotifyerrors(data:httpurlresponse:) │ │ └── index.html │ │ ├── decodespotifyobject(data:httpurlresponse:responsetype:) │ │ └── index.html │ │ ├── device │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(id:isactive:isprivatesession:isrestricted:name:type:volumepercent:) │ │ │ └── index.html │ │ ├── isactive │ │ │ └── index.html │ │ ├── isprivatesession │ │ │ └── index.html │ │ ├── isrestricted │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── volumepercent │ │ │ └── index.html │ │ ├── devicetype │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── audiodongle │ │ │ └── index.html │ │ ├── automobile │ │ │ └── index.html │ │ ├── avr │ │ │ └── index.html │ │ ├── castaudio │ │ │ └── index.html │ │ ├── castvideo │ │ │ └── index.html │ │ ├── computer │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── gameconsole │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashvalue │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rawvalue:) │ │ │ └── index.html │ │ ├── rawrepresentable-implementations │ │ │ └── index.html │ │ ├── smartphone │ │ │ └── index.html │ │ ├── speaker │ │ │ └── index.html │ │ ├── stb │ │ │ └── index.html │ │ ├── tablet │ │ │ └── index.html │ │ ├── tv │ │ │ └── index.html │ │ └── unknown │ │ │ └── index.html │ │ ├── endpoints │ │ ├── accountsbase │ │ │ └── index.html │ │ ├── apibase │ │ │ └── index.html │ │ ├── apiendpoint(_:queryitems:) │ │ │ └── index.html │ │ ├── apiversion1 │ │ │ └── index.html │ │ ├── authorize │ │ │ └── index.html │ │ ├── gettokens │ │ │ └── index.html │ │ ├── index.html │ │ └── token │ │ │ └── index.html │ │ ├── episode │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── audiopreviewurl │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── durationms │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── htmldescription │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:show:audiopreviewurl:description:htmldescription:resumepoint:durationms:isexplicit:releasedate:uri:id:images:href:isplayable:externalurls:isexternallyhosted:languages:releasedateprecision:restrictions:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── isexplicit │ │ │ └── index.html │ │ ├── isexternallyhosted │ │ │ └── index.html │ │ ├── isplayable │ │ │ └── index.html │ │ ├── languages │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── releasedate │ │ │ └── index.html │ │ ├── releasedateprecision │ │ │ └── index.html │ │ ├── restrictions │ │ │ └── index.html │ │ ├── resumepoint │ │ │ └── index.html │ │ ├── show │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── featuredplaylists │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(message:playlists:) │ │ │ └── index.html │ │ ├── message │ │ │ └── index.html │ │ └── playlists │ │ │ └── index.html │ │ ├── followers │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(href:total:) │ │ │ └── index.html │ │ └── total │ │ │ └── index.html │ │ ├── foundation │ │ ├── characterset │ │ │ ├── index.html │ │ │ └── urlqueryandpathallowed │ │ │ │ └── index.html │ │ ├── data │ │ │ ├── base64urlencodedstring(options:) │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ └── init(base64urlencoded:options:) │ │ │ │ └── index.html │ │ ├── date │ │ │ ├── approximatelyequatable-implementations │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── init(millisecondssince1970:) │ │ │ │ └── index.html │ │ │ ├── isapproximatelyequal(to:) │ │ │ │ └── index.html │ │ │ └── millisecondssince1970 │ │ │ │ └── index.html │ │ ├── dateformatter │ │ │ ├── featuredplaylists │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── millisecondstime │ │ │ │ └── index.html │ │ │ ├── spotifyalbumlong │ │ │ │ └── index.html │ │ │ ├── spotifyalbummedium │ │ │ │ └── index.html │ │ │ └── spotifyalbumshort │ │ │ │ └── index.html │ │ ├── index.html │ │ ├── url │ │ │ ├── appending(queryitems:)-4id6o │ │ │ │ └── index.html │ │ │ ├── appending(queryitems:)-fcfy │ │ │ │ └── index.html │ │ │ ├── components │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── queryitems │ │ │ │ └── index.html │ │ │ ├── queryitemsdict │ │ │ │ └── index.html │ │ │ ├── removequeryitems() │ │ │ │ └── index.html │ │ │ ├── removetrailingslashinpath() │ │ │ │ └── index.html │ │ │ ├── removingqueryitems() │ │ │ │ └── index.html │ │ │ ├── removingtrailingslashinpath() │ │ │ │ └── index.html │ │ │ ├── sortedqueryitems() │ │ │ │ └── index.html │ │ │ └── sortqueryitems() │ │ │ │ └── index.html │ │ ├── urlcomponents │ │ │ ├── index.html │ │ │ ├── queryitemsdict │ │ │ │ └── index.html │ │ │ ├── removetrailingslashinpath() │ │ │ │ └── index.html │ │ │ └── removingtrailingslashinpath() │ │ │ │ └── index.html │ │ └── urlsession │ │ │ ├── defaultnetworkadaptor(request:) │ │ │ └── index.html │ │ │ └── index.html │ │ ├── generatepageoffsets(_:maxextrapages:) │ │ └── index.html │ │ ├── headers │ │ ├── basicbase64encoded(clientid:clientsecret:) │ │ │ └── index.html │ │ ├── bearerauthorization(_:) │ │ │ └── index.html │ │ ├── bearerauthorizationandcontenttypejson(_:) │ │ │ └── index.html │ │ ├── contenttypeimagejpeg │ │ │ └── index.html │ │ ├── contenttypejson │ │ │ └── index.html │ │ ├── formurlencoded │ │ │ └── index.html │ │ └── index.html │ │ ├── idcategory │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ad │ │ │ └── index.html │ │ ├── album │ │ │ └── index.html │ │ ├── artist │ │ │ └── index.html │ │ ├── audiobook │ │ │ └── index.html │ │ ├── chapter │ │ │ └── index.html │ │ ├── collection │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── episode │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── genre │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashvalue │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rawvalue:) │ │ │ └── index.html │ │ ├── local │ │ │ └── index.html │ │ ├── playlist │ │ │ └── index.html │ │ ├── rawrepresentable-implementations │ │ │ └── index.html │ │ ├── show │ │ │ └── index.html │ │ ├── track │ │ │ └── index.html │ │ ├── unknown │ │ │ └── index.html │ │ └── user │ │ │ └── index.html │ │ ├── index.html │ │ ├── logging │ │ ├── index.html │ │ └── logger │ │ │ ├── index.html │ │ │ ├── init(label:level:) │ │ │ └── index.html │ │ │ └── init(label:level:factory:) │ │ │ └── index.html │ │ ├── media-objects │ │ └── index.html │ │ ├── newalbumreleases │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── albums │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(message:albums:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ └── message │ │ │ └── index.html │ │ ├── other-objects │ │ └── index.html │ │ ├── paginated │ │ ├── index.html │ │ └── next │ │ │ └── index.html │ │ ├── pagingobject │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── estimatedindex │ │ │ └── index.html │ │ ├── estimatedtotalpages │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashable-implementations │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(href:items:limit:next:previous:offset:total:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── items │ │ │ └── index.html │ │ ├── limit │ │ │ └── index.html │ │ ├── next │ │ │ └── index.html │ │ ├── offset │ │ │ └── index.html │ │ ├── previous │ │ │ └── index.html │ │ └── total │ │ │ └── index.html │ │ ├── pagingobjectprotocol │ │ ├── href │ │ │ └── index.html │ │ ├── index.html │ │ ├── item │ │ │ └── index.html │ │ ├── items │ │ │ └── index.html │ │ ├── limit │ │ │ └── index.html │ │ ├── next │ │ │ └── index.html │ │ ├── offset │ │ │ └── index.html │ │ ├── previous │ │ │ └── index.html │ │ └── total │ │ │ └── index.html │ │ ├── pkcerefreshtokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(refreshtoken:clientid:) │ │ │ └── index.html │ │ └── refreshtoken │ │ │ └── index.html │ │ ├── pkcetokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── code │ │ │ └── index.html │ │ ├── codeverifier │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(code:codeverifier:redirecturi:clientid:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ └── redirecturi │ │ │ └── index.html │ │ ├── playbackactions │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── allcases-swift.type.property │ │ │ └── index.html │ │ ├── allcases-swift.typealias │ │ │ └── index.html │ │ ├── caseiterable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashvalue │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rawvalue:) │ │ │ └── index.html │ │ ├── interruptplayback │ │ │ └── index.html │ │ ├── pause │ │ │ └── index.html │ │ ├── rawrepresentable-implementations │ │ │ └── index.html │ │ ├── resume │ │ │ └── index.html │ │ ├── seek │ │ │ └── index.html │ │ ├── skiptonext │ │ │ └── index.html │ │ ├── skiptoprevious │ │ │ └── index.html │ │ ├── togglerepeatcontext │ │ │ └── index.html │ │ ├── togglerepeattrack │ │ │ └── index.html │ │ ├── toggleshuffle │ │ │ └── index.html │ │ └── transferplayback │ │ │ └── index.html │ │ ├── playbackrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── context-swift.enum │ │ │ ├── !=(_:_:) │ │ │ │ └── index.html │ │ │ ├── ==(_:_:) │ │ │ │ └── index.html │ │ │ ├── contexturi(_:) │ │ │ │ └── index.html │ │ │ ├── decodable-implementations │ │ │ │ └── index.html │ │ │ ├── encodable-implementations │ │ │ │ └── index.html │ │ │ ├── encode(to:) │ │ │ │ └── index.html │ │ │ ├── equatable-implementations │ │ │ │ └── index.html │ │ │ ├── hash(into:) │ │ │ │ └── index.html │ │ │ ├── hashable-implementations │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── init(from:) │ │ │ │ └── index.html │ │ │ └── uris(_:) │ │ │ │ └── index.html │ │ ├── context-swift.property │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(_:positionms:) │ │ │ └── index.html │ │ ├── init(context:offset:positionms:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── offset-swift.enum │ │ │ ├── !=(_:_:) │ │ │ │ └── index.html │ │ │ ├── ==(_:_:) │ │ │ │ └── index.html │ │ │ ├── decodable-implementations │ │ │ │ └── index.html │ │ │ ├── encodable-implementations │ │ │ │ └── index.html │ │ │ ├── encode(to:) │ │ │ │ └── index.html │ │ │ ├── equatable-implementations │ │ │ │ └── index.html │ │ │ ├── hash(into:) │ │ │ │ └── index.html │ │ │ ├── hashable-implementations │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── init(from:) │ │ │ │ └── index.html │ │ │ ├── position(_:) │ │ │ │ └── index.html │ │ │ └── uri(_:) │ │ │ │ └── index.html │ │ ├── offset-swift.property │ │ │ └── index.html │ │ └── positionms │ │ │ └── index.html │ │ ├── player-objects │ │ └── index.html │ │ ├── playhistory │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── context │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(track:playedat:context:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── playedat │ │ │ └── index.html │ │ └── track │ │ │ └── index.html │ │ ├── playlist-objects │ │ └── index.html │ │ ├── playlist │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── followers │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:items:owner:ispublic:iscollaborative:description:snapshotid:externalurls:followers:href:id:uri:images:) │ │ │ └── index.html │ │ ├── iscollaborative │ │ │ └── index.html │ │ ├── ispublic │ │ │ └── index.html │ │ ├── items │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── owner │ │ │ └── index.html │ │ ├── snapshotid │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── playlistdetails │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:ispublic:iscollaborative:description:) │ │ │ └── index.html │ │ ├── iscollaborative │ │ │ └── index.html │ │ ├── ispublic │ │ │ └── index.html │ │ └── name │ │ │ └── index.html │ │ ├── playlistitem │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── durationms │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── episode(_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── isexplicit │ │ │ └── index.html │ │ ├── isplayable │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── track(_:) │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── playlistitemcontainer │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── addedat │ │ │ └── index.html │ │ ├── addedby │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(addedat:addedby:islocal:item:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── islocal │ │ │ └── index.html │ │ └── item │ │ │ └── index.html │ │ ├── playlistitems │ │ └── index.html │ │ ├── playlistitemsreference │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(href:total:) │ │ │ └── index.html │ │ └── total │ │ │ └── index.html │ │ ├── playlisttracks │ │ └── index.html │ │ ├── proxypkcerefreshtokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(refreshtoken:) │ │ │ └── index.html │ │ ├── method │ │ │ └── index.html │ │ └── refreshtoken │ │ │ └── index.html │ │ ├── proxypkcetokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── code │ │ │ └── index.html │ │ ├── codeverifier │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(code:codeverifier:redirecturi:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ └── redirecturi │ │ │ └── index.html │ │ ├── proxytokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── code │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(code:redirecturi:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ └── redirecturi │ │ │ └── index.html │ │ ├── ratelimitederror │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── anyfailingpublisher(_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── error-implementations │ │ │ └── index.html │ │ ├── errordescription │ │ │ └── index.html │ │ ├── failurereason │ │ │ └── index.html │ │ ├── helpanchor │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── localizeddescription │ │ │ └── index.html │ │ ├── localizederror-implementations │ │ │ └── index.html │ │ ├── recoverysuggestion │ │ │ └── index.html │ │ └── retryafter │ │ │ └── index.html │ │ ├── recommendationseed │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── afterfilteringsize │ │ │ └── index.html │ │ ├── afterrelinkingsize │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(afterfilteringsize:afterrelinkingsize:href:id:initialpoolsize:type:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── initialpoolsize │ │ │ └── index.html │ │ └── type │ │ │ └── index.html │ │ ├── recommendationsresponse │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(seeds:tracks:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── seedartists │ │ │ └── index.html │ │ ├── seedgenres │ │ │ └── index.html │ │ ├── seeds │ │ │ └── index.html │ │ ├── seedtracks │ │ │ └── index.html │ │ └── tracks │ │ │ └── index.html │ │ ├── refreshtokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(refreshtoken:) │ │ │ └── index.html │ │ └── refreshtoken │ │ │ └── index.html │ │ ├── reorderplaylistitems │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rangestart:rangelength:insertbefore:snapshotid:) │ │ │ └── index.html │ │ ├── insertbefore │ │ │ └── index.html │ │ ├── rangelength │ │ │ └── index.html │ │ ├── rangestart │ │ │ └── index.html │ │ └── snapshotid │ │ │ └── index.html │ │ ├── repeatmode │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── context │ │ │ └── index.html │ │ ├── cycle() │ │ │ └── index.html │ │ ├── cycled() │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashvalue │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rawvalue:) │ │ │ └── index.html │ │ ├── off │ │ │ └── index.html │ │ ├── rawrepresentable-implementations │ │ │ └── index.html │ │ └── track │ │ │ └── index.html │ │ ├── resumepoint │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── fullyplayed │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(fullyplayed:resumepositionms:) │ │ │ └── index.html │ │ └── resumepositionms │ │ │ └── index.html │ │ ├── running-the-unit-tests │ │ └── index.html │ │ ├── savedalbum │ │ └── index.html │ │ ├── savedaudiobook │ │ └── index.html │ │ ├── savedepisode │ │ └── index.html │ │ ├── saveditem │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── addedat │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(addedat:item:type:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── item │ │ │ └── index.html │ │ └── type │ │ │ └── index.html │ │ ├── savedshow │ │ └── index.html │ │ ├── savedtrack │ │ └── index.html │ │ ├── saving-the-authorization-information-to-persistent-storage │ │ └── index.html │ │ ├── scope │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── allcases-swift.type.property │ │ │ └── index.html │ │ ├── allcases-swift.typealias │ │ │ └── index.html │ │ ├── appremotecontrol │ │ │ └── index.html │ │ ├── caseiterable-implementations │ │ │ └── index.html │ │ ├── contains(_:) │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashvalue │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rawvalue:) │ │ │ └── index.html │ │ ├── makeset(_:) │ │ │ └── index.html │ │ ├── makestring(_:)-7pkz7 │ │ │ └── index.html │ │ ├── makestring(_:)-7y7yy │ │ │ └── index.html │ │ ├── playlistmodifyprivate │ │ │ └── index.html │ │ ├── playlistmodifypublic │ │ │ └── index.html │ │ ├── playlistreadcollaborative │ │ │ └── index.html │ │ ├── playlistreadprivate │ │ │ └── index.html │ │ ├── rawrepresentable-implementations │ │ │ └── index.html │ │ ├── streaming │ │ │ └── index.html │ │ ├── ugcimageupload │ │ │ └── index.html │ │ ├── userfollowmodify │ │ │ └── index.html │ │ ├── userfollowread │ │ │ └── index.html │ │ ├── userlibrarymodify │ │ │ └── index.html │ │ ├── userlibraryread │ │ │ └── index.html │ │ ├── usermodifyplaybackstate │ │ │ └── index.html │ │ ├── userreadcurrentlyplaying │ │ │ └── index.html │ │ ├── userreademail │ │ │ └── index.html │ │ ├── userreadplaybackposition │ │ │ └── index.html │ │ ├── userreadplaybackstate │ │ │ └── index.html │ │ ├── userreadprivate │ │ │ └── index.html │ │ ├── userreadrecentlyplayed │ │ │ └── index.html │ │ └── usertopread │ │ │ └── index.html │ │ ├── searchresult │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── albums │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── artists │ │ │ └── index.html │ │ ├── audiobooks │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── episodes │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(artists:albums:tracks:playlists:episodes:shows:audiobooks:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── playlists │ │ │ └── index.html │ │ ├── shows │ │ │ └── index.html │ │ └── tracks │ │ │ └── index.html │ │ ├── section │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── confidence │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── duration │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(start:duration:confidence:loudness:tempo:tempoconfidence:key:keyconfidence:mode:modeconfidence:timesignature:timesignatureconfidence:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── key │ │ │ └── index.html │ │ ├── keyconfidence │ │ │ └── index.html │ │ ├── loudness │ │ │ └── index.html │ │ ├── mode │ │ │ └── index.html │ │ ├── modeconfidence │ │ │ └── index.html │ │ ├── start │ │ │ └── index.html │ │ ├── tempo │ │ │ └── index.html │ │ ├── tempoconfidence │ │ │ └── index.html │ │ ├── timesignature │ │ │ └── index.html │ │ └── timesignatureconfidence │ │ │ └── index.html │ │ ├── segment │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── confidence │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── duration │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(start:duration:confidence:loudnessstart:loudnessmax:loudnessmaxtime:pitches:timbre:loudnessend:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── loudnessend │ │ │ └── index.html │ │ ├── loudnessmax │ │ │ └── index.html │ │ ├── loudnessmaxtime │ │ │ └── index.html │ │ ├── loudnessstart │ │ │ └── index.html │ │ ├── pitches │ │ │ └── index.html │ │ ├── start │ │ │ └── index.html │ │ └── timbre │ │ │ └── index.html │ │ ├── show │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── availablemarkets │ │ │ └── index.html │ │ ├── copyrights │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── episodes │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── htmldescription │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:description:htmldescription:episodes:totalepisodes:isexplicit:uri:id:images:availablemarkets:href:externalurls:isexternallyhosted:languages:copyrights:mediatype:publisher:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── isexplicit │ │ │ └── index.html │ │ ├── isexternallyhosted │ │ │ └── index.html │ │ ├── languages │ │ │ └── index.html │ │ ├── mediatype │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── publisher │ │ │ └── index.html │ │ ├── totalepisodes │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── spotifyapi │ │ ├── addtoplaylist(_:uris:position:) │ │ │ └── index.html │ │ ├── addtoqueue(_:deviceid:) │ │ │ └── index.html │ │ ├── album(_:market:) │ │ │ └── index.html │ │ ├── albums(_:market:) │ │ │ └── index.html │ │ ├── albumtracks(_:market:limit:offset:) │ │ │ └── index.html │ │ ├── apirequestlogger │ │ │ └── index.html │ │ ├── artist(_:) │ │ │ └── index.html │ │ ├── artistalbums(_:groups:country:limit:offset:) │ │ │ └── index.html │ │ ├── artists(_:) │ │ │ └── index.html │ │ ├── artisttoptracks(_:country:) │ │ │ └── index.html │ │ ├── audiobook(_:market:) │ │ │ └── index.html │ │ ├── audiobookchapters(_:market:limit:offset:) │ │ │ └── index.html │ │ ├── audiobooks(_:market:) │ │ │ └── index.html │ │ ├── authdidchangelogger │ │ │ └── index.html │ │ ├── authorizationmanager │ │ │ └── index.html │ │ ├── authorizationmanagerdidchange │ │ │ └── index.html │ │ ├── authorizationmanagerdiddeauthorize │ │ │ └── index.html │ │ ├── availabledevices() │ │ │ └── index.html │ │ ├── availablemarkets() │ │ │ └── index.html │ │ ├── categories(country:locale:limit:offset:) │ │ │ └── index.html │ │ ├── category(_:country:locale:) │ │ │ └── index.html │ │ ├── categoryplaylists(_:country:limit:offset:) │ │ │ └── index.html │ │ ├── changeplaylistdetails(_:to:) │ │ │ └── index.html │ │ ├── chapter(_:market:) │ │ │ └── index.html │ │ ├── chapters(_:market:) │ │ │ └── index.html │ │ ├── createplaylist(for:_:) │ │ │ └── index.html │ │ ├── currentplayback(market:) │ │ │ └── index.html │ │ ├── currentuserfollowedartists(after:limit:) │ │ │ └── index.html │ │ ├── currentuserfollowsartists(_:) │ │ │ └── index.html │ │ ├── currentuserfollowsplaylist(_:) │ │ │ └── index.html │ │ ├── currentuserfollowsusers(_:) │ │ │ └── index.html │ │ ├── currentuserplaylists(limit:offset:) │ │ │ └── index.html │ │ ├── currentuserprofile() │ │ │ └── index.html │ │ ├── currentusersavedalbums(limit:offset:market:) │ │ │ └── index.html │ │ ├── currentusersavedalbumscontains(_:) │ │ │ └── index.html │ │ ├── currentusersavedaudiobooks(limit:offset:) │ │ │ └── index.html │ │ ├── currentusersavedaudiobookscontains(_:) │ │ │ └── index.html │ │ ├── currentusersavedepisodes(limit:offset:market:) │ │ │ └── index.html │ │ ├── currentusersavedepisodescontains(_:) │ │ │ └── index.html │ │ ├── currentusersavedshows(limit:offset:) │ │ │ └── index.html │ │ ├── currentusersavedshowscontains(_:) │ │ │ └── index.html │ │ ├── currentusersavedtracks(limit:offset:market:) │ │ │ └── index.html │ │ ├── currentusersavedtrackscontains(_:) │ │ │ └── index.html │ │ ├── currentusertopartists(_:offset:limit:) │ │ │ └── index.html │ │ ├── currentusertoptracks(_:offset:limit:) │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── episode(_:market:) │ │ │ └── index.html │ │ ├── episodes(_:market:) │ │ │ └── index.html │ │ ├── extendpages(_:maxextrapages:) │ │ │ └── index.html │ │ ├── extendpagesconcurrently(_:maxextrapages:) │ │ │ └── index.html │ │ ├── featuredplaylists(locale:country:timestamp:limit:offset:) │ │ │ └── index.html │ │ ├── filteredplaylist(_:filters:additionaltypes:market:) │ │ │ └── index.html │ │ ├── filteredplaylistitems(_:filters:additionaltypes:limit:offset:market:) │ │ │ └── index.html │ │ ├── followartistsforcurrentuser(_:) │ │ │ └── index.html │ │ ├── followplaylistforcurrentuser(_:publicly:) │ │ │ └── index.html │ │ ├── followusersforcurrentuser(_:) │ │ │ └── index.html │ │ ├── getfromhref(_:responsetype:) │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(authorizationmanager:maxretrydelay:networkadaptor:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── logger │ │ │ └── index.html │ │ ├── maxretrydelay │ │ │ └── index.html │ │ ├── networkadaptor │ │ │ └── index.html │ │ ├── newalbumreleases(country:limit:offset:) │ │ │ └── index.html │ │ ├── pauseplayback(deviceid:) │ │ │ └── index.html │ │ ├── play(_:deviceid:) │ │ │ └── index.html │ │ ├── playlist(_:market:) │ │ │ └── index.html │ │ ├── playlistimage(_:) │ │ │ └── index.html │ │ ├── playlistitems(_:limit:offset:market:) │ │ │ └── index.html │ │ ├── playlisttracks(_:limit:offset:market:) │ │ │ └── index.html │ │ ├── queue() │ │ │ └── index.html │ │ ├── recentlyplayed(_:limit:) │ │ │ └── index.html │ │ ├── recommendationgenres() │ │ │ └── index.html │ │ ├── recommendations(_:limit:market:) │ │ │ └── index.html │ │ ├── relatedartists(_:) │ │ │ └── index.html │ │ ├── removealloccurrencesfromplaylist(_:of:snapshotid:) │ │ │ └── index.html │ │ ├── removesavedalbumsforcurrentuser(_:) │ │ │ └── index.html │ │ ├── removesavedaudiobooksforcurrentuser(_:) │ │ │ └── index.html │ │ ├── removesavedepisodesforcurrentuser(_:) │ │ │ └── index.html │ │ ├── removesavedshowsforcurrentuser(_:market:) │ │ │ └── index.html │ │ ├── removesavedtracksforcurrentuser(_:) │ │ │ └── index.html │ │ ├── reorderplaylistitems(_:body:) │ │ │ └── index.html │ │ ├── replaceallplaylistitems(_:with:) │ │ │ └── index.html │ │ ├── resumeplayback(deviceid:) │ │ │ └── index.html │ │ ├── savealbumsforcurrentuser(_:) │ │ │ └── index.html │ │ ├── saveaudiobooksforcurrentuser(_:) │ │ │ └── index.html │ │ ├── saveepisodesforcurrentuser(_:) │ │ │ └── index.html │ │ ├── saveshowsforcurrentuser(_:) │ │ │ └── index.html │ │ ├── savetracksforcurrentuser(_:) │ │ │ └── index.html │ │ ├── search(query:categories:market:limit:offset:includeexternal:) │ │ │ └── index.html │ │ ├── seektoposition(_:deviceid:) │ │ │ └── index.html │ │ ├── setrepeatmode(to:deviceid:) │ │ │ └── index.html │ │ ├── setshuffle(to:deviceid:) │ │ │ └── index.html │ │ ├── setupdebugging() │ │ │ └── index.html │ │ ├── setvolume(to:deviceid:) │ │ │ └── index.html │ │ ├── show(_:market:) │ │ │ └── index.html │ │ ├── showepisodes(_:market:offset:limit:) │ │ │ └── index.html │ │ ├── shows(_:market:) │ │ │ └── index.html │ │ ├── skiptonext(deviceid:) │ │ │ └── index.html │ │ ├── skiptoprevious(deviceid:) │ │ │ └── index.html │ │ ├── track(_:market:) │ │ │ └── index.html │ │ ├── trackaudioanalysis(_:) │ │ │ └── index.html │ │ ├── trackaudiofeatures(_:) │ │ │ └── index.html │ │ ├── tracks(_:market:) │ │ │ └── index.html │ │ ├── tracksaudiofeatures(_:) │ │ │ └── index.html │ │ ├── transferplayback(to:play:) │ │ │ └── index.html │ │ ├── unfollowartistsforcurrentuser(_:) │ │ │ └── index.html │ │ ├── unfollowplaylistforcurrentuser(_:) │ │ │ └── index.html │ │ ├── unfollowusersforcurrentuser(_:) │ │ │ └── index.html │ │ ├── uploadplaylistimage(_:imagedata:) │ │ │ └── index.html │ │ ├── userplaylists(for:limit:offset:) │ │ │ └── index.html │ │ └── userprofile(_:) │ │ │ └── index.html │ │ ├── spotifyapiloghandler │ │ ├── bootstrap() │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(label:loglevel:metadata:) │ │ │ └── index.html │ │ ├── label │ │ │ └── index.html │ │ ├── log(level:message:metadata:file:function:line:) │ │ │ └── index.html │ │ ├── log(level:message:metadata:source:file:function:line:) │ │ │ └── index.html │ │ ├── loghandler-implementations │ │ │ └── index.html │ │ ├── loglevel │ │ │ └── index.html │ │ ├── metadata │ │ │ └── index.html │ │ └── subscript(metadatakey:) │ │ │ └── index.html │ │ ├── spotifyauthenticationerror │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── anyfailingpublisher(_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── error-implementations │ │ │ └── index.html │ │ ├── error │ │ │ └── index.html │ │ ├── errordescription │ │ │ └── index.html │ │ ├── failurereason │ │ │ └── index.html │ │ ├── helpanchor │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── localizeddescription │ │ │ └── index.html │ │ ├── localizederror-implementations │ │ │ └── index.html │ │ └── recoverysuggestion │ │ │ └── index.html │ │ ├── spotifyauthorizationerror │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── accesswasdenied │ │ │ └── index.html │ │ ├── anyfailingpublisher(_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── error-implementations │ │ │ └── index.html │ │ ├── error │ │ │ └── index.html │ │ ├── errordescription │ │ │ └── index.html │ │ ├── failurereason │ │ │ └── index.html │ │ ├── helpanchor │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── localizeddescription │ │ │ └── index.html │ │ ├── localizederror-implementations │ │ │ └── index.html │ │ ├── recoverysuggestion │ │ │ └── index.html │ │ └── state │ │ │ └── index.html │ │ ├── spotifyauthorizationmanager │ │ ├── accesstoken │ │ │ └── index.html │ │ ├── accesstokenisexpired(tolerance:) │ │ │ └── index.html │ │ ├── deauthorize() │ │ │ └── index.html │ │ ├── didchange │ │ │ └── index.html │ │ ├── diddeauthorize │ │ │ └── index.html │ │ ├── expirationdate │ │ │ └── index.html │ │ ├── index.html │ │ ├── isauthorized(for:) │ │ │ └── index.html │ │ ├── refreshtokens(onlyifexpired:tolerance:) │ │ │ └── index.html │ │ └── scopes │ │ │ └── index.html │ │ ├── spotifycategory │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── icons │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:id:href:icons:) │ │ │ └── index.html │ │ └── name │ │ │ └── index.html │ │ ├── spotifycontext │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(uri:href:externalurls:type:) │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── spotifycopyright │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(text:type:) │ │ │ └── index.html │ │ ├── text │ │ │ └── index.html │ │ └── type │ │ │ └── index.html │ │ ├── spotifycursor │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── after │ │ │ └── index.html │ │ ├── before │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(before:after:) │ │ │ └── index.html │ │ └── init(from:) │ │ │ └── index.html │ │ ├── spotifydecodelogger │ │ └── index.html │ │ ├── spotifydecodingerror │ │ ├── anyfailingpublisher(_:) │ │ │ └── index.html │ │ ├── datadumpfolder │ │ │ └── index.html │ │ ├── debugerrordescription │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── error-implementations │ │ │ └── index.html │ │ ├── errordescription │ │ │ └── index.html │ │ ├── expectedresponsetype │ │ │ └── index.html │ │ ├── failurereason │ │ │ └── index.html │ │ ├── helpanchor │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(url:rawdata:responsetype:statuscode:underlyingerror:) │ │ │ └── index.html │ │ ├── localizeddescription │ │ │ └── index.html │ │ ├── localizederror-implementations │ │ │ └── index.html │ │ ├── prettycodingpath │ │ │ └── index.html │ │ ├── rawdata │ │ │ └── index.html │ │ ├── recoverysuggestion │ │ │ └── index.html │ │ ├── statuscode │ │ │ └── index.html │ │ ├── underlyingerror │ │ │ └── index.html │ │ ├── url │ │ │ └── index.html │ │ └── writetofolder(_:) │ │ │ └── index.html │ │ ├── spotifyerror │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── anyfailingpublisher(_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── error-implementations │ │ │ └── index.html │ │ ├── errordescription │ │ │ └── index.html │ │ ├── failurereason │ │ │ └── index.html │ │ ├── helpanchor │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── localizeddescription │ │ │ └── index.html │ │ ├── localizederror-implementations │ │ │ └── index.html │ │ ├── message │ │ │ └── index.html │ │ ├── recoverysuggestion │ │ │ └── index.html │ │ └── statuscode │ │ │ └── index.html │ │ ├── spotifygeneralerror │ │ ├── anyfailingpublisher(_:) │ │ │ └── index.html │ │ ├── customstringconvertible-implementations │ │ │ └── index.html │ │ ├── description │ │ │ └── index.html │ │ ├── error-implementations │ │ │ └── index.html │ │ ├── errordescription │ │ │ └── index.html │ │ ├── failurereason │ │ │ └── index.html │ │ ├── helpanchor │ │ │ └── index.html │ │ ├── httperror(_:_:) │ │ │ └── index.html │ │ ├── identifierparsingerror(message:) │ │ │ └── index.html │ │ ├── index.html │ │ ├── insufficientscope(requiredscopes:authorizedscopes:) │ │ │ └── index.html │ │ ├── invalididcategory(expected:received:) │ │ │ └── index.html │ │ ├── invalidstate(supplied:received:) │ │ │ └── index.html │ │ ├── localizeddescription │ │ │ └── index.html │ │ ├── localizederror-implementations │ │ │ └── index.html │ │ ├── other(_:localizeddescription:) │ │ │ └── index.html │ │ ├── recoverysuggestion │ │ │ └── index.html │ │ ├── toplevelkeynotfound(key:dict:) │ │ │ └── index.html │ │ └── unauthorized(_:) │ │ │ └── index.html │ │ ├── spotifyidentifier │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── commaseparatedidsstring(_:ensurecategorymatches:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── idcategory │ │ │ └── index.html │ │ ├── idsarray(_:ensurecategorymatches:) │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(id:idcategory:) │ │ │ └── index.html │ │ ├── init(uri:ensurecategorymatches:) │ │ │ └── index.html │ │ ├── init(url:) │ │ │ └── index.html │ │ ├── uri │ │ │ └── index.html │ │ └── url │ │ │ └── index.html │ │ ├── spotifyimage │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── height │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(height:width:url:) │ │ │ └── index.html │ │ ├── load() │ │ │ └── index.html │ │ ├── url │ │ │ └── index.html │ │ └── width │ │ │ └── index.html │ │ ├── spotifyplayererror │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── anyfailingpublisher(_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── error-implementations │ │ │ └── index.html │ │ ├── errordescription │ │ │ └── index.html │ │ ├── errorreason │ │ │ ├── !=(_:_:) │ │ │ │ └── index.html │ │ │ ├── alreadypaused │ │ │ │ └── index.html │ │ │ ├── alreadyplaying │ │ │ │ └── index.html │ │ │ ├── contextdisallow │ │ │ │ └── index.html │ │ │ ├── devicenotcontrollable │ │ │ │ └── index.html │ │ │ ├── encode(to:) │ │ │ │ └── index.html │ │ │ ├── endlesscontext │ │ │ │ └── index.html │ │ │ ├── equatable-implementations │ │ │ │ └── index.html │ │ │ ├── hash(into:) │ │ │ │ └── index.html │ │ │ ├── hashvalue │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── init(from:) │ │ │ │ └── index.html │ │ │ ├── init(rawvalue:) │ │ │ │ └── index.html │ │ │ ├── noactivedevice │ │ │ │ └── index.html │ │ │ ├── nonexttrack │ │ │ │ └── index.html │ │ │ ├── noprevioustrack │ │ │ │ └── index.html │ │ │ ├── nospecifictrack │ │ │ │ └── index.html │ │ │ ├── notpaused │ │ │ │ └── index.html │ │ │ ├── notplayingcontext │ │ │ │ └── index.html │ │ │ ├── notplayinglocally │ │ │ │ └── index.html │ │ │ ├── notplayingtrack │ │ │ │ └── index.html │ │ │ ├── premiumrequired │ │ │ │ └── index.html │ │ │ ├── ratelimited │ │ │ │ └── index.html │ │ │ ├── rawrepresentable-implementations │ │ │ │ └── index.html │ │ │ ├── remotecontroldisallow │ │ │ │ └── index.html │ │ │ ├── unknown │ │ │ │ └── index.html │ │ │ └── volumecontroldisallow │ │ │ │ └── index.html │ │ ├── failurereason │ │ │ └── index.html │ │ ├── helpanchor │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── localizeddescription │ │ │ └── index.html │ │ ├── localizederror-implementations │ │ │ └── index.html │ │ ├── message │ │ │ └── index.html │ │ ├── reason │ │ │ └── index.html │ │ ├── recoverysuggestion │ │ │ └── index.html │ │ └── statuscode │ │ │ └── index.html │ │ ├── spotifyqueue │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── currentlyplaying │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(currentlyplaying:queue:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ └── queue │ │ │ └── index.html │ │ ├── spotifyscopeauthorizationmanager │ │ └── index.html │ │ ├── spotifytimeinterval │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── confidence │ │ │ └── index.html │ │ ├── duration │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(start:duration:confidence:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ └── start │ │ │ └── index.html │ │ ├── spotifytimestampformatter │ │ ├── date(from:) │ │ │ └── index.html │ │ ├── index.html │ │ ├── millisecondsformatter │ │ │ └── index.html │ │ ├── secondsformatter │ │ │ └── index.html │ │ ├── shared │ │ │ └── index.html │ │ └── string(from:) │ │ │ └── index.html │ │ ├── spotifyuriconvertible │ │ ├── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── spotifyuser │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── allowsexplicitcontent │ │ │ └── index.html │ │ ├── country │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── displayname │ │ │ └── index.html │ │ ├── email │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── explicitcontentsettingislocked │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── followers │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── images │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(displayname:uri:id:images:href:allowsexplicitcontent:explicitcontentsettingislocked:followers:country:email:product:externalurls:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── product │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── swift │ │ ├── additivearithmetic │ │ │ ├── index.html │ │ │ └── isapproximatelyequal(to:absolutetolerance:relativetolerance:norm:) │ │ │ │ └── index.html │ │ ├── collection │ │ │ ├── chunked(size:) │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── decodingerror │ │ │ ├── context │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ └── prettycodingpath │ │ │ │ └── index.html │ │ ├── dictionary │ │ │ ├── formurlencoded() │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── error │ │ │ ├── anyfailingpublisher(_:) │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── index.html │ │ ├── keyeddecodingcontainer │ │ │ ├── decodeandunwraparray(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodedatefromexpiresinseconds(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodedatefromexpiresinsecondsifpresent(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodemillisecondssince1970(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodemillisecondssince1970ifpresent(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodespotifydate(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodespotifydateifpresent(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodespotifyimages(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodespotifyscopesifpresent(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodespotifytimestamp(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodespotifytimestampifpresent(forkey:) │ │ │ │ └── index.html │ │ │ ├── decodeuseruri(forkey:) │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── keyedencodingcontainer │ │ │ ├── encodemillisecondssince1970(_:forkey:) │ │ │ │ └── index.html │ │ │ ├── encodemillisecondssince1970ifpresent(_:forkey:) │ │ │ │ └── index.html │ │ │ ├── encodespotifydate(_:dateprecision:forkey:) │ │ │ │ └── index.html │ │ │ ├── encodespotifydateifpresent(_:dateprecision:forkey:) │ │ │ │ └── index.html │ │ │ ├── encodespotifyscopesifpresent(_:forkey:) │ │ │ │ └── index.html │ │ │ ├── encodespotifytimestamp(_:forkey:) │ │ │ │ └── index.html │ │ │ ├── encodespotifytimestampifpresent(_:forkey:) │ │ │ │ └── index.html │ │ │ ├── encodeuseruri(_:forkey:) │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── numeric │ │ │ ├── index.html │ │ │ ├── isapproximatelyequal(to:absolutetolerance:relativetolerance:) │ │ │ │ └── index.html │ │ │ └── isapproximatelyequal(to:relativetolerance:norm:) │ │ │ │ └── index.html │ │ ├── optional │ │ │ ├── approximatelyequatable-implementations │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ └── isapproximatelyequal(to:) │ │ │ │ └── index.html │ │ ├── randomaccesscollection │ │ │ ├── index.html │ │ │ └── isapproximatelyequal(to:) │ │ │ │ └── index.html │ │ ├── sequence │ │ │ ├── commaseparatedstring() │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── isapproximatelyequal(to:) │ │ │ │ └── index.html │ │ │ ├── largest │ │ │ │ └── index.html │ │ │ └── removingduplicates() │ │ │ │ └── index.html │ │ ├── set │ │ │ ├── approximatelyequatable-implementations │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ └── isapproximatelyequal(to:) │ │ │ │ └── index.html │ │ ├── string │ │ │ ├── base64decoded(encoding:options:) │ │ │ │ └── index.html │ │ │ ├── base64encoded(_:) │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── makecodechallenge(codeverifier:) │ │ │ │ └── index.html │ │ │ ├── randomurlsafe(length:) │ │ │ │ └── index.html │ │ │ ├── randomurlsafe(length:using:) │ │ │ │ └── index.html │ │ │ ├── spotifyuriconvertible-implementations │ │ │ │ └── index.html │ │ │ ├── strip(_:) │ │ │ │ └── index.html │ │ │ ├── uri │ │ │ │ └── index.html │ │ │ └── urlsafecharacters │ │ │ │ └── index.html │ │ └── substring │ │ │ ├── index.html │ │ │ ├── spotifyuriconvertible-implementations │ │ │ └── index.html │ │ │ └── uri │ │ │ └── index.html │ │ ├── timerange │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashvalue │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(rawvalue:) │ │ │ └── index.html │ │ ├── longterm │ │ │ └── index.html │ │ ├── mediumterm │ │ │ └── index.html │ │ ├── rawrepresentable-implementations │ │ │ └── index.html │ │ └── shortterm │ │ │ └── index.html │ │ ├── timereference │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── after(_:)-swift.enum.case │ │ │ └── index.html │ │ ├── after(_:)-swift.type.method │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── asqueryitem() │ │ │ └── index.html │ │ ├── before(_:)-swift.enum.case │ │ │ └── index.html │ │ ├── before(_:)-swift.type.method │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ └── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── tokensrequest │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── clientid │ │ │ └── index.html │ │ ├── clientsecret │ │ │ └── index.html │ │ ├── code │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── formurlencoded() │ │ │ └── index.html │ │ ├── granttype │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(code:redirecturi:clientid:clientsecret:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ └── redirecturi │ │ │ └── index.html │ │ ├── track │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── album │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── artists │ │ │ └── index.html │ │ ├── availablemarkets │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── discnumber │ │ │ └── index.html │ │ ├── durationms │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalids │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(name:album:artists:uri:id:islocal:popularity:durationms:tracknumber:isexplicit:isplayable:href:previewurl:externalurls:externalids:availablemarkets:linkedfrom:restrictions:discnumber:type:) │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── isexplicit │ │ │ └── index.html │ │ ├── islocal │ │ │ └── index.html │ │ ├── isplayable │ │ │ └── index.html │ │ ├── linkedfrom │ │ │ └── index.html │ │ ├── name │ │ │ └── index.html │ │ ├── popularity │ │ │ └── index.html │ │ ├── previewurl │ │ │ └── index.html │ │ ├── restrictions │ │ │ └── index.html │ │ ├── tracknumber │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── trackattributes │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── acousticness │ │ │ └── index.html │ │ ├── approximatelyequatable-implementations │ │ │ └── index.html │ │ ├── danceability │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── durationms │ │ │ └── index.html │ │ ├── energy │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(seedartists:seedtracks:seedgenres:acousticness:danceability:durationms:energy:instrumentalness:key:liveness:loudness:mode:popularity:speechiness:tempo:timesignature:valence:) │ │ │ └── index.html │ │ ├── instrumentalness │ │ │ └── index.html │ │ ├── isapproximatelyequal(to:) │ │ │ └── index.html │ │ ├── key │ │ │ └── index.html │ │ ├── liveness │ │ │ └── index.html │ │ ├── loudness │ │ │ └── index.html │ │ ├── mode │ │ │ └── index.html │ │ ├── popularity │ │ │ └── index.html │ │ ├── querydictionary() │ │ │ └── index.html │ │ ├── seedartists │ │ │ └── index.html │ │ ├── seedgenres │ │ │ └── index.html │ │ ├── seedtracks │ │ │ └── index.html │ │ ├── speechiness │ │ │ └── index.html │ │ ├── tempo │ │ │ └── index.html │ │ ├── timesignature │ │ │ └── index.html │ │ └── valence │ │ │ └── index.html │ │ ├── tracklink │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── externalurls │ │ │ └── index.html │ │ ├── href │ │ │ └── index.html │ │ ├── id │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(externalurls:href:uri:id:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── type │ │ │ └── index.html │ │ └── uri │ │ │ └── index.html │ │ ├── uriscontainer │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(_:snapshotid:) │ │ │ └── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── items │ │ │ └── index.html │ │ └── snapshotid │ │ │ └── index.html │ │ ├── urisdictwithinsertionindex │ │ ├── !=(_:_:) │ │ │ └── index.html │ │ ├── ==(_:_:) │ │ │ └── index.html │ │ ├── decodable-implementations │ │ │ └── index.html │ │ ├── encodable-implementations │ │ │ └── index.html │ │ ├── encode(to:) │ │ │ └── index.html │ │ ├── equatable-implementations │ │ │ └── index.html │ │ ├── hash(into:) │ │ │ └── index.html │ │ ├── hashable-implementations │ │ │ └── index.html │ │ ├── index.html │ │ ├── init(from:) │ │ │ └── index.html │ │ ├── init(uris:position:) │ │ │ └── index.html │ │ ├── position │ │ │ └── index.html │ │ └── uris │ │ │ └── index.html │ │ ├── urlquerydictionary(_:) │ │ └── index.html │ │ ├── using-the-player-endpoints │ │ └── index.html │ │ └── working-with-paginated-results │ │ └── index.html ├── favicon.ico ├── favicon.svg ├── images │ └── SpotifyWebAPI │ │ ├── Change_Test_Plan.png │ │ ├── JSON_Viewer.png │ │ └── SpotifyAPIMainTestPlan.png ├── img │ ├── added-icon.832a5d2c.svg │ ├── deprecated-icon.7bf1740a.svg │ └── modified-icon.efb2697d.svg ├── index.html ├── index │ ├── availability.index │ ├── data.mdb │ ├── index.json │ └── navigator.index ├── js │ ├── 104.fe5974d0.js │ ├── 337.274a8ccc.js │ ├── 842.49774dc9.js │ ├── 866.eea4607d.js │ ├── chunk-vendors.bdb7cbba.js │ ├── documentation-topic.09a6ef86.js │ ├── highlight-js-bash-js.702f0c5c.js │ ├── highlight-js-c-js.063069d3.js │ ├── highlight-js-cpp-js.458a9ae4.js │ ├── highlight-js-css-js.bfc4251f.js │ ├── highlight-js-custom-markdown.78c9f6ed.js │ ├── highlight-js-custom-swift.738731d1.js │ ├── highlight-js-diff-js.4db9a783.js │ ├── highlight-js-http-js.f78e83c2.js │ ├── highlight-js-java-js.4fe21e94.js │ ├── highlight-js-javascript-js.dfc9d16d.js │ ├── highlight-js-json-js.2a1856ba.js │ ├── highlight-js-llvm-js.26121771.js │ ├── highlight-js-markdown-js.a2f456af.js │ ├── highlight-js-objectivec-js.74dea052.js │ ├── highlight-js-perl-js.da6eda82.js │ ├── highlight-js-php-js.c458ffa4.js │ ├── highlight-js-python-js.60354774.js │ ├── highlight-js-ruby-js.7272231f.js │ ├── highlight-js-scss-js.adcd11a2.js │ ├── highlight-js-shell-js.0ad5b20f.js │ ├── highlight-js-swift-js.bdd5bff5.js │ ├── highlight-js-xml-js.0d78f903.js │ ├── index.a08b31d0.js │ ├── topic.37e71576.js │ └── tutorials-overview.acb09e8a.js ├── metadata.json └── theme-settings.json ├── enable_testing.py ├── preview_documentation.sh ├── rm_credentials.sh ├── set_credentials.sh └── test_linux.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | /docs -diff -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | .swiftpm/xcode/xcuserdata 5 | .swiftpm/xcode/package.xcworkspace/xcuserdata 6 | /Tests/Private 7 | spotify_credentials.txt 8 | /Private 9 | /Package.resolved 10 | .vscode 11 | .devcontainer 12 | .idea 13 | .devcontainer 14 | 15 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | README.md 2 | test-project 3 | definition-manifest.json 4 | .devcontainer/library-scripts/README.md 5 | .vscode 6 | .npmignore 7 | -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | builder: 3 | configs: 4 | - platform: watchos 5 | scheme: SpotifyAPI 6 | - platform: ios 7 | scheme: SpotifyAPI 8 | - platform: macos-xcodebuild 9 | scheme: SpotifyAPI 10 | - platform: macos-xcodebuild-arm 11 | scheme: SpotifyAPI 12 | - platform: tvos 13 | scheme: SpotifyAPI 14 | - platform: linux 15 | scheme: SpotifyAPI 16 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Peter Schorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Sources/SpotifyAPITestUtilities/README.md: -------------------------------------------------------------------------------- 1 | # SpotifyAPITestUtilities 2 | 3 | This module is used in the test targets of this package and has no stable API. Do not use it in production code. 4 | -------------------------------------------------------------------------------- /Sources/SpotifyAPITestUtilities/Resources/requirements.txt: -------------------------------------------------------------------------------- 1 | selenium==4.5.0 2 | webdriver_manager==3.8.3 3 | -------------------------------------------------------------------------------- /Sources/SpotifyAPITestUtilities/SpotifyAPITestUtilities.docc/SpotifyAPITestUtilities.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyAPITestUtilities`` 2 | 3 | This module is used in the test targets of this package and has no stable API. Do not use it in production code. 4 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleAlbums.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | extension Album { 5 | 6 | /// Sample data for testing purposes. 7 | public static let abbeyRoad = Bundle.module.decodeJSON( 8 | forResource: "Abbey Road - Album", type: Self.self 9 | )! 10 | 11 | /// Sample data for testing purposes. 12 | public static let darkSideOfTheMoon = Bundle.module.decodeJSON( 13 | forResource: "Dark Side Of The Moon - Album", type: Self.self 14 | )! 15 | 16 | /// Sample data for testing purposes. 17 | public static let inRainbows = Bundle.module.decodeJSON( 18 | forResource: "In Rainbows - Album", type: Self.self 19 | )! 20 | 21 | /// Sample data for testing purposes. 22 | public static let jinx = Bundle.module.decodeJSON( 23 | forResource: "Jinx - Album", type: Self.self 24 | )! 25 | 26 | /// Sample data for testing purposes. 27 | public static let meddle = Bundle.module.decodeJSON( 28 | forResource: "Meddle - Album", type: Self.self 29 | )! 30 | 31 | /// Sample data for testing purposes. 32 | public static let skiptracing = Bundle.module.decodeJSON( 33 | forResource: "Skiptracing - Album", type: Self.self 34 | )! 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleArtists.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension Artist { 5 | 6 | /// Sample data for testing purposes. 7 | static let crumb = Bundle.module.decodeJSON( 8 | forResource: "Crumb - Artist", type: Self.self 9 | )! 10 | 11 | /// Sample data for testing purposes. 12 | static let levitationRoom = Bundle.module.decodeJSON( 13 | forResource: "Levitation Room - Artist", type: Self.self 14 | )! 15 | 16 | /// Sample data for testing purposes. 17 | static let pinkFloyd = Bundle.module.decodeJSON( 18 | forResource: "Pink Floyd - Artist", type: Self.self 19 | )! 20 | 21 | /// Sample data for testing purposes. 22 | static let radiohead = Bundle.module.decodeJSON( 23 | forResource: "Radiohead - Artist", type: Self.self 24 | )! 25 | 26 | /// Sample data for testing purposes. 27 | static let skinshape = Bundle.module.decodeJSON( 28 | forResource: "Skinshape - Artist", type: Self.self 29 | )! 30 | 31 | /// Sample data for testing purposes. 32 | static let theBeatles = Bundle.module.decodeJSON( 33 | forResource: "The Beatles - Artist", type: Self.self 34 | )! 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleAudioAnalysis.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension AudioAnalysis { 5 | 6 | /// Sample data for testing purposes. 7 | static let anyColourYouLike = Bundle.module.decodeJSON( 8 | forResource: "Any Colour You Like - AudioAnalysis", type: Self.self 9 | )! 10 | 11 | } 12 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleAudioFeatures.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension AudioFeatures { 5 | 6 | /// Sample data for testing purposes. 7 | static let fearless = Bundle.module.decodeJSON( 8 | forResource: "Fearless - AudioFeatures", type: Self.self 9 | )! 10 | 11 | } 12 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleAudiobooks.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension Audiobook { 5 | 6 | /// Sample data for testing purposes. 7 | static let harryPotterAndTheSorcerersStone = Bundle.module.decodeJSON( 8 | forResource: "Harry Potter and the Sorcerer's Stone - Audiobook", 9 | type: Self.self 10 | )! 11 | 12 | /// Sample data for testing purposes. 13 | static let enlightenmentNow = Bundle.module.decodeJSON( 14 | forResource: "Enlightenment Now - Audiobook", 15 | type: Self.self 16 | )! 17 | 18 | /// Sample data for testing purposes. 19 | static let freeWill = Bundle.module.decodeJSON( 20 | forResource: "Free Will - Audiobook", 21 | type: Self.self 22 | )! 23 | 24 | } 25 | 26 | public extension AudiobookChapter { 27 | 28 | /// Sample data for testing purposes. 29 | static let freeWillChapter1 = Bundle.module.decodeJSON( 30 | forResource: "Free Will Chapter 1 - AudiobookChapter", 31 | type: Self.self 32 | )! 33 | 34 | /// Sample data for testing purposes. 35 | static let steveJobsChapter1 = Bundle.module.decodeJSON( 36 | forResource: "Steve Jobs Chapter 1 - AudiobookChapter", 37 | type: Self.self 38 | )! 39 | 40 | /// Sample data for testing purposes. 41 | static let enlightenmentNowChapter3 = Bundle.module.decodeJSON( 42 | forResource: "Enlightenment Now Chapter 3 - AudiobookChapter", 43 | type: Self.self 44 | )! 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleBrowse.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension PagingObject where Item == Playlist { 5 | 6 | /// Sample data for testing purposes. 7 | static let sampleCategoryPlaylists = Bundle.module.decodeJSON( 8 | forResource: "Category Playlists - PagingObject>", 9 | type: Self.self 10 | )! 11 | 12 | } 13 | 14 | public extension FeaturedPlaylists { 15 | 16 | /// Sample data for testing purposes. 17 | static let sampleFeaturedPlaylists = Bundle.module.decodeJSON( 18 | forResource: "Featured Playlists - FeaturedPlaylists", 19 | type: Self.self 20 | )! 21 | 22 | } 23 | 24 | public extension SpotifyCategory { 25 | 26 | /// Sample data for testing purposes. 27 | static let sampleCategories = Bundle.module.decodeJSON( 28 | forResource: "categories - SpotifyCategory", 29 | type: Self.self 30 | )! 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleEpisodes.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension Episode { 5 | 6 | /// Sample data for testing purposes. 7 | static let seanCarroll111 = Bundle.module.decodeJSON( 8 | forResource: "Sean Carroll 111 - Episode", type: Self.self 9 | )! 10 | 11 | /// Sample data for testing purposes. 12 | static let seanCarroll112 = Bundle.module.decodeJSON( 13 | forResource: "Sean Carroll 112 - Episode", type: Self.self 14 | )! 15 | 16 | /// Sample data for testing purposes. 17 | static let samHarris213 = Bundle.module.decodeJSON( 18 | forResource: "Sam Harris 213 - Episode", type: Self.self 19 | )! 20 | 21 | /// Sample data for testing purposes. 22 | static let samHarris214 = Bundle.module.decodeJSON( 23 | forResource: "Sam Harris 214 - Episode", type: Self.self 24 | )! 25 | 26 | /// Sample data for testing purposes. 27 | static let samHarris215 = Bundle.module.decodeJSON( 28 | forResource: "Sam Harris 215 - Episode", type: Self.self 29 | )! 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleLibrary.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | 5 | public extension PagingObject where Item == SavedAlbum { 6 | 7 | /// Sample data for testing purposes. 8 | static let sampleCurrentUserSavedAlbums = Bundle.module.decodeJSON( 9 | forResource: "Current User Saved Albums - PagingObject>", 10 | type: Self.self 11 | )! 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExamplePlayer.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension CursorPagingObject where Item == PlayHistory { 5 | 6 | /// Sample data for testing purposes. 7 | static let sampleRecentlyPlayed = Bundle.module.decodeJSON( 8 | forResource: "Recently Played - CursorPagingObject", 9 | type: Self.self 10 | )! 11 | } 12 | 13 | public extension CurrentlyPlayingContext { 14 | 15 | /// Sample data for testing purposes. 16 | static let sampleCurrentPlayback = Bundle.module.decodeJSON( 17 | forResource: "Current Playback - CurrentlyPlayingContext", 18 | type: Self.self 19 | )! 20 | 21 | } 22 | 23 | public extension SpotifyQueue { 24 | 25 | /// Sample data for testing purposes. 26 | static let sampleQueue = Bundle.module.decodeJSON( 27 | forResource: "Queue - SpotifyQueue", 28 | type: Self.self 29 | )! 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleSearch.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension SearchResult { 5 | 6 | /// Sample data for testing purposes. 7 | static let queryCrumb = Bundle.module.decodeJSON( 8 | forResource: "Search for 'Crumb' - SearchResult", 9 | type: Self.self 10 | )! 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleShows.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension Show { 5 | 6 | /// Sample data for testing purposes. 7 | static let seanCarroll = Bundle.module.decodeJSON( 8 | forResource: "Sean Carroll - Show", type: Self.self 9 | )! 10 | 11 | /// Sample data for testing purposes. 12 | static let samHarris = Bundle.module.decodeJSON( 13 | forResource: "Sam Harris - Show", type: Self.self 14 | )! 15 | 16 | /// Sample data for testing purposes. 17 | static let joeRogan = Bundle.module.decodeJSON( 18 | forResource: "Joe Rogan - Show", type: Self.self 19 | )! 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ExampleUserProfile.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SpotifyWebAPI 3 | 4 | public extension SpotifyUser { 5 | 6 | /// Sample data for testing purposes. 7 | static let sampleCurrentUserProfile = Bundle.module.decodeJSON( 8 | forResource: "Current User Profile - SpotifyUser", 9 | type: Self.self 10 | )! 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/ImageAssets.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A namespace of images that can be used for testing. They are stored in jpeg 4 | /// format. 5 | public enum SpotifyExampleImages { 6 | 7 | /// A picture of Annabelle. 600 x 800; 121 KB of JPEG data. 8 | public static let annabelle = Bundle.module.decodeJPEGImage( 9 | forResource: "Annabelle Compressed" 10 | )! 11 | 12 | /** 13 | A picture of Annabelle. 1532 x 1149; 554 KB of JPEG data. 14 | 15 | Exceeds the size limit (256 KB) of the endpoint for uploading an image to a 16 | playlist. 17 | */ 18 | public static let annabelleTooLarge = Bundle.module.decodeJPEGImage( 19 | forResource: "Annabelle Large" 20 | )! 21 | 22 | } 23 | 24 | 25 | private extension Bundle { 26 | 27 | func decodeJPEGImage(forResource name: String) -> Data? { 28 | guard let url = Bundle.module.url( 29 | forResource: name, withExtension: "jpeg" 30 | ) else { 31 | return nil 32 | } 33 | let data = try? Data(contentsOf: url) 34 | return data 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/README.md: -------------------------------------------------------------------------------- 1 | # SpotifyExampleContent 2 | 3 | Contains various sample data that can be used for testing purposes, especially with SwiftUI previews. 4 | 5 | Includes URIs for playlists, artists, albums, tracks, episodes, shows, users, audiobooks, audiobook chapters, and devices. 6 | 7 | Most importantly, there are sample versions of many of the objects in the object model, including, but not limited to, `Track`, `Album`, `Playlist`, `Episode`, and `Show`. You are highly encouraged to browse the source code of this module to see all of the available sample data. 8 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Artists/Crumb - Artist.json: -------------------------------------------------------------------------------- 1 | {"images":[{"width":640,"url":"https:\/\/i.scdn.co\/image\/f70c7ab74ab6fc16db4d0b959d1788708dddb6d5","height":640},{"width":320,"url":"https:\/\/i.scdn.co\/image\/519f3363e78956d993204662ce4561da56e0fb1e","height":320},{"width":160,"url":"https:\/\/i.scdn.co\/image\/ce91d71ba7022e0330a2b1ae7d4eeb5b5ec0ad9b","height":160}],"genres":["indie garage rock","neo-psychedelic"],"id":"4kSGbjWGxTchKpIxXPJv0B","external_urls":{"spotify":"https:\/\/open.spotify.com\/artist\/4kSGbjWGxTchKpIxXPJv0B"},"popularity":64,"followers":{"total":255317},"href":"https:\/\/api.spotify.com\/v1\/artists\/4kSGbjWGxTchKpIxXPJv0B","type":"artist","name":"Crumb","uri":"spotify:artist:4kSGbjWGxTchKpIxXPJv0B"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Artists/Levitation Room - Artist.json: -------------------------------------------------------------------------------- 1 | {"images":[{"width":640,"url":"https:\/\/i.scdn.co\/image\/93c4ad2ae5d939de734cfafae79536ba55380160","height":640},{"width":320,"url":"https:\/\/i.scdn.co\/image\/94c0ec56bea2f1c88a68f97f71ffbf8579b6b608","height":320},{"width":160,"url":"https:\/\/i.scdn.co\/image\/fe5e08aa26ab26aa7f01a31513f41f6129b23eea","height":160}],"genres":["indie garage rock","neo-psychedelic"],"id":"0SVxQVCnJn1BNUMY9ZcRO4","external_urls":{"spotify":"https:\/\/open.spotify.com\/artist\/0SVxQVCnJn1BNUMY9ZcRO4"},"popularity":47,"followers":{"total":38980},"href":"https:\/\/api.spotify.com\/v1\/artists\/0SVxQVCnJn1BNUMY9ZcRO4","type":"artist","name":"levitation room","uri":"spotify:artist:0SVxQVCnJn1BNUMY9ZcRO4"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Artists/Pink Floyd - Artist.json: -------------------------------------------------------------------------------- 1 | {"images":[{"width":1000,"url":"https:\/\/i.scdn.co\/image\/e69f71e2be4b67b82af90fb8e9d805715e0684fa","height":977},{"width":640,"url":"https:\/\/i.scdn.co\/image\/d011c95081cd9a329e506abd7ded47535d524a07","height":625},{"width":200,"url":"https:\/\/i.scdn.co\/image\/f0a39a8a196a87a7236bdcf8a8708f6d5d3547cc","height":195},{"width":64,"url":"https:\/\/i.scdn.co\/image\/ec1fb7127168dbaa962404031409c5a293b95ec6","height":63}],"genres":["album rock","art rock","classic rock","progressive rock","psychedelic rock","rock","symphonic rock"],"id":"0k17h0D3J5VfsdmQ1iZtE9","external_urls":{"spotify":"https:\/\/open.spotify.com\/artist\/0k17h0D3J5VfsdmQ1iZtE9"},"popularity":83,"followers":{"total":12886125},"href":"https:\/\/api.spotify.com\/v1\/artists\/0k17h0D3J5VfsdmQ1iZtE9","type":"artist","name":"Pink Floyd","uri":"spotify:artist:0k17h0D3J5VfsdmQ1iZtE9"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Artists/Radiohead - Artist.json: -------------------------------------------------------------------------------- 1 | {"images":[{"width":640,"url":"https:\/\/i.scdn.co\/image\/afcd616e1ef2d2786f47b3b4a8a6aeea24a72adc","height":640},{"width":320,"url":"https:\/\/i.scdn.co\/image\/563754af10b3d9f9f62a3458e699f58c4a02870f","height":320},{"width":160,"url":"https:\/\/i.scdn.co\/image\/4067ea225d8b42fa6951857d3af27dd07d60f3c6","height":160}],"genres":["alternative rock","art rock","melancholia","oxford indie","permanent wave","rock"],"id":"4Z8W4fKeB5YxbusRsdQVPb","external_urls":{"spotify":"https:\/\/open.spotify.com\/artist\/4Z8W4fKeB5YxbusRsdQVPb"},"popularity":81,"followers":{"total":5471852},"href":"https:\/\/api.spotify.com\/v1\/artists\/4Z8W4fKeB5YxbusRsdQVPb","type":"artist","name":"Radiohead","uri":"spotify:artist:4Z8W4fKeB5YxbusRsdQVPb"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Artists/Skinshape - Artist.json: -------------------------------------------------------------------------------- 1 | {"images":[{"width":640,"url":"https:\/\/i.scdn.co\/image\/e7037cff3df768f43634218a4d04ecf70f3db1a7","height":640},{"width":320,"url":"https:\/\/i.scdn.co\/image\/fad7d45409e7281d60d7725a4eda1815eb6d954d","height":320},{"width":160,"url":"https:\/\/i.scdn.co\/image\/8c74ab329666241012938d934898d847a4039163","height":160}],"genres":["indie soul","psychedelic soul"],"id":"1itM5tXaK5THggpXA7ovAe","external_urls":{"spotify":"https:\/\/open.spotify.com\/artist\/1itM5tXaK5THggpXA7ovAe"},"popularity":59,"followers":{"total":137337},"href":"https:\/\/api.spotify.com\/v1\/artists\/1itM5tXaK5THggpXA7ovAe","type":"artist","name":"Skinshape","uri":"spotify:artist:1itM5tXaK5THggpXA7ovAe"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Artists/The Beatles - Artist.json: -------------------------------------------------------------------------------- 1 | {"images":[{"width":640,"url":"https:\/\/i.scdn.co\/image\/6b2a709752ef9c7aaf0d270344157f6cd2e0f1a7","height":640},{"width":320,"url":"https:\/\/i.scdn.co\/image\/1047bf172446f2a815a99ab0a0395099d621be51","height":320},{"width":160,"url":"https:\/\/i.scdn.co\/image\/0561b59a91a5e904ad2d192747715688d5f05012","height":160}],"genres":["beatlesque","british invasion","classic rock","merseybeat","psychedelic rock","rock"],"id":"3WrFJ7ztbogyGnTHbHJFl2","external_urls":{"spotify":"https:\/\/open.spotify.com\/artist\/3WrFJ7ztbogyGnTHbHJFl2"},"popularity":89,"followers":{"total":17306061},"href":"https:\/\/api.spotify.com\/v1\/artists\/3WrFJ7ztbogyGnTHbHJFl2","type":"artist","name":"The Beatles","uri":"spotify:artist:3WrFJ7ztbogyGnTHbHJFl2"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Audo Analysis/Fearless - AudioFeatures.json: -------------------------------------------------------------------------------- 1 | {"energy":0.34100000000000003,"acousticness":0.16,"id":"7AalBKBoLDR4UmRYRJpdbj","track_href":"https:\/\/api.spotify.com\/v1\/tracks\/7AalBKBoLDR4UmRYRJpdbj","uri":"spotify:track:7AalBKBoLDR4UmRYRJpdbj","liveness":0.44800000000000001,"type":"audio_features","speechiness":0.041799999999999997,"key":7,"mode":1,"valence":0.17899999999999999,"instrumentalness":0.040800000000000003,"time_signature":4,"analysis_url":"https:\/\/api.spotify.com\/v1\/audio-analysis\/7AalBKBoLDR4UmRYRJpdbj","tempo":143.71899999999999,"danceability":0.38,"duration_ms":367933,"loudness":-15.718999999999999} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Browse/categories - SpotifyCategory.json: -------------------------------------------------------------------------------- 1 | {"id":"at_home","name":"At Home","href":"https:\/\/api.spotify.com\/v1\/browse\/categories\/at_home","icons":[{"url":"https:\/\/t.scdn.co\/images\/04da469dd7be4dab96659aa1fa9f0ac9.jpeg"}]} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Images/Annabelle Compressed.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/Sources/SpotifyExampleContent/Resources/Images/Annabelle Compressed.jpeg -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Images/Annabelle Large.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/Sources/SpotifyExampleContent/Resources/Images/Annabelle Large.jpeg -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/PlaylistItems/Echoes - Acoustic Version - PlaylistItem.json: -------------------------------------------------------------------------------- 1 | {"name":"Echoes - Acoustic Version","album":{"type":"album","external_urls":{},"available_markets":[],"name":"","artists":[],"images":[]},"track_number":0,"uri":"spotify:local:::Echoes+-+Acoustic+Version:348","artists":[{"name":"","external_urls":{},"type":"artist"}],"disc_number":0,"is_local":true,"popularity":0,"available_markets":[],"type":"track","explicit":false,"duration_ms":348000,"external_urls":{},"external_ids":{}} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/PlaylistItems/Hans Zimmer & Radiohead - Ocean Bloom (full song HQ) - PlaylistItem.json: -------------------------------------------------------------------------------- 1 | {"name":"Hans Zimmer & Radiohead - Ocean Bloom (full song HQ)","album":{"type":"album","external_urls":{},"available_markets":[],"name":"","artists":[],"images":[]},"track_number":0,"uri":"spotify:local:lrd::Hans+Zimmer+%26+Radiohead+-+Ocean+Bloom+%28full+song+HQ%29:315","artists":[{"name":"lrd","external_urls":{},"type":"artist"}],"disc_number":0,"is_local":true,"popularity":0,"available_markets":[],"type":"track","explicit":false,"duration_ms":315000,"external_urls":{},"external_ids":{}} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/PlaylistItems/Killshot - PlaylistItem.json: -------------------------------------------------------------------------------- 1 | {"name":"Killshot","album":{"type":"album","external_urls":{},"available_markets":[],"name":"","artists":[],"images":[]},"track_number":0,"uri":"spotify:local:Eminem::Killshot:253","artists":[{"name":"Eminem","external_urls":{},"type":"artist"}],"disc_number":0,"is_local":true,"popularity":0,"available_markets":[],"type":"track","explicit":false,"duration_ms":253000,"external_urls":{},"external_ids":{}} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/Lucy in the sky with diamonds - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/4FgAYjgX8lTlgOOxFkjgBG"},"id":"4FgAYjgX8lTlgOOxFkjgBG","description":"","tracks":{"total":43,"href":"https:\/\/api.spotify.com\/v1\/playlists\/4FgAYjgX8lTlgOOxFkjgBG\/tracks"},"uri":"spotify:playlist:4FgAYjgX8lTlgOOxFkjgBG","href":"https:\/\/api.spotify.com\/v1\/playlists\/4FgAYjgX8lTlgOOxFkjgBG","owner":{"id":"petervschorn","display_name":"petervschorn","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/petervschorn"},"href":"https:\/\/api.spotify.com\/v1\/users\/petervschorn","uri":"spotify:user:petervschorn","type":"user"},"name":"Lucy in the sky with diamonds","collaborative":false,"images":[{"url":"https:\/\/i.scdn.co\/image\/ab67706c0000bebb03e6bb6f35d07aa7d8f24fe7"}],"public":true,"snapshot_id":"NjksYTE0MzkwNGM1MjExMjg4MmVhNGU0NWQ2ZjI1Zjk5OGM4ZWNiMTg5Nw==","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/Men I Trust - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/2EgZjzog2eSfApWQHZVn6t"},"id":"2EgZjzog2eSfApWQHZVn6t","description":"","tracks":{"total":10,"href":"https:\/\/api.spotify.com\/v1\/playlists\/2EgZjzog2eSfApWQHZVn6t\/tracks"},"uri":"spotify:playlist:2EgZjzog2eSfApWQHZVn6t","href":"https:\/\/api.spotify.com\/v1\/playlists\/2EgZjzog2eSfApWQHZVn6t","owner":{"id":"petervschorn","display_name":"petervschorn","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/petervschorn"},"href":"https:\/\/api.spotify.com\/v1\/users\/petervschorn","uri":"spotify:user:petervschorn","type":"user"},"name":"Men I Trust","collaborative":false,"images":[{"width":640,"url":"https:\/\/mosaic.scdn.co\/640\/ab67616d0000b2734bf3b48e615335264b9fcb22ab67616d0000b273591fa5bb8ab3ec41455d6279ab67616d0000b273b5d2a7e29794ff7e91305aa8ab67616d0000b273dc6d950cc4e0346270892b2a","height":640},{"width":300,"url":"https:\/\/mosaic.scdn.co\/300\/ab67616d0000b2734bf3b48e615335264b9fcb22ab67616d0000b273591fa5bb8ab3ec41455d6279ab67616d0000b273b5d2a7e29794ff7e91305aa8ab67616d0000b273dc6d950cc4e0346270892b2a","height":300},{"width":60,"url":"https:\/\/mosaic.scdn.co\/60\/ab67616d0000b2734bf3b48e615335264b9fcb22ab67616d0000b273591fa5bb8ab3ec41455d6279ab67616d0000b273b5d2a7e29794ff7e91305aa8ab67616d0000b273dc6d950cc4e0346270892b2a","height":60}],"public":true,"snapshot_id":"NDQsYjA1YTZhNDI4NjgyMTYxODk5NzFiZjdkNzYzYjZiYjY3OTc2YTNkZQ==","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/Modern Psychedelia - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/37i9dQZF1DX8gDIpdqp1XJ"},"id":"37i9dQZF1DX8gDIpdqp1XJ","description":"The best of modern psych. Cover: Khruangbin<\/a>","tracks":{"total":150,"href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DX8gDIpdqp1XJ\/tracks"},"uri":"spotify:playlist:37i9dQZF1DX8gDIpdqp1XJ","href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DX8gDIpdqp1XJ","owner":{"id":"spotify","display_name":"Spotify","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/spotify"},"href":"https:\/\/api.spotify.com\/v1\/users\/spotify","uri":"spotify:user:spotify","type":"user"},"name":"Modern Psychedelia","collaborative":false,"images":[{"url":"https:\/\/i.scdn.co\/image\/ab67706f00000003dd0587449bff66bd37fef082"}],"public":false,"snapshot_id":"MTYwMjk2MTQyNCwwMDAwMDAwMGQ0MWQ4Y2Q5OGYwMGIyMDRlOTgwMDk5OGVjZjg0Mjdl","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/Rock Classics - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/37i9dQZF1DWXRqgorJj26U"},"id":"37i9dQZF1DWXRqgorJj26U","description":"Rock legends and epic songs that continue to inspire generations.","tracks":{"total":145,"href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DWXRqgorJj26U\/tracks"},"uri":"spotify:playlist:37i9dQZF1DWXRqgorJj26U","href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DWXRqgorJj26U","owner":{"id":"spotify","display_name":"Spotify","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/spotify"},"href":"https:\/\/api.spotify.com\/v1\/users\/spotify","uri":"spotify:user:spotify","type":"user"},"name":"Rock Classics","collaborative":false,"images":[{"url":"https:\/\/i.scdn.co\/image\/ab67706f00000003519fc8771d90f496501a4da3"}],"public":false,"snapshot_id":"MTYwMDc5MTM4OSwwMDAwMDA1NzAwMDAwMTc0YjY5YTI1OGMwMDAwMDE3M2ZlNjNkYjRm","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/This Is King Gizzard & The Lizard Wizard - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/37i9dQZF1DX21LiAJsYT57"},"id":"37i9dQZF1DX21LiAJsYT57","description":"Australia's prolific Psych Rock masters, all in the one place.","tracks":{"total":72,"href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DX21LiAJsYT57\/tracks"},"uri":"spotify:playlist:37i9dQZF1DX21LiAJsYT57","href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DX21LiAJsYT57","owner":{"id":"spotify","display_name":"Spotify","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/spotify"},"href":"https:\/\/api.spotify.com\/v1\/users\/spotify","uri":"spotify:user:spotify","type":"user"},"name":"This Is King Gizzard & The Lizard Wizard","collaborative":false,"images":[{"url":"https:\/\/i.scdn.co\/image\/ab67706f00000003e48a6a0ea9250d98709477fa"}],"public":false,"snapshot_id":"MTYwMDE3ODQ2MCwwMDAwMDAwNDAwMDAwMTc0OTIxMTk1YjAwMDAwMDE3MzVhMGNiNDNj","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/This Is MF DOOM - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/37i9dQZF1DZ06evO1nxlXq"},"id":"37i9dQZF1DZ06evO1nxlXq","description":"This is MF DOOM. The essential tracks, all in one playlist.","tracks":{"total":39,"href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DZ06evO1nxlXq\/tracks"},"uri":"spotify:playlist:37i9dQZF1DZ06evO1nxlXq","href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DZ06evO1nxlXq","owner":{"id":"spotify","display_name":"Spotify","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/spotify"},"href":"https:\/\/api.spotify.com\/v1\/users\/spotify","uri":"spotify:user:spotify","type":"user"},"name":"This Is MF DOOM","collaborative":false,"images":[{"url":"https:\/\/thisis-images.scdn.co\/37i9dQZF1DZ06evO1nxlXq-large.jpg"}],"public":false,"snapshot_id":"MjY3MTU1MzgsMDAwMDAwMDA1YTA2MjE0YmJlYjZjYWZhNjc3MzcxZTkwNTJhYzFhOA==","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/This Is Mild High Club - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/37i9dQZF1DZ06evO3ncXGU"},"id":"37i9dQZF1DZ06evO3ncXGU","description":"This is Mild High Club. The essential tracks, all in one playlist.","tracks":{"total":19,"href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DZ06evO3ncXGU\/tracks"},"uri":"spotify:playlist:37i9dQZF1DZ06evO3ncXGU","href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DZ06evO3ncXGU","owner":{"id":"spotify","display_name":"Spotify","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/spotify"},"href":"https:\/\/api.spotify.com\/v1\/users\/spotify","uri":"spotify:user:spotify","type":"user"},"name":"This Is Mild High Club","collaborative":false,"images":[{"url":"https:\/\/thisis-images.scdn.co\/37i9dQZF1DZ06evO3ncXGU-large.jpg"}],"public":true,"snapshot_id":"MjY3MTU1MzcsMDAwMDAwMDBjMGMxZGZlZThiYzBlM2M0MDZhNzhmZTUyMDRkMjYzNQ==","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/This Is Radiohead - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/37i9dQZF1DX1XDyq5cTk95"},"id":"37i9dQZF1DX1XDyq5cTk95","description":"The essential Radiohead, all in one playlist.","tracks":{"total":67,"href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DX1XDyq5cTk95\/tracks"},"uri":"spotify:playlist:37i9dQZF1DX1XDyq5cTk95","href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DX1XDyq5cTk95","owner":{"id":"spotify","display_name":"Spotify","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/spotify"},"href":"https:\/\/api.spotify.com\/v1\/users\/spotify","uri":"spotify:user:spotify","type":"user"},"name":"This Is Radiohead","collaborative":false,"images":[{"url":"https:\/\/i.scdn.co\/image\/ab67706f000000038981ea633dea6cb2aaf72f43"}],"public":false,"snapshot_id":"MTYwMTQ3ODE4MywwMDAwMDAxZDAwMDAwMTc0ZGY4OWNhYjEwMDAwMDE3NGRmODNjNDFj","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/This Is Sonic Youth - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/37i9dQZF1DWYq5msVbwd94"},"id":"37i9dQZF1DWYq5msVbwd94","description":"A taste of the influential band<\/a>'s catalog. See their timeline here<\/a>.","tracks":{"total":43,"href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DWYq5msVbwd94\/tracks"},"uri":"spotify:playlist:37i9dQZF1DWYq5msVbwd94","href":"https:\/\/api.spotify.com\/v1\/playlists\/37i9dQZF1DWYq5msVbwd94","owner":{"id":"spotify","display_name":"Spotify","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/spotify"},"href":"https:\/\/api.spotify.com\/v1\/users\/spotify","uri":"spotify:user:spotify","type":"user"},"name":"This Is: Sonic Youth","collaborative":false,"images":[{"url":"https:\/\/i.scdn.co\/image\/ab67706f00000003d12f1fd59b35f77942ab4385"}],"public":false,"snapshot_id":"MTU4Mzg0Nzc1OSwwMDAwMDAwNzAwMDAwMTYxNGUwYTRmY2IwMDAwMDE3MGM0YWVkZjYx","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/Playlists/This is Skinshape - Playlist.json: -------------------------------------------------------------------------------- 1 | {"external_urls":{"spotify":"https:\/\/open.spotify.com\/playlist\/1YNW1LO3O1CZ15pHa1UtUb"},"id":"1YNW1LO3O1CZ15pHa1UtUb","description":"Allof Skinshapes current catalog in one place!! Enjoy! And Share!","tracks":{"total":47,"href":"https:\/\/api.spotify.com\/v1\/playlists\/1YNW1LO3O1CZ15pHa1UtUb\/tracks"},"uri":"spotify:playlist:1YNW1LO3O1CZ15pHa1UtUb","href":"https:\/\/api.spotify.com\/v1\/playlists\/1YNW1LO3O1CZ15pHa1UtUb","owner":{"id":"siegeart","display_name":"Siege Art","external_urls":{"spotify":"https:\/\/open.spotify.com\/user\/siegeart"},"href":"https:\/\/api.spotify.com\/v1\/users\/siegeart","uri":"spotify:user:siegeart","type":"user"},"name":"This is: Skinshape","collaborative":false,"images":[{"width":640,"url":"https:\/\/mosaic.scdn.co\/640\/ab67616d0000b273464f8c954c863d38d2ef29adab67616d0000b27355832e9fb94c657e6e94cb2dab67616d0000b2735fa25f88c68c1c167ddc3d10ab67616d0000b273e08bc8e2a15d7a93ec5309ef","height":640},{"width":300,"url":"https:\/\/mosaic.scdn.co\/300\/ab67616d0000b273464f8c954c863d38d2ef29adab67616d0000b27355832e9fb94c657e6e94cb2dab67616d0000b2735fa25f88c68c1c167ddc3d10ab67616d0000b273e08bc8e2a15d7a93ec5309ef","height":300},{"width":60,"url":"https:\/\/mosaic.scdn.co\/60\/ab67616d0000b273464f8c954c863d38d2ef29adab67616d0000b27355832e9fb94c657e6e94cb2dab67616d0000b2735fa25f88c68c1c167ddc3d10ab67616d0000b273e08bc8e2a15d7a93ec5309ef","height":60}],"public":false,"snapshot_id":"MTksMzMyMzBjZTcxNjEyYzU3NTk1NDRiMjJiMjFjNzI0MDNjZGZmZTgwYw==","type":"playlist"} -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/Resources/User Profile/Current User Profile - SpotifyUser.json: -------------------------------------------------------------------------------- 1 | { 2 | "country": "US", 3 | "display_name": "petervschorn", 4 | "email": "youalmostgotme@gmail.com", 5 | "explicit_content": { 6 | "filter_enabled": false, 7 | "filter_locked": false 8 | }, 9 | "external_urls": { 10 | "spotify": "https://open.spotify.com/user/petervschorn" 11 | }, 12 | "followers": { 13 | "href": null, 14 | "total": 2 15 | }, 16 | "href": "https://api.spotify.com/v1/users/petervschorn", 17 | "id": "petervschorn", 18 | "images": [], 19 | "product": "premium", 20 | "type": "user", 21 | "uri": "spotify:user:petervschorn" 22 | } 23 | -------------------------------------------------------------------------------- /Sources/SpotifyExampleContent/SpotifyExampleContent.docc/SpotifyExampleContent.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyExampleContent`` 2 | 3 | Contains various sample data that can be used for testing purposes, especially with SwiftUI previews. 4 | 5 | ## Overview 6 | 7 | Includes URIs for playlists, artists, albums, tracks, episodes, shows, users, audiobooks, audiobook chapters, and devices. 8 | 9 | Most importantly, there are sample versions of many of the objects in the object model, as described in . 10 | 11 | ## Topics 12 | 13 | ### Articles 14 | 15 | - 16 | 17 | ### URIS 18 | 19 | - ``URIs/Playlists`` 20 | - ``URIs/Artists`` 21 | - ``URIs/Albums`` 22 | - ``URIs/Tracks`` 23 | - ``URIs/Episodes`` 24 | - ``URIs/Shows`` 25 | - ``URIs/Audiobooks`` 26 | - ``URIs/Chapters`` 27 | - ``URIs/Users`` 28 | - ``URIs/Devices`` 29 | 30 | ### Image Assets 31 | 32 | - ``SpotifyExampleImages`` 33 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Authorization/SpotifyScopeAuthorizationManager.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | A type that can manage the authorization process for the Spotify web API and 5 | that **supports authorization scopes**. 6 | 7 | ``AuthorizationCodeFlowBackendManager`` and 8 | ``AuthorizationCodeFlowPKCEBackendManager`` conform to this protocol. 9 | ``ClientCredentialsFlowBackendManager`` is not a conforming type because it 10 | does not support authorization scopes. 11 | */ 12 | public protocol SpotifyScopeAuthorizationManager: SpotifyAuthorizationManager { } 13 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Errors/RateLimitedError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | Too Many Requests - Rate limiting has been applied. 5 | 6 | The ``retryAfter`` property specifies the number of seconds you must wait 7 | before you try the request again. 8 | 9 | Rate limiting is applied as per application based on Client ID, and regardless 10 | of the number of users who use the application simultaneously. 11 | 12 | To reduce the amount of requests, use endpoints that fetch multiple entities in 13 | one request. For example: If you often request single tracks, albums, or 14 | artists, use endpoints such as Get Several Tracks, Get Several Albums or Get 15 | Several Artists, instead. 16 | 17 | Read more at the [Spotify web API reference][1]. 18 | 19 | [1]: https://developer.spotify.com/documentation/web-api/#rate-limiting 20 | */ 21 | public struct RateLimitedError: LocalizedError, Codable, Hashable { 22 | 23 | /// The number of seconds you must wait before you try the request again. 24 | public let retryAfter: Int? 25 | 26 | public var errorDescription: String? { 27 | var description = "You have made too many requests (rate limiting error)." 28 | if let seconds = retryAfter { 29 | if seconds == 1 { 30 | description += " Try again in 1 second." 31 | } 32 | else { 33 | description += " Try again in \(seconds) seconds." 34 | } 35 | } 36 | else { 37 | description += " Try again later." 38 | } 39 | 40 | return description 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Audiobook Objects/AudiobookAuthor.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// An audiobook author or narrator. 4 | public struct AudiobookAuthor: Hashable, Codable { 5 | 6 | /// The name of the author or narrator. 7 | public let name: String 8 | 9 | /// Creates an audiobook author or narrator. 10 | /// 11 | /// - Parameter name: The name of the author or narrator. 12 | public init(name: String) { 13 | self.name = name 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Other Spotify Objects/AlbumType.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// An album type. 4 | public enum AlbumType: String, CaseIterable, Codable, Hashable { 5 | 6 | /// An album. 7 | case album 8 | 9 | /// A single. 10 | case single 11 | 12 | /// Appears on. 13 | case appearsOn = "appears_on" 14 | 15 | /// A compilation. 16 | case compilation 17 | 18 | /// An EP 19 | case ep 20 | 21 | /// something else 22 | case other 23 | 24 | /** 25 | Creates a new instance with the specified raw value. 26 | 27 | - Parameter rawValue: The raw value for an album type. **It is** 28 | **case-insensitive**. 29 | */ 30 | @inlinable 31 | public init?(rawValue: String) { 32 | 33 | let lowercasedRawValue = rawValue.lowercased() 34 | for category in Self.allCases { 35 | if category.rawValue == lowercasedRawValue { 36 | self = category 37 | return 38 | } 39 | } 40 | self = .other 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Other Spotify Objects/Copyright.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Spotify copyright object. 4 | public struct SpotifyCopyright: Codable, Hashable { 5 | 6 | /// The copyright text. 7 | public let text: String 8 | 9 | /// The type of copyright. 10 | /// 11 | /// C = the copyright; P = the sound recording (performance) copyright. 12 | public let type: String 13 | 14 | /** 15 | Creates a Spotify copyright object. 16 | 17 | - Parameters: 18 | - text: The copyright text. 19 | - type: The type of copyright: C = the copyright; P = the sound recording 20 | (performance) copyright. 21 | */ 22 | public init(text: String, type: String) { 23 | self.text = text 24 | self.type = type 25 | } 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Other Spotify Objects/FeaturedPlaylists.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | An array of simplified playlist objects wrapped in a paging object and a 5 | message that can be displayed to the user, such as "Good Morning", or "Editor's 6 | picks". 7 | 8 | Returned by the endpoint for a [list of featured playlists][1]. 9 | 10 | [1]: https://developer.spotify.com/documentation/web-api/reference/#/operations/get-featured-playlists 11 | */ 12 | public struct FeaturedPlaylists: Codable, Hashable { 13 | 14 | /// A message that can be displayed to the user, such as 15 | /// "Good Morning", or "Editor's picks". 16 | public let message: String? 17 | 18 | /// The featured playlists. 19 | public let playlists: PagingObject> 20 | 21 | /** 22 | Creates a Featured Playlists object. 23 | 24 | Returned by the endpoint for a [list of featured playlists][1]. 25 | 26 | - Parameters: 27 | - message: A message that can be displayed to the user, such as "Good 28 | Morning", or "Editor's picks". 29 | - playlists: The featured playlists. 30 | 31 | [1]: https://developer.spotify.com/documentation/web-api/reference/#/operations/get-featured-playlists 32 | */ 33 | public init( 34 | message: String? = nil, 35 | playlists: PagingObject> 36 | ) { 37 | self.message = message 38 | self.playlists = playlists 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Other Spotify Objects/SpotifyCategory.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Spotify category object. 4 | public struct SpotifyCategory: Codable, Hashable { 5 | 6 | /// The name of the category. 7 | public let name: String 8 | 9 | /// The id of the category. 10 | public let id: String 11 | 12 | /** 13 | A link to the Spotify web API endpoint providing the full category object. 14 | 15 | Use ``SpotifyAPI/getFromHref(_:responseType:)``, passing in 16 | ``SpotifyCategory`` as the response type to retrieve the results. 17 | */ 18 | public let href: URL 19 | 20 | /// The category icon, in various sizes. 21 | public let icons: [SpotifyImage] 22 | 23 | /** 24 | Creates a Spotify category object. 25 | 26 | - Parameters: 27 | - name: The name of the category. 28 | - id: The id of the category. 29 | - href: A link to the Spotify web API endpoint providing the full 30 | category object. 31 | - icons: The category icon, in various sizes. 32 | */ 33 | public init( 34 | name: String, 35 | id: String, 36 | href: URL, 37 | icons: [SpotifyImage] 38 | ) { 39 | self.name = name 40 | self.id = id 41 | self.href = href 42 | self.icons = icons 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Player Objects/DeviceType.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// The types of devices that Spotify content can be played on. 4 | /// 5 | /// Read more at the [Spotify web API reference][1]. 6 | /// 7 | /// [1]: https://developer.spotify.com/documentation/web-api/reference/player/get-a-users-available-devices/#device-types 8 | public enum DeviceType: String, Codable, Hashable, CaseIterable { 9 | 10 | /// A computer. 11 | case computer = "Computer" 12 | 13 | /// A tablet. 14 | case tablet = "Tablet" 15 | 16 | /// A smartphone. 17 | case smartphone = "Smartphone" 18 | 19 | /// A speaker. 20 | case speaker = "Speaker" 21 | 22 | /// A TV. 23 | case tv = "TV" 24 | 25 | /// An AVR. 26 | case avr = "AVR" 27 | 28 | /// An STB. 29 | case stb = "STB" 30 | 31 | /// An audio dongle. 32 | case audioDongle = "AudioDongle" 33 | 34 | /// A game console. 35 | case gameConsole = "GameConsole" 36 | 37 | /// A video cast. 38 | case castVideo = "CastVideo" 39 | 40 | /// An audio cast. 41 | case castAudio = "CastAudio" 42 | 43 | /// An automobile. 44 | case automobile = "Automobile" 45 | 46 | /// Unknown. 47 | case unknown = "Unknown" 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Player Objects/RepeatMode.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// The repeat mode of the user's player. Either ``off``, ``track``, or 4 | /// ``context``. 5 | public enum RepeatMode: String, Codable, Hashable, CaseIterable { 6 | 7 | /// Repeat mode is off. 8 | case off 9 | 10 | /// The current context, such as a playlist, is playing on repeat. 11 | case context 12 | 13 | /// The current track is playing on repeat. 14 | case track 15 | 16 | } 17 | 18 | public extension RepeatMode { 19 | 20 | /** 21 | Cycles self among the between modes. 22 | 23 | If the repeat mode is ``off``, then it becomes ``context``; if the repeat 24 | mode is ``context``, then it becomes ``track``; if the repeat mode is 25 | ``track``, then it becomes ``off``. 26 | 27 | See also ``cycled()``. 28 | */ 29 | mutating func cycle() { 30 | self = self.cycled() 31 | } 32 | 33 | /** 34 | Returns self cycled among the repeat modes. 35 | 36 | If the repeat mode is ``off``, then ``context`` is returned; if the repeat 37 | mode is ``context``, then ``track`` is returned; if the repeat mode is 38 | ``track``, then ``off`` is returned. 39 | 40 | See also ``cycle()``. 41 | */ 42 | func cycled() -> Self { 43 | 44 | switch self { 45 | case .off: 46 | return .context 47 | case .context: 48 | return .track 49 | case .track: 50 | return .off 51 | } 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Player Objects/ResumePoint.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | A Spotify resume point object. Represents the user’s most recent position 5 | in an episode or audiobook chapter. 6 | 7 | Retrieving this object requires the ``Scope/userReadPlaybackPosition`` scope. 8 | 9 | */ 10 | public struct ResumePoint: Codable, Hashable { 11 | 12 | /// Whether or not the content has been fully played by the user. 13 | public let fullyPlayed: Bool 14 | 15 | /// The user's most recent position in the content in milliseconds. 16 | public let resumePositionMS: Int 17 | 18 | /** 19 | Creates a resume point object. 20 | 21 | Represents the user’s most recent position in an episode or audiobook 22 | chapter. 23 | 24 | - Parameters: 25 | - fullyPlayed: Whether or not the content has been fully played by the 26 | user. 27 | - resumePositionMS: The user's most recent position in the content in 28 | milliseconds. 29 | */ 30 | public init(fullyPlayed: Bool, resumePositionMS: Int) { 31 | self.fullyPlayed = fullyPlayed 32 | self.resumePositionMS = resumePositionMS 33 | } 34 | 35 | private enum CodingKeys: String, CodingKey { 36 | case fullyPlayed = "fully_played" 37 | case resumePositionMS = "resume_position_ms" 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Post Request Objects/Other Objects/TimeRange.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Time Range. Used by the 4 | /// ``SpotifyAPI/currentUserTopArtists(_:offset:limit:)`` and 5 | /// ``SpotifyAPI/currentUserTopTracks(_:offset:limit:)`` methods. 6 | public enum TimeRange: String, Codable, Hashable, CaseIterable { 7 | 8 | /// Long term. 9 | case longTerm = "long_term" 10 | 11 | /// Medium term. 12 | case mediumTerm = "medium_term" 13 | 14 | /// Short term. 15 | case shortTerm = "short_term" 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/Post Request Objects/Player Objects/TransferPlaybackRequest.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Used in a request to transfer the user's playback to a different device. 4 | struct TransferPlaybackRequest: Codable, Hashable { 5 | 6 | /// Although an array is accepted, only a single device id is currently 7 | /// supported. Supplying more than one will return 400 Bad Request 8 | let deviceIds: [String] 9 | 10 | /// If `true`, then ensure playback happens on the new device. If `false` or 11 | /// not provided, then keep the current playback state. 12 | let play: Bool 13 | 14 | enum CodingKeys: String, CodingKey { 15 | case deviceIds = "device_ids" 16 | case play 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Object Model/TypeAliases.swift: -------------------------------------------------------------------------------- 1 | 2 | /// The tracks in a playlist. Each ``Track`` is optional. 3 | public typealias PlaylistTracks = PagingObject> 4 | 5 | /// The episodes and tracks in a playlist. each ``PlaylistItem`` is optional. 6 | public typealias PlaylistItems = PagingObject> 7 | 8 | /// A track saved in the user's "Your Music" library. 9 | public typealias SavedTrack = SavedItem 10 | 11 | /// An album saved in the user's "Your Music" library. 12 | public typealias SavedAlbum = SavedItem 13 | 14 | /// A show saved in the user's "Your Music" library. 15 | public typealias SavedShow = SavedItem 16 | 17 | /// An episode saved in the user's "Your Music" library. 18 | public typealias SavedEpisode = SavedItem 19 | 20 | /// An audiobook saved in the user's "Your Music" library. 21 | public typealias SavedAudiobook = SavedItem 22 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Other/AuthorizationManagerLoggers.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Logging 3 | 4 | enum AuthorizationManagerLoggers { 5 | 6 | /* 7 | These loggers are publicly exposed though computed properties on the 8 | authorization managers. 9 | */ 10 | 11 | /// Publicly exposed via ``AuthorizationCodeFlowManagerBase/baseLogger``. 12 | static var authorizationCodeFlowManagerBaseLogger = Logger( 13 | label: "AuthorizationCodeFlowManagerBase", 14 | level: .critical 15 | ) 16 | 17 | /// Publicly exposed via ``AuthorizationCodeFlowBackendManager/logger`` 18 | static var authorizationCodeFlowManagerLogger = Logger( 19 | label: "AuthorizationCodeFlowManager", 20 | level: .critical 21 | ) 22 | 23 | /// Publicly exposed via ``AuthorizationCodeFlowPKCEBackendManager/logger`` 24 | static var authorizationCodeFlowPKCEManagerLogger = Logger( 25 | label: "AuthorizationCodeFlowPKCEManager", 26 | level: .critical 27 | ) 28 | 29 | /// Publicly exposed via ``ClientCredentialsFlowBackendManager/logger``. 30 | static var clientCredentialsFlowManagerLogger = Logger( 31 | label: "ClientCredentialsFlowManager", 32 | level: .critical 33 | ) 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Other/DateExtensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Date { 4 | 5 | /// The interval, in milliseconds, between the date value and 00:00:00 UTC 6 | /// on 1 January 1970. Equivalent to `self.timeIntervalSince1970 * 1000`. 7 | var millisecondsSince1970: Double { 8 | return self.timeIntervalSince1970 * 1000 9 | } 10 | 11 | /** 12 | Creates a date value initialized relative to 00:00:00 UTC on 1 January 1970 13 | by a given number of **milliseconds**. 14 | 15 | equivalent to 16 | ``` 17 | self.init(timeIntervalSince1970: TimeInterval(milliseconds) / 1000) 18 | ``` 19 | - Parameter millisecondsSince1970: A time interval in milliseconds. 20 | */ 21 | init(millisecondsSince1970: Double) { 22 | self.init( 23 | timeIntervalSince1970: TimeInterval(millisecondsSince1970) / 1000 24 | ) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Other/DebugHooks.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Combine) 2 | import Combine 3 | #else 4 | import OpenCombine 5 | import OpenCombineDispatch 6 | import OpenCombineFoundation 7 | #endif 8 | import Foundation 9 | 10 | #if canImport(FoundationNetworking) 11 | import FoundationNetworking 12 | #endif 13 | 14 | #if DEBUG 15 | enum DebugHooks { 16 | 17 | static let receiveRateLimitedError = PassthroughSubject() 18 | 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/Other/Paginated.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | A type that contains paginated results. 5 | 6 | The only requirement is 7 | ``` 8 | var next: URL? { get } 9 | ``` 10 | a link (href) to the next page of results. 11 | 12 | ``PagingObject`` and ``CursorPagingObject`` are conforming types. 13 | 14 | Conforming types can be used in ``SpotifyAPI/extendPages(_:maxExtraPages:)``, 15 | ``SpotifyAPI/extendPagesConcurrently(_:maxExtraPages:)``, and the combine 16 | operators of the same names to retrieve additional pages of results. 17 | */ 18 | public protocol Paginated: Codable { 19 | 20 | /// A link (href) to the next page of results. 21 | var next: URL? { get } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/README.md: -------------------------------------------------------------------------------- 1 | # SpotifyWebAPI 2 | 3 | The main module for this package. See the README in the root directory of this package. 4 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Collections/Object Model/Audio Analysis Objects.md: -------------------------------------------------------------------------------- 1 | # Audio Analysis Objects 2 | 3 | Objects that relate to audio analysis. 4 | 5 | ## Topics 6 | 7 | ### Audio Analysis Objects 8 | 9 | - ``AudioAnalysis`` 10 | - ``AudioFeatures`` 11 | - ``Section`` 12 | - ``Segment`` 13 | - ``SpotifyTimeInterval`` 14 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Collections/Object Model/Audiobook Objects.md: -------------------------------------------------------------------------------- 1 | # Audiobook Objects 2 | 3 | Objects that relate to the audiobook and audiobook chapter endpoints. 4 | 5 | ## Topics 6 | 7 | ### Audiobook Objects 8 | 9 | - ``Audiobook`` 10 | - ``AudiobookChapter`` 11 | - ``AudiobookAuthor`` 12 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Collections/Object Model/Media Objects.md: -------------------------------------------------------------------------------- 1 | # Media Objects 2 | 3 | Objects that represent Spotify content items. 4 | 5 | ## Topics 6 | 7 | ### Media Objects 8 | 9 | - ``Track`` 10 | - ``Album`` 11 | - ``Artist`` 12 | - ``Episode`` 13 | - ``Show`` 14 | 15 | ### Music Library 16 | 17 | - ``SavedItem`` 18 | - ``SavedTrack`` 19 | - ``SavedAlbum`` 20 | - ``SavedEpisode`` 21 | - ``SavedShow`` 22 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Collections/Object Model/Other Objects.md: -------------------------------------------------------------------------------- 1 | # Other Objects 2 | 3 | Other objects in the object model. 4 | 5 | ## Topics 6 | 7 | ### Other Objects 8 | 9 | - ``PagingObject`` 10 | - ``SavedItem`` 11 | - ``SearchResult`` 12 | - ``SpotifyImage`` 13 | - ``SpotifyUser`` 14 | - ``Followers`` 15 | - ``CursorPagingObject`` 16 | - ``SpotifyCursor`` 17 | - ``TrackLink`` 18 | - ``SpotifyCopyright`` 19 | - ``AlbumType`` 20 | - ``TimeRange`` 21 | - ``FeaturedPlaylists`` 22 | - ``NewAlbumReleases`` 23 | - ``RecommendationSeed`` 24 | - ``RecommendationsResponse`` 25 | - ``TrackAttributes`` 26 | - ``AttributeRange`` 27 | - ``SpotifyCategory`` 28 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Collections/Object Model/Player Objects.md: -------------------------------------------------------------------------------- 1 | # Player Objects 2 | 3 | Objects that relate to the player endpoints. 4 | 5 | ## Topics 6 | 7 | ### Player Objects 8 | 9 | - ``Device`` 10 | - ``DeviceType`` 11 | - ``SpotifyQueue`` 12 | - ``CurrentlyPlayingContext`` 13 | - ``SpotifyContext`` 14 | - ``PlaybackActions`` 15 | - ``PlayHistory`` 16 | - ``ResumePoint`` 17 | - ``RepeatMode`` 18 | - ``PlaybackRequest`` 19 | - ``TimeReference`` 20 | 21 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Collections/Object Model/Playlist Objects.md: -------------------------------------------------------------------------------- 1 | # Playlist Objects 2 | 3 | Objects that relate to Spotify playlists. 4 | 5 | ## Topics 6 | 7 | ### Playlist Objects 8 | 9 | - ``Playlist`` 10 | - ``PlaylistItem`` 11 | - ``PlaylistItemContainer`` 12 | - ``PlaylistItemsReference`` 13 | - ``PlaylistItems`` 14 | - ``PlaylistTracks`` 15 | 16 | ### Modifying Playlists 17 | 18 | - ``PlaylistDetails`` 19 | - ``ReorderPlaylistItems`` 20 | - ``URIsContainer`` 21 | - ``URIsDictWithInsertionIndex`` 22 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Resources/Change_Test_Plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Resources/Change_Test_Plan.png -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Resources/JSON_Viewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Resources/JSON_Viewer.png -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Resources/SpotifyAPIMainTestPlan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Resources/SpotifyAPIMainTestPlan.png -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/AuthorizationCodeFlowBackendManager.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/AuthorizationCodeFlowBackendManager`` 2 | 3 | ## Topics 4 | 5 | ### Initializers 6 | 7 | - ``init(backend:)`` 8 | - ``init(backend:accessToken:expirationDate:refreshToken:scopes:)`` 9 | - ``init(from:)`` 10 | 11 | ### Authorization 12 | 13 | - ``makeAuthorizationURL(redirectURI:showDialog:state:scopes:)`` 14 | - ``requestAccessAndRefreshTokens(redirectURIWithQuery:state:)`` 15 | - ``refreshTokens(onlyIfExpired:tolerance:)`` 16 | 17 | - ``AuthorizationCodeFlowManagerBase/deauthorize()`` 18 | - ``AuthorizationCodeFlowManagerBase/isAuthorized(for:)`` 19 | 20 | - ``AuthorizationCodeFlowManagerBase/scopes`` 21 | - ``AuthorizationCodeFlowManagerBase/accessToken`` 22 | - ``AuthorizationCodeFlowManagerBase/refreshToken`` 23 | - ``AuthorizationCodeFlowManagerBase/expirationDate`` 24 | - ``AuthorizationCodeFlowManagerBase/backend`` 25 | 26 | ### Subscribing to Changes 27 | 28 | - ``AuthorizationCodeFlowManagerBase/didChange`` 29 | - ``AuthorizationCodeFlowManagerBase/didDeauthorize`` 30 | 31 | ### Logging 32 | 33 | - ``logger`` 34 | - ``AuthorizationCodeFlowManagerBase/baseLogger`` 35 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/AuthorizationCodeFlowManager.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/AuthorizationCodeFlowManager`` 2 | 3 | ## Topics 4 | 5 | ### Initializers 6 | 7 | - ``init(clientId:clientSecret:)`` 8 | - ``init(clientId:clientSecret:accessToken:expirationDate:refreshToken:scopes:)`` 9 | 10 | ### Authorization 11 | 12 | - ``AuthorizationCodeFlowBackendManager/makeAuthorizationURL(redirectURI:showDialog:state:scopes:)`` 13 | - ``AuthorizationCodeFlowBackendManager/requestAccessAndRefreshTokens(redirectURIWithQuery:state:)`` 14 | 15 | - ``AuthorizationCodeFlowManagerBase/deauthorize()`` 16 | - ``AuthorizationCodeFlowManagerBase/isAuthorized(for:)`` 17 | 18 | - ``clientId`` 19 | - ``clientSecret`` 20 | 21 | - ``AuthorizationCodeFlowManagerBase/scopes`` 22 | - ``AuthorizationCodeFlowManagerBase/accessToken`` 23 | - ``AuthorizationCodeFlowManagerBase/refreshToken`` 24 | - ``AuthorizationCodeFlowManagerBase/expirationDate`` 25 | - ``AuthorizationCodeFlowManagerBase/backend`` 26 | 27 | ### Subscribing to Changes 28 | 29 | - ``AuthorizationCodeFlowManagerBase/didChange`` 30 | - ``AuthorizationCodeFlowManagerBase/didDeauthorize`` 31 | 32 | ### Logging 33 | 34 | - ``AuthorizationCodeFlowBackendManager/logger`` 35 | - ``AuthorizationCodeFlowManagerBase/baseLogger`` 36 | 37 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/AuthorizationCodeFlowManagerBase.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/AuthorizationCodeFlowManagerBase`` 2 | 3 | ## Topics 4 | 5 | ### Authorization 6 | 7 | - ``accessTokenIsExpired(tolerance:)`` 8 | - ``deauthorize()`` 9 | - ``isAuthorized(for:)`` 10 | 11 | - ``scopes`` 12 | - ``accessToken`` 13 | - ``refreshToken`` 14 | - ``expirationDate`` 15 | - ``backend`` 16 | 17 | ### Subscribing to Changes 18 | 19 | - ``didChange`` 20 | - ``didDeauthorize`` 21 | 22 | ### Logging 23 | 24 | - ``baseLogger`` 25 | 26 | ### Testing 27 | 28 | - ``setExpirationDate(to:)`` 29 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/AuthorizationCodeFlowPKCEBackendManager.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/AuthorizationCodeFlowPKCEBackendManager`` 2 | 3 | ## Topics 4 | 5 | ### Initializers 6 | 7 | - ``init(backend:)`` 8 | - ``init(backend:accessToken:expirationDate:refreshToken:scopes:)`` 9 | - ``init(from:)`` 10 | 11 | ### Authorization 12 | 13 | - ``makeAuthorizationURL(redirectURI:codeChallenge:state:scopes:)`` 14 | - ``requestAccessAndRefreshTokens(redirectURIWithQuery:codeVerifier:state:)`` 15 | - ``refreshTokens(onlyIfExpired:tolerance:)`` 16 | 17 | - ``AuthorizationCodeFlowManagerBase/deauthorize()`` 18 | - ``AuthorizationCodeFlowManagerBase/isAuthorized(for:)`` 19 | 20 | - ``AuthorizationCodeFlowManagerBase/scopes`` 21 | - ``AuthorizationCodeFlowManagerBase/accessToken`` 22 | - ``AuthorizationCodeFlowManagerBase/refreshToken`` 23 | - ``AuthorizationCodeFlowManagerBase/expirationDate`` 24 | - ``AuthorizationCodeFlowManagerBase/backend`` 25 | 26 | ### Subscribing to Changes 27 | 28 | - ``AuthorizationCodeFlowManagerBase/didChange`` 29 | - ``AuthorizationCodeFlowManagerBase/didDeauthorize`` 30 | 31 | ### Logging 32 | 33 | - ``AuthorizationCodeFlowPKCEBackendManager/logger`` 34 | - ``AuthorizationCodeFlowManagerBase/baseLogger`` 35 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/AuthorizationCodeFlowPKCEManager.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/AuthorizationCodeFlowPKCEManager`` 2 | 3 | ## Topics 4 | 5 | ### Initializers 6 | 7 | - ``init(clientId:)`` 8 | - ``init(clientId:accessToken:expirationDate:refreshToken:scopes:)`` 9 | 10 | ### Authorization 11 | 12 | - ``AuthorizationCodeFlowPKCEBackendManager/makeAuthorizationURL(redirectURI:codeChallenge:state:scopes:)`` 13 | - ``AuthorizationCodeFlowPKCEBackendManager/requestAccessAndRefreshTokens(redirectURIWithQuery:codeVerifier:state:)`` 14 | 15 | - ``AuthorizationCodeFlowManagerBase/deauthorize()`` 16 | - ``AuthorizationCodeFlowManagerBase/isAuthorized(for:)`` 17 | 18 | - ``clientId`` 19 | 20 | - ``AuthorizationCodeFlowManagerBase/scopes`` 21 | - ``AuthorizationCodeFlowManagerBase/accessToken`` 22 | - ``AuthorizationCodeFlowManagerBase/refreshToken`` 23 | - ``AuthorizationCodeFlowManagerBase/expirationDate`` 24 | - ``AuthorizationCodeFlowManagerBase/backend`` 25 | 26 | ### Subscribing to Changes 27 | 28 | - ``AuthorizationCodeFlowManagerBase/didChange`` 29 | - ``AuthorizationCodeFlowManagerBase/didDeauthorize`` 30 | 31 | ### Logging 32 | 33 | - ``AuthorizationCodeFlowPKCEBackendManager/logger`` 34 | - ``AuthorizationCodeFlowManagerBase/baseLogger`` 35 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/ClientCredentialsFlowBackendManager.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/ClientCredentialsFlowBackendManager`` 2 | 3 | ## Topics 4 | 5 | ### Initializers 6 | 7 | - ``init(backend:)`` 8 | - ``init(backend:accessToken:expirationDate:)`` 9 | - ``init(from:)`` 10 | 11 | ### Authorization 12 | 13 | - ``authorize()`` 14 | - ``deauthorize()`` 15 | - ``isAuthorized(for:)`` 16 | - ``refreshTokens(onlyIfExpired:tolerance:)`` 17 | - ``accessTokenIsExpired(tolerance:)`` 18 | 19 | - ``backend`` 20 | - ``accessToken`` 21 | - ``expirationDate`` 22 | - ``scopes`` 23 | 24 | ### Subscribing to Changes 25 | 26 | - ``didChange`` 27 | - ``didDeauthorize`` 28 | 29 | ### Logging 30 | 31 | - ``logger`` 32 | 33 | ### Testing 34 | 35 | - ``setExpirationDate(to:)`` 36 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/ClientCredentialsFlowManager.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/ClientCredentialsFlowManager`` 2 | 3 | ## Topics 4 | 5 | ### Initializers 6 | 7 | - ``init(clientId:clientSecret:)`` 8 | - ``init(clientId:clientSecret:accessToken:expirationDate:)`` 9 | 10 | ### Authorization 11 | 12 | - ``ClientCredentialsFlowBackendManager/authorize()`` 13 | - ``ClientCredentialsFlowBackendManager/deauthorize()`` 14 | - ``ClientCredentialsFlowBackendManager/isAuthorized(for:)`` 15 | 16 | - ``clientId`` 17 | - ``clientSecret`` 18 | - ``ClientCredentialsFlowBackendManager/accessToken`` 19 | - ``ClientCredentialsFlowBackendManager/expirationDate`` 20 | - ``ClientCredentialsFlowBackendManager/scopes`` 21 | 22 | ### Subscribing to Changes 23 | 24 | - ``ClientCredentialsFlowBackendManager/didChange`` 25 | - ``ClientCredentialsFlowBackendManager/didDeauthorize`` 26 | 27 | ### Logging 28 | 29 | - ``ClientCredentialsFlowBackendManager/logger`` 30 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/Symbols/Authorization/Scope.md: -------------------------------------------------------------------------------- 1 | # ``SpotifyWebAPI/Scope`` 2 | 3 | ## Topics 4 | 5 | ### Images 6 | 7 | - ``ugcImageUpload`` 8 | 9 | ### Playback 10 | 11 | - ``userReadPlaybackState`` 12 | - ``userModifyPlaybackState`` 13 | - ``userReadCurrentlyPlaying`` 14 | 15 | ### Spotify Connect 16 | 17 | - ``streaming`` 18 | - ``appRemoteControl`` 19 | 20 | ### Users 21 | 22 | - ``userReadEmail`` 23 | - ``userReadPrivate`` 24 | 25 | ### Playlists 26 | 27 | - ``playlistReadCollaborative`` 28 | - ``playlistModifyPublic`` 29 | - ``playlistReadPrivate`` 30 | - ``playlistModifyPrivate`` 31 | 32 | ### Library 33 | 34 | - ``userLibraryModify`` 35 | - ``userLibraryRead`` 36 | 37 | ### Listen History 38 | 39 | - ``userTopRead`` 40 | - ``userReadPlaybackPosition`` 41 | - ``userReadRecentlyPlayed`` 42 | 43 | ### Follow 44 | 45 | - ``userFollowRead`` 46 | - ``userFollowModify`` 47 | 48 | [1]: https://developer.spotify.com/documentation/general/guides/authorization/scopes/ 49 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/SpotifyWebAPI.docc/theme-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme": { 3 | "icons": { 4 | "article": "/Users/pschorn/Code/Swift/Libraries/SpotifyAPI/docs/images/simple-box.svg" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Sources/SpotifyWebAPI/URLExtensions/URLQueryItemExtensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Sequence where Element == URLQueryItem { 4 | 5 | func sortedByNameThenValue() -> [URLQueryItem] { 6 | return self.sorted { lhs, rhs in 7 | if lhs.name != rhs.name { 8 | return lhs.name < rhs.name 9 | } 10 | return (lhs.value ?? "") < (rhs.value ?? "") 11 | } 12 | } 13 | 14 | } 15 | 16 | extension Array where Element == URLQueryItem { 17 | 18 | mutating func sortByNameThenValue() { 19 | self = self.sortedByNameThenValue() 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Tests/SpotifyAPIMainTests/Coding Tests/Authorization Objects/CodingAuthInfoTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | @testable import SpotifyWebAPI 4 | import SpotifyAPITestUtilities 5 | 6 | final class CodingAuthInfoTests: SpotifyAPITestCase { 7 | 8 | static let allTests = [ 9 | ("testCodingAuthInfo", testCodingAuthInfo) 10 | ] 11 | 12 | func testCodingAuthInfo() { 13 | 14 | for _ in 1...100 { 15 | let authInfo = AuthInfo.withRandomValues() 16 | encodeDecode(authInfo) 17 | 18 | let authInfo2 = AuthInfo.withRandomValues() 19 | XCTAssertNotEqual(authInfo, authInfo2) 20 | } 21 | 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Tests/SpotifyAPIMainTests/Coding Tests/CodingTimeReferenceTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | import SpotifyWebAPI 4 | import SpotifyAPITestUtilities 5 | 6 | final class CodingTimeReferenceTests: SpotifyAPITestCase { 7 | 8 | static let allTests = [ 9 | ("testCodingTimeReference", testCodingTimeReference) 10 | ] 11 | 12 | func testCodingTimeReference() { 13 | 14 | let timeReference1 = TimeReference.before(Date()) 15 | encodeDecode(timeReference1) 16 | 17 | let timeReference2 = TimeReference.after(Date()) 18 | encodeDecode(timeReference2) 19 | 20 | for _ in 1...1_000 { 21 | let randomInterval = Double.random(in: -1_000_000_000...1_000_000_000) 22 | let date = Date().addingTimeInterval(randomInterval) 23 | let timeReference3 = TimeReference.before(date) 24 | 25 | encodeDecode(timeReference3) 26 | 27 | } 28 | 29 | for _ in 1...1_000 { 30 | let randomInterval = Double.random(in: -1_000_000_000...1_000_000_000) 31 | let date = Date().addingTimeInterval(randomInterval) 32 | let timeReference3 = TimeReference.after(date) 33 | 34 | encodeDecode(timeReference3) 35 | 36 | } 37 | 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Tests/SpotifyAPIMainTests/Coding Tests/SpotifyPlayerErrorCodingTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | import SpotifyWebAPI 4 | import SpotifyExampleContent 5 | import SpotifyAPITestUtilities 6 | 7 | final class CodingSpotifyPlayerErrorTests: SpotifyAPITestCase { 8 | 9 | static let allTests = [ 10 | ("testCodingVolumeControlDisallow", testCodingVolumeControlDisallow) 11 | ] 12 | 13 | func testCodingVolumeControlDisallow() throws { 14 | 15 | let errorData = """ 16 | { 17 | "error": { 18 | "status": 403, 19 | "message": "Player command failed: Cannot control device volume", 20 | "reason": "VOLUME_CONTROL_DISALLOW" 21 | } 22 | } 23 | """.data(using: .utf8)! 24 | 25 | decodeEncodeDecode(errorData, type: SpotifyPlayerError.self, areEqual: ==) 26 | 27 | let error = try JSONDecoder().decode( 28 | SpotifyPlayerError.self, from: errorData 29 | ) 30 | 31 | XCTAssertEqual(error.statusCode, 403) 32 | XCTAssertEqual( 33 | error.message, 34 | "Player command failed: Cannot control device volume" 35 | ) 36 | XCTAssertEqual(error.reason, .volumeControlDisallow) 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Tests/SpotifyAPIMainTests/Documentation Tests/MiscellaneousDocumentationTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | #if canImport(Combine) 3 | import Combine 4 | #else 5 | import OpenCombine 6 | import OpenCombineDispatch 7 | import OpenCombineFoundation 8 | #endif 9 | import SpotifyWebAPI 10 | 11 | // These methods exist to ensure that they compile. 12 | // They are not meant to be called. 13 | 14 | private func testCodeVerifierCodeChallenge() { 15 | 16 | let codeVerifier = String.randomURLSafe(length: 128) 17 | let codeChallenge = String.makeCodeChallenge(codeVerifier: codeVerifier) 18 | 19 | // suppress warnings. 20 | _ = codeVerifier 21 | _ = codeChallenge 22 | 23 | } 24 | 25 | 26 | #if canImport(UIKit) 27 | import UIKit 28 | 29 | private func uploadPlaylistImageDocsTest( 30 | uiImage: UIImage, spotify: SpotifyAPI 31 | ) { 32 | 33 | let jpegData = uiImage.jpegData( 34 | compressionQuality: 0.5 35 | )! 36 | let base64EncodedData = jpegData.base64EncodedData() 37 | 38 | _ = spotify.uploadPlaylistImage("", imageData: base64EncodedData) 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Tests/SpotifyAPIMainTests/Other Tests/RepeatModeTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | import SpotifyWebAPI 4 | import SpotifyAPITestUtilities 5 | 6 | class RepeatModeTests: SpotifyAPITestCase { 7 | 8 | static let allTests = [ 9 | ("testCycle", testCycle), 10 | ("testCycled", testCycled) 11 | ] 12 | 13 | func testCycle() { 14 | 15 | // off 16 | // context 17 | // track 18 | 19 | var repeatMode = RepeatMode.off 20 | repeatMode.cycle() 21 | XCTAssertEqual(repeatMode, .context) 22 | repeatMode.cycle() 23 | XCTAssertEqual(repeatMode, .track) 24 | repeatMode.cycle() 25 | XCTAssertEqual(repeatMode, .off) 26 | 27 | } 28 | 29 | func testCycled() { 30 | 31 | let context = RepeatMode.context 32 | let track = context.cycled() 33 | XCTAssertEqual(track, .track) 34 | let off = track.cycled() 35 | XCTAssertEqual(off, .off) 36 | let context2 = off.cycled() 37 | XCTAssertEqual(context2, .context) 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /build_documentation.sh: -------------------------------------------------------------------------------- 1 | swift package --allow-writing-to-package-directory \ 2 | generate-documentation \ 3 | --target SpotifyWebAPI \ 4 | --include-extended-types \ 5 | --output-path 'docs' \ 6 | --transform-for-static-hosting \ 7 | --hosting-base-path SpotifyAPI 8 | -------------------------------------------------------------------------------- /docker_linux.sh: -------------------------------------------------------------------------------- 1 | TAG=${1:-swift:latest} 2 | 3 | docker run \ 4 | --rm \ 5 | --volume "$(pwd):/src" \ 6 | --workdir "/src" \ 7 | -it \ 8 | --privileged \ 9 | -e SPOTIFY_DATA_DUMP_FOLDER="/logs" \ 10 | -e SPOTIFY_CLIENT_CREDENTIALS_FLOW_TOKENS_URL=$SPOTIFY_CLIENT_CREDENTIALS_FLOW_TOKENS_URL \ 11 | -e SPOTIFY_SWIFT_TESTING_CLIENT_ID=$SPOTIFY_SWIFT_TESTING_CLIENT_ID \ 12 | -e SPOTIFY_SWIFT_TESTING_CLIENT_SECRET=$SPOTIFY_SWIFT_TESTING_CLIENT_SECRET \ 13 | $TAG 14 | -------------------------------------------------------------------------------- /docs/developer-og-twitter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/developer-og-twitter.jpg -------------------------------------------------------------------------------- /docs/developer-og.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/developer-og.jpg -------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/!=(_:_:)/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/albumtype/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/artists/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/genres/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/href/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/id/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/images/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/label/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/name/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/tracks/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/type/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/album/uri/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/albumtype/album/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/albumtype/ep/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/albumtype/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/albumtype/other/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/!=(_:_:)/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/genres/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/href/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/id/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/images/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/name/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/type/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/artist/uri/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/attributerange/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/audioanalysis/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/audiobook/href/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/audiobook/id/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/audiobook/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/audiobook/name/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/audiobook/type/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/audiobook/uri/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/authinfo/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/combine/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/debugging/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/device/id/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/device/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/devicetype/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/endpoints/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/episode/id/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/episode/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/followers/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/foundation/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/headers/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/idcategory/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/logging/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/paginated/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/playlist/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/repeatmode/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/savedalbum/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/saveditem/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/savedshow/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/savedtrack/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/scope/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/section/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/segment/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/show/href/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/show/id/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/show/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/show/name/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/show/type/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/show/uri/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/spotifyapi/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/swift/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/swift/set/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/timerange/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/track/href/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/track/id/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/track/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/track/name/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/track/type/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/track/uri/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/documentation/spotifywebapi/tracklink/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/favicon.ico -------------------------------------------------------------------------------- /docs/favicon.svg: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /docs/images/SpotifyWebAPI/Change_Test_Plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/images/SpotifyWebAPI/Change_Test_Plan.png -------------------------------------------------------------------------------- /docs/images/SpotifyWebAPI/JSON_Viewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/images/SpotifyWebAPI/JSON_Viewer.png -------------------------------------------------------------------------------- /docs/images/SpotifyWebAPI/SpotifyAPIMainTestPlan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/images/SpotifyWebAPI/SpotifyAPIMainTestPlan.png -------------------------------------------------------------------------------- /docs/img/added-icon.832a5d2c.svg: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /docs/img/deprecated-icon.7bf1740a.svg: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /docs/img/modified-icon.efb2697d.svg: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | Documentation
-------------------------------------------------------------------------------- /docs/index/availability.index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/index/availability.index -------------------------------------------------------------------------------- /docs/index/data.mdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/index/data.mdb -------------------------------------------------------------------------------- /docs/index/navigator.index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peter-Schorn/SpotifyAPI/391af49951fa2a854f63bde1e6f6726ba2763da7/docs/index/navigator.index -------------------------------------------------------------------------------- /docs/js/highlight-js-diff-js.4db9a783.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * This source file is part of the Swift.org open source project 3 | * 4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors 5 | * Licensed under Apache License v2.0 with Runtime Library Exception 6 | * 7 | * See https://swift.org/LICENSE.txt for license information 8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | */ 10 | (self["webpackChunkswift_docc_render"]=self["webpackChunkswift_docc_render"]||[]).push([[213],{7731:function(e){function n(e){const n=e.regex;return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,match:n.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/)},{className:"comment",variants:[{begin:n.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/),end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,end:/$/}]}}e.exports=n}}]); -------------------------------------------------------------------------------- /docs/js/highlight-js-http-js.f78e83c2.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * This source file is part of the Swift.org open source project 3 | * 4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors 5 | * Licensed under Apache License v2.0 with Runtime Library Exception 6 | * 7 | * See https://swift.org/LICENSE.txt for license information 8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | */ 10 | (self["webpackChunkswift_docc_render"]=self["webpackChunkswift_docc_render"]||[]).push([[878],{8937:function(e){function n(e){const n=e.regex,a="HTTP/(2|1\\.[01])",s=/[A-Za-z][A-Za-z0-9-]*/,t={className:"attribute",begin:n.concat("^",s,"(?=\\:\\s)"),starts:{contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]}},i=[t,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+a+" \\d{3})",end:/$/,contains:[{className:"meta",begin:a},{className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},{begin:"(?=^[A-Z]+ (.*?) "+a+"$)",end:/$/,contains:[{className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:a},{className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},e.inherit(t,{relevance:0})]}}e.exports=n}}]); -------------------------------------------------------------------------------- /docs/js/highlight-js-json-js.2a1856ba.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * This source file is part of the Swift.org open source project 3 | * 4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors 5 | * Licensed under Apache License v2.0 with Runtime Library Exception 6 | * 7 | * See https://swift.org/LICENSE.txt for license information 8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | */ 10 | (self["webpackChunkswift_docc_render"]=self["webpackChunkswift_docc_render"]||[]).push([[82],{14:function(e){function n(e){const n={className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},c={match:/[{}[\],:]/,className:"punctuation",relevance:0},a={beginKeywords:["true","false","null"].join(" ")};return{name:"JSON",contains:[n,c,e.QUOTE_STRING_MODE,a,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}}e.exports=n}}]); -------------------------------------------------------------------------------- /docs/js/highlight-js-shell-js.0ad5b20f.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * This source file is part of the Swift.org open source project 3 | * 4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors 5 | * Licensed under Apache License v2.0 with Runtime Library Exception 6 | * 7 | * See https://swift.org/LICENSE.txt for license information 8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | */ 10 | (self["webpackChunkswift_docc_render"]=self["webpackChunkswift_docc_render"]||[]).push([[176],{7874:function(s){function e(s){return{name:"Shell Session",aliases:["console","shellsession"],contains:[{className:"meta",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]}}s.exports=e}}]); -------------------------------------------------------------------------------- /docs/metadata.json: -------------------------------------------------------------------------------- 1 | {"bundleDisplayName":"SpotifyWebAPI","bundleIdentifier":"SpotifyWebAPI","schemaVersion":{"minor":1,"patch":0,"major":0}} -------------------------------------------------------------------------------- /docs/theme-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme": { 3 | "icons": { 4 | "article": "/Users/pschorn/Code/Swift/Libraries/SpotifyAPI/docs/images/simple-box.svg" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /preview_documentation.sh: -------------------------------------------------------------------------------- 1 | swift package --disable-sandbox preview-documentation --target SpotifyWebAPI 2 | -------------------------------------------------------------------------------- /rm_credentials.sh: -------------------------------------------------------------------------------- 1 | cd 'Sources/SpotifyAPITestUtilities/Authorization' 2 | 3 | sed -E -i.bak 's/(let __clientId__ = )".*"/\1""/' 'AuthorizationConstants.swift' \ 4 | && rm AuthorizationConstants.swift.bak 5 | 6 | sed -E -i.bak 's/(let __clientSecret__ = )".*"/\1""/' 'AuthorizationConstants.swift' \ 7 | && rm AuthorizationConstants.swift.bak 8 | 9 | sed -E -i.bak 's/(let __clientCredentialsFlowTokensURL__ = )".*"/\1""/' 'AuthorizationConstants.swift' \ 10 | && rm AuthorizationConstants.swift.bak 11 | -------------------------------------------------------------------------------- /set_credentials.sh: -------------------------------------------------------------------------------- 1 | cd 'Sources/SpotifyAPITestUtilities/Authorization' 2 | 3 | sed -E -i.bak "s~(let __clientId__ = )\".*\"~\1\"$SPOTIFY_SWIFT_TESTING_CLIENT_ID\"~" 'AuthorizationConstants.swift' \ 4 | && rm AuthorizationConstants.swift.bak 5 | 6 | sed -E -i.bak "s~(let __clientSecret__ = )\".*\"~\1\"$SPOTIFY_SWIFT_TESTING_CLIENT_SECRET\"~" 'AuthorizationConstants.swift' \ 7 | && rm AuthorizationConstants.swift.bak 8 | 9 | sed -E -i.bak "s~(let __clientCredentialsFlowTokensURL__ = )\".*\"~\1\"$SPOTIFY_CLIENT_CREDENTIALS_FLOW_TOKENS_URL\"~" 'AuthorizationConstants.swift' \ 10 | && rm AuthorizationConstants.swift.bak 11 | --------------------------------------------------------------------------------