From 8cfa25a45e78642590e4046b924cef158bc59732 Mon Sep 17 00:00:00 2001 From: Jonas Thelemann Date: Thu, 30 Apr 2026 20:28:36 +0200 Subject: [PATCH] feat(api)!: sync specification feat: implement feedback feat: adopt api naming feat: add deprecated endpoints fix: add deprecations fix: update naming --- README.md | 164 +- .../CheckUsersSavedAlbumsExample.java | 5 +- .../data/albums/GetAlbumsTracksExample.java | 4 +- .../GetCurrentUsersSavedAlbumsExample.java | 21 +- .../CheckUsersSavedAudiobooksExample.java | 58 + .../GetAudiobookChaptersExample.java | 59 + .../data/audiobooks/GetAudiobookExample.java | 56 + .../GetSeveralAudiobooksExample.java | 59 + .../GetUsersSavedAudiobooksExample.java | 61 + ...RemoveAudiobooksForCurrentUserExample.java | 58 + .../SaveAudiobooksForCurrentUserExample.java | 58 + .../GetSeveralBrowseCategoriesExample.java | 62 + .../GetSingleBrowseCategoryExample.java | 60 + examples/data/chapters/GetChapterExample.java | 56 + .../chapters/GetSeveralChaptersExample.java | 59 + .../CheckUsersSavedEpisodesExample.java | 5 +- .../GetUsersSavedEpisodesExample.java | 5 +- .../GetAvailableGenreSeedsExample.java | 19 +- .../library/RemoveFromLibraryExample.java | 16 +- .../data/library/SaveToLibraryExample.java | 16 +- .../markets/GetAvailableMarketsExample.java | 53 + .../AddItemToUsersPlaybackQueueExample.java | 18 +- ...rrentUsersRecentlyPlayedTracksExample.java | 18 +- ...ationAboutUsersCurrentPlaybackExample.java | 6 +- .../data/player/GetTheUsersQueueExample.java | 16 +- .../GetUsersAvailableDevicesExample.java | 6 +- .../GetUsersCurrentlyPlayingTrackExample.java | 6 +- .../player/PauseUsersPlaybackExample.java | 4 +- ...ositionInCurrentlyPlayingTrackExample.java | 6 +- .../SetRepeatModeOnUsersPlaybackExample.java | 6 +- .../SetVolumeForUsersPlaybackExample.java | 6 +- .../SkipUsersPlaybackToNextTrackExample.java | 6 +- ...ipUsersPlaybackToPreviousTrackExample.java | 6 +- .../StartResumeUsersPlaybackExample.java | 18 +- .../ToggleShuffleForUsersPlaybackExample.java | 6 +- .../player/TransferUsersPlaybackExample.java | 6 +- .../AddItemsToPlaylistDeprecatedExample.java | 62 + .../ChangePlaylistsDetailsExample.java | 18 +- .../GetCategoryPlaylistsExample.java} | 17 +- ...a => GetCurrentUsersPlaylistsExample.java} | 8 +- .../GetFeaturedPlaylistsExample.java} | 23 +- .../GetPlaylistCoverImageExample.java | 14 +- .../playlists/GetPlaylistsItemsExample.java | 6 +- .../RemoveItemsFromPlaylistExample.java | 18 +- ...> UpdatePlaylistsItemsReorderExample.java} | 10 +- ...> UpdatePlaylistsItemsReplaceExample.java} | 8 +- ...UploadCustomPlaylistCoverImageExample.java | 18 +- examples/data/search/SearchItemExample.java | 16 +- .../CheckUsersSavedShowsExample.java | 5 +- .../data/shows/GetShowsEpisodesExample.java | 4 +- .../GetUsersSavedShowsExample.java | 5 +- .../CheckUsersSavedTracksExample.java | 5 +- .../GetAudioAnalysisForTrackExample.java | 18 +- ...tAudioFeaturesForSeveralTracksExample.java | 18 +- .../GetAudioFeaturesForTrackExample.java | 18 +- .../GetRecommendationsExample.java | 5 +- .../GetUsersSavedTracksExample.java | 5 +- ...rrentUserFollowsArtistsOrUsersExample.java | 5 +- .../CheckUsersFollowPlaylistExample.java | 21 +- .../FollowArtistsOrUsersExample.java | 5 +- .../FollowPlaylistExample.java | 9 +- .../GetCurrentUsersProfileExample.java | 5 +- .../GetUsersFollowedArtistsExample.java | 21 +- .../GetUsersTopArtistsAndTracksExample.java | 7 +- .../UnfollowArtistsOrUsersExample.java | 5 +- .../UnfollowPlaylistExample.java | 8 +- .../simplified/GetUsersTopArtistsExample.java | 4 +- .../simplified/GetUsersTopTracksExample.java | 4 +- .../se/michaelthelin/spotify/SpotifyApi.java | 934 +- .../spotify/enums/ModelObjectType.java | 2 + .../model_objects/interfaces/IEpisode.java | 2 +- .../model_objects/interfaces/IPlaylist.java | 15 +- .../model_objects/interfaces/IShow.java | 1 - .../model_objects/interfaces/ITrack.java | 2 +- .../model_objects/special/SearchResult.java | 8 +- .../model_objects/specification/Artist.java | 2 +- .../specification/Audiobook.java | 657 ++ .../specification/AudiobookSimplified.java | 628 ++ .../model_objects/specification/Author.java | 115 + .../model_objects/specification/Chapter.java | 685 ++ .../specification/ChapterRestriction.java | 124 + .../specification/ChapterSimplified.java | 657 ++ .../model_objects/specification/Episode.java | 4 +- .../specification/EpisodeSimplified.java | 4 +- .../model_objects/specification/Narrator.java | 115 + .../model_objects/specification/Playlist.java | 6 +- .../specification/PlaylistSimplified.java | 6 +- .../specification/SavedAudiobook.java | 135 + .../specification/SavedEpisode.java | 135 + .../model_objects/specification/Show.java | 1 + .../specification/ShowSimplified.java | 1 + .../model_objects/specification/Track.java | 4 +- .../specification/TrackSimplified.java | 2 +- .../CheckUsersSavedAlbumsRequest.java | 5 +- ...equest.java => GetAlbumTracksRequest.java} | 28 +- .../data/albums/GetNewReleasesRequest.java | 102 + .../data/albums/GetSeveralAlbumsRequest.java | 100 + .../GetUsersSavedAlbumsRequest.java} | 28 +- .../RemoveAlbumsForCurrentUserRequest.java | 92 + .../SaveAlbumsForCurrentUserRequest.java | 92 + .../GetArtistsRelatedArtistsRequest.java | 3 + .../artists/GetArtistsTopTracksRequest.java | 100 + .../artists/GetSeveralArtistsRequest.java | 86 + .../CheckUsersSavedAudiobooksRequest.java | 90 + .../GetAudiobookChaptersRequest.java | 124 + .../data/audiobooks/GetAudiobookRequest.java | 98 + .../GetSeveralAudiobooksRequest.java | 101 + .../GetUsersSavedAudiobooksRequest.java | 99 + ...RemoveAudiobooksForCurrentUserRequest.java | 89 + .../SaveAudiobooksForCurrentUserRequest.java | 89 + .../GetSeveralBrowseCategoriesRequest.java | 115 + .../GetSingleBrowseCategoryRequest.java | 100 + .../data/chapters/GetChapterRequest.java | 97 + .../chapters/GetSeveralChaptersRequest.java | 100 + .../CheckUsersSavedEpisodesRequest.java | 5 +- .../episodes/GetSeveralEpisodesRequest.java | 99 + .../GetUsersSavedEpisodesRequest.java | 4 +- .../RemoveEpisodesForCurrentUserRequest.java | 92 + .../SaveEpisodesForCurrentUserRequest.java | 92 + .../follow/legacy/FollowPlaylistRequest.java | 115 - .../legacy/UnfollowPlaylistRequest.java | 99 - .../GetRecommendationGenresRequest.java} | 25 +- .../library/CheckUsersSavedItemsRequest.java | 90 + ...ava => RemoveItemsFromLibraryRequest.java} | 22 +- ...st.java => SaveItemsToLibraryRequest.java} | 22 +- .../markets/GetAvailableMarketsRequest.java | 76 + ...ava => AddItemToPlaybackQueueRequest.java} | 24 +- ...t.java => GetAvailableDevicesRequest.java} | 20 +- ...a => GetCurrentlyPlayingTrackRequest.java} | 26 +- ...uest.java => GetPlaybackStateRequest.java} | 24 +- ...va => GetRecentlyPlayedTracksRequest.java} | 26 +- ...Request.java => GetUsersQueueRequest.java} | 24 +- ...Request.java => PausePlaybackRequest.java} | 22 +- ...equest.java => SeekToPositionRequest.java} | 24 +- ...est.java => SetPlaybackVolumeRequest.java} | 24 +- ...Request.java => SetRepeatModeRequest.java} | 24 +- ...ackRequest.java => SkipToNextRequest.java} | 22 +- ...equest.java => SkipToPreviousRequest.java} | 24 +- ...t.java => StartResumePlaybackRequest.java} | 30 +- ...java => TogglePlaybackShuffleRequest.java} | 24 +- ...uest.java => TransferPlaybackRequest.java} | 24 +- ...> AddCustomPlaylistCoverImageRequest.java} | 24 +- .../AddItemsToPlaylistDeprecatedRequest.java | 171 + .../playlists/AddItemsToPlaylistRequest.java | 2 +- ...java => ChangePlaylistDetailsRequest.java} | 30 +- .../CreatePlaylistForUserRequest.java | 139 + .../GetCategoryPlaylistsRequest.java} | 33 +- ...a => GetCurrentUsersPlaylistsRequest.java} | 24 +- .../GetFeaturedPlaylistsRequest.java} | 35 +- .../GetPlaylistItemsDeprecatedRequest.java | 168 + ...uest.java => GetPlaylistItemsRequest.java} | 34 +- .../playlists/GetUsersPlaylistsRequest.java | 115 + .../RemovePlaylistItemsDeprecatedRequest.java | 147 + ...t.java => RemovePlaylistItemsRequest.java} | 28 +- ...laylistsItemsReorderDeprecatedRequest.java | 159 + ...> UpdatePlaylistsItemsReorderRequest.java} | 32 +- ...laylistsItemsReplaceDeprecatedRequest.java | 131 + ...> UpdatePlaylistsItemsReplaceRequest.java} | 28 +- ...Request.java => SearchForItemRequest.java} | 32 +- .../simplified/SearchAlbumsRequest.java | 3 +- .../simplified/SearchArtistsRequest.java | 3 +- .../simplified/SearchEpisodesRequest.java | 3 +- .../simplified/SearchPlaylistsRequest.java | 3 +- .../search/simplified/SearchShowsRequest.java | 3 +- .../simplified/SearchTracksRequest.java | 3 +- .../CheckUsersSavedShowsRequest.java | 5 +- .../data/shows/GetSeveralShowsRequest.java | 99 + ...quest.java => GetShowEpisodesRequest.java} | 28 +- .../GetUsersSavedShowsRequest.java | 2 +- .../RemoveShowsForCurrentUserRequest.java | 57 + .../shows/SaveShowsForCurrentUserRequest.java | 57 + .../CheckUsersSavedTracksRequest.java | 5 +- .../GetRecommendationsRequest.java | 5 +- ...GetSeveralTracksAudioFeaturesRequest.java} | 25 +- .../data/tracks/GetSeveralTracksRequest.java | 100 + ...ava => GetTracksAudioAnalysisRequest.java} | 25 +- ...ava => GetTracksAudioFeaturesRequest.java} | 25 +- .../GetUsersSavedTracksRequest.java | 2 +- .../tracks/RemoveUsersSavedTracksRequest.java | 57 + .../SaveTracksForCurrentUserRequest.java | 57 + ...rrentUserFollowsArtistsOrUsersRequest.java | 5 +- .../CheckIfUserFollowsPlaylistRequest.java} | 45 +- .../FollowArtistsOrUsersRequest.java | 5 +- .../FollowPlaylistRequest.java | 5 +- .../GetCurrentUsersProfileRequest.java | 2 +- .../GetFollowedArtistsRequest.java} | 28 +- .../data/users/GetUsersProfileRequest.java | 89 + .../GetUsersTopArtistsAndTracksRequest.java | 8 +- .../UnfollowArtistsOrUsersRequest.java | 5 +- .../UnfollowPlaylistRequest.java | 5 +- .../interfaces/IArtistTrackModelObject.java | 2 +- .../simplified/GetUsersTopArtistsRequest.java | 2 +- .../simplified/GetUsersTopTracksRequest.java | 2 +- src/test/fixtures/open-api-schema.yaml | 7523 +++++++++++++++++ .../CheckUsersSavedAlbumsRequest.json | 0 .../data/albums/GetNewReleasesRequest.json | 45 + .../data/albums/GetSeveralAlbumsRequest.json | 32 + .../GetUsersSavedAlbumsRequest.json} | 0 .../RemoveAlbumsForCurrentUserRequest.json | 1 + .../SaveAlbumsForCurrentUserRequest.json | 1 + .../artists/GetArtistsTopTracksRequest.json | 65 + .../artists/GetSeveralArtistsRequest.json | 30 + .../CheckUsersSavedAudiobooksRequest.json} | 0 .../GetAudiobookChaptersRequest.json | 37 + .../data/audiobooks/GetAudiobookRequest.json | 46 + .../GetSeveralAudiobooksRequest.json | 35 + .../GetUsersSavedAudiobooksRequest.json | 44 + ...RemoveAudiobooksForCurrentUserRequest.json | 1 + .../SaveAudiobooksForCurrentUserRequest.json | 1 + .../data/categories/GetCategoriesRequest.json | 36 + .../data/categories/GetCategoryRequest.json | 12 + .../data/chapters/GetChapterRequest.json | 58 + .../chapters/GetSeveralChaptersRequest.json | 62 + .../CheckUsersSavedEpisodesRequest.json | 4 + .../episodes/GetSeveralEpisodesRequest.json | 30 + .../GetUsersSavedEpisodesRequest.json | 0 .../RemoveEpisodesForCurrentUserRequest.json | 1 + .../SaveEpisodesForCurrentUserRequest.json | 1 + .../GetRecommendationGenresRequest.json} | 0 .../library/CheckLibraryContainsRequest.json | 4 + .../markets/GetAvailableMarketsRequest.json | 190 + ...QueueRequest.json => GetQueueRequest.json} | 0 ...est.json => GetRecentlyPlayedRequest.json} | 0 .../CreatePlaylistForUserRequest.json | 42 + .../GetCategoryPlaylistsRequest.json} | 0 .../GetFeaturedPlaylistsRequest.json} | 0 ...json => GetListUsersPlaylistsRequest.json} | 0 ...etListUsersPlaylistsRequest_UserWith$.json | 64 + ...uest.json => GetPlaylistCoverRequest.json} | 0 .../GetPlaylistsItemsRequest_Episode.json | 2 +- .../playlists/RemoveItemsPlaylistRequest.json | 3 + .../ReplacePlaylistsItemsRequest.json | 3 + ...rchItemRequest.json => SearchRequest.json} | 0 .../CheckUsersSavedShowsRequest.json | 0 .../data/shows/GetSeveralShowsRequest.json | 25 + .../GetUsersSavedShowsRequest.json | 0 .../RemoveShowsForCurrentUserRequest.json | 1 + .../shows/SaveShowsForCurrentUserRequest.json | 1 + .../CheckUsersSavedTracksRequest.json | 0 ...uest.json => GetAudioAnalysisRequest.json} | 0 ...uest.json => GetAudioFeaturesRequest.json} | 0 .../GetRecommendationsRequest.json | 0 ...on => GetSeveralAudioFeaturesRequest.json} | 0 .../data/tracks/GetSeveralTracksRequest.json | 65 + .../GetUsersSavedTracksRequest.json | 0 .../RemoveTracksForCurrentUserRequest.json | 1 + .../SaveTracksForCurrentUserRequest.json | 1 + ...rrentUserFollowsArtistsOrUsersRequest.json | 0 .../CheckIfUserFollowsPlaylistRequest.json} | 0 .../GetCurrentUsersProfileRequest.json | 0 .../GetFollowedRequest.json} | 0 .../GetFollowedRequest_None.json} | 0 .../data/users/GetUsersProfileRequest.json | 25 + .../simplified/GetUsersTopArtistsRequest.json | 0 .../simplified/GetUsersTopTracksRequest.json | 0 .../java/se/michaelthelin/spotify/ITest.java | 2 + .../CheckUsersSavedAlbumsRequestTest.java | 5 +- .../albums/GetAlbumsTracksRequestTest.java | 2 +- .../albums/GetNewReleasesRequestTest.java | 60 + .../albums/GetSeveralAlbumsRequestTest.java | 51 + .../GetUsersSavedAlbumsRequestTest.java} | 10 +- ...RemoveAlbumsForCurrentUserRequestTest.java | 48 + .../SaveAlbumsForCurrentUserRequestTest.java | 48 + .../data/artists/GetArtistRequestTest.java | 1 - .../GetArtistsTopTracksRequestTest.java | 51 + .../artists/GetSeveralArtistsRequestTest.java | 51 + .../CheckUsersSavedAudiobooksRequestTest.java | 48 + .../GetAudiobookChaptersRequestTest.java | 62 + .../audiobooks/GetAudiobookRequestTest.java | 54 + .../GetSeveralAudiobooksRequestTest.java | 51 + .../GetUsersSavedAudiobooksRequestTest.java | 62 + ...veAudiobooksForCurrentUserRequestTest.java | 48 + ...veAudiobooksForCurrentUserRequestTest.java | 48 + .../categories/GetCategoriesRequestTest.java | 66 + .../categories/GetCategoryRequestTest.java | 60 + .../data/chapters/GetChapterRequestTest.java | 53 + .../GetSeveralChaptersRequestTest.java | 51 + .../CheckUsersSavedEpisodesRequestTest.java | 5 +- .../data/episodes/GetEpisodeRequestTest.java | 2 +- .../GetSeveralEpisodesRequestTest.java | 51 + .../GetUsersSavedEpisodesRequestTest.java | 4 +- ...moveEpisodesForCurrentUserRequestTest.java | 48 + ...SaveEpisodesForCurrentUserRequestTest.java | 48 + .../legacy/FollowPlaylistRequestTest.java | 55 - .../GetRecommendationGenresRequestTest.java} | 10 +- .../CheckLibraryContainsRequestTest.java | 49 + ...ava => RemoveLibraryItemsRequestTest.java} | 6 +- ....java => SaveLibraryItemsRequestTest.java} | 6 +- .../GetAvailableMarketsRequestTest.java | 51 + ...stTest.java => AddToQueueRequestTest.java} | 8 +- ...nAboutUsersCurrentPlaybackRequestTest.java | 12 +- ...uestTest.java => GetQueueRequestTest.java} | 10 +- ...java => GetRecentlyPlayedRequestTest.java} | 10 +- .../player/GetUsersAvailableDevicesTest.java | 8 +- ...UsersCurrentlyPlayingTrackRequestTest.java | 12 +- .../player/PauseUsersPlaybackRequestTest.java | 4 +- ...ionInCurrentlyPlayingTrackRequestTest.java | 4 +- ...tRepeatModeOnUsersPlaybackRequestTest.java | 4 +- .../SetVolumeForUsersPlaybackRequestTest.java | 4 +- ...ipUsersPlaybackToNextTrackRequestTest.java | 4 +- ...ersPlaybackToPreviousTrackRequestTest.java | 4 +- ...StartUsersPlaybackRequestNumericTest.java} | 14 +- ...ava => StartUsersPlaybackRequestTest.java} | 8 +- ...gleShuffleForUsersPlaybackRequestTest.java | 4 +- .../TransferUsersPlaybackRequestTest.java | 4 +- ...dCustomPlaylistCoverImageRequestTest.java} | 8 +- ...ItemsToPlaylistDeprecatedRequestTest.java} | 42 +- .../AddItemsToPlaylistRequestTest.java | 4 +- ... => ChangePlaylistDetailsRequestTest.java} | 8 +- ... => CreatePlaylistForUserRequestTest.java} | 34 +- .../playlists/CreatePlaylistRequestTest.java | 2 +- .../GetCategoryPlaylistsRequestTest.java} | 11 +- ... GetCurrentUsersPlaylistsRequestTest.java} | 8 +- .../GetFeaturedPlaylistsRequestTest.java} | 11 +- .../GetPlaylistCoverImageRequestTest.java | 2 +- .../playlists/GetPlaylistRequestTest.java | 2 +- .../GetPlaylistsItemsRequestTest.java | 124 - .../GetUsersPlaylistsRequestTest.java | 59 + .../ReorderPlaylistsItemsRequestTest.java | 71 - ...equestTest.java => SearchRequestTest.java} | 10 +- .../CheckUsersSavedShowsRequestTest.java | 5 +- .../shows/GetSeveralShowsRequestTest.java | 51 + .../shows/GetShowsEpisodesRequestTest.java | 2 +- .../GetUsersSavedShowsRequestTest.java | 4 +- .../RemoveShowsForCurrentUserRequestTest.java | 48 + .../SaveShowsForCurrentUserRequestTest.java | 48 + .../CheckUsersSavedTracksRequestTest.java | 5 +- ....java => GetAudioAnalysisRequestTest.java} | 11 +- ....java => GetAudioFeaturesRequestTest.java} | 11 +- .../GetRecommendationsRequestTest.java | 5 +- ...> GetSeveralAudioFeaturesRequestTest.java} | 11 +- .../tracks/GetSeveralTracksRequestTest.java | 51 + .../data/tracks/GetTrackRequestTest.java | 2 +- .../GetUsersSavedTracksRequestTest.java | 4 +- ...emoveTracksForCurrentUserRequestTest.java} | 17 +- .../SaveTracksForCurrentUserRequestTest.java | 48 + ...tUserFollowsArtistsOrUsersRequestTest.java | 5 +- ...heckIfUserFollowsPlaylistRequestTest.java} | 12 +- .../FollowArtistsOrUsersRequestTest.java | 3 +- .../FollowPlaylistRequestTest.java | 3 +- .../GetCurrentUsersProfileRequestTest.java | 4 +- .../GetFollowedRequestTest.java} | 14 +- .../users/GetUsersProfileRequestTest.java | 66 + .../UnfollowArtistsOrUsersRequestTest.java | 3 +- .../UnfollowPlaylistRequestTest.java | 3 +- .../GetUsersTopArtistsRequestTest.java | 4 +- .../GetUsersTopTracksRequestTest.java | 4 +- 347 files changed, 19621 insertions(+), 1763 deletions(-) rename examples/data/{library => albums}/CheckUsersSavedAlbumsExample.java (94%) rename examples/data/{library => albums}/GetCurrentUsersSavedAlbumsExample.java (74%) create mode 100644 examples/data/audiobooks/CheckUsersSavedAudiobooksExample.java create mode 100644 examples/data/audiobooks/GetAudiobookChaptersExample.java create mode 100644 examples/data/audiobooks/GetAudiobookExample.java create mode 100644 examples/data/audiobooks/GetSeveralAudiobooksExample.java create mode 100644 examples/data/audiobooks/GetUsersSavedAudiobooksExample.java create mode 100644 examples/data/audiobooks/RemoveAudiobooksForCurrentUserExample.java create mode 100644 examples/data/audiobooks/SaveAudiobooksForCurrentUserExample.java create mode 100644 examples/data/categories/GetSeveralBrowseCategoriesExample.java create mode 100644 examples/data/categories/GetSingleBrowseCategoryExample.java create mode 100644 examples/data/chapters/GetChapterExample.java create mode 100644 examples/data/chapters/GetSeveralChaptersExample.java rename examples/data/{library => episodes}/CheckUsersSavedEpisodesExample.java (94%) rename examples/data/{library => episodes}/GetUsersSavedEpisodesExample.java (95%) rename examples/data/{browse/miscellaneous => genres}/GetAvailableGenreSeedsExample.java (69%) create mode 100644 examples/data/markets/GetAvailableMarketsExample.java create mode 100644 examples/data/playlists/AddItemsToPlaylistDeprecatedExample.java rename examples/data/{browse/GetCategorysPlaylistsExample.java => playlists/GetCategoryPlaylistsExample.java} (81%) rename examples/data/playlists/{GetListOfCurrentUsersPlaylistsExample.java => GetCurrentUsersPlaylistsExample.java} (87%) rename examples/data/{browse/GetListOfFeaturedPlaylistsExample.java => playlists/GetFeaturedPlaylistsExample.java} (72%) rename examples/data/playlists/{ReorderPlaylistsItemsExample.java => UpdatePlaylistsItemsReorderExample.java} (85%) rename examples/data/playlists/{ReplacePlaylistsItemsExample.java => UpdatePlaylistsItemsReplaceExample.java} (86%) rename examples/data/{library => shows}/CheckUsersSavedShowsExample.java (94%) rename examples/data/{library => shows}/GetUsersSavedShowsExample.java (95%) rename examples/data/{library => tracks}/CheckUsersSavedTracksExample.java (94%) rename examples/data/{browse => tracks}/GetRecommendationsExample.java (96%) rename examples/data/{library => tracks}/GetUsersSavedTracksExample.java (95%) rename examples/data/{follow => users}/CheckCurrentUserFollowsArtistsOrUsersExample.java (94%) rename examples/data/{follow => users}/CheckUsersFollowPlaylistExample.java (70%) rename examples/data/{follow => users}/FollowArtistsOrUsersExample.java (95%) rename examples/data/{follow => users}/FollowPlaylistExample.java (88%) rename examples/data/{users_profile => users}/GetCurrentUsersProfileExample.java (94%) rename examples/data/{follow => users}/GetUsersFollowedArtistsExample.java (78%) rename examples/data/{personalization => users}/GetUsersTopArtistsAndTracksExample.java (91%) rename examples/data/{follow => users}/UnfollowArtistsOrUsersExample.java (95%) rename examples/data/{follow => users}/UnfollowPlaylistExample.java (89%) rename examples/data/{personalization => users}/simplified/GetUsersTopArtistsExample.java (93%) rename examples/data/{personalization => users}/simplified/GetUsersTopTracksExample.java (93%) create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/Audiobook.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/AudiobookSimplified.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/Author.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/Chapter.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterRestriction.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterSimplified.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/Narrator.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedAudiobook.java create mode 100644 src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedEpisode.java rename src/main/java/se/michaelthelin/spotify/requests/data/{library => albums}/CheckUsersSavedAlbumsRequest.java (95%) rename src/main/java/se/michaelthelin/spotify/requests/data/albums/{GetAlbumsTracksRequest.java => GetAlbumTracksRequest.java} (80%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{library/GetCurrentUsersSavedAlbumsRequest.java => albums/GetUsersSavedAlbumsRequest.java} (76%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSeveralBrowseCategoriesRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSingleBrowseCategoryRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{library => episodes}/CheckUsersSavedEpisodesRequest.java (95%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{library => episodes}/GetUsersSavedEpisodesRequest.java (97%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequest.java delete mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequest.java delete mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/UnfollowPlaylistRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{browse/miscellaneous/GetAvailableGenreSeedsRequest.java => genres/GetRecommendationGenresRequest.java} (67%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedItemsRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/library/{RemoveFromLibraryRequest.java => RemoveItemsFromLibraryRequest.java} (75%) rename src/main/java/se/michaelthelin/spotify/requests/data/library/{SaveToLibraryRequest.java => SaveItemsToLibraryRequest.java} (76%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/player/{AddItemToUsersPlaybackQueueRequest.java => AddItemToPlaybackQueueRequest.java} (76%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{GetUsersAvailableDevicesRequest.java => GetAvailableDevicesRequest.java} (71%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{GetUsersCurrentlyPlayingTrackRequest.java => GetCurrentlyPlayingTrackRequest.java} (75%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{GetInformationAboutUsersCurrentPlaybackRequest.java => GetPlaybackStateRequest.java} (75%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{GetCurrentUsersRecentlyPlayedTracksRequest.java => GetRecentlyPlayedTracksRequest.java} (79%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{GetTheUsersQueueRequest.java => GetUsersQueueRequest.java} (75%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{PauseUsersPlaybackRequest.java => PausePlaybackRequest.java} (76%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{SeekToPositionInCurrentlyPlayingTrackRequest.java => SeekToPositionRequest.java} (74%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{SetVolumeForUsersPlaybackRequest.java => SetPlaybackVolumeRequest.java} (76%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{SetRepeatModeOnUsersPlaybackRequest.java => SetRepeatModeRequest.java} (76%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{SkipUsersPlaybackToNextTrackRequest.java => SkipToNextRequest.java} (74%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{SkipUsersPlaybackToPreviousTrackRequest.java => SkipToPreviousRequest.java} (73%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{StartResumeUsersPlaybackRequest.java => StartResumePlaybackRequest.java} (83%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{ToggleShuffleForUsersPlaybackRequest.java => TogglePlaybackShuffleRequest.java} (74%) rename src/main/java/se/michaelthelin/spotify/requests/data/player/{TransferUsersPlaybackRequest.java => TransferPlaybackRequest.java} (78%) rename src/main/java/se/michaelthelin/spotify/requests/data/playlists/{UploadCustomPlaylistCoverImageRequest.java => AddCustomPlaylistCoverImageRequest.java} (76%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistDeprecatedRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/playlists/{ChangePlaylistsDetailsRequest.java => ChangePlaylistDetailsRequest.java} (79%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistForUserRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{browse/GetCategorysPlaylistsRequest.java => playlists/GetCategoryPlaylistsRequest.java} (75%) rename src/main/java/se/michaelthelin/spotify/requests/data/playlists/{GetListOfCurrentUsersPlaylistsRequest.java => GetCurrentUsersPlaylistsRequest.java} (77%) rename src/main/java/se/michaelthelin/spotify/requests/data/{browse/GetListOfFeaturedPlaylistsRequest.java => playlists/GetFeaturedPlaylistsRequest.java} (82%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistItemsDeprecatedRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/playlists/{GetPlaylistsItemsRequest.java => GetPlaylistItemsRequest.java} (81%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemovePlaylistItemsDeprecatedRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/playlists/{RemoveItemsFromPlaylistRequest.java => RemovePlaylistItemsRequest.java} (84%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReorderDeprecatedRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/playlists/{ReorderPlaylistsItemsRequest.java => UpdatePlaylistsItemsReorderRequest.java} (80%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReplaceDeprecatedRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/playlists/{ReplacePlaylistsItemsRequest.java => UpdatePlaylistsItemsReplaceRequest.java} (78%) rename src/main/java/se/michaelthelin/spotify/requests/data/search/{SearchItemRequest.java => SearchForItemRequest.java} (82%) rename src/main/java/se/michaelthelin/spotify/requests/data/{library => shows}/CheckUsersSavedShowsRequest.java (95%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/shows/{GetShowsEpisodesRequest.java => GetShowEpisodesRequest.java} (82%) rename src/main/java/se/michaelthelin/spotify/requests/data/{library => shows}/GetUsersSavedShowsRequest.java (98%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/shows/RemoveShowsForCurrentUserRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{library => tracks}/CheckUsersSavedTracksRequest.java (95%) rename src/main/java/se/michaelthelin/spotify/requests/data/{browse => tracks}/GetRecommendationsRequest.java (99%) rename src/main/java/se/michaelthelin/spotify/requests/data/tracks/{GetAudioFeaturesForSeveralTracksRequest.java => GetSeveralTracksAudioFeaturesRequest.java} (69%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/tracks/{GetAudioAnalysisForTrackRequest.java => GetTracksAudioAnalysisRequest.java} (70%) rename src/main/java/se/michaelthelin/spotify/requests/data/tracks/{GetAudioFeaturesForTrackRequest.java => GetTracksAudioFeaturesRequest.java} (70%) rename src/main/java/se/michaelthelin/spotify/requests/data/{library => tracks}/GetUsersSavedTracksRequest.java (98%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/tracks/RemoveUsersSavedTracksRequest.java create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{follow => users}/CheckCurrentUserFollowsArtistsOrUsersRequest.java (96%) rename src/main/java/se/michaelthelin/spotify/requests/data/{follow/CheckUsersFollowPlaylistRequest.java => users/CheckIfUserFollowsPlaylistRequest.java} (67%) rename src/main/java/se/michaelthelin/spotify/requests/data/{follow => users}/FollowArtistsOrUsersRequest.java (96%) rename src/main/java/se/michaelthelin/spotify/requests/data/{follow => users}/FollowPlaylistRequest.java (96%) rename src/main/java/se/michaelthelin/spotify/requests/data/{users_profile => users}/GetCurrentUsersProfileRequest.java (97%) rename src/main/java/se/michaelthelin/spotify/requests/data/{follow/GetUsersFollowedArtistsRequest.java => users/GetFollowedArtistsRequest.java} (76%) create mode 100644 src/main/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequest.java rename src/main/java/se/michaelthelin/spotify/requests/data/{personalization => users}/GetUsersTopArtistsAndTracksRequest.java (94%) rename src/main/java/se/michaelthelin/spotify/requests/data/{follow => users}/UnfollowArtistsOrUsersRequest.java (96%) rename src/main/java/se/michaelthelin/spotify/requests/data/{follow => users}/UnfollowPlaylistRequest.java (95%) rename src/main/java/se/michaelthelin/spotify/requests/data/{personalization => users}/interfaces/IArtistTrackModelObject.java (81%) rename src/main/java/se/michaelthelin/spotify/requests/data/{personalization => users}/simplified/GetUsersTopArtistsRequest.java (98%) rename src/main/java/se/michaelthelin/spotify/requests/data/{personalization => users}/simplified/GetUsersTopTracksRequest.java (98%) create mode 100644 src/test/fixtures/open-api-schema.yaml rename src/test/fixtures/requests/data/{library => albums}/CheckUsersSavedAlbumsRequest.json (100%) create mode 100644 src/test/fixtures/requests/data/albums/GetNewReleasesRequest.json create mode 100644 src/test/fixtures/requests/data/albums/GetSeveralAlbumsRequest.json rename src/test/fixtures/requests/data/{library/GetCurrentUsersSavedAlbumsRequest.json => albums/GetUsersSavedAlbumsRequest.json} (100%) create mode 100644 src/test/fixtures/requests/data/albums/RemoveAlbumsForCurrentUserRequest.json create mode 100644 src/test/fixtures/requests/data/albums/SaveAlbumsForCurrentUserRequest.json create mode 100644 src/test/fixtures/requests/data/artists/GetArtistsTopTracksRequest.json create mode 100644 src/test/fixtures/requests/data/artists/GetSeveralArtistsRequest.json rename src/test/fixtures/requests/data/{library/CheckUsersSavedEpisodesRequest.json => audiobooks/CheckUsersSavedAudiobooksRequest.json} (100%) create mode 100644 src/test/fixtures/requests/data/audiobooks/GetAudiobookChaptersRequest.json create mode 100644 src/test/fixtures/requests/data/audiobooks/GetAudiobookRequest.json create mode 100644 src/test/fixtures/requests/data/audiobooks/GetSeveralAudiobooksRequest.json create mode 100644 src/test/fixtures/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.json create mode 100644 src/test/fixtures/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.json create mode 100644 src/test/fixtures/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.json create mode 100644 src/test/fixtures/requests/data/categories/GetCategoriesRequest.json create mode 100644 src/test/fixtures/requests/data/categories/GetCategoryRequest.json create mode 100644 src/test/fixtures/requests/data/chapters/GetChapterRequest.json create mode 100644 src/test/fixtures/requests/data/chapters/GetSeveralChaptersRequest.json create mode 100644 src/test/fixtures/requests/data/episodes/CheckUsersSavedEpisodesRequest.json create mode 100644 src/test/fixtures/requests/data/episodes/GetSeveralEpisodesRequest.json rename src/test/fixtures/requests/data/{library => episodes}/GetUsersSavedEpisodesRequest.json (100%) create mode 100644 src/test/fixtures/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.json create mode 100644 src/test/fixtures/requests/data/episodes/SaveEpisodesForCurrentUserRequest.json rename src/test/fixtures/requests/data/{browse/miscellaneous/GetAvailableGenreSeedsRequest.json => genres/GetRecommendationGenresRequest.json} (100%) create mode 100644 src/test/fixtures/requests/data/library/CheckLibraryContainsRequest.json create mode 100644 src/test/fixtures/requests/data/markets/GetAvailableMarketsRequest.json rename src/test/fixtures/requests/data/player/{GetTheUsersQueueRequest.json => GetQueueRequest.json} (100%) rename src/test/fixtures/requests/data/player/{GetCurrentUsersRecentlyPlayedTracksRequest.json => GetRecentlyPlayedRequest.json} (100%) create mode 100644 src/test/fixtures/requests/data/playlists/CreatePlaylistForUserRequest.json rename src/test/fixtures/requests/data/{browse/GetCategorysPlaylistsRequest.json => playlists/GetCategoryPlaylistsRequest.json} (100%) rename src/test/fixtures/requests/data/{browse/GetListOfFeaturedPlaylistsRequest.json => playlists/GetFeaturedPlaylistsRequest.json} (100%) rename src/test/fixtures/requests/data/playlists/{GetListOfUsersPlaylistsRequest_UserWith$.json => GetListUsersPlaylistsRequest.json} (100%) create mode 100644 src/test/fixtures/requests/data/playlists/GetListUsersPlaylistsRequest_UserWith$.json rename src/test/fixtures/requests/data/playlists/{GetPlaylistCoverImageRequest.json => GetPlaylistCoverRequest.json} (100%) create mode 100644 src/test/fixtures/requests/data/playlists/RemoveItemsPlaylistRequest.json create mode 100644 src/test/fixtures/requests/data/playlists/ReplacePlaylistsItemsRequest.json rename src/test/fixtures/requests/data/search/{SearchItemRequest.json => SearchRequest.json} (100%) rename src/test/fixtures/requests/data/{library => shows}/CheckUsersSavedShowsRequest.json (100%) create mode 100644 src/test/fixtures/requests/data/shows/GetSeveralShowsRequest.json rename src/test/fixtures/requests/data/{library => shows}/GetUsersSavedShowsRequest.json (100%) create mode 100644 src/test/fixtures/requests/data/shows/RemoveShowsForCurrentUserRequest.json create mode 100644 src/test/fixtures/requests/data/shows/SaveShowsForCurrentUserRequest.json rename src/test/fixtures/requests/data/{library => tracks}/CheckUsersSavedTracksRequest.json (100%) rename src/test/fixtures/requests/data/tracks/{GetAudioAnalysisForTrackRequest.json => GetAudioAnalysisRequest.json} (100%) rename src/test/fixtures/requests/data/tracks/{GetAudioFeaturesForTrackRequest.json => GetAudioFeaturesRequest.json} (100%) rename src/test/fixtures/requests/data/{browse => tracks}/GetRecommendationsRequest.json (100%) rename src/test/fixtures/requests/data/tracks/{GetAudioFeaturesForSeveralTracksRequest.json => GetSeveralAudioFeaturesRequest.json} (100%) create mode 100644 src/test/fixtures/requests/data/tracks/GetSeveralTracksRequest.json rename src/test/fixtures/requests/data/{library => tracks}/GetUsersSavedTracksRequest.json (100%) create mode 100644 src/test/fixtures/requests/data/tracks/RemoveTracksForCurrentUserRequest.json create mode 100644 src/test/fixtures/requests/data/tracks/SaveTracksForCurrentUserRequest.json rename src/test/fixtures/requests/data/{follow => users}/CheckCurrentUserFollowsArtistsOrUsersRequest.json (100%) rename src/test/fixtures/requests/data/{follow/CheckUsersFollowPlaylistRequest.json => users/CheckIfUserFollowsPlaylistRequest.json} (100%) rename src/test/fixtures/requests/data/{users_profile => users}/GetCurrentUsersProfileRequest.json (100%) rename src/test/fixtures/requests/data/{follow/GetUsersFollowedArtistsRequest.json => users/GetFollowedRequest.json} (100%) rename src/test/fixtures/requests/data/{follow/GetUsersFollowedArtistsRequest_None.json => users/GetFollowedRequest_None.json} (100%) create mode 100644 src/test/fixtures/requests/data/users/GetUsersProfileRequest.json rename src/test/fixtures/requests/data/{personalization => users}/simplified/GetUsersTopArtistsRequest.json (100%) rename src/test/fixtures/requests/data/{personalization => users}/simplified/GetUsersTopTracksRequest.json (100%) rename src/test/java/se/michaelthelin/spotify/requests/data/{library => albums}/CheckUsersSavedAlbumsRequestTest.java (90%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{library/GetCurrentUsersSavedAlbumsRequestTest.java => albums/GetUsersSavedAlbumsRequestTest.java} (83%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoriesRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoryRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{library => episodes}/CheckUsersSavedEpisodesRequestTest.java (90%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{library => episodes}/GetUsersSavedEpisodesRequestTest.java (95%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/episodes/RemoveEpisodesForCurrentUserRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequestTest.java delete mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{browse/miscellaneous/GetAvailableGenreSeedsRequestTest.java => genres/GetRecommendationGenresRequestTest.java} (74%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/library/CheckLibraryContainsRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/library/{RemoveFromLibraryRequestTest.java => RemoveLibraryItemsRequestTest.java} (83%) rename src/test/java/se/michaelthelin/spotify/requests/data/library/{SaveToLibraryRequestTest.java => SaveLibraryItemsRequestTest.java} (84%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/player/{AddItemToUsersPlaybackQueueRequestTest.java => AddToQueueRequestTest.java} (82%) rename src/test/java/se/michaelthelin/spotify/requests/data/player/{GetTheUsersQueueRequestTest.java => GetQueueRequestTest.java} (87%) rename src/test/java/se/michaelthelin/spotify/requests/data/player/{GetCurrentUsersRecentlyPlayedTracksRequestTest.java => GetRecentlyPlayedRequestTest.java} (84%) rename src/test/java/se/michaelthelin/spotify/requests/data/player/{StartResumeUsersPlaybackRequestNumericTest.java => StartUsersPlaybackRequestNumericTest.java} (87%) rename src/test/java/se/michaelthelin/spotify/requests/data/player/{StartResumeUsersPlaybackRequestTest.java => StartUsersPlaybackRequestTest.java} (88%) rename src/test/java/se/michaelthelin/spotify/requests/data/playlists/{UploadCustomPlaylistCoverImageRequestTest.java => AddCustomPlaylistCoverImageRequestTest.java} (84%) rename src/test/java/se/michaelthelin/spotify/requests/data/playlists/{ReplacePlaylistsItemsRequestTest.java => AddItemsToPlaylistDeprecatedRequestTest.java} (55%) rename src/test/java/se/michaelthelin/spotify/requests/data/playlists/{ChangePlaylistsDetailsRequestTest.java => ChangePlaylistDetailsRequestTest.java} (88%) rename src/test/java/se/michaelthelin/spotify/requests/data/playlists/{RemoveItemsFromPlaylistRequestTest.java => CreatePlaylistForUserRequestTest.java} (55%) rename src/test/java/se/michaelthelin/spotify/requests/data/{browse/GetCategorysPlaylistRequestTest.java => playlists/GetCategoryPlaylistsRequestTest.java} (84%) rename src/test/java/se/michaelthelin/spotify/requests/data/playlists/{GetListOfCurrentUsersPlaylistsRequestTest.java => GetCurrentUsersPlaylistsRequestTest.java} (87%) rename src/test/java/se/michaelthelin/spotify/requests/data/{browse/GetListOfFeaturedPlaylistsRequestTest.java => playlists/GetFeaturedPlaylistsRequestTest.java} (79%) delete mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistsItemsRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequestTest.java delete mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/playlists/ReorderPlaylistsItemsRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/search/{SearchItemRequestTest.java => SearchRequestTest.java} (86%) rename src/test/java/se/michaelthelin/spotify/requests/data/{library => shows}/CheckUsersSavedShowsRequestTest.java (90%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{library => shows}/GetUsersSavedShowsRequestTest.java (94%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/shows/RemoveShowsForCurrentUserRequestTest.java create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{library => tracks}/CheckUsersSavedTracksRequestTest.java (90%) rename src/test/java/se/michaelthelin/spotify/requests/data/tracks/{GetAudioAnalysisForTrackRequestTest.java => GetAudioAnalysisRequestTest.java} (84%) rename src/test/java/se/michaelthelin/spotify/requests/data/tracks/{GetAudioFeaturesForTrackRequestTest.java => GetAudioFeaturesRequestTest.java} (88%) rename src/test/java/se/michaelthelin/spotify/requests/data/{browse => tracks}/GetRecommendationsRequestTest.java (92%) rename src/test/java/se/michaelthelin/spotify/requests/data/tracks/{GetAudioFeaturesForSeveralTracksRequestTest.java => GetSeveralAudioFeaturesRequestTest.java} (77%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{library => tracks}/GetUsersSavedTracksRequestTest.java (94%) rename src/test/java/se/michaelthelin/spotify/requests/data/{follow/legacy/UnfollowPlaylistRequestTest.java => tracks/RemoveTracksForCurrentUserRequestTest.java} (71%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{follow => users}/CheckCurrentUserFollowsArtistsOrUsersRequestTest.java (90%) rename src/test/java/se/michaelthelin/spotify/requests/data/{follow/CheckUsersFollowPlaylistRequestTest.java => users/CheckIfUserFollowsPlaylistRequestTest.java} (73%) rename src/test/java/se/michaelthelin/spotify/requests/data/{follow => users}/FollowArtistsOrUsersRequestTest.java (96%) rename src/test/java/se/michaelthelin/spotify/requests/data/{follow => users}/FollowPlaylistRequestTest.java (95%) rename src/test/java/se/michaelthelin/spotify/requests/data/{users_profile => users}/GetCurrentUsersProfileRequestTest.java (93%) rename src/test/java/se/michaelthelin/spotify/requests/data/{follow/GetUsersFollowedArtistsRequestTest.java => users/GetFollowedRequestTest.java} (83%) create mode 100644 src/test/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequestTest.java rename src/test/java/se/michaelthelin/spotify/requests/data/{follow => users}/UnfollowArtistsOrUsersRequestTest.java (96%) rename src/test/java/se/michaelthelin/spotify/requests/data/{follow => users}/UnfollowPlaylistRequestTest.java (94%) rename src/test/java/se/michaelthelin/spotify/requests/data/{personalization => users}/simplified/GetUsersTopArtistsRequestTest.java (93%) rename src/test/java/se/michaelthelin/spotify/requests/data/{personalization => users}/simplified/GetUsersTopTracksRequestTest.java (93%) diff --git a/README.md b/README.md index 1ff840f5f..0f735f3d1 100644 --- a/README.md +++ b/README.md @@ -222,132 +222,134 @@ access token only once, after which it becomes invalid. ## Examples + +> **Deprecated** examples are marked with ⚠️ and will be removed in v11.0. See [MIGRATION.md](MIGRATION.md) for alternatives. + - **Albums** - [Get an Album](examples/data/albums/GetAlbumExample.java) - [Get an Album's Tracks](examples/data/albums/GetAlbumsTracksExample.java) - - [Get several Albums](examples/data/albums/GetSeveralAlbumsExample.java) + - [Check User's Saved Albums](examples/data/albums/CheckUsersSavedAlbumsExample.java) + - [Get Current User's Saved Albums](examples/data/albums/GetCurrentUsersSavedAlbumsExample.java) - **Artists** - [Get an Artist](examples/data/artists/GetArtistExample.java) - [Get an Artist's Albums](examples/data/artists/GetArtistsAlbumsExample.java) - - [Get an Artist's Top Tracks](examples/data/artists/GetArtistsTopTracksExample.java) - [Get an Artist's Related Artists](examples/data/artists/GetArtistsRelatedArtistsExample.java) - - [Get Several Artists](examples/data/artists/GetSeveralArtistsExample.java) + - ⚠️ [Get an Artist's Top Tracks](examples/data/artists/) — deprecated; use search instead + + +- **Audiobooks** + - [Get an Audiobook](examples/data/audiobooks/GetAudiobookExample.java) + - [Get an Audiobook's Chapters](examples/data/audiobooks/GetAudiobookChaptersExample.java) + - ⚠️ [Get Several Audiobooks](examples/data/audiobooks/GetSeveralAudiobooksExample.java) + - ⚠️ [Get User's Saved Audiobooks](examples/data/audiobooks/GetUsersSavedAudiobooksExample.java) + - ⚠️ [Check User's Saved Audiobooks](examples/data/audiobooks/CheckUsersSavedAudiobooksExample.java) + - ⚠️ [Save Audiobooks for Current User](examples/data/audiobooks/SaveAudiobooksForCurrentUserExample.java) + - ⚠️ [Remove Audiobooks for Current User](examples/data/audiobooks/RemoveAudiobooksForCurrentUserExample.java) + + +- **Browsing & Discovery** + - [Get Available Genre Seeds](examples/data/genres/GetAvailableGenreSeedsExample.java) + - ⚠️ [Get Categories](examples/data/categories/GetSeveralBrowseCategoriesExample.java) + - ⚠️ [Get a Category](examples/data/categories/GetSingleBrowseCategoryExample.java) + - ⚠️ [Get a Category's Playlists](examples/data/playlists/GetCategoryPlaylistsExample.java) + - ⚠️ [Get Featured Playlists](examples/data/playlists/GetFeaturedPlaylistsExample.java) + - ⚠️ [Get Available Markets](examples/data/markets/GetAvailableMarketsExample.java) -- **Browse** - - Miscellaneous - - [Get Available Genre Seeds](examples/data/browse/miscellaneous/GetAvailableGenreSeedsExample.java) - - [Get a Category](examples/data/browse/GetCategoryExample.java) - - [Get a Category's Playlists](examples/data/browse/GetCategorysPlaylistsExample.java) - - [Get a List of Categories](examples/data/browse/GetListOfCategoriesExample.java) - - [Get a List of Featured Playlists](examples/data/browse/GetListOfFeaturedPlaylistsExample.java) - - [Get a List of New Releases](examples/data/browse/GetListOfNewReleasesExample.java) - - [Get Recommendations](examples/data/browse/GetRecommendationsExample.java) +- **Chapters** + - [Get a Chapter](examples/data/chapters/GetChapterExample.java) + - ⚠️ [Get Several Chapters](examples/data/chapters/GetSeveralChaptersExample.java) - **Episodes** - [Get an Episode](examples/data/episodes/GetEpisodeExample.java) - - [Get several Episodes](examples/data/episodes/GetSeveralEpisodesExample.java) - - -- **Follow** - - [Check if Current User Follows Artists or Users](examples/data/follow/CheckCurrentUserFollowsArtistsOrUsersExample.java) - - [Check if Users Follow a Playlist](examples/data/follow/CheckUsersFollowPlaylistExample.java) - - [Follow Artists or Users](examples/data/follow/FollowArtistsOrUsersExample.java) - - [Follow a Playlist](examples/data/follow/FollowPlaylistExample.java) - - [Get User's Followed Artists](examples/data/follow/GetUsersFollowedArtistsExample.java) - - [Unfollow Artists or Users](examples/data/follow/UnfollowArtistsOrUsersExample.java) - - [Unfollow a Playlist](examples/data/follow/UnfollowPlaylistExample.java) - - -- **Library** - - [Check User's Saved Albums](examples/data/library/CheckUsersSavedAlbumsExample.java) - - [Check User's Saved Episodes](examples/data/library/CheckUsersSavedEpisodesExample.java) - - [Check User's Saved Shows](examples/data/library/CheckUsersSavedShowsExample.java) - - [Check User's Saved Tracks](examples/data/library/CheckUsersSavedTracksExample.java) - - [Get Current User's Saved Albums](examples/data/library/GetCurrentUsersSavedAlbumsExample.java) - - [Get User's Saved Episodes](examples/data/library/GetUsersSavedEpisodesExample.java) - - [Get User's Saved Shows](examples/data/library/GetUsersSavedShowsExample.java) - - [Get User's Saved Tracks](examples/data/library/GetUsersSavedTracksExample.java) - - [Remove Albums for Current User](examples/data/library/RemoveAlbumsForCurrentUserExample.java) - - [Remove User's Saved Episodes](examples/data/library/RemoveUsersSavedEpisodesExample.java) - - [Remove User's Saved Shows](examples/data/library/RemoveUsersSavedShowsExample.java) - - [Remove User's Saved Tracks](examples/data/library/RemoveUsersSavedTracksExample.java) - - [Save Albums for Current User](examples/data/library/SaveAlbumsForCurrentUserExample.java) - - [Save Episodes for Current User](examples/data/library/SaveEpisodesForCurrentUserExample.java) - - [Save Shows for Current User](examples/data/library/SaveShowsForCurrentUserExample.java) - - [Save Tracks for User](examples/data/library/SaveTracksForUserExample.java) + - [Check User's Saved Episodes](examples/data/episodes/CheckUsersSavedEpisodesExample.java) + - [Get User's Saved Episodes](examples/data/episodes/GetUsersSavedEpisodesExample.java) + + +- **Library (Unified Save/Remove/Check API)** + - [Save Items to Library](examples/data/library/SaveToLibraryExample.java) + - [Remove Items from Library](examples/data/library/RemoveFromLibraryExample.java) - **Personalization** + - [Get a User's Top Artists and Tracks](examples/data/users/GetUsersTopArtistsAndTracksExample.java) - Simplified - - [Get a User's Top Artists](examples/data/personalization/simplified/GetUsersTopArtistsExample.java) - - [Get a User's Top Tracks](examples/data/personalization/simplified/GetUsersTopTracksExample.java) - - [Get a User's Top Artists and Tracks](examples/data/personalization/GetUsersTopArtistsAndTracksExample.java) + - [Get a User's Top Artists](examples/data/users/simplified/GetUsersTopArtistsExample.java) + - [Get a User's Top Tracks](examples/data/users/simplified/GetUsersTopTracksExample.java) - **Player** - - [Add Item to User's Playback Queue](examples/data/player/AddItemToUsersPlaybackQueueExample.java) - - [Get a User's Available Devices](examples/data/player/GetUsersAvailableDevicesExample.java) - - [Get Information About The User's Current Playback](examples/data/player/GetInformationAboutUsersCurrentPlaybackExample.java) - - [Get Current User's Recently Played Tracks](examples/data/player/GetCurrentUsersRecentlyPlayedTracksExample.java) - - [Get the User's Currently Playing Track](examples/data/player/GetUsersCurrentlyPlayingTrackExample.java) - - [Pause a User's Playback](examples/data/player/PauseUsersPlaybackExample.java) - - [Seek To Position In Currently Playing Track](examples/data/player/SeekToPositionInCurrentlyPlayingTrackExample.java) - - [Set Repeat Mode On User's Playback](examples/data/player/SetRepeatModeOnUsersPlaybackExample.java) - - [Set Volume For User's Playback](examples/data/player/SetVolumeForUsersPlaybackExample.java) - - [Skip User's Playback To Next Track](examples/data/player/SkipUsersPlaybackToNextTrackExample.java) - - [Skip User's Playback To Previous Track](examples/data/player/SkipUsersPlaybackToPreviousTrackExample.java) - - [Start/Resume a User's Playback](examples/data/player/StartResumeUsersPlaybackExample.java) - - [Toggle Shuffle For User's Playback](examples/data/player/ToggleShuffleForUsersPlaybackExample.java) - - [Transfer a User's Playback](examples/data/player/TransferUsersPlaybackExample.java) + - [Get Available Devices](examples/data/player/GetUsersAvailableDevicesExample.java) + - [Get Current Playback State](examples/data/player/GetInformationAboutUsersCurrentPlaybackExample.java) + - [Get Currently Playing Track](examples/data/player/GetUsersCurrentlyPlayingTrackExample.java) + - [Get Recently Played Tracks](examples/data/player/GetCurrentUsersRecentlyPlayedTracksExample.java) + - [Get User's Queue](examples/data/player/GetTheUsersQueueExample.java) + - [Start/Resume Playback](examples/data/player/StartResumeUsersPlaybackExample.java) + - [Pause Playback](examples/data/player/PauseUsersPlaybackExample.java) + - [Skip to Next Track](examples/data/player/SkipUsersPlaybackToNextTrackExample.java) + - [Skip to Previous Track](examples/data/player/SkipUsersPlaybackToPreviousTrackExample.java) + - [Seek to Position](examples/data/player/SeekToPositionInCurrentlyPlayingTrackExample.java) + - [Set Repeat Mode](examples/data/player/SetRepeatModeOnUsersPlaybackExample.java) + - [Toggle Shuffle](examples/data/player/ToggleShuffleForUsersPlaybackExample.java) + - [Set Volume](examples/data/player/SetVolumeForUsersPlaybackExample.java) + - [Transfer Playback](examples/data/player/TransferUsersPlaybackExample.java) + - [Add Item to Queue](examples/data/player/AddItemToUsersPlaybackQueueExample.java) - **Playlists** - - [Add Items to a Playlist](examples/data/playlists/AddItemsToPlaylistExample.java) - - [Change a Playlist's Details](examples/data/playlists/ChangePlaylistsDetailsExample.java) - - [Create a Playlist](examples/data/playlists/CreatePlaylistExample.java) - - [Get a List of Current User's Playlists](examples/data/playlists/GetListOfCurrentUsersPlaylistsExample.java) - - [Get a List of a User's Playlists](examples/data/playlists/GetListOfUsersPlaylistsExample.java) - [Get a Playlist](examples/data/playlists/GetPlaylistExample.java) - - [Get a Playlist Cover Image](examples/data/playlists/GetPlaylistCoverImageExample.java) + - [Get Current User's Playlists](examples/data/playlists/GetCurrentUsersPlaylistsExample.java) - [Get a Playlist's Items](examples/data/playlists/GetPlaylistsItemsExample.java) + - [Get a Playlist Cover Image](examples/data/playlists/GetPlaylistCoverImageExample.java) + - [Add Items to a Playlist](examples/data/playlists/AddItemsToPlaylistExample.java) - [Remove Items from a Playlist](examples/data/playlists/RemoveItemsFromPlaylistExample.java) - - [Reorder a Playlist's Items](examples/data/playlists/ReorderPlaylistsItemsExample.java) - - [Replace a Playlist's Items](examples/data/playlists/ReplacePlaylistsItemsExample.java) - - [Upload a Custom Playlist Cover Image](examples/data/playlists/UploadCustomPlaylistCoverImageExample.java) + - [Update Playlist Details](examples/data/playlists/ChangePlaylistsDetailsExample.java) + - [Reorder Playlist Items](examples/data/playlists/UpdatePlaylistsItemsReorderExample.java) + - [Replace Playlist Items](examples/data/playlists/UpdatePlaylistsItemsReplaceExample.java) + - [Upload Playlist Cover Image](examples/data/playlists/UploadCustomPlaylistCoverImageExample.java) + - ⚠️ [Add Items (Deprecated Format)](examples/data/playlists/AddItemsToPlaylistDeprecatedExample.java) - **Search** - - Simplified + - [Search for Item](examples/data/search/SearchItemExample.java) + - Simplified (Direct Type Search) - [Search Albums](examples/data/search/simplified/SearchAlbumsExample.java) - [Search Artists](examples/data/search/simplified/SearchArtistsExample.java) + - [Search Tracks](examples/data/search/simplified/SearchTracksExample.java) + - [Search Shows](examples/data/search/simplified/SearchShowsExample.java) - [Search Episodes](examples/data/search/simplified/SearchEpisodesExample.java) - [Search Playlists](examples/data/search/simplified/SearchPlaylistsExample.java) - - [Search Shows](examples/data/search/simplified/SearchShowsExample.java) - - [Search Tracks](examples/data/search/simplified/SearchTracksExample.java) - - [Search Item](examples/data/search/SearchItemExample.java) - **Shows** - [Get a Show](examples/data/shows/GetShowExample.java) - - [Get several Show](examples/data/shows/GetSeveralShowsExample.java) - [Get a Show's Episodes](examples/data/shows/GetShowsEpisodesExample.java) + - [Check User's Saved Shows](examples/data/shows/CheckUsersSavedShowsExample.java) + - [Get User's Saved Shows](examples/data/shows/GetUsersSavedShowsExample.java) - **Tracks** - - [Get Audio Analysis for a Track](examples/data/tracks/GetAudioAnalysisForTrackExample.java) + - [Get a Track](examples/data/tracks/GetTrackExample.java) + - [Check User's Saved Tracks](examples/data/tracks/CheckUsersSavedTracksExample.java) + - [Get User's Saved Tracks](examples/data/tracks/GetUsersSavedTracksExample.java) - [Get Audio Features for a Track](examples/data/tracks/GetAudioFeaturesForTrackExample.java) - [Get Audio Features for Several Tracks](examples/data/tracks/GetAudioFeaturesForSeveralTracksExample.java) - - [Get Several Tracks](examples/data/tracks/GetSeveralTracksExample.java) - - [Get a Track](examples/data/tracks/GetTrackExample.java) - - -- **User's Profile** - - [Get Current User's Profile](examples/data/users_profile/GetCurrentUsersProfileExample.java) - - [Get a User's Profile](examples/data/users_profile/GetUsersProfileExample.java) + - [Get Audio Analysis for a Track](examples/data/tracks/GetAudioAnalysisForTrackExample.java) + - [Get Recommendations](examples/data/tracks/GetRecommendationsExample.java) + + +- **User's Profile & Following** + - [Get Current User's Profile](examples/data/users/GetCurrentUsersProfileExample.java) + - ⚠️ [Get User's Followed Artists](examples/data/users/GetUsersFollowedArtistsExample.java) + - ⚠️ [Follow Artists or Users](examples/data/users/FollowArtistsOrUsersExample.java) + - ⚠️ [Unfollow Artists or Users](examples/data/users/UnfollowArtistsOrUsersExample.java) + - ⚠️ [Check if User Follows Artists or Users](examples/data/users/CheckCurrentUserFollowsArtistsOrUsersExample.java) + - ⚠️ [Follow a Playlist](examples/data/users/FollowPlaylistExample.java) + - ⚠️ [Unfollow a Playlist](examples/data/users/UnfollowPlaylistExample.java) + - ⚠️ [Check if Users Follow a Playlist](examples/data/users/CheckUsersFollowPlaylistExample.java) ## Contributions See [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/examples/data/library/CheckUsersSavedAlbumsExample.java b/examples/data/albums/CheckUsersSavedAlbumsExample.java similarity index 94% rename from examples/data/library/CheckUsersSavedAlbumsExample.java rename to examples/data/albums/CheckUsersSavedAlbumsExample.java index 33bdc724d..daa3afa7d 100644 --- a/examples/data/library/CheckUsersSavedAlbumsExample.java +++ b/examples/data/albums/CheckUsersSavedAlbumsExample.java @@ -1,8 +1,9 @@ -package data.library; +package data.albums; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.library.CheckUsersSavedAlbumsRequest; +import se.michaelthelin.spotify.requests.data.albums.CheckUsersSavedAlbumsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/albums/GetAlbumsTracksExample.java b/examples/data/albums/GetAlbumsTracksExample.java index 4a859e643..810603973 100644 --- a/examples/data/albums/GetAlbumsTracksExample.java +++ b/examples/data/albums/GetAlbumsTracksExample.java @@ -4,7 +4,7 @@ import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.TrackSimplified; -import se.michaelthelin.spotify.requests.data.albums.GetAlbumsTracksRequest; +import se.michaelthelin.spotify.requests.data.albums.GetAlbumTracksRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -19,7 +19,7 @@ public class GetAlbumsTracksExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetAlbumsTracksRequest getAlbumsTracksRequest = spotifyApi.getAlbumsTracks(id) + private static final GetAlbumTracksRequest getAlbumsTracksRequest = spotifyApi.getAlbumTracks(id) // .limit(10) // .offset(0) // .market(CountryCode.SE) diff --git a/examples/data/library/GetCurrentUsersSavedAlbumsExample.java b/examples/data/albums/GetCurrentUsersSavedAlbumsExample.java similarity index 74% rename from examples/data/library/GetCurrentUsersSavedAlbumsExample.java rename to examples/data/albums/GetCurrentUsersSavedAlbumsExample.java index 1c49a2b1c..71c6d31ba 100644 --- a/examples/data/library/GetCurrentUsersSavedAlbumsExample.java +++ b/examples/data/albums/GetCurrentUsersSavedAlbumsExample.java @@ -1,10 +1,11 @@ -package data.library; +package data.albums; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.SavedAlbum; -import se.michaelthelin.spotify.requests.data.library.GetCurrentUsersSavedAlbumsRequest; +import se.michaelthelin.spotify.requests.data.albums.GetUsersSavedAlbumsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -18,16 +19,16 @@ public class GetCurrentUsersSavedAlbumsExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetCurrentUsersSavedAlbumsRequest getCurrentUsersSavedAlbumsRequest = spotifyApi - .getCurrentUsersSavedAlbums() + private static final GetUsersSavedAlbumsRequest getUsersSavedAlbumsRequest = spotifyApi + .getUsersSavedAlbums() // .limit(10) // .market(CountryCode.SE) // .offset(0) .build(); - public static void getCurrentUsersSavedAlbums_Sync() { + public static void getUsersSavedAlbums_Sync() { try { - final Paging savedAlbumPaging = getCurrentUsersSavedAlbumsRequest.execute(); + final Paging savedAlbumPaging = getUsersSavedAlbumsRequest.execute(); System.out.println("Total: " + savedAlbumPaging.getTotal()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -35,9 +36,9 @@ public static void getCurrentUsersSavedAlbums_Sync() { } } - public static void getCurrentUsersSavedAlbums_Async() { + public static void getUsersSavedAlbums_Async() { try { - final CompletableFuture> pagingFuture = getCurrentUsersSavedAlbumsRequest.executeAsync(); + final CompletableFuture> pagingFuture = getUsersSavedAlbumsRequest.executeAsync(); // Thread free to do other tasks... @@ -53,7 +54,7 @@ public static void getCurrentUsersSavedAlbums_Async() { } public static void main(String[] args) { - getCurrentUsersSavedAlbums_Sync(); - getCurrentUsersSavedAlbums_Async(); + getUsersSavedAlbums_Sync(); + getUsersSavedAlbums_Async(); } } diff --git a/examples/data/audiobooks/CheckUsersSavedAudiobooksExample.java b/examples/data/audiobooks/CheckUsersSavedAudiobooksExample.java new file mode 100644 index 000000000..fdc699c2b --- /dev/null +++ b/examples/data/audiobooks/CheckUsersSavedAudiobooksExample.java @@ -0,0 +1,58 @@ +package data.audiobooks; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.audiobooks.CheckUsersSavedAudiobooksRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated Check if one or more audiobooks are already saved in the current Spotify user's library. + */ +@Deprecated +public class CheckUsersSavedAudiobooksExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String ids = "7iHfbu1YMWVo6aiRxbLrvT,2Takcwg7h193S42OLvM3c7"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final CheckUsersSavedAudiobooksRequest checkUsersSavedAudiobooksRequest = spotifyApi.checkUsersSavedAudiobooks(ids) + .build(); + + public static void checkUsersSavedAudiobooks_Sync() { + try { + final Boolean[] booleans = checkUsersSavedAudiobooksRequest.execute(); + + System.out.println("Number of results: " + booleans.length); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void checkUsersSavedAudiobooks_Async() { + try { + final CompletableFuture booleansFuture = checkUsersSavedAudiobooksRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Boolean[] booleans = booleansFuture.join(); + + System.out.println("Number of results: " + booleans.length); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + checkUsersSavedAudiobooks_Sync(); + checkUsersSavedAudiobooks_Async(); + } +} diff --git a/examples/data/audiobooks/GetAudiobookChaptersExample.java b/examples/data/audiobooks/GetAudiobookChaptersExample.java new file mode 100644 index 000000000..93f80e0c3 --- /dev/null +++ b/examples/data/audiobooks/GetAudiobookChaptersExample.java @@ -0,0 +1,59 @@ +package data.audiobooks; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.ChapterSimplified; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.audiobooks.GetAudiobookChaptersRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +public class GetAudiobookChaptersExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String id = "7iHfbu1YMWVo6aiRxbLrvT"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetAudiobookChaptersRequest getAudiobookChaptersRequest = spotifyApi.getAudiobookChapters(id) +// .market(CountryCode.US) +// .limit(10) +// .offset(0) + .build(); + + public static void getAudiobookChapters_Sync() { + try { + final Paging chapterPaging = getAudiobookChaptersRequest.execute(); + + System.out.println("Total: " + chapterPaging.getTotal()); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getAudiobookChapters_Async() { + try { + final CompletableFuture> chapterPagingFuture = getAudiobookChaptersRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Paging chapterPaging = chapterPagingFuture.join(); + + System.out.println("Total: " + chapterPaging.getTotal()); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getAudiobookChapters_Sync(); + getAudiobookChapters_Async(); + } +} diff --git a/examples/data/audiobooks/GetAudiobookExample.java b/examples/data/audiobooks/GetAudiobookExample.java new file mode 100644 index 000000000..5cf626052 --- /dev/null +++ b/examples/data/audiobooks/GetAudiobookExample.java @@ -0,0 +1,56 @@ +package data.audiobooks; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Audiobook; +import se.michaelthelin.spotify.requests.data.audiobooks.GetAudiobookRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +public class GetAudiobookExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String id = "7iHfbu1YMWVo6aiRxbLrvT"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetAudiobookRequest getAudiobookRequest = spotifyApi.getAudiobook(id) +// .market(CountryCode.US) + .build(); + + public static void getAudiobook_Sync() { + try { + final Audiobook audiobook = getAudiobookRequest.execute(); + + System.out.println("Name: " + audiobook.getName()); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getAudiobook_Async() { + try { + final CompletableFuture audiobookFuture = getAudiobookRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Audiobook audiobook = audiobookFuture.join(); + + System.out.println("Name: " + audiobook.getName()); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getAudiobook_Sync(); + getAudiobook_Async(); + } +} diff --git a/examples/data/audiobooks/GetSeveralAudiobooksExample.java b/examples/data/audiobooks/GetSeveralAudiobooksExample.java new file mode 100644 index 000000000..bfa5d1485 --- /dev/null +++ b/examples/data/audiobooks/GetSeveralAudiobooksExample.java @@ -0,0 +1,59 @@ +package data.audiobooks; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.AudiobookSimplified; +import se.michaelthelin.spotify.requests.data.audiobooks.GetSeveralAudiobooksRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated Get Spotify catalog information for several audiobooks identified by their Spotify IDs. + */ +@Deprecated +public class GetSeveralAudiobooksExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String ids = "7iHfbu1YMWVo6aiRxbLrvT,2Takcwg7h193S42OLvM3c7"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetSeveralAudiobooksRequest getSeveralAudiobooksRequest = spotifyApi.getSeveralAudiobooks(ids) + .build(); + + public static void getSeveralAudiobooks_Sync() { + try { + final AudiobookSimplified[] audiobooks = getSeveralAudiobooksRequest.execute(); + + System.out.println("Number of audiobooks: " + audiobooks.length); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getSeveralAudiobooks_Async() { + try { + final CompletableFuture audiobooksFuture = getSeveralAudiobooksRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final AudiobookSimplified[] audiobooks = audiobooksFuture.join(); + + System.out.println("Number of audiobooks: " + audiobooks.length); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getSeveralAudiobooks_Sync(); + getSeveralAudiobooks_Async(); + } +} diff --git a/examples/data/audiobooks/GetUsersSavedAudiobooksExample.java b/examples/data/audiobooks/GetUsersSavedAudiobooksExample.java new file mode 100644 index 000000000..1aaca5d57 --- /dev/null +++ b/examples/data/audiobooks/GetUsersSavedAudiobooksExample.java @@ -0,0 +1,61 @@ +package data.audiobooks; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.SavedAudiobook; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.audiobooks.GetUsersSavedAudiobooksRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated Get a list of the audiobooks saved in the current Spotify user's library. + */ +@Deprecated +public class GetUsersSavedAudiobooksExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetUsersSavedAudiobooksRequest getUsersSavedAudiobooksRequest = spotifyApi.getUsersSavedAudiobooks() +// .limit(10) +// .offset(0) + .build(); + + public static void getUsersSavedAudiobooks_Sync() { + try { + final Paging audiobookPaging = getUsersSavedAudiobooksRequest.execute(); + + System.out.println("Total: " + audiobookPaging.getTotal()); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getUsersSavedAudiobooks_Async() { + try { + final CompletableFuture> audiobookPagingFuture = getUsersSavedAudiobooksRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Paging audiobookPaging = audiobookPagingFuture.join(); + + System.out.println("Total: " + audiobookPaging.getTotal()); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getUsersSavedAudiobooks_Sync(); + getUsersSavedAudiobooks_Async(); + } +} diff --git a/examples/data/audiobooks/RemoveAudiobooksForCurrentUserExample.java b/examples/data/audiobooks/RemoveAudiobooksForCurrentUserExample.java new file mode 100644 index 000000000..1672b14eb --- /dev/null +++ b/examples/data/audiobooks/RemoveAudiobooksForCurrentUserExample.java @@ -0,0 +1,58 @@ +package data.audiobooks; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.audiobooks.RemoveAudiobooksForCurrentUserRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated Remove one or more audiobooks from the current Spotify user's library. + */ +@Deprecated +public class RemoveAudiobooksForCurrentUserExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String ids = "7iHfbu1YMWVo6aiRxbLrvT"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final RemoveAudiobooksForCurrentUserRequest removeAudiobooksForCurrentUserRequest = spotifyApi.removeAudiobooksForCurrentUser(ids) + .build(); + + public static void removeAudiobooksForCurrentUser_Sync() { + try { + final String string = removeAudiobooksForCurrentUserRequest.execute(); + + System.out.println("Null: " + (string == null)); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void removeAudiobooksForCurrentUser_Async() { + try { + final CompletableFuture stringFuture = removeAudiobooksForCurrentUserRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final String string = stringFuture.join(); + + System.out.println("Null: " + (string == null)); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + removeAudiobooksForCurrentUser_Sync(); + removeAudiobooksForCurrentUser_Async(); + } +} diff --git a/examples/data/audiobooks/SaveAudiobooksForCurrentUserExample.java b/examples/data/audiobooks/SaveAudiobooksForCurrentUserExample.java new file mode 100644 index 000000000..06c43d501 --- /dev/null +++ b/examples/data/audiobooks/SaveAudiobooksForCurrentUserExample.java @@ -0,0 +1,58 @@ +package data.audiobooks; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.audiobooks.SaveAudiobooksForCurrentUserRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated Save one or more audiobooks to the current Spotify user's library. + */ +@Deprecated +public class SaveAudiobooksForCurrentUserExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String ids = "7iHfbu1YMWVo6aiRxbLrvT"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final SaveAudiobooksForCurrentUserRequest saveAudiobooksForCurrentUserRequest = spotifyApi.saveAudiobooksForCurrentUser(ids) + .build(); + + public static void saveAudiobooksForCurrentUser_Sync() { + try { + final String string = saveAudiobooksForCurrentUserRequest.execute(); + + System.out.println("Null: " + (string == null)); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void saveAudiobooksForCurrentUser_Async() { + try { + final CompletableFuture stringFuture = saveAudiobooksForCurrentUserRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final String string = stringFuture.join(); + + System.out.println("Null: " + (string == null)); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + saveAudiobooksForCurrentUser_Sync(); + saveAudiobooksForCurrentUser_Async(); + } +} diff --git a/examples/data/categories/GetSeveralBrowseCategoriesExample.java b/examples/data/categories/GetSeveralBrowseCategoriesExample.java new file mode 100644 index 000000000..c646299f2 --- /dev/null +++ b/examples/data/categories/GetSeveralBrowseCategoriesExample.java @@ -0,0 +1,62 @@ +package data.categories; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Category; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.categories.GetSeveralBrowseCategoriesRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ +@Deprecated +public class GetSeveralBrowseCategoriesExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetSeveralBrowseCategoriesRequest getSeveralBrowseCategoriesRequest = spotifyApi.getSeveralBrowseCategories() +// .locale("sv_SE") +// .limit(10) +// .offset(0) + .build(); + + public static void getSeveralBrowseCategories_Sync() { + try { + final Paging categoryPaging = getSeveralBrowseCategoriesRequest.execute(); + + System.out.println("Total: " + categoryPaging.getTotal()); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getSeveralBrowseCategories_Async() { + try { + final CompletableFuture> categoryPagingFuture = getSeveralBrowseCategoriesRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Paging categoryPaging = categoryPagingFuture.join(); + + System.out.println("Total: " + categoryPaging.getTotal()); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getSeveralBrowseCategories_Sync(); + getSeveralBrowseCategories_Async(); + } +} diff --git a/examples/data/categories/GetSingleBrowseCategoryExample.java b/examples/data/categories/GetSingleBrowseCategoryExample.java new file mode 100644 index 000000000..514e17342 --- /dev/null +++ b/examples/data/categories/GetSingleBrowseCategoryExample.java @@ -0,0 +1,60 @@ +package data.categories; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Category; +import se.michaelthelin.spotify.requests.data.categories.GetSingleBrowseCategoryRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ +@Deprecated +public class GetSingleBrowseCategoryExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String categoryId = "dinner"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetSingleBrowseCategoryRequest getSingleBrowseCategoryRequest = spotifyApi.getSingleBrowseCategory(categoryId) +// .locale("sv_SE") + .build(); + + public static void getSingleBrowseCategory_Sync() { + try { + final Category category = getSingleBrowseCategoryRequest.execute(); + + System.out.println("Name: " + category.getName()); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getSingleBrowseCategory_Async() { + try { + final CompletableFuture categoryFuture = getSingleBrowseCategoryRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Category category = categoryFuture.join(); + + System.out.println("Name: " + category.getName()); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getSingleBrowseCategory_Sync(); + getSingleBrowseCategory_Async(); + } +} diff --git a/examples/data/chapters/GetChapterExample.java b/examples/data/chapters/GetChapterExample.java new file mode 100644 index 000000000..fb5fee15f --- /dev/null +++ b/examples/data/chapters/GetChapterExample.java @@ -0,0 +1,56 @@ +package data.chapters; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Chapter; +import se.michaelthelin.spotify.requests.data.chapters.GetChapterRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +public class GetChapterExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String id = "0D5wENF1pZcV7iSSUkxyQK"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetChapterRequest getChapterRequest = spotifyApi.getChapter(id) +// .market(CountryCode.US) + .build(); + + public static void getChapter_Sync() { + try { + final Chapter chapter = getChapterRequest.execute(); + + System.out.println("Name: " + chapter.getName()); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getChapter_Async() { + try { + final CompletableFuture chapterFuture = getChapterRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Chapter chapter = chapterFuture.join(); + + System.out.println("Name: " + chapter.getName()); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getChapter_Sync(); + getChapter_Async(); + } +} diff --git a/examples/data/chapters/GetSeveralChaptersExample.java b/examples/data/chapters/GetSeveralChaptersExample.java new file mode 100644 index 000000000..3c0fcb285 --- /dev/null +++ b/examples/data/chapters/GetSeveralChaptersExample.java @@ -0,0 +1,59 @@ +package data.chapters; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Chapter; +import se.michaelthelin.spotify.requests.data.chapters.GetSeveralChaptersRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated Get Spotify catalog information for several chapters identified by their Spotify IDs. + */ +@Deprecated +public class GetSeveralChaptersExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String ids = "0D5wENF1pZcV7iSSUkxyQK,0IsXCFLeyikOH6CLIZpnM7"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetSeveralChaptersRequest getSeveralChaptersRequest = spotifyApi.getSeveralChapters(ids) + .build(); + + public static void getSeveralChapters_Sync() { + try { + final Chapter[] chapters = getSeveralChaptersRequest.execute(); + + System.out.println("Number of chapters: " + chapters.length); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getSeveralChapters_Async() { + try { + final CompletableFuture chaptersFuture = getSeveralChaptersRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final Chapter[] chapters = chaptersFuture.join(); + + System.out.println("Number of chapters: " + chapters.length); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getSeveralChapters_Sync(); + getSeveralChapters_Async(); + } +} diff --git a/examples/data/library/CheckUsersSavedEpisodesExample.java b/examples/data/episodes/CheckUsersSavedEpisodesExample.java similarity index 94% rename from examples/data/library/CheckUsersSavedEpisodesExample.java rename to examples/data/episodes/CheckUsersSavedEpisodesExample.java index c25bae076..41a1bac39 100644 --- a/examples/data/library/CheckUsersSavedEpisodesExample.java +++ b/examples/data/episodes/CheckUsersSavedEpisodesExample.java @@ -1,8 +1,9 @@ -package data.library; +package data.episodes; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.library.CheckUsersSavedEpisodesRequest; +import se.michaelthelin.spotify.requests.data.episodes.CheckUsersSavedEpisodesRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/library/GetUsersSavedEpisodesExample.java b/examples/data/episodes/GetUsersSavedEpisodesExample.java similarity index 95% rename from examples/data/library/GetUsersSavedEpisodesExample.java rename to examples/data/episodes/GetUsersSavedEpisodesExample.java index 25692df77..21c65e005 100644 --- a/examples/data/library/GetUsersSavedEpisodesExample.java +++ b/examples/data/episodes/GetUsersSavedEpisodesExample.java @@ -1,10 +1,11 @@ -package data.library; +package data.episodes; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.episodes.GetUsersSavedEpisodesRequest; import se.michaelthelin.spotify.model_objects.miscellaneous.SavedEpisode; -import se.michaelthelin.spotify.requests.data.library.GetUsersSavedEpisodesRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/browse/miscellaneous/GetAvailableGenreSeedsExample.java b/examples/data/genres/GetAvailableGenreSeedsExample.java similarity index 69% rename from examples/data/browse/miscellaneous/GetAvailableGenreSeedsExample.java rename to examples/data/genres/GetAvailableGenreSeedsExample.java index 4986f59e9..e3f78b704 100644 --- a/examples/data/browse/miscellaneous/GetAvailableGenreSeedsExample.java +++ b/examples/data/genres/GetAvailableGenreSeedsExample.java @@ -1,8 +1,9 @@ -package data.browse.miscellaneous; +package data.genres; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.browse.miscellaneous.GetAvailableGenreSeedsRequest; +import se.michaelthelin.spotify.requests.data.genres.GetRecommendationGenresRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -16,12 +17,12 @@ public class GetAvailableGenreSeedsExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetAvailableGenreSeedsRequest getAvailableGenreSeedsRequest = spotifyApi.getAvailableGenreSeeds() + private static final GetRecommendationGenresRequest getRecommendationGenresRequest = spotifyApi.getRecommendationGenres() .build(); - public static void getAvailableGenreSeeds_Sync() { + public static void getRecommendationGenres_Sync() { try { - final String[] strings = getAvailableGenreSeedsRequest.execute(); + final String[] strings = getRecommendationGenresRequest.execute(); System.out.println("Length: " + strings.length); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -29,9 +30,9 @@ public static void getAvailableGenreSeeds_Sync() { } } - public static void getAvailableGenreSeeds_Async() { + public static void getRecommendationGenres_Async() { try { - final CompletableFuture stringsFuture = getAvailableGenreSeedsRequest.executeAsync(); + final CompletableFuture stringsFuture = getRecommendationGenresRequest.executeAsync(); // Thread free to do other tasks... @@ -47,7 +48,7 @@ public static void getAvailableGenreSeeds_Async() { } public static void main(String[] args) { - getAvailableGenreSeeds_Sync(); - getAvailableGenreSeeds_Async(); + getRecommendationGenres_Sync(); + getRecommendationGenres_Async(); } } diff --git a/examples/data/library/RemoveFromLibraryExample.java b/examples/data/library/RemoveFromLibraryExample.java index a76e6a650..d79e111df 100644 --- a/examples/data/library/RemoveFromLibraryExample.java +++ b/examples/data/library/RemoveFromLibraryExample.java @@ -4,7 +4,7 @@ import com.google.gson.JsonParser; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.library.RemoveFromLibraryRequest; +import se.michaelthelin.spotify.requests.data.library.RemoveItemsFromLibraryRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -19,12 +19,12 @@ public class RemoveFromLibraryExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final RemoveFromLibraryRequest removeFromLibraryRequest = spotifyApi.removeFromLibrary(uris) + private static final RemoveItemsFromLibraryRequest removeLibraryItemsRequest = spotifyApi.removeItemsFromLibrary(uris) .build(); - public static void removeFromLibrary_Sync() { + public static void removeLibraryItems_Sync() { try { - final String string = removeFromLibraryRequest.execute(); + final String string = removeLibraryItemsRequest.execute(); System.out.println("Null: " + (string == null)); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void removeFromLibrary_Sync() { } } - public static void removeFromLibrary_Async() { + public static void removeLibraryItems_Async() { try { - final CompletableFuture stringFuture = removeFromLibraryRequest.executeAsync(); + final CompletableFuture stringFuture = removeLibraryItemsRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void removeFromLibrary_Async() { } public static void main(String[] args) { - removeFromLibrary_Sync(); - removeFromLibrary_Async(); + removeLibraryItems_Sync(); + removeLibraryItems_Async(); } } diff --git a/examples/data/library/SaveToLibraryExample.java b/examples/data/library/SaveToLibraryExample.java index 68759f3f5..8dbf5b179 100644 --- a/examples/data/library/SaveToLibraryExample.java +++ b/examples/data/library/SaveToLibraryExample.java @@ -4,7 +4,7 @@ import com.google.gson.JsonParser; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.library.SaveToLibraryRequest; +import se.michaelthelin.spotify.requests.data.library.SaveItemsToLibraryRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -19,12 +19,12 @@ public class SaveToLibraryExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final SaveToLibraryRequest saveToLibraryRequest = spotifyApi.saveToLibrary(uris) + private static final SaveItemsToLibraryRequest saveLibraryItemsRequest = spotifyApi.saveItemsToLibrary(uris) .build(); - public static void saveToLibrary_Sync() { + public static void saveLibraryItems_Sync() { try { - final String string = saveToLibraryRequest.execute(); + final String string = saveLibraryItemsRequest.execute(); System.out.println("Null: " + (string == null)); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void saveToLibrary_Sync() { } } - public static void saveToLibrary_Async() { + public static void saveLibraryItems_Async() { try { - final CompletableFuture stringFuture = saveToLibraryRequest.executeAsync(); + final CompletableFuture stringFuture = saveLibraryItemsRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void saveToLibrary_Async() { } public static void main(String[] args) { - saveToLibrary_Sync(); - saveToLibrary_Async(); + saveLibraryItems_Sync(); + saveLibraryItems_Async(); } } diff --git a/examples/data/markets/GetAvailableMarketsExample.java b/examples/data/markets/GetAvailableMarketsExample.java new file mode 100644 index 000000000..f29af9d26 --- /dev/null +++ b/examples/data/markets/GetAvailableMarketsExample.java @@ -0,0 +1,53 @@ +package data.markets; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.markets.GetAvailableMarketsRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +public class GetAvailableMarketsExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final GetAvailableMarketsRequest getAvailableMarketsRequest = spotifyApi.getAvailableMarkets() + .build(); + + public static void getAvailableMarkets_Sync() { + try { + final String[] markets = getAvailableMarketsRequest.execute(); + + System.out.println("Number of markets: " + markets.length); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void getAvailableMarkets_Async() { + try { + final CompletableFuture marketsFuture = getAvailableMarketsRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final String[] markets = marketsFuture.join(); + + System.out.println("Number of markets: " + markets.length); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + getAvailableMarkets_Sync(); + getAvailableMarkets_Async(); + } +} diff --git a/examples/data/player/AddItemToUsersPlaybackQueueExample.java b/examples/data/player/AddItemToUsersPlaybackQueueExample.java index b3f34724a..3f7d9266f 100644 --- a/examples/data/player/AddItemToUsersPlaybackQueueExample.java +++ b/examples/data/player/AddItemToUsersPlaybackQueueExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.AddItemToUsersPlaybackQueueRequest; +import se.michaelthelin.spotify.requests.data.player.AddItemToPlaybackQueueRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,14 +17,14 @@ public class AddItemToUsersPlaybackQueueExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final AddItemToUsersPlaybackQueueRequest addItemToUsersPlaybackQueueRequest = spotifyApi - .addItemToUsersPlaybackQueue(trackUri) + private static final AddItemToPlaybackQueueRequest addToQueueRequest = spotifyApi + .addItemToPlaybackQueue(trackUri) // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); - public static void addItemToUsersPlaybackQueue_Sync() { + public static void addToQueue_Sync() { try { - final String string = addItemToUsersPlaybackQueueRequest.execute(); + final String string = addToQueueRequest.execute(); System.out.println("Null: " + string); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void addItemToUsersPlaybackQueue_Sync() { } } - public static void addItemToUsersPlaybackQueue_Async() { + public static void addToQueue_Async() { try { - final CompletableFuture stringFuture = addItemToUsersPlaybackQueueRequest.executeAsync(); + final CompletableFuture stringFuture = addToQueueRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void addItemToUsersPlaybackQueue_Async() { } public static void main(String[] args) { - addItemToUsersPlaybackQueue_Sync(); - addItemToUsersPlaybackQueue_Async(); + addToQueue_Sync(); + addToQueue_Async(); } } diff --git a/examples/data/player/GetCurrentUsersRecentlyPlayedTracksExample.java b/examples/data/player/GetCurrentUsersRecentlyPlayedTracksExample.java index 044310894..babe51301 100644 --- a/examples/data/player/GetCurrentUsersRecentlyPlayedTracksExample.java +++ b/examples/data/player/GetCurrentUsersRecentlyPlayedTracksExample.java @@ -4,7 +4,7 @@ import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.PagingCursorbased; import se.michaelthelin.spotify.model_objects.specification.PlayHistory; -import se.michaelthelin.spotify.requests.data.player.GetCurrentUsersRecentlyPlayedTracksRequest; +import se.michaelthelin.spotify.requests.data.player.GetRecentlyPlayedTracksRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -18,16 +18,16 @@ public class GetCurrentUsersRecentlyPlayedTracksExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetCurrentUsersRecentlyPlayedTracksRequest getCurrentUsersRecentlyPlayedTracksRequest = - spotifyApi.getCurrentUsersRecentlyPlayedTracks() + private static final GetRecentlyPlayedTracksRequest getRecentlyPlayedRequest = + spotifyApi.getRecentlyPlayedTracks() // .after(new Date(1517087230000L)) // .before(new Date(1453932420000L)) // .limit(10) .build(); - public static void getCurrentUsersRecentlyPlayedTracks_Sync() { + public static void getRecentlyPlayed_Sync() { try { - final PagingCursorbased playHistoryPagingCursorbased = getCurrentUsersRecentlyPlayedTracksRequest.execute(); + final PagingCursorbased playHistoryPagingCursorbased = getRecentlyPlayedRequest.execute(); System.out.println("Total: " + playHistoryPagingCursorbased.getTotal()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -35,9 +35,9 @@ public static void getCurrentUsersRecentlyPlayedTracks_Sync() { } } - public static void getCurrentUsersRecentlyPlayedTracks_Async() { + public static void getRecentlyPlayed_Async() { try { - final CompletableFuture> pagingCursorbasedFuture = getCurrentUsersRecentlyPlayedTracksRequest.executeAsync(); + final CompletableFuture> pagingCursorbasedFuture = getRecentlyPlayedRequest.executeAsync(); // Thread free to do other tasks... @@ -53,7 +53,7 @@ public static void getCurrentUsersRecentlyPlayedTracks_Async() { } public static void main(String[] args) { - getCurrentUsersRecentlyPlayedTracks_Sync(); - getCurrentUsersRecentlyPlayedTracks_Async(); + getRecentlyPlayed_Sync(); + getRecentlyPlayed_Async(); } } diff --git a/examples/data/player/GetInformationAboutUsersCurrentPlaybackExample.java b/examples/data/player/GetInformationAboutUsersCurrentPlaybackExample.java index caddd641e..561595251 100644 --- a/examples/data/player/GetInformationAboutUsersCurrentPlaybackExample.java +++ b/examples/data/player/GetInformationAboutUsersCurrentPlaybackExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlayingContext; -import se.michaelthelin.spotify.requests.data.player.GetInformationAboutUsersCurrentPlaybackRequest; +import se.michaelthelin.spotify.requests.data.player.GetPlaybackStateRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,8 +17,8 @@ public class GetInformationAboutUsersCurrentPlaybackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetInformationAboutUsersCurrentPlaybackRequest getInformationAboutUsersCurrentPlaybackRequest = - spotifyApi.getInformationAboutUsersCurrentPlayback() + private static final GetPlaybackStateRequest getInformationAboutUsersCurrentPlaybackRequest = + spotifyApi.getPlaybackState() // .market(CountryCode.SE) // .additionalTypes("track,episode") .build(); diff --git a/examples/data/player/GetTheUsersQueueExample.java b/examples/data/player/GetTheUsersQueueExample.java index cac089d52..082906637 100644 --- a/examples/data/player/GetTheUsersQueueExample.java +++ b/examples/data/player/GetTheUsersQueueExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.special.PlaybackQueue; -import se.michaelthelin.spotify.requests.data.player.GetTheUsersQueueRequest; +import se.michaelthelin.spotify.requests.data.player.GetUsersQueueRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -18,12 +18,12 @@ public class GetTheUsersQueueExample { .setAccessToken(accessToken) .build(); - private static final GetTheUsersQueueRequest getTheUsersQueueRequest = spotifyApi.getTheUsersQueue() + private static final GetUsersQueueRequest getQueueRequest = spotifyApi.getUsersQueue() .build(); - public static void getTheUsersQueue_Sync() { + public static void getQueue_Sync() { try { - final PlaybackQueue playbackQueue = getTheUsersQueueRequest.execute(); + final PlaybackQueue playbackQueue = getQueueRequest.execute(); System.out.println("Count of items in the queue: " + playbackQueue.getQueue().size()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -31,9 +31,9 @@ public static void getTheUsersQueue_Sync() { } } - public static void getTheUsersQueue_Async() { + public static void getQueue_Async() { try { - final CompletableFuture playbackQueueFuture = getTheUsersQueueRequest.executeAsync(); + final CompletableFuture playbackQueueFuture = getQueueRequest.executeAsync(); // Thread free to do other tasks... @@ -49,7 +49,7 @@ public static void getTheUsersQueue_Async() { } public static void main(String[] args) { - getTheUsersQueue_Sync(); - getTheUsersQueue_Async(); + getQueue_Sync(); + getQueue_Async(); } } diff --git a/examples/data/player/GetUsersAvailableDevicesExample.java b/examples/data/player/GetUsersAvailableDevicesExample.java index 209eac036..afd9947d9 100644 --- a/examples/data/player/GetUsersAvailableDevicesExample.java +++ b/examples/data/player/GetUsersAvailableDevicesExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.miscellaneous.Device; -import se.michaelthelin.spotify.requests.data.player.GetUsersAvailableDevicesRequest; +import se.michaelthelin.spotify.requests.data.player.GetAvailableDevicesRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,8 +17,8 @@ public class GetUsersAvailableDevicesExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetUsersAvailableDevicesRequest getUsersAvailableDevicesRequest = spotifyApi - .getUsersAvailableDevices() + private static final GetAvailableDevicesRequest getUsersAvailableDevicesRequest = spotifyApi + .getAvailableDevices() .build(); public static void getUsersAvailableDevices_Sync() { diff --git a/examples/data/player/GetUsersCurrentlyPlayingTrackExample.java b/examples/data/player/GetUsersCurrentlyPlayingTrackExample.java index c6aa38f03..e391da2fe 100644 --- a/examples/data/player/GetUsersCurrentlyPlayingTrackExample.java +++ b/examples/data/player/GetUsersCurrentlyPlayingTrackExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying; -import se.michaelthelin.spotify.requests.data.player.GetUsersCurrentlyPlayingTrackRequest; +import se.michaelthelin.spotify.requests.data.player.GetCurrentlyPlayingTrackRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,8 +17,8 @@ public class GetUsersCurrentlyPlayingTrackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetUsersCurrentlyPlayingTrackRequest getUsersCurrentlyPlayingTrackRequest = spotifyApi - .getUsersCurrentlyPlayingTrack() + private static final GetCurrentlyPlayingTrackRequest getUsersCurrentlyPlayingTrackRequest = spotifyApi + .getCurrentlyPlayingTrack() // .market(CountryCode.SE) // .additionalTypes("track,episode") .build(); diff --git a/examples/data/player/PauseUsersPlaybackExample.java b/examples/data/player/PauseUsersPlaybackExample.java index bd938c157..ae3acbfc9 100644 --- a/examples/data/player/PauseUsersPlaybackExample.java +++ b/examples/data/player/PauseUsersPlaybackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.PauseUsersPlaybackRequest; +import se.michaelthelin.spotify.requests.data.player.PausePlaybackRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -16,7 +16,7 @@ public class PauseUsersPlaybackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final PauseUsersPlaybackRequest pauseUsersPlaybackRequest = spotifyApi.pauseUsersPlayback() + private static final PausePlaybackRequest pauseUsersPlaybackRequest = spotifyApi.pausePlayback() // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); diff --git a/examples/data/player/SeekToPositionInCurrentlyPlayingTrackExample.java b/examples/data/player/SeekToPositionInCurrentlyPlayingTrackExample.java index dc06e9c7f..326cd0ff3 100644 --- a/examples/data/player/SeekToPositionInCurrentlyPlayingTrackExample.java +++ b/examples/data/player/SeekToPositionInCurrentlyPlayingTrackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.SeekToPositionInCurrentlyPlayingTrackRequest; +import se.michaelthelin.spotify.requests.data.player.SeekToPositionRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,8 +17,8 @@ public class SeekToPositionInCurrentlyPlayingTrackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final SeekToPositionInCurrentlyPlayingTrackRequest seekToPositionInCurrentlyPlayingTrackRequest = - spotifyApi.seekToPositionInCurrentlyPlayingTrack(positionMs) + private static final SeekToPositionRequest seekToPositionInCurrentlyPlayingTrackRequest = + spotifyApi.seekToPosition(positionMs) // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); diff --git a/examples/data/player/SetRepeatModeOnUsersPlaybackExample.java b/examples/data/player/SetRepeatModeOnUsersPlaybackExample.java index 6f926a2c8..20fce3ac3 100644 --- a/examples/data/player/SetRepeatModeOnUsersPlaybackExample.java +++ b/examples/data/player/SetRepeatModeOnUsersPlaybackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.SetRepeatModeOnUsersPlaybackRequest; +import se.michaelthelin.spotify.requests.data.player.SetRepeatModeRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,8 +17,8 @@ public class SetRepeatModeOnUsersPlaybackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final SetRepeatModeOnUsersPlaybackRequest setRepeatModeOnUsersPlaybackRequest = spotifyApi - .setRepeatModeOnUsersPlayback(state) + private static final SetRepeatModeRequest setRepeatModeOnUsersPlaybackRequest = spotifyApi + .setRepeatMode(state) // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); diff --git a/examples/data/player/SetVolumeForUsersPlaybackExample.java b/examples/data/player/SetVolumeForUsersPlaybackExample.java index 5469396e5..868839c19 100644 --- a/examples/data/player/SetVolumeForUsersPlaybackExample.java +++ b/examples/data/player/SetVolumeForUsersPlaybackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.SetVolumeForUsersPlaybackRequest; +import se.michaelthelin.spotify.requests.data.player.SetPlaybackVolumeRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,8 +17,8 @@ public class SetVolumeForUsersPlaybackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final SetVolumeForUsersPlaybackRequest setVolumeForUsersPlaybackRequest = spotifyApi - .setVolumeForUsersPlayback(volumePercent) + private static final SetPlaybackVolumeRequest setVolumeForUsersPlaybackRequest = spotifyApi + .setPlaybackVolume(volumePercent) // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); diff --git a/examples/data/player/SkipUsersPlaybackToNextTrackExample.java b/examples/data/player/SkipUsersPlaybackToNextTrackExample.java index ad9fdf22a..94fada0b6 100644 --- a/examples/data/player/SkipUsersPlaybackToNextTrackExample.java +++ b/examples/data/player/SkipUsersPlaybackToNextTrackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.SkipUsersPlaybackToNextTrackRequest; +import se.michaelthelin.spotify.requests.data.player.SkipToNextRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -16,8 +16,8 @@ public class SkipUsersPlaybackToNextTrackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final SkipUsersPlaybackToNextTrackRequest skipUsersPlaybackToNextTrackRequest = spotifyApi - .skipUsersPlaybackToNextTrack() + private static final SkipToNextRequest skipUsersPlaybackToNextTrackRequest = spotifyApi + .skipToNext() // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); diff --git a/examples/data/player/SkipUsersPlaybackToPreviousTrackExample.java b/examples/data/player/SkipUsersPlaybackToPreviousTrackExample.java index c272aea75..b8e8e5e74 100644 --- a/examples/data/player/SkipUsersPlaybackToPreviousTrackExample.java +++ b/examples/data/player/SkipUsersPlaybackToPreviousTrackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.SkipUsersPlaybackToPreviousTrackRequest; +import se.michaelthelin.spotify.requests.data.player.SkipToPreviousRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -16,8 +16,8 @@ public class SkipUsersPlaybackToPreviousTrackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final SkipUsersPlaybackToPreviousTrackRequest skipUsersPlaybackToPreviousTrackRequest = spotifyApi - .skipUsersPlaybackToPreviousTrack() + private static final SkipToPreviousRequest skipUsersPlaybackToPreviousTrackRequest = spotifyApi + .skipToPrevious() // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); diff --git a/examples/data/player/StartResumeUsersPlaybackExample.java b/examples/data/player/StartResumeUsersPlaybackExample.java index b0fc213bd..f7fad9639 100644 --- a/examples/data/player/StartResumeUsersPlaybackExample.java +++ b/examples/data/player/StartResumeUsersPlaybackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.StartResumeUsersPlaybackRequest; +import se.michaelthelin.spotify.requests.data.player.StartResumePlaybackRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -16,8 +16,8 @@ public class StartResumeUsersPlaybackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final StartResumeUsersPlaybackRequest startResumeUsersPlaybackRequest = spotifyApi - .startResumeUsersPlayback() + private static final StartResumePlaybackRequest startUsersPlaybackRequest = spotifyApi + .startResumePlayback() // .context_uri("spotify:album:5zT1JLIj9E57p3e1rFm9Uq") // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") // .offset(JsonParser.parseString("{\"uri\":\"spotify:track:01iyCAUm8EvOFqVWYJ3dVX\"}").getAsJsonObject()) @@ -25,9 +25,9 @@ public class StartResumeUsersPlaybackExample { // .position_ms(10000) .build(); - public static void startResumeUsersPlayback_Sync() { + public static void startUsersPlayback_Sync() { try { - final String string = startResumeUsersPlaybackRequest.execute(); + final String string = startUsersPlaybackRequest.execute(); System.out.println("Null: " + string); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -35,9 +35,9 @@ public static void startResumeUsersPlayback_Sync() { } } - public static void startResumeUsersPlayback_Async() { + public static void startUsersPlayback_Async() { try { - final CompletableFuture stringFuture = startResumeUsersPlaybackRequest.executeAsync(); + final CompletableFuture stringFuture = startUsersPlaybackRequest.executeAsync(); // Thread free to do other tasks... @@ -53,7 +53,7 @@ public static void startResumeUsersPlayback_Async() { } public static void main(String[] args) { - startResumeUsersPlayback_Sync(); - startResumeUsersPlayback_Async(); + startUsersPlayback_Sync(); + startUsersPlayback_Async(); } } diff --git a/examples/data/player/ToggleShuffleForUsersPlaybackExample.java b/examples/data/player/ToggleShuffleForUsersPlaybackExample.java index fdcdf0585..e154f2fac 100644 --- a/examples/data/player/ToggleShuffleForUsersPlaybackExample.java +++ b/examples/data/player/ToggleShuffleForUsersPlaybackExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.ToggleShuffleForUsersPlaybackRequest; +import se.michaelthelin.spotify.requests.data.player.TogglePlaybackShuffleRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,8 +17,8 @@ public class ToggleShuffleForUsersPlaybackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final ToggleShuffleForUsersPlaybackRequest toggleShuffleForUsersPlaybackRequest = spotifyApi - .toggleShuffleForUsersPlayback(state) + private static final TogglePlaybackShuffleRequest toggleShuffleForUsersPlaybackRequest = spotifyApi + .togglePlaybackShuffle(state) // .device_id("5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e") .build(); diff --git a/examples/data/player/TransferUsersPlaybackExample.java b/examples/data/player/TransferUsersPlaybackExample.java index 9d152042a..7e8c76847 100644 --- a/examples/data/player/TransferUsersPlaybackExample.java +++ b/examples/data/player/TransferUsersPlaybackExample.java @@ -4,7 +4,7 @@ import com.google.gson.JsonParser; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.player.TransferUsersPlaybackRequest; +import se.michaelthelin.spotify.requests.data.player.TransferPlaybackRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -19,8 +19,8 @@ public class TransferUsersPlaybackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final TransferUsersPlaybackRequest transferUsersPlaybackRequest = spotifyApi - .transferUsersPlayback(deviceIds) + private static final TransferPlaybackRequest transferUsersPlaybackRequest = spotifyApi + .transferPlayback(deviceIds) // .play(false) .build(); diff --git a/examples/data/playlists/AddItemsToPlaylistDeprecatedExample.java b/examples/data/playlists/AddItemsToPlaylistDeprecatedExample.java new file mode 100644 index 000000000..4d82d4880 --- /dev/null +++ b/examples/data/playlists/AddItemsToPlaylistDeprecatedExample.java @@ -0,0 +1,62 @@ +package data.playlists; + +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.special.SnapshotResult; +import se.michaelthelin.spotify.requests.data.playlists.AddItemsToPlaylistDeprecatedRequest; +import org.apache.hc.core5.http.ParseException; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * @deprecated Use {@link AddItemsToPlaylistExample} instead. + */ +@Deprecated +public class AddItemsToPlaylistDeprecatedExample { + private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; + private static final String playlistId = "3AGOiaoRXMSjswCLtuNqv5"; + private static final String[] uris = new String[]{"spotify:track:01iyCAUm8EvOFqVWYJ3dVX", "spotify:episode:4GI3dxEafwap1sFiTGPKd1"}; + + private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() + .setAccessToken(accessToken) + .build(); + private static final AddItemsToPlaylistDeprecatedRequest addItemsToPlaylistDeprecatedRequest = spotifyApi + .addItemsToPlaylistDeprecated(playlistId, uris) +// .position(0) + .build(); + + public static void addItemsToPlaylistDeprecated_Sync() { + try { + final SnapshotResult snapshotResult = addItemsToPlaylistDeprecatedRequest.execute(); + + System.out.println("Snapshot ID: " + snapshotResult.getSnapshotId()); + } catch (IOException | SpotifyWebApiException | ParseException e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void addItemsToPlaylistDeprecated_Async() { + try { + final CompletableFuture snapshotResultFuture = addItemsToPlaylistDeprecatedRequest.executeAsync(); + + // Thread free to do other tasks... + + // Example Only. Never block in production code. + final SnapshotResult snapshotResult = snapshotResultFuture.join(); + + System.out.println("Snapshot ID: " + snapshotResult.getSnapshotId()); + } catch (CompletionException e) { + System.out.println("Error: " + e.getCause().getMessage()); + } catch (CancellationException e) { + System.out.println("Async operation cancelled."); + } + } + + public static void main(String[] args) { + addItemsToPlaylistDeprecated_Sync(); + addItemsToPlaylistDeprecated_Async(); + } +} diff --git a/examples/data/playlists/ChangePlaylistsDetailsExample.java b/examples/data/playlists/ChangePlaylistsDetailsExample.java index 63be9b53c..487d63b71 100644 --- a/examples/data/playlists/ChangePlaylistsDetailsExample.java +++ b/examples/data/playlists/ChangePlaylistsDetailsExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.playlists.ChangePlaylistsDetailsRequest; +import se.michaelthelin.spotify.requests.data.playlists.ChangePlaylistDetailsRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,17 +17,17 @@ public class ChangePlaylistsDetailsExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final ChangePlaylistsDetailsRequest changePlaylistsDetailsRequest = spotifyApi - .changePlaylistsDetails(playlistId) + private static final ChangePlaylistDetailsRequest changePlaylistDetailsRequest = spotifyApi + .changePlaylistDetails(playlistId) // .name("Abba") // .public_(false) // .collaborative(false) // .description("Amazing music.") .build(); - public static void changePlaylistsDetails_Sync() { + public static void changePlaylistDetails_Sync() { try { - final String string = changePlaylistsDetailsRequest.execute(); + final String string = changePlaylistDetailsRequest.execute(); System.out.println("Null: " + string); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -35,9 +35,9 @@ public static void changePlaylistsDetails_Sync() { } } - public static void changePlaylistsDetails_Async() { + public static void changePlaylistDetails_Async() { try { - final CompletableFuture stringFuture = changePlaylistsDetailsRequest.executeAsync(); + final CompletableFuture stringFuture = changePlaylistDetailsRequest.executeAsync(); // Thread free to do other tasks... @@ -53,7 +53,7 @@ public static void changePlaylistsDetails_Async() { } public static void main(String[] args) { - changePlaylistsDetails_Sync(); - changePlaylistsDetails_Async(); + changePlaylistDetails_Sync(); + changePlaylistDetails_Async(); } } diff --git a/examples/data/browse/GetCategorysPlaylistsExample.java b/examples/data/playlists/GetCategoryPlaylistsExample.java similarity index 81% rename from examples/data/browse/GetCategorysPlaylistsExample.java rename to examples/data/playlists/GetCategoryPlaylistsExample.java index 06c1529b1..bb5486d04 100644 --- a/examples/data/browse/GetCategorysPlaylistsExample.java +++ b/examples/data/playlists/GetCategoryPlaylistsExample.java @@ -1,10 +1,11 @@ -package data.browse; +package data.playlists; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.PlaylistSimplified; -import se.michaelthelin.spotify.requests.data.browse.GetCategorysPlaylistsRequest; +import se.michaelthelin.spotify.requests.data.playlists.GetCategoryPlaylistsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -12,20 +13,20 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -public class GetCategorysPlaylistsExample { +public class GetCategoryPlaylistsExample { private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; private static final String categoryId = "dinner"; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetCategorysPlaylistsRequest getCategoryRequest = spotifyApi.getCategorysPlaylists(categoryId) + private static final GetCategoryPlaylistsRequest getCategoryRequest = spotifyApi.getCategoryPlaylists(categoryId) // .country(CountryCode.SE) // .limit(10) // .offset(0) .build(); - public static void getCategorysPlaylists_Sync() { + public static void getCategoryPlaylists_Sync() { try { final Paging playlistSimplifiedPaging = getCategoryRequest.execute(); @@ -35,7 +36,7 @@ public static void getCategorysPlaylists_Sync() { } } - public static void getCategorysPlaylists_Async() { + public static void getCategoryPlaylists_Async() { try { final CompletableFuture> pagingFuture = getCategoryRequest.executeAsync(); @@ -53,7 +54,7 @@ public static void getCategorysPlaylists_Async() { } public static void main(String[] args) { - getCategorysPlaylists_Sync(); - getCategorysPlaylists_Async(); + getCategoryPlaylists_Sync(); + getCategoryPlaylists_Async(); } } diff --git a/examples/data/playlists/GetListOfCurrentUsersPlaylistsExample.java b/examples/data/playlists/GetCurrentUsersPlaylistsExample.java similarity index 87% rename from examples/data/playlists/GetListOfCurrentUsersPlaylistsExample.java rename to examples/data/playlists/GetCurrentUsersPlaylistsExample.java index 500724d57..2a91227c7 100644 --- a/examples/data/playlists/GetListOfCurrentUsersPlaylistsExample.java +++ b/examples/data/playlists/GetCurrentUsersPlaylistsExample.java @@ -4,7 +4,7 @@ import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.PlaylistSimplified; -import se.michaelthelin.spotify.requests.data.playlists.GetListOfCurrentUsersPlaylistsRequest; +import se.michaelthelin.spotify.requests.data.playlists.GetCurrentUsersPlaylistsRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -12,14 +12,14 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -public class GetListOfCurrentUsersPlaylistsExample { +public class GetCurrentUsersPlaylistsExample { private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetListOfCurrentUsersPlaylistsRequest getListOfCurrentUsersPlaylistsRequest = spotifyApi - .getListOfCurrentUsersPlaylists() + private static final GetCurrentUsersPlaylistsRequest getListOfCurrentUsersPlaylistsRequest = spotifyApi + .getCurrentUsersPlaylists() // .limit(10) // .offset(0) .build(); diff --git a/examples/data/browse/GetListOfFeaturedPlaylistsExample.java b/examples/data/playlists/GetFeaturedPlaylistsExample.java similarity index 72% rename from examples/data/browse/GetListOfFeaturedPlaylistsExample.java rename to examples/data/playlists/GetFeaturedPlaylistsExample.java index ab5254d4d..59777e6cd 100644 --- a/examples/data/browse/GetListOfFeaturedPlaylistsExample.java +++ b/examples/data/playlists/GetFeaturedPlaylistsExample.java @@ -1,9 +1,10 @@ -package data.browse; +package data.playlists; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.special.FeaturedPlaylists; -import se.michaelthelin.spotify.requests.data.browse.GetListOfFeaturedPlaylistsRequest; +import se.michaelthelin.spotify.requests.data.playlists.GetFeaturedPlaylistsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -11,23 +12,23 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -public class GetListOfFeaturedPlaylistsExample { +public class GetFeaturedPlaylistsExample { private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetListOfFeaturedPlaylistsRequest getListOfFeaturedPlaylistsRequest = spotifyApi - .getListOfFeaturedPlaylists() + private static final GetFeaturedPlaylistsRequest getFeaturedPlaylistsRequest = spotifyApi + .getFeaturedPlaylists() // .country(CountryCode.SE) // .limit(10) // .offset(0) // .timestamp(new Date(1414054800000L)) .build(); - public static void getListOfFeaturedPlaylists_Sync() { + public static void getFeaturedPlaylists_Sync() { try { - final FeaturedPlaylists featuredPlaylists = getListOfFeaturedPlaylistsRequest.execute(); + final FeaturedPlaylists featuredPlaylists = getFeaturedPlaylistsRequest.execute(); System.out.println("Message: " + featuredPlaylists.getMessage()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -35,9 +36,9 @@ public static void getListOfFeaturedPlaylists_Sync() { } } - public static void getListOfFeaturedPlaylists_Async() { + public static void getFeaturedPlaylists_Async() { try { - final CompletableFuture featuredPlaylistsFuture = getListOfFeaturedPlaylistsRequest.executeAsync(); + final CompletableFuture featuredPlaylistsFuture = getFeaturedPlaylistsRequest.executeAsync(); // Thread free to do other tasks... @@ -53,7 +54,7 @@ public static void getListOfFeaturedPlaylists_Async() { } public static void main(String[] args) { - getListOfFeaturedPlaylists_Sync(); - getListOfFeaturedPlaylists_Async(); + getFeaturedPlaylists_Sync(); + getFeaturedPlaylists_Async(); } } diff --git a/examples/data/playlists/GetPlaylistCoverImageExample.java b/examples/data/playlists/GetPlaylistCoverImageExample.java index cdb7a04c4..14b76c85b 100644 --- a/examples/data/playlists/GetPlaylistCoverImageExample.java +++ b/examples/data/playlists/GetPlaylistCoverImageExample.java @@ -18,13 +18,13 @@ public class GetPlaylistCoverImageExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetPlaylistCoverImageRequest getPlaylistCoverImageRequest = spotifyApi + private static final GetPlaylistCoverImageRequest getPlaylistCoverRequest = spotifyApi .getPlaylistCoverImage(playlistId) .build(); - public static void getPlaylistCoverImage_Sync() { + public static void getPlaylistCover_Sync() { try { - final Image[] images = getPlaylistCoverImageRequest.execute(); + final Image[] images = getPlaylistCoverRequest.execute(); System.out.println("Length: " + images.length); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void getPlaylistCoverImage_Sync() { } } - public static void getPlaylistCoverImage_Async() { + public static void getPlaylistCover_Async() { try { - final CompletableFuture imagesFuture = getPlaylistCoverImageRequest.executeAsync(); + final CompletableFuture imagesFuture = getPlaylistCoverRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void getPlaylistCoverImage_Async() { } public static void main(String[] args) { - getPlaylistCoverImage_Sync(); - getPlaylistCoverImage_Async(); + getPlaylistCover_Sync(); + getPlaylistCover_Async(); } } diff --git a/examples/data/playlists/GetPlaylistsItemsExample.java b/examples/data/playlists/GetPlaylistsItemsExample.java index ad39ffddc..6b3702066 100644 --- a/examples/data/playlists/GetPlaylistsItemsExample.java +++ b/examples/data/playlists/GetPlaylistsItemsExample.java @@ -6,7 +6,7 @@ import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.PlaylistTrack; import se.michaelthelin.spotify.model_objects.specification.Track; -import se.michaelthelin.spotify.requests.data.playlists.GetPlaylistsItemsRequest; +import se.michaelthelin.spotify.requests.data.playlists.GetPlaylistItemsRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -21,8 +21,8 @@ public class GetPlaylistsItemsExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetPlaylistsItemsRequest getPlaylistsItemsRequest = spotifyApi - .getPlaylistsItems(playlistId) + private static final GetPlaylistItemsRequest getPlaylistsItemsRequest = spotifyApi + .getPlaylistItems(playlistId) // .fields("description") // .limit(10) // .offset(0) diff --git a/examples/data/playlists/RemoveItemsFromPlaylistExample.java b/examples/data/playlists/RemoveItemsFromPlaylistExample.java index 9300ade2b..669ac8a1d 100644 --- a/examples/data/playlists/RemoveItemsFromPlaylistExample.java +++ b/examples/data/playlists/RemoveItemsFromPlaylistExample.java @@ -5,7 +5,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.special.SnapshotResult; -import se.michaelthelin.spotify.requests.data.playlists.RemoveItemsFromPlaylistRequest; +import se.michaelthelin.spotify.requests.data.playlists.RemovePlaylistItemsRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -21,14 +21,14 @@ public class RemoveItemsFromPlaylistExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final RemoveItemsFromPlaylistRequest removeItemsFromPlaylistRequest = spotifyApi - .removeItemsFromPlaylist(playlistId, tracks) + private static final RemovePlaylistItemsRequest removeItemsPlaylistRequest = spotifyApi + .removePlaylistItems(playlistId, tracks) // .snapshotId("JbtmHBDBAYu3/bt8BOXKjzKx3i0b6LCa/wVjyl6qQ2Yf6nFXkbmzuEa+ZI/U1yF+") .build(); - public static void removeItemsFromPlaylist_Sync() { + public static void removeItemsPlaylist_Sync() { try { - final SnapshotResult snapshotResult = removeItemsFromPlaylistRequest.execute(); + final SnapshotResult snapshotResult = removeItemsPlaylistRequest.execute(); System.out.println("Snapshot ID: " + snapshotResult.getSnapshotId()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -36,9 +36,9 @@ public static void removeItemsFromPlaylist_Sync() { } } - public static void removeItemsFromPlaylist_Async() { + public static void removeItemsPlaylist_Async() { try { - final CompletableFuture snapshotResultFuture = removeItemsFromPlaylistRequest.executeAsync(); + final CompletableFuture snapshotResultFuture = removeItemsPlaylistRequest.executeAsync(); // Thread free to do other tasks... @@ -54,7 +54,7 @@ public static void removeItemsFromPlaylist_Async() { } public static void main(String[] args) { - removeItemsFromPlaylist_Sync(); - removeItemsFromPlaylist_Async(); + removeItemsPlaylist_Sync(); + removeItemsPlaylist_Async(); } } diff --git a/examples/data/playlists/ReorderPlaylistsItemsExample.java b/examples/data/playlists/UpdatePlaylistsItemsReorderExample.java similarity index 85% rename from examples/data/playlists/ReorderPlaylistsItemsExample.java rename to examples/data/playlists/UpdatePlaylistsItemsReorderExample.java index 0c2538520..4466d64f9 100644 --- a/examples/data/playlists/ReorderPlaylistsItemsExample.java +++ b/examples/data/playlists/UpdatePlaylistsItemsReorderExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.special.SnapshotResult; -import se.michaelthelin.spotify.requests.data.playlists.ReorderPlaylistsItemsRequest; +import se.michaelthelin.spotify.requests.data.playlists.UpdatePlaylistsItemsReorderRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -11,18 +11,18 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -public class ReorderPlaylistsItemsExample { +public class UpdatePlaylistsItemsReorderExample { private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; private static final String playlistId = "3AGOiaoRXMSjswCLtuNqv5"; private static final int rangeStart = 0; - private static final int rangeLength = 1; + // private static final int rangeLength = 1; private static final int insertBefore = 0; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final ReorderPlaylistsItemsRequest reorderPlaylistsItemsRequest = spotifyApi. - reorderPlaylistsItems(playlistId, rangeStart, insertBefore) + private static final UpdatePlaylistsItemsReorderRequest reorderPlaylistsItemsRequest = spotifyApi. + updatePlaylistsItemsReorder(playlistId, rangeStart, insertBefore) // .range_length(rangeLength) // .snapshot_id("JbtmHBDBAYu3/bt8BOXKjzKx3i0b6LCa/wVjyl6qQ2Yf6nFXkbmzuEa+ZI/U1yF+") .build(); diff --git a/examples/data/playlists/ReplacePlaylistsItemsExample.java b/examples/data/playlists/UpdatePlaylistsItemsReplaceExample.java similarity index 86% rename from examples/data/playlists/ReplacePlaylistsItemsExample.java rename to examples/data/playlists/UpdatePlaylistsItemsReplaceExample.java index f26fa5f1e..82ae7cc1b 100644 --- a/examples/data/playlists/ReplacePlaylistsItemsExample.java +++ b/examples/data/playlists/UpdatePlaylistsItemsReplaceExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.playlists.ReplacePlaylistsItemsRequest; +import se.michaelthelin.spotify.requests.data.playlists.UpdatePlaylistsItemsReplaceRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -10,7 +10,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -public class ReplacePlaylistsItemsExample { +public class UpdatePlaylistsItemsReplaceExample { private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; private static final String playlistId = "3AGOiaoRXMSjswCLtuNqv5"; private static final String[] uris = new String[]{"uris"}; @@ -18,8 +18,8 @@ public class ReplacePlaylistsItemsExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final ReplacePlaylistsItemsRequest replacePlaylistsItemsRequest = spotifyApi - .replacePlaylistsItems(playlistId, uris) + private static final UpdatePlaylistsItemsReplaceRequest replacePlaylistsItemsRequest = spotifyApi + .updatePlaylistsItemsReplace(playlistId, uris) .build(); public static void replacePlaylistsItems_Sync() { diff --git a/examples/data/playlists/UploadCustomPlaylistCoverImageExample.java b/examples/data/playlists/UploadCustomPlaylistCoverImageExample.java index 2ff0a192c..67a40c2c8 100644 --- a/examples/data/playlists/UploadCustomPlaylistCoverImageExample.java +++ b/examples/data/playlists/UploadCustomPlaylistCoverImageExample.java @@ -2,7 +2,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.playlists.UploadCustomPlaylistCoverImageRequest; +import se.michaelthelin.spotify.requests.data.playlists.AddCustomPlaylistCoverImageRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -17,14 +17,14 @@ public class UploadCustomPlaylistCoverImageExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final UploadCustomPlaylistCoverImageRequest uploadCustomPlaylistCoverImageRequest = spotifyApi - .uploadCustomPlaylistCoverImage(playlistId) + private static final AddCustomPlaylistCoverImageRequest uploadCustomPlaylistCoverRequest = spotifyApi + .addCustomPlaylistCoverImage(playlistId) .image_data("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") .build(); - public static void uploadCustomPlaylistCoverImage_Sync() { + public static void uploadCustomPlaylistCover_Sync() { try { - final String string = uploadCustomPlaylistCoverImageRequest.execute(); + final String string = uploadCustomPlaylistCoverRequest.execute(); System.out.println("Null: " + string); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void uploadCustomPlaylistCoverImage_Sync() { } } - public static void uploadCustomPlaylistCoverImage_Async() { + public static void uploadCustomPlaylistCover_Async() { try { - final CompletableFuture stringFuture = uploadCustomPlaylistCoverImageRequest.executeAsync(); + final CompletableFuture stringFuture = uploadCustomPlaylistCoverRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void uploadCustomPlaylistCoverImage_Async() { } public static void main(String[] args) { - uploadCustomPlaylistCoverImage_Sync(); - uploadCustomPlaylistCoverImage_Async(); + uploadCustomPlaylistCover_Sync(); + uploadCustomPlaylistCover_Async(); } } diff --git a/examples/data/search/SearchItemExample.java b/examples/data/search/SearchItemExample.java index e6e9a07d4..faa9e38ac 100644 --- a/examples/data/search/SearchItemExample.java +++ b/examples/data/search/SearchItemExample.java @@ -4,7 +4,7 @@ import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.special.SearchResult; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; +import se.michaelthelin.spotify.requests.data.search.SearchForItemRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -20,16 +20,16 @@ public class SearchItemExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final SearchItemRequest searchItemRequest = spotifyApi.searchItem(q, type) + private static final SearchForItemRequest searchRequest = spotifyApi.searchForItem(q, type) // .market(CountryCode.SE) // .limit(10) // .offset(0) // .includeExternal("audio") .build(); - public static void searchItem_Sync() { + public static void search_Sync() { try { - final SearchResult searchResult = searchItemRequest.execute(); + final SearchResult searchResult = searchRequest.execute(); System.out.println("Total tracks: " + searchResult.getTracks().getTotal()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -37,9 +37,9 @@ public static void searchItem_Sync() { } } - public static void searchItem_Async() { + public static void search_Async() { try { - final CompletableFuture searchResultFuture = searchItemRequest.executeAsync(); + final CompletableFuture searchResultFuture = searchRequest.executeAsync(); // Thread free to do other tasks... @@ -55,7 +55,7 @@ public static void searchItem_Async() { } public static void main(String[] args) { - searchItem_Sync(); - searchItem_Async(); + search_Sync(); + search_Async(); } } diff --git a/examples/data/library/CheckUsersSavedShowsExample.java b/examples/data/shows/CheckUsersSavedShowsExample.java similarity index 94% rename from examples/data/library/CheckUsersSavedShowsExample.java rename to examples/data/shows/CheckUsersSavedShowsExample.java index 7613f75ce..3a924a7c2 100644 --- a/examples/data/library/CheckUsersSavedShowsExample.java +++ b/examples/data/shows/CheckUsersSavedShowsExample.java @@ -1,8 +1,9 @@ -package data.library; +package data.shows; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.library.CheckUsersSavedShowsRequest; +import se.michaelthelin.spotify.requests.data.shows.CheckUsersSavedShowsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/shows/GetShowsEpisodesExample.java b/examples/data/shows/GetShowsEpisodesExample.java index e507943fd..832e3719d 100644 --- a/examples/data/shows/GetShowsEpisodesExample.java +++ b/examples/data/shows/GetShowsEpisodesExample.java @@ -4,7 +4,7 @@ import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.EpisodeSimplified; import se.michaelthelin.spotify.model_objects.specification.Paging; -import se.michaelthelin.spotify.requests.data.shows.GetShowsEpisodesRequest; +import se.michaelthelin.spotify.requests.data.shows.GetShowEpisodesRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -19,7 +19,7 @@ public class GetShowsEpisodesExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetShowsEpisodesRequest getShowsEpisodesRequest = spotifyApi.getShowEpisodes(id) + private static final GetShowEpisodesRequest getShowsEpisodesRequest = spotifyApi.getShowEpisodes(id) // .limit(10) // .offset(0) // .market(CountryCode.SE) diff --git a/examples/data/library/GetUsersSavedShowsExample.java b/examples/data/shows/GetUsersSavedShowsExample.java similarity index 95% rename from examples/data/library/GetUsersSavedShowsExample.java rename to examples/data/shows/GetUsersSavedShowsExample.java index 18cc711af..3917d2ec7 100644 --- a/examples/data/library/GetUsersSavedShowsExample.java +++ b/examples/data/shows/GetUsersSavedShowsExample.java @@ -1,10 +1,11 @@ -package data.library; +package data.shows; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.SavedShow; -import se.michaelthelin.spotify.requests.data.library.GetUsersSavedShowsRequest; +import se.michaelthelin.spotify.requests.data.shows.GetUsersSavedShowsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/library/CheckUsersSavedTracksExample.java b/examples/data/tracks/CheckUsersSavedTracksExample.java similarity index 94% rename from examples/data/library/CheckUsersSavedTracksExample.java rename to examples/data/tracks/CheckUsersSavedTracksExample.java index eda39e2e7..776ba80a6 100644 --- a/examples/data/library/CheckUsersSavedTracksExample.java +++ b/examples/data/tracks/CheckUsersSavedTracksExample.java @@ -1,8 +1,9 @@ -package data.library; +package data.tracks; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.library.CheckUsersSavedTracksRequest; +import se.michaelthelin.spotify.requests.data.tracks.CheckUsersSavedTracksRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/tracks/GetAudioAnalysisForTrackExample.java b/examples/data/tracks/GetAudioAnalysisForTrackExample.java index 3b77094fa..e00f722f6 100644 --- a/examples/data/tracks/GetAudioAnalysisForTrackExample.java +++ b/examples/data/tracks/GetAudioAnalysisForTrackExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.miscellaneous.AudioAnalysis; -import se.michaelthelin.spotify.requests.data.tracks.GetAudioAnalysisForTrackRequest; +import se.michaelthelin.spotify.requests.data.tracks.GetTracksAudioAnalysisRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -18,13 +18,13 @@ public class GetAudioAnalysisForTrackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetAudioAnalysisForTrackRequest getAudioAnalysisForTrackRequest = spotifyApi - .getAudioAnalysisForTrack(id) + private static final GetTracksAudioAnalysisRequest getAudioAnalysisRequest = spotifyApi + .getTracksAudioAnalysis(id) .build(); - public static void getAudioAnalysisForTrack_Sync() { + public static void getAudioAnalysis_Sync() { try { - final AudioAnalysis audioAnalysis = getAudioAnalysisForTrackRequest.execute(); + final AudioAnalysis audioAnalysis = getAudioAnalysisRequest.execute(); System.out.println("Track duration: " + audioAnalysis.getTrack().getDuration()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void getAudioAnalysisForTrack_Sync() { } } - public static void getAudioAnalysisForTrack_Async() { + public static void getAudioAnalysis_Async() { try { - final CompletableFuture audioAnalysisFuture = getAudioAnalysisForTrackRequest.executeAsync(); + final CompletableFuture audioAnalysisFuture = getAudioAnalysisRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void getAudioAnalysisForTrack_Async() { } public static void main(String[] args) { - getAudioAnalysisForTrack_Sync(); - getAudioAnalysisForTrack_Async(); + getAudioAnalysis_Sync(); + getAudioAnalysis_Async(); } } diff --git a/examples/data/tracks/GetAudioFeaturesForSeveralTracksExample.java b/examples/data/tracks/GetAudioFeaturesForSeveralTracksExample.java index a53b52696..996e3f941 100644 --- a/examples/data/tracks/GetAudioFeaturesForSeveralTracksExample.java +++ b/examples/data/tracks/GetAudioFeaturesForSeveralTracksExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.AudioFeatures; -import se.michaelthelin.spotify.requests.data.tracks.GetAudioFeaturesForSeveralTracksRequest; +import se.michaelthelin.spotify.requests.data.tracks.GetSeveralTracksAudioFeaturesRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -18,13 +18,13 @@ public class GetAudioFeaturesForSeveralTracksExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetAudioFeaturesForSeveralTracksRequest getAudioFeaturesForSeveralTracksRequest = spotifyApi - .getAudioFeaturesForSeveralTracks(ids) + private static final GetSeveralTracksAudioFeaturesRequest getSeveralAudioFeaturesRequest = spotifyApi + .getSeveralTracksAudioFeatures(ids) .build(); - public static void getAudioFeaturesForSeveralTracks_Sync() { + public static void getSeveralAudioFeatures_Sync() { try { - final AudioFeatures[] audioFeatures = getAudioFeaturesForSeveralTracksRequest.execute(); + final AudioFeatures[] audioFeatures = getSeveralAudioFeaturesRequest.execute(); System.out.println("Length: " + audioFeatures.length); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void getAudioFeaturesForSeveralTracks_Sync() { } } - public static void getAudioFeaturesForSeveralTracks_Async() { + public static void getSeveralAudioFeatures_Async() { try { - final CompletableFuture audioFeaturesFuture = getAudioFeaturesForSeveralTracksRequest.executeAsync(); + final CompletableFuture audioFeaturesFuture = getSeveralAudioFeaturesRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void getAudioFeaturesForSeveralTracks_Async() { } public static void main(String[] args) { - getAudioFeaturesForSeveralTracks_Sync(); - getAudioFeaturesForSeveralTracks_Async(); + getSeveralAudioFeatures_Sync(); + getSeveralAudioFeatures_Async(); } } diff --git a/examples/data/tracks/GetAudioFeaturesForTrackExample.java b/examples/data/tracks/GetAudioFeaturesForTrackExample.java index 8d175ca19..6fa35889e 100644 --- a/examples/data/tracks/GetAudioFeaturesForTrackExample.java +++ b/examples/data/tracks/GetAudioFeaturesForTrackExample.java @@ -3,7 +3,7 @@ import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.AudioFeatures; -import se.michaelthelin.spotify.requests.data.tracks.GetAudioFeaturesForTrackRequest; +import se.michaelthelin.spotify.requests.data.tracks.GetTracksAudioFeaturesRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -18,13 +18,13 @@ public class GetAudioFeaturesForTrackExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetAudioFeaturesForTrackRequest getAudioFeaturesForTrackRequest = spotifyApi - .getAudioFeaturesForTrack(id) + private static final GetTracksAudioFeaturesRequest getAudioFeaturesRequest = spotifyApi + .getTracksAudioFeatures(id) .build(); - public static void getAudioFeaturesForTrack_Sync() { + public static void getAudioFeatures_Sync() { try { - final AudioFeatures audioFeatures = getAudioFeaturesForTrackRequest.execute(); + final AudioFeatures audioFeatures = getAudioFeaturesRequest.execute(); System.out.println("ID: " + audioFeatures.getId()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +32,9 @@ public static void getAudioFeaturesForTrack_Sync() { } } - public static void getAudioFeaturesForTrack_Async() { + public static void getAudioFeatures_Async() { try { - final CompletableFuture audioFeaturesFuture = getAudioFeaturesForTrackRequest.executeAsync(); + final CompletableFuture audioFeaturesFuture = getAudioFeaturesRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +50,7 @@ public static void getAudioFeaturesForTrack_Async() { } public static void main(String[] args) { - getAudioFeaturesForTrack_Sync(); - getAudioFeaturesForTrack_Async(); + getAudioFeatures_Sync(); + getAudioFeatures_Async(); } } diff --git a/examples/data/browse/GetRecommendationsExample.java b/examples/data/tracks/GetRecommendationsExample.java similarity index 96% rename from examples/data/browse/GetRecommendationsExample.java rename to examples/data/tracks/GetRecommendationsExample.java index dcbe3feb2..ae2d6e053 100644 --- a/examples/data/browse/GetRecommendationsExample.java +++ b/examples/data/tracks/GetRecommendationsExample.java @@ -1,9 +1,10 @@ -package data.browse; +package data.tracks; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Recommendations; -import se.michaelthelin.spotify.requests.data.browse.GetRecommendationsRequest; +import se.michaelthelin.spotify.requests.data.tracks.GetRecommendationsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/library/GetUsersSavedTracksExample.java b/examples/data/tracks/GetUsersSavedTracksExample.java similarity index 95% rename from examples/data/library/GetUsersSavedTracksExample.java rename to examples/data/tracks/GetUsersSavedTracksExample.java index be31354f2..9d885d41a 100644 --- a/examples/data/library/GetUsersSavedTracksExample.java +++ b/examples/data/tracks/GetUsersSavedTracksExample.java @@ -1,10 +1,11 @@ -package data.library; +package data.tracks; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.SavedTrack; -import se.michaelthelin.spotify.requests.data.library.GetUsersSavedTracksRequest; +import se.michaelthelin.spotify.requests.data.tracks.GetUsersSavedTracksRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/follow/CheckCurrentUserFollowsArtistsOrUsersExample.java b/examples/data/users/CheckCurrentUserFollowsArtistsOrUsersExample.java similarity index 94% rename from examples/data/follow/CheckCurrentUserFollowsArtistsOrUsersExample.java rename to examples/data/users/CheckCurrentUserFollowsArtistsOrUsersExample.java index eadc4942a..70eaf72db 100644 --- a/examples/data/follow/CheckCurrentUserFollowsArtistsOrUsersExample.java +++ b/examples/data/users/CheckCurrentUserFollowsArtistsOrUsersExample.java @@ -1,9 +1,10 @@ -package data.follow; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.follow.CheckCurrentUserFollowsArtistsOrUsersRequest; +import se.michaelthelin.spotify.requests.data.users.CheckCurrentUserFollowsArtistsOrUsersRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/follow/CheckUsersFollowPlaylistExample.java b/examples/data/users/CheckUsersFollowPlaylistExample.java similarity index 70% rename from examples/data/follow/CheckUsersFollowPlaylistExample.java rename to examples/data/users/CheckUsersFollowPlaylistExample.java index 8e934035e..d5bd074b1 100644 --- a/examples/data/follow/CheckUsersFollowPlaylistExample.java +++ b/examples/data/users/CheckUsersFollowPlaylistExample.java @@ -1,8 +1,9 @@ -package data.follow; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.follow.CheckUsersFollowPlaylistRequest; +import se.michaelthelin.spotify.requests.data.users.CheckIfUserFollowsPlaylistRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -18,13 +19,13 @@ public class CheckUsersFollowPlaylistExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final CheckUsersFollowPlaylistRequest checkUsersFollowPlaylistRequest = spotifyApi - .checkUsersFollowPlaylist(playlistId, ids) + private static final CheckIfUserFollowsPlaylistRequest checkIfUserFollowsPlaylistRequest = spotifyApi + .checkIfUserFollowsPlaylist(playlistId, ids) .build(); - public static void checkUsersFollowPlaylist_Sync() { + public static void checkIfUserFollowsPlaylist_Sync() { try { - final Boolean[] booleans = checkUsersFollowPlaylistRequest.execute(); + final Boolean[] booleans = checkIfUserFollowsPlaylistRequest.execute(); System.out.println("Length: " + booleans.length); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -32,9 +33,9 @@ public static void checkUsersFollowPlaylist_Sync() { } } - public static void checkUsersFollowPlaylist_Async() { + public static void checkIfUserFollowsPlaylist_Async() { try { - final CompletableFuture booleansFuture = checkUsersFollowPlaylistRequest.executeAsync(); + final CompletableFuture booleansFuture = checkIfUserFollowsPlaylistRequest.executeAsync(); // Thread free to do other tasks... @@ -50,7 +51,7 @@ public static void checkUsersFollowPlaylist_Async() { } public static void main(String[] args) { - checkUsersFollowPlaylist_Sync(); - checkUsersFollowPlaylist_Async(); + checkIfUserFollowsPlaylist_Sync(); + checkIfUserFollowsPlaylist_Async(); } } diff --git a/examples/data/follow/FollowArtistsOrUsersExample.java b/examples/data/users/FollowArtistsOrUsersExample.java similarity index 95% rename from examples/data/follow/FollowArtistsOrUsersExample.java rename to examples/data/users/FollowArtistsOrUsersExample.java index b17664f1c..04f1051db 100644 --- a/examples/data/follow/FollowArtistsOrUsersExample.java +++ b/examples/data/users/FollowArtistsOrUsersExample.java @@ -1,9 +1,10 @@ -package data.follow; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.follow.FollowArtistsOrUsersRequest; +import se.michaelthelin.spotify.requests.data.users.FollowArtistsOrUsersRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/follow/FollowPlaylistExample.java b/examples/data/users/FollowPlaylistExample.java similarity index 88% rename from examples/data/follow/FollowPlaylistExample.java rename to examples/data/users/FollowPlaylistExample.java index ce2c3acd2..9eedd4376 100644 --- a/examples/data/follow/FollowPlaylistExample.java +++ b/examples/data/users/FollowPlaylistExample.java @@ -1,8 +1,9 @@ -package data.follow; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.follow.legacy.FollowPlaylistRequest; +import se.michaelthelin.spotify.requests.data.users.FollowPlaylistRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -12,16 +13,14 @@ public class FollowPlaylistExample { private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; - private static final String ownerId = "abbaspotify"; private static final String playlistId = "3AGOiaoRXMSjswCLtuNqv5"; private static final Boolean public_ = false; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - @SuppressWarnings("ConstantConditions") private static final FollowPlaylistRequest followPlaylistRequest = spotifyApi - .followPlaylist(ownerId, playlistId, public_) + .followPlaylist(playlistId, public_) .build(); public static void followPlaylist_Sync() { diff --git a/examples/data/users_profile/GetCurrentUsersProfileExample.java b/examples/data/users/GetCurrentUsersProfileExample.java similarity index 94% rename from examples/data/users_profile/GetCurrentUsersProfileExample.java rename to examples/data/users/GetCurrentUsersProfileExample.java index 941633e9c..66f3c0757 100644 --- a/examples/data/users_profile/GetCurrentUsersProfileExample.java +++ b/examples/data/users/GetCurrentUsersProfileExample.java @@ -1,9 +1,10 @@ -package data.users_profile; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.User; -import se.michaelthelin.spotify.requests.data.users_profile.GetCurrentUsersProfileRequest; +import se.michaelthelin.spotify.requests.data.users.GetCurrentUsersProfileRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/follow/GetUsersFollowedArtistsExample.java b/examples/data/users/GetUsersFollowedArtistsExample.java similarity index 78% rename from examples/data/follow/GetUsersFollowedArtistsExample.java rename to examples/data/users/GetUsersFollowedArtistsExample.java index ae21f79b5..1b82da1ca 100644 --- a/examples/data/follow/GetUsersFollowedArtistsExample.java +++ b/examples/data/users/GetUsersFollowedArtistsExample.java @@ -1,11 +1,12 @@ -package data.follow; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Artist; import se.michaelthelin.spotify.model_objects.specification.PagingCursorbased; -import se.michaelthelin.spotify.requests.data.follow.GetUsersFollowedArtistsRequest; +import se.michaelthelin.spotify.requests.data.users.GetFollowedArtistsRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -20,15 +21,15 @@ public class GetUsersFollowedArtistsExample { private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); - private static final GetUsersFollowedArtistsRequest getUsersFollowedArtistsRequest = spotifyApi - .getUsersFollowedArtists(type) + private static final GetFollowedArtistsRequest getFollowedRequest = spotifyApi + .getFollowedArtists(type) // .after("0LcJLqbBmaGUft1e9Mm8HV") // .limit(10) .build(); - public static void getUsersFollowedArtists_Sync() { + public static void getFollowed_Sync() { try { - final PagingCursorbased artistPagingCursorbased = getUsersFollowedArtistsRequest.execute(); + final PagingCursorbased artistPagingCursorbased = getFollowedRequest.execute(); System.out.println("Total: " + artistPagingCursorbased.getTotal()); } catch (IOException | SpotifyWebApiException | ParseException e) { @@ -36,9 +37,9 @@ public static void getUsersFollowedArtists_Sync() { } } - public static void getUsersFollowedArtists_Async() { + public static void getFollowed_Async() { try { - final CompletableFuture> pagingCursorbasedFuture = getUsersFollowedArtistsRequest.executeAsync(); + final CompletableFuture> pagingCursorbasedFuture = getFollowedRequest.executeAsync(); // Thread free to do other tasks... @@ -54,7 +55,7 @@ public static void getUsersFollowedArtists_Async() { } public static void main(String[] args) { - getUsersFollowedArtists_Sync(); - getUsersFollowedArtists_Async(); + getFollowed_Sync(); + getFollowed_Async(); } } diff --git a/examples/data/personalization/GetUsersTopArtistsAndTracksExample.java b/examples/data/users/GetUsersTopArtistsAndTracksExample.java similarity index 91% rename from examples/data/personalization/GetUsersTopArtistsAndTracksExample.java rename to examples/data/users/GetUsersTopArtistsAndTracksExample.java index 3f3d634cd..e6315246a 100644 --- a/examples/data/personalization/GetUsersTopArtistsAndTracksExample.java +++ b/examples/data/users/GetUsersTopArtistsAndTracksExample.java @@ -1,11 +1,12 @@ -package data.personalization; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; -import se.michaelthelin.spotify.requests.data.personalization.GetUsersTopArtistsAndTracksRequest; -import se.michaelthelin.spotify.requests.data.personalization.interfaces.IArtistTrackModelObject; +import se.michaelthelin.spotify.requests.data.users.interfaces.IArtistTrackModelObject; +import se.michaelthelin.spotify.requests.data.users.GetUsersTopArtistsAndTracksRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/follow/UnfollowArtistsOrUsersExample.java b/examples/data/users/UnfollowArtistsOrUsersExample.java similarity index 95% rename from examples/data/follow/UnfollowArtistsOrUsersExample.java rename to examples/data/users/UnfollowArtistsOrUsersExample.java index 33fd63853..9cd569447 100644 --- a/examples/data/follow/UnfollowArtistsOrUsersExample.java +++ b/examples/data/users/UnfollowArtistsOrUsersExample.java @@ -1,9 +1,10 @@ -package data.follow; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.follow.UnfollowArtistsOrUsersRequest; +import se.michaelthelin.spotify.requests.data.users.UnfollowArtistsOrUsersRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/follow/UnfollowPlaylistExample.java b/examples/data/users/UnfollowPlaylistExample.java similarity index 89% rename from examples/data/follow/UnfollowPlaylistExample.java rename to examples/data/users/UnfollowPlaylistExample.java index a1684db87..7d3b50746 100644 --- a/examples/data/follow/UnfollowPlaylistExample.java +++ b/examples/data/users/UnfollowPlaylistExample.java @@ -1,8 +1,9 @@ -package data.follow; +package data.users; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.follow.legacy.UnfollowPlaylistRequest; +import se.michaelthelin.spotify.requests.data.users.UnfollowPlaylistRequest; + import org.apache.hc.core5.http.ParseException; import java.io.IOException; @@ -12,14 +13,13 @@ public class UnfollowPlaylistExample { private static final String accessToken = "taHZ2SdB-bPA3FsK3D7ZN5npZS47cMy-IEySVEGttOhXmqaVAIo0ESvTCLjLBifhHOHOIuhFUKPW1WMDP7w6dj3MAZdWT8CLI2MkZaXbYLTeoDvXesf2eeiLYPBGdx8tIwQJKgV8XdnzH_DONk"; - private static final String ownerId = "abbaspotify"; private static final String playlistId = "3AGOiaoRXMSjswCLtuNqv5"; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setAccessToken(accessToken) .build(); private static final UnfollowPlaylistRequest unfollowPlaylistRequest = spotifyApi - .unfollowPlaylist(ownerId, playlistId) + .unfollowPlaylist(playlistId) .build(); public static void unfollowPlaylist_Sync() { diff --git a/examples/data/personalization/simplified/GetUsersTopArtistsExample.java b/examples/data/users/simplified/GetUsersTopArtistsExample.java similarity index 93% rename from examples/data/personalization/simplified/GetUsersTopArtistsExample.java rename to examples/data/users/simplified/GetUsersTopArtistsExample.java index f38583239..a43050e43 100644 --- a/examples/data/personalization/simplified/GetUsersTopArtistsExample.java +++ b/examples/data/users/simplified/GetUsersTopArtistsExample.java @@ -1,10 +1,10 @@ -package data.personalization.simplified; +package data.users.simplified; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Artist; import se.michaelthelin.spotify.model_objects.specification.Paging; -import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopArtistsRequest; +import se.michaelthelin.spotify.requests.data.users.simplified.GetUsersTopArtistsRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/examples/data/personalization/simplified/GetUsersTopTracksExample.java b/examples/data/users/simplified/GetUsersTopTracksExample.java similarity index 93% rename from examples/data/personalization/simplified/GetUsersTopTracksExample.java rename to examples/data/users/simplified/GetUsersTopTracksExample.java index 920fbf1a5..7064b776f 100644 --- a/examples/data/personalization/simplified/GetUsersTopTracksExample.java +++ b/examples/data/users/simplified/GetUsersTopTracksExample.java @@ -1,10 +1,10 @@ -package data.personalization.simplified; +package data.users.simplified; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.model_objects.specification.Track; -import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopTracksRequest; +import se.michaelthelin.spotify.requests.data.users.simplified.GetUsersTopTracksRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; diff --git a/src/main/java/se/michaelthelin/spotify/SpotifyApi.java b/src/main/java/se/michaelthelin/spotify/SpotifyApi.java index 39f9bc261..ec00a76a8 100644 --- a/src/main/java/se/michaelthelin/spotify/SpotifyApi.java +++ b/src/main/java/se/michaelthelin/spotify/SpotifyApi.java @@ -1,7 +1,6 @@ package se.michaelthelin.spotify; import com.google.gson.JsonArray; -import com.neovisionaries.i18n.CountryCode; import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.model_objects.specification.Artist; import se.michaelthelin.spotify.model_objects.specification.Track; @@ -11,30 +10,61 @@ import se.michaelthelin.spotify.requests.authorization.authorization_code.pkce.AuthorizationCodePKCERefreshRequest; import se.michaelthelin.spotify.requests.authorization.authorization_code.pkce.AuthorizationCodePKCERequest; import se.michaelthelin.spotify.requests.authorization.client_credentials.ClientCredentialsRequest; +import se.michaelthelin.spotify.requests.data.albums.CheckUsersSavedAlbumsRequest; import se.michaelthelin.spotify.requests.data.albums.GetAlbumRequest; -import se.michaelthelin.spotify.requests.data.albums.GetAlbumsTracksRequest; +import se.michaelthelin.spotify.requests.data.albums.GetAlbumTracksRequest; +import se.michaelthelin.spotify.requests.data.albums.GetNewReleasesRequest; +import se.michaelthelin.spotify.requests.data.albums.GetSeveralAlbumsRequest; +import se.michaelthelin.spotify.requests.data.albums.GetUsersSavedAlbumsRequest; +import se.michaelthelin.spotify.requests.data.albums.RemoveAlbumsForCurrentUserRequest; +import se.michaelthelin.spotify.requests.data.albums.SaveAlbumsForCurrentUserRequest; import se.michaelthelin.spotify.requests.data.artists.*; -import se.michaelthelin.spotify.requests.data.browse.*; -import se.michaelthelin.spotify.requests.data.browse.miscellaneous.GetAvailableGenreSeedsRequest; +import se.michaelthelin.spotify.requests.data.audiobooks.CheckUsersSavedAudiobooksRequest; +import se.michaelthelin.spotify.requests.data.audiobooks.GetAudiobookChaptersRequest; +import se.michaelthelin.spotify.requests.data.audiobooks.GetAudiobookRequest; +import se.michaelthelin.spotify.requests.data.audiobooks.GetSeveralAudiobooksRequest; +import se.michaelthelin.spotify.requests.data.audiobooks.GetUsersSavedAudiobooksRequest; +import se.michaelthelin.spotify.requests.data.audiobooks.RemoveAudiobooksForCurrentUserRequest; +import se.michaelthelin.spotify.requests.data.audiobooks.SaveAudiobooksForCurrentUserRequest; +import se.michaelthelin.spotify.requests.data.categories.*; +import se.michaelthelin.spotify.requests.data.chapters.GetChapterRequest; +import se.michaelthelin.spotify.requests.data.chapters.GetSeveralChaptersRequest; +import se.michaelthelin.spotify.requests.data.episodes.CheckUsersSavedEpisodesRequest; import se.michaelthelin.spotify.requests.data.episodes.GetEpisodeRequest; -import se.michaelthelin.spotify.requests.data.follow.*; -import se.michaelthelin.spotify.requests.data.follow.legacy.FollowPlaylistRequest; -import se.michaelthelin.spotify.requests.data.follow.legacy.UnfollowPlaylistRequest; -import se.michaelthelin.spotify.requests.data.library.*; -import se.michaelthelin.spotify.requests.data.personalization.GetUsersTopArtistsAndTracksRequest; -import se.michaelthelin.spotify.requests.data.personalization.interfaces.IArtistTrackModelObject; -import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopArtistsRequest; -import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopTracksRequest; +import se.michaelthelin.spotify.requests.data.episodes.GetSeveralEpisodesRequest; +import se.michaelthelin.spotify.requests.data.episodes.GetUsersSavedEpisodesRequest; +import se.michaelthelin.spotify.requests.data.episodes.RemoveEpisodesForCurrentUserRequest; +import se.michaelthelin.spotify.requests.data.episodes.SaveEpisodesForCurrentUserRequest; +import se.michaelthelin.spotify.requests.data.genres.GetRecommendationGenresRequest; +import se.michaelthelin.spotify.requests.data.library.CheckUsersSavedItemsRequest; +import se.michaelthelin.spotify.requests.data.library.RemoveItemsFromLibraryRequest; +import se.michaelthelin.spotify.requests.data.library.SaveItemsToLibraryRequest; +import se.michaelthelin.spotify.requests.data.markets.GetAvailableMarketsRequest; +import se.michaelthelin.spotify.requests.data.users.CheckCurrentUserFollowsArtistsOrUsersRequest; +import se.michaelthelin.spotify.requests.data.users.CheckIfUserFollowsPlaylistRequest; +import se.michaelthelin.spotify.requests.data.users.FollowArtistsOrUsersRequest; +import se.michaelthelin.spotify.requests.data.users.FollowPlaylistRequest; +import se.michaelthelin.spotify.requests.data.users.GetUsersProfileRequest; +import se.michaelthelin.spotify.requests.data.users.UnfollowArtistsOrUsersRequest; +import se.michaelthelin.spotify.requests.data.users.interfaces.IArtistTrackModelObject; +import se.michaelthelin.spotify.requests.data.users.simplified.GetUsersTopArtistsRequest; +import se.michaelthelin.spotify.requests.data.users.simplified.GetUsersTopTracksRequest; import se.michaelthelin.spotify.requests.data.player.*; import se.michaelthelin.spotify.requests.data.playlists.*; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; +import se.michaelthelin.spotify.requests.data.search.SearchForItemRequest; import se.michaelthelin.spotify.requests.data.search.simplified.*; import se.michaelthelin.spotify.requests.data.search.simplified.special.SearchAlbumsSpecialRequest; import se.michaelthelin.spotify.requests.data.shows.GetShowRequest; -import se.michaelthelin.spotify.requests.data.shows.GetShowsEpisodesRequest; +import se.michaelthelin.spotify.requests.data.shows.GetShowEpisodesRequest; +import se.michaelthelin.spotify.requests.data.shows.CheckUsersSavedShowsRequest; +import se.michaelthelin.spotify.requests.data.shows.GetSeveralShowsRequest; +import se.michaelthelin.spotify.requests.data.shows.GetUsersSavedShowsRequest; +import se.michaelthelin.spotify.requests.data.shows.RemoveShowsForCurrentUserRequest; +import se.michaelthelin.spotify.requests.data.shows.SaveShowsForCurrentUserRequest; import se.michaelthelin.spotify.requests.data.tracks.*; -import se.michaelthelin.spotify.requests.data.users_profile.GetCurrentUsersProfileRequest; - +import se.michaelthelin.spotify.requests.data.users.GetCurrentUsersProfileRequest; +import se.michaelthelin.spotify.requests.data.users.GetFollowedArtistsRequest; +import se.michaelthelin.spotify.requests.data.users.GetUsersTopArtistsAndTracksRequest; import java.net.URI; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -547,9 +577,9 @@ public ClientCredentialsRequest.Builder clientCredentials() { } /** - * Returns an album with the ID given below. + * Get Spotify catalog information for a single album. * - * @param id The Spotify album ID of the album you're trying to retrieve. + * @param id The Spotify ID for the album. * @return A {@link GetAlbumRequest.Builder}. * @see Spotify: URLs & IDs */ @@ -560,20 +590,108 @@ public GetAlbumRequest.Builder getAlbum(String id) { } /** - * Returns the tracks of the album with the ID given below. + * Get Spotify catalog information about an album's tracks. + * Optional parameters can be used to limit the number of tracks returned. + * + * @param id The Spotify ID of the album. + * @return A {@link GetAlbumTracksRequest.Builder}. + * @see Spotify: URLs & IDs + */ + public GetAlbumTracksRequest.Builder getAlbumTracks(String id) { + return new GetAlbumTracksRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .id(id); + } + + /** + * Get Spotify catalog information for several albums identified by their Spotify IDs. + * + * @param ids A comma-separated list of the Spotify IDs for the albums. Maximum: 20 IDs. + * @return A {@link GetSeveralAlbumsRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetSeveralAlbumsRequest.Builder getSeveralAlbums(String ids) { + return new GetSeveralAlbumsRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Get an audiobook. + * + * @param id The Spotify ID for the audiobook. + * @return A {@link GetAudiobookRequest.Builder}. + * @see Spotify: URLs & IDs + */ + public GetAudiobookRequest.Builder getAudiobook(String id) { + return new GetAudiobookRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .id(id); + } + + /** + * Get Spotify catalog information for several audiobooks identified by their Spotify IDs. + * + * @param ids A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link GetSeveralAudiobooksRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetSeveralAudiobooksRequest.Builder getSeveralAudiobooks(String ids) { + return new GetSeveralAudiobooksRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Get Spotify catalog information about an audiobook's chapters. + * + * @param id The Spotify ID for the audiobook. + * @return A {@link GetAudiobookChaptersRequest.Builder}. + * @see Spotify: URLs & IDs + */ + public GetAudiobookChaptersRequest.Builder getAudiobookChapters(String id) { + return new GetAudiobookChaptersRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .id(id); + } + + /** + * Get Spotify catalog information for a single audiobook chapter. Chapters are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets. * - * @param id The Spotify ID of the album you're trying to retrieve. - * @return A {@link GetAlbumsTracksRequest.Builder}. + * @param id The Spotify ID for the chapter. + * @return A {@link GetChapterRequest.Builder}. * @see Spotify: URLs & IDs */ - public GetAlbumsTracksRequest.Builder getAlbumsTracks(String id) { - return new GetAlbumsTracksRequest.Builder(accessToken) + public GetChapterRequest.Builder getChapter(String id) { + return new GetChapterRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .id(id); } /** - * Get an artist. + * Get Spotify catalog information for several chapters identified by their Spotify IDs. + * + * @param ids A comma-separated list of the Spotify IDs for the chapters. Maximum: 50 IDs. + * @return A {@link GetSeveralChaptersRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetSeveralChaptersRequest.Builder getSeveralChapters(String ids) { + return new GetSeveralChaptersRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Get Spotify catalog information for a single artist identified by their unique Spotify ID. * * @param id The Spotify ID of the artist. * @return A {@link GetArtistRequest.Builder}. @@ -586,7 +704,7 @@ public GetArtistRequest.Builder getArtist(String id) { } /** - * Get the albums of a specific artist. + * Get Spotify catalog information about an artist's albums. * * @param id The Spotify ID of the artist. * @return A {@link GetArtistsAlbumsRequest.Builder}. @@ -599,27 +717,105 @@ public GetArtistsAlbumsRequest.Builder getArtistsAlbums(String id) { } /** - * Get artists related/similar to an artist. + * Get Spotify catalog information about artists similar to a given artist. Similarity is based on analysis of the Spotify community's listening history. * * @param id The Spotify ID of the artist. * @return A {@link GetArtistsRelatedArtistsRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. */ + @Deprecated public GetArtistsRelatedArtistsRequest.Builder getArtistsRelatedArtists(String id) { return new GetArtistsRelatedArtistsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .id(id); } + /** + * Get Spotify catalog information about an artist's top tracks by country. + * + * @param id The Spotify ID for the artist. + * @return A {@link GetArtistsTopTracksRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetArtistsTopTracksRequest.Builder getArtistsTopTracks(String id) { + return new GetArtistsTopTracksRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .id(id); + } + + /** + * Get Spotify catalog information for several artists based on their Spotify IDs. + * + * @param ids A comma-separated list of the Spotify IDs for the artists. Maximum: 50 IDs. + * @return A {@link GetSeveralArtistsRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetSeveralArtistsRequest.Builder getSeveralArtists(String ids) { + return new GetSeveralArtistsRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Get a list of categories used to tag items in Spotify. + * + * @return A {@link GetSeveralBrowseCategoriesRequest.Builder}. + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public GetSeveralBrowseCategoriesRequest.Builder getSeveralBrowseCategories() { + return new GetSeveralBrowseCategoriesRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port); + } + + /** + * Get a single category used to tag items in Spotify (on, for example, the Spotify player's "Browse" tab). + * + * @param category_id The Spotify category ID for the category. + * @return A {@link GetSingleBrowseCategoryRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public GetSingleBrowseCategoryRequest.Builder getSingleBrowseCategory(String category_id) { + return new GetSingleBrowseCategoryRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .category_id(category_id); + } + + /** + * Get a list of new album releases featured in Spotify. + * + * @return A {@link GetNewReleasesRequest.Builder}. + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public GetNewReleasesRequest.Builder getNewReleases() { + return new GetNewReleasesRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port); + } + /** * Get the playlists from a specific category. * * @param category_id The Spotify category ID for the category. - * @return A {@link GetCategorysPlaylistsRequest.Builder}. + * @return A {@link GetCategoryPlaylistsRequest.Builder}. * @see Spotify: URLs & IDs + + * + * @deprecated Use the Search API instead. */ - public GetCategorysPlaylistsRequest.Builder getCategorysPlaylists(String category_id) { - return new GetCategorysPlaylistsRequest.Builder(accessToken) + @Deprecated + public GetCategoryPlaylistsRequest.Builder getCategoryPlaylists(String category_id) { + return new GetCategoryPlaylistsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .category_id(category_id); } @@ -627,10 +823,13 @@ public GetCategorysPlaylistsRequest.Builder getCategorysPlaylists(String categor /** * Get "Featured Playlists" of different countries which may match a specific language. * - * @return A {@link GetListOfFeaturedPlaylistsRequest.Builder}. + * @return A {@link GetFeaturedPlaylistsRequest.Builder}. + * + * @deprecated This endpoint has been deprecated by Spotify. */ - public GetListOfFeaturedPlaylistsRequest.Builder getListOfFeaturedPlaylists() { - return new GetListOfFeaturedPlaylistsRequest.Builder(accessToken) + @Deprecated + public GetFeaturedPlaylistsRequest.Builder getFeaturedPlaylists() { + return new GetFeaturedPlaylistsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -638,7 +837,10 @@ public GetListOfFeaturedPlaylistsRequest.Builder getListOfFeaturedPlaylists() { * Create a playlist-style listening experience based on seed artists, tracks and genres. * * @return A {@link GetRecommendationsRequest.Builder}. + * + * @deprecated This endpoint has been deprecated by Spotify. */ + @Deprecated public GetRecommendationsRequest.Builder getRecommendations() { return new GetRecommendationsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); @@ -647,15 +849,18 @@ public GetRecommendationsRequest.Builder getRecommendations() { /** * Retrieve a list of available genres seed parameter values for recommendations. * - * @return A {@link GetAvailableGenreSeedsRequest.Builder}. + * @return A {@link GetRecommendationGenresRequest.Builder}. + * + * @deprecated This endpoint has been deprecated by Spotify. */ - public GetAvailableGenreSeedsRequest.Builder getAvailableGenreSeeds() { - return new GetAvailableGenreSeedsRequest.Builder(accessToken) + @Deprecated + public GetRecommendationGenresRequest.Builder getRecommendationGenres() { + return new GetRecommendationGenresRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } /** - * Get an episode. + * Get Spotify catalog information for a single episode identified by its unique Spotify ID. * * @param id The Spotify ID of the episode. * @return A {@link GetEpisodeRequest.Builder}. @@ -667,6 +872,22 @@ public GetEpisodeRequest.Builder getEpisode(String id) { .id(id); } + /** + * Get Spotify catalog information for several episodes based on their Spotify IDs. + * + * @param ids A comma-separated list of the Spotify IDs for the episodes. Maximum: 50 IDs. + * @return A {@link GetSeveralEpisodesRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetSeveralEpisodesRequest.Builder getSeveralEpisodes(String ids) { + return new GetSeveralEpisodesRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + /** * Check to see if the current user is following one or more artists or other Spotify users. * @@ -674,7 +895,11 @@ public GetEpisodeRequest.Builder getEpisode(String id) { * @param ids A list of the artist or the user Spotify IDs to check. Maximum: 50 IDs. * @return A {@link CheckCurrentUserFollowsArtistsOrUsersRequest.Builder}. * @see Spotify: URLs & IDs + + * + * @deprecated This endpoint has been deprecated by Spotify. */ + @Deprecated public CheckCurrentUserFollowsArtistsOrUsersRequest.Builder checkCurrentUserFollowsArtistsOrUsers( ModelObjectType type, String[] ids) { return new CheckCurrentUserFollowsArtistsOrUsersRequest.Builder(accessToken) @@ -686,37 +911,19 @@ public CheckCurrentUserFollowsArtistsOrUsersRequest.Builder checkCurrentUserFoll /** * Check to see if one or more Spotify users are following a specified playlist. * - * @param owner_id The Spotify User ID of the person who owns the playlist. * @param playlist_id The Spotify ID of the playlist. * @param ids A list of Spotify User IDs; the IDs of the users that you want to check to see if they * follow the playlist. Maximum: 5 IDs. - * @return A {@link CheckUsersFollowPlaylistRequest.Builder}. + * @return A {@link CheckIfUserFollowsPlaylistRequest.Builder}. * @see Spotify: URLs & IDs - * - * @deprecated since the endpoint no longer needs the owner_id param. Use {@link #checkUsersFollowPlaylist(String, String[])} instead. - */ - @Deprecated(since = "8.3.7") - public CheckUsersFollowPlaylistRequest.Builder checkUsersFollowPlaylist( - String owner_id, String playlist_id, String[] ids) { - return new CheckUsersFollowPlaylistRequest.Builder(accessToken) - .setDefaults(httpManager, scheme, host, port) - .owner_id(owner_id) - .playlist_id(playlist_id) - .ids(concat(ids, ',')); - } - /** - * Check to see if one or more Spotify users are following a specified playlist. * - * @param playlist_id The Spotify ID of the playlist. - * @param ids A list of Spotify User IDs; the IDs of the users that you want to check to see if they - * follow the playlist. Maximum: 5 IDs. - * @return A {@link CheckUsersFollowPlaylistRequest.Builder}. - * @see Spotify: URLs & IDs + * @deprecated This endpoint has been deprecated by Spotify. */ - public CheckUsersFollowPlaylistRequest.Builder checkUsersFollowPlaylist( + @Deprecated + public CheckIfUserFollowsPlaylistRequest.Builder checkIfUserFollowsPlaylist( String playlist_id, String[] ids) { - return new CheckUsersFollowPlaylistRequest.Builder(accessToken) + return new CheckIfUserFollowsPlaylistRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id) .ids(concat(ids, ',')); @@ -729,7 +936,11 @@ public CheckUsersFollowPlaylistRequest.Builder checkUsersFollowPlaylist( * @param ids A list of the artist or the user Spotify IDs. Maximum: 50 IDs. * @return A {@link FollowArtistsOrUsersRequest.Builder}. * @see Spotify: URLs & IDs + + * + * @deprecated This endpoint has been deprecated by Spotify. */ + @Deprecated public FollowArtistsOrUsersRequest.Builder followArtistsOrUsers(ModelObjectType type, String[] ids) { return new FollowArtistsOrUsersRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) @@ -744,7 +955,10 @@ public FollowArtistsOrUsersRequest.Builder followArtistsOrUsers(ModelObjectType * @param ids A list of the artist or the user Spotify IDs. Maximum: 50 IDs. * @return A {@link FollowArtistsOrUsersRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. */ + @Deprecated public FollowArtistsOrUsersRequest.Builder followArtistsOrUsers(ModelObjectType type, JsonArray ids) { return new FollowArtistsOrUsersRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) @@ -755,7 +969,6 @@ public FollowArtistsOrUsersRequest.Builder followArtistsOrUsers(ModelObjectType /** * Add the current user as a follower of a playlist. * - * @param owner_id The Spotify user ID of the person who owns the playlist. * @param playlist_id The Spotify ID of the playlist. Any playlist can be followed, regardless of its * public/private status, as long as you know its playlist ID. * @param public_ Default: true. If true the playlist will be included in user's public playlists, if false it @@ -763,29 +976,13 @@ public FollowArtistsOrUsersRequest.Builder followArtistsOrUsers(ModelObjectType * playlist-modify-private scope. * @return A {@link FollowPlaylistRequest.Builder}. * @see Spotify: URLs & IDs - */ - public FollowPlaylistRequest.Builder followPlaylist(String owner_id, String playlist_id, boolean public_) { - return new FollowPlaylistRequest.Builder(accessToken) - .setDefaults(httpManager, scheme, host, port) - .owner_id(owner_id) - .playlist_id(playlist_id) - .public_(public_); - } - - /** - * Add the current user as a follower of a playlist. * - * @param playlist_id The Spotify ID of the playlist. Any playlist can be followed, regardless of its - * public/private status, as long as you know its playlist ID. - * @param public_ Default: true. If true the playlist will be included in user's public playlists, if false it - * will remain private. To be able to follow playlists privately, the user must have granted the - * playlist-modify-private scope. - * @return A {@link FollowPlaylistRequest.Builder}. - * @see Spotify: URLs & IDs + * @deprecated This endpoint has been deprecated by Spotify. */ - public se.michaelthelin.spotify.requests.data.follow.FollowPlaylistRequest.Builder followPlaylist(String playlist_id, boolean public_) { - return new se.michaelthelin.spotify.requests.data.follow.FollowPlaylistRequest.Builder(accessToken) + @Deprecated + public se.michaelthelin.spotify.requests.data.users.FollowPlaylistRequest.Builder followPlaylist(String playlist_id, boolean public_) { + return new se.michaelthelin.spotify.requests.data.users.FollowPlaylistRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id) .public_(public_); @@ -796,11 +993,11 @@ public se.michaelthelin.spotify.requests.data.follow.FollowPlaylistRequest.Build * Get the current user’s followed artists. * * @param type The ID type: currently only artist is supported. - * @return A {@link GetUsersFollowedArtistsRequest.Builder}. + * @return A {@link GetFollowedArtistsRequest.Builder}. * @see Spotify: URLs & IDs */ - public GetUsersFollowedArtistsRequest.Builder getUsersFollowedArtists(ModelObjectType type) { - return new GetUsersFollowedArtistsRequest.Builder(accessToken) + public GetFollowedArtistsRequest.Builder getFollowedArtists(ModelObjectType type) { + return new GetFollowedArtistsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .type(type); } @@ -812,7 +1009,10 @@ public GetUsersFollowedArtistsRequest.Builder getUsersFollowedArtists(ModelObjec * @param ids A list of the artist or the user Spotify IDs. Maximum: 50 IDs. * @return A {@link UnfollowArtistsOrUsersRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. */ + @Deprecated public UnfollowArtistsOrUsersRequest.Builder unfollowArtistsOrUsers(ModelObjectType type, String[] ids) { return new UnfollowArtistsOrUsersRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) @@ -827,7 +1027,10 @@ public UnfollowArtistsOrUsersRequest.Builder unfollowArtistsOrUsers(ModelObjectT * @param ids A JSON array of the artist or the user Spotify IDs. Maximum: 50 IDs. * @return A {@link UnfollowArtistsOrUsersRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. */ + @Deprecated public UnfollowArtistsOrUsersRequest.Builder unfollowArtistsOrUsers(ModelObjectType type, JsonArray ids) { return new UnfollowArtistsOrUsersRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) @@ -836,40 +1039,32 @@ public UnfollowArtistsOrUsersRequest.Builder unfollowArtistsOrUsers(ModelObjectT } /** - * Remove the specified user as a follower of a playlist. + * Remove the current user as a follower of a playlist. * - * @param owner_id The owners username. * @param playlist_id The playlist's ID. - * @return An {@link UnfollowPlaylistRequest.Builder}. + * @return An {@link se.michaelthelin.spotify.requests.data.users.UnfollowPlaylistRequest.Builder}. * @see Spotify: URLs & IDs - */ - public UnfollowPlaylistRequest.Builder unfollowPlaylist(String owner_id, String playlist_id) { - return new UnfollowPlaylistRequest.Builder(accessToken) - .setDefaults(httpManager, scheme, host, port) - .owner_id(owner_id) - .playlist_id(playlist_id); - } - /** - * Remove the current user as a follower of a playlist. * - * @param playlist_id The playlist's ID. - * @return An {@link se.michaelthelin.spotify.requests.data.follow.UnfollowPlaylistRequest.Builder}. - * @see Spotify: URLs & IDs + * @deprecated This endpoint has been deprecated by Spotify. */ - public se.michaelthelin.spotify.requests.data.follow.UnfollowPlaylistRequest.Builder unfollowPlaylist(String playlist_id) { - return new se.michaelthelin.spotify.requests.data.follow.UnfollowPlaylistRequest.Builder(accessToken) + @Deprecated + public se.michaelthelin.spotify.requests.data.users.UnfollowPlaylistRequest.Builder unfollowPlaylist(String playlist_id) { + return new se.michaelthelin.spotify.requests.data.users.UnfollowPlaylistRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id); } /** - * Check if an album is saved in the user's "Your Music" library. + * Check if one or more albums are already saved in the current Spotify user's 'Your Music' library. * * @param ids The album IDs to check for in the user's Your Music library. Maximum: 50 IDs. * @return A {@link CheckUsersSavedAlbumsRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated Use {@link se.michaelthelin.spotify.requests.data.library.CheckLibraryContainsRequest} instead. */ + @Deprecated public CheckUsersSavedAlbumsRequest.Builder checkUsersSavedAlbums(String... ids) { return new CheckUsersSavedAlbumsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) @@ -877,12 +1072,15 @@ public CheckUsersSavedAlbumsRequest.Builder checkUsersSavedAlbums(String... ids) } /** - * Check if a show is saved in the users "Your Music" library. + * Check if one or more shows are already saved in the current Spotify user's library. * * @param ids The show IDs to check for in the user's Your Music library. Maximum: 50 IDs. * @return A {@link CheckUsersSavedShowsRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated Use {@link se.michaelthelin.spotify.requests.data.library.CheckLibraryContainsRequest} instead. */ + @Deprecated public CheckUsersSavedShowsRequest.Builder checkUsersSavedShows(String... ids) { return new CheckUsersSavedShowsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) @@ -890,13 +1088,15 @@ public CheckUsersSavedShowsRequest.Builder checkUsersSavedShows(String... ids) { } /** - * Check if one or more episodes is already saved in the current Spotify user's 'Your Episodes' library. - * This endpoint is in beta and could change without warning. + * Check if one or more episodes are already saved in the current Spotify user's 'Your Episodes' library. * * @param ids The episode IDs to check for in the user's 'Your Episodes' library. Maximum: 50 IDs. * @return A {@link CheckUsersSavedEpisodesRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated Use {@link se.michaelthelin.spotify.requests.data.library.CheckLibraryContainsRequest} instead. */ + @Deprecated public CheckUsersSavedEpisodesRequest.Builder checkUsersSavedEpisodes(String... ids) { return new CheckUsersSavedEpisodesRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) @@ -904,25 +1104,45 @@ public CheckUsersSavedEpisodesRequest.Builder checkUsersSavedEpisodes(String... } /** - * Check if a track is saved in the user's "Your Music" library. + * Check if one or more tracks are already saved in the current Spotify user's 'Your Music' library. * * @param ids The track IDs to check for in the user's Your Music library. Maximum: 50 IDs. * @return A {@link CheckUsersSavedTracksRequest.Builder}. * @see Spotify: URLs & IDs + * + * @deprecated Use {@link se.michaelthelin.spotify.requests.data.library.CheckLibraryContainsRequest} instead. */ + @Deprecated public CheckUsersSavedTracksRequest.Builder checkUsersSavedTracks(String... ids) { return new CheckUsersSavedTracksRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .ids(concat(ids, ',')); } + /** + * Check if one or more audiobooks are already saved in the current Spotify user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link CheckUsersSavedAudiobooksRequest.Builder}. + * @see Spotify: URLs & IDs + + * + * @deprecated Use {@link se.michaelthelin.spotify.requests.data.library.CheckLibraryContainsRequest} instead. + */ + @Deprecated + public CheckUsersSavedAudiobooksRequest.Builder checkUsersSavedAudiobooks(String ids) { + return new CheckUsersSavedAudiobooksRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + /** * Get a list of the albums saved in the current Spotify user’s "Your Music" library. * - * @return A {@link GetCurrentUsersSavedAlbumsRequest.Builder}. + * @return A {@link GetUsersSavedAlbumsRequest.Builder}. */ - public GetCurrentUsersSavedAlbumsRequest.Builder getCurrentUsersSavedAlbums() { - return new GetCurrentUsersSavedAlbumsRequest.Builder(accessToken) + public GetUsersSavedAlbumsRequest.Builder getUsersSavedAlbums() { + return new GetUsersSavedAlbumsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -947,6 +1167,16 @@ public GetUsersSavedEpisodesRequest.Builder getUsersSavedEpisodes() { .setDefaults(httpManager, scheme, host, port); } + /** + * Get a list of the audiobooks saved in the current Spotify user's library. + * + * @return A {@link GetUsersSavedAudiobooksRequest.Builder}. + */ + public GetUsersSavedAudiobooksRequest.Builder getUsersSavedAudiobooks() { + return new GetUsersSavedAudiobooksRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port); + } + /** * Get an user's "Your Music" tracks. * @@ -958,25 +1188,184 @@ public GetUsersSavedTracksRequest.Builder getUsersSavedTracks() { } /** - * Save a list of Spotify URIs to the user's library. + * Add one or more items to the current user's library. Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, users, and playlists. * * @param uris The Spotify URIs to save. Maximum: 50 URIs. - * @return A {@link SaveToLibraryRequest.Builder}. + * @return A {@link SaveItemsToLibraryRequest.Builder}. + */ + public SaveItemsToLibraryRequest.Builder saveItemsToLibrary(JsonArray uris) { + return new SaveItemsToLibraryRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .uris(uris); + } + + /** + * Save one or more audiobooks to the current Spotify user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link SaveAudiobooksForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + */ + public SaveAudiobooksForCurrentUserRequest.Builder saveAudiobooksForCurrentUser(String ids) { + return new SaveAudiobooksForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Remove one or more audiobooks from the current Spotify user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link RemoveAudiobooksForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + */ + public RemoveAudiobooksForCurrentUserRequest.Builder removeAudiobooksForCurrentUser(String ids) { + return new RemoveAudiobooksForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Check if one or more items are already saved in the current Spotify user's library. + * + * @param uris A comma-separated list of the Spotify URIs for the items. Maximum: 40 URIs. + * @return A {@link CheckUsersSavedItemsRequest.Builder}. + * @see Spotify: URLs & IDs */ - public SaveToLibraryRequest.Builder saveToLibrary(JsonArray uris) { - return new SaveToLibraryRequest.Builder(accessToken) + public CheckUsersSavedItemsRequest.Builder checkUsersSavedItems(String uris) { + return new CheckUsersSavedItemsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .uris(uris); } + /** + * Save one or more albums to the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the albums. Maximum: 50 IDs. + * @return A {@link SaveAlbumsForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public SaveAlbumsForCurrentUserRequest.Builder saveAlbumsForCurrentUser(String ids) { + return new SaveAlbumsForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Remove one or more albums from the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the albums. Maximum: 50 IDs. + * @return A {@link RemoveAlbumsForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public RemoveAlbumsForCurrentUserRequest.Builder removeAlbumsForCurrentUser(String ids) { + return new RemoveAlbumsForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Save one or more episodes to the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the episodes. Maximum: 50 IDs. + * @return A {@link SaveEpisodesForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public SaveEpisodesForCurrentUserRequest.Builder saveEpisodesForCurrentUser(String ids) { + return new SaveEpisodesForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Remove one or more episodes from the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the episodes. Maximum: 50 IDs. + * @return A {@link RemoveEpisodesForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public RemoveEpisodesForCurrentUserRequest.Builder removeEpisodesForCurrentUser(String ids) { + return new RemoveEpisodesForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Save one or more shows to the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the shows. Maximum: 50 IDs. + * @return A {@link SaveShowsForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public SaveShowsForCurrentUserRequest.Builder saveShowsForCurrentUser(String ids) { + return new SaveShowsForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Remove one or more shows from the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the shows. Maximum: 50 IDs. + * @return A {@link RemoveShowsForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public RemoveShowsForCurrentUserRequest.Builder removeShowsForCurrentUser(String ids) { + return new RemoveShowsForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Save one or more tracks to the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the tracks. Maximum: 50 IDs. + * @return A {@link SaveTracksForCurrentUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public SaveTracksForCurrentUserRequest.Builder saveTracksForCurrentUser(String ids) { + return new SaveTracksForCurrentUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Remove one or more tracks from the current user's library. + * + * @param ids A comma-separated list of the Spotify IDs for the tracks. Maximum: 50 IDs. + * @return A {@link RemoveUsersSavedTracksRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public RemoveUsersSavedTracksRequest.Builder removeUsersSavedTracks(String ids) { + return new RemoveUsersSavedTracksRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + /** * Remove a list of Spotify URIs from the user's library. * * @param uris The Spotify URIs to remove. Maximum: 50 URIs. - * @return A {@link RemoveFromLibraryRequest.Builder}. + * @return A {@link RemoveItemsFromLibraryRequest.Builder}. */ - public RemoveFromLibraryRequest.Builder removeFromLibrary(JsonArray uris) { - return new RemoveFromLibraryRequest.Builder(accessToken) + public RemoveItemsFromLibraryRequest.Builder removeItemsFromLibrary(JsonArray uris) { + return new RemoveItemsFromLibraryRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .uris(uris); } @@ -1024,10 +1413,10 @@ public GetUsersTopTracksRequest.Builder getUsersTopTracks() { /** * Get information about the user's current playback state, including context, track progress, and active device. * - * @return A {@link GetInformationAboutUsersCurrentPlaybackRequest.Builder}. + * @return A {@link GetPlaybackStateRequest.Builder}. */ - public GetInformationAboutUsersCurrentPlaybackRequest.Builder getInformationAboutUsersCurrentPlayback() { - return new GetInformationAboutUsersCurrentPlaybackRequest.Builder(accessToken) + public GetPlaybackStateRequest.Builder getPlaybackState() { + return new GetPlaybackStateRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -1040,40 +1429,40 @@ public GetInformationAboutUsersCurrentPlaybackRequest.Builder getInformationAbou * Any tracks listened to while the user had "Private Session" enabled in their client will not be returned in the * list of recently played tracks. * - * @return A {@link GetCurrentUsersRecentlyPlayedTracksRequest.Builder}. + * @return A {@link GetRecentlyPlayedTracksRequest.Builder}. */ - public GetCurrentUsersRecentlyPlayedTracksRequest.Builder getCurrentUsersRecentlyPlayedTracks() { - return new GetCurrentUsersRecentlyPlayedTracksRequest.Builder(accessToken) + public GetRecentlyPlayedTracksRequest.Builder getRecentlyPlayedTracks() { + return new GetRecentlyPlayedTracksRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } /** * Get information about an user's available devices. * - * @return A {@link GetUsersAvailableDevicesRequest.Builder}. + * @return A {@link GetAvailableDevicesRequest.Builder}. */ - public GetUsersAvailableDevicesRequest.Builder getUsersAvailableDevices() { - return new GetUsersAvailableDevicesRequest.Builder(accessToken) + public GetAvailableDevicesRequest.Builder getAvailableDevices() { + return new GetAvailableDevicesRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } /** * Get the object currently being played on the user's Spotify account. * - * @return A {@link GetUsersCurrentlyPlayingTrackRequest.Builder}. + * @return A {@link GetCurrentlyPlayingTrackRequest.Builder}. */ - public GetUsersCurrentlyPlayingTrackRequest.Builder getUsersCurrentlyPlayingTrack() { - return new GetUsersCurrentlyPlayingTrackRequest.Builder(accessToken) + public GetCurrentlyPlayingTrackRequest.Builder getCurrentlyPlayingTrack() { + return new GetCurrentlyPlayingTrackRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } /** * Pause playback on the user's account. * - * @return A {@link PauseUsersPlaybackRequest.Builder}. + * @return A {@link PausePlaybackRequest.Builder}. */ - public PauseUsersPlaybackRequest.Builder pauseUsersPlayback() { - return new PauseUsersPlaybackRequest.Builder(accessToken) + public PausePlaybackRequest.Builder pausePlayback() { + return new PausePlaybackRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -1082,10 +1471,10 @@ public PauseUsersPlaybackRequest.Builder pauseUsersPlayback() { * * @param position_ms The position in milliseconds to seek to. Must be a positive number. Passing in a position that * is greater than the length of the track will cause the player to start playing the next song. - * @return A {@link SeekToPositionInCurrentlyPlayingTrackRequest.Builder}. + * @return A {@link SeekToPositionRequest.Builder}. */ - public SeekToPositionInCurrentlyPlayingTrackRequest.Builder seekToPositionInCurrentlyPlayingTrack(int position_ms) { - return new SeekToPositionInCurrentlyPlayingTrackRequest.Builder(accessToken) + public SeekToPositionRequest.Builder seekToPosition(int position_ms) { + return new SeekToPositionRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .position_ms(position_ms); } @@ -1095,10 +1484,10 @@ public SeekToPositionInCurrentlyPlayingTrackRequest.Builder seekToPositionInCurr * * @param state track, context or off. track will repeat the current track. context will repeat the current * context. off will turn repeat off. - * @return A {@link SetRepeatModeOnUsersPlaybackRequest.Builder}. + * @return A {@link SetRepeatModeRequest.Builder}. */ - public SetRepeatModeOnUsersPlaybackRequest.Builder setRepeatModeOnUsersPlayback(String state) { - return new SetRepeatModeOnUsersPlaybackRequest.Builder(accessToken) + public SetRepeatModeRequest.Builder setRepeatMode(String state) { + return new SetRepeatModeRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .state(state); } @@ -1107,10 +1496,10 @@ public SetRepeatModeOnUsersPlaybackRequest.Builder setRepeatModeOnUsersPlayback( * Set the volume for the user's current playback device. * * @param volume_percent Integer. The volume to set. Must be a value from 0 to 100 inclusive. - * @return A {@link SetVolumeForUsersPlaybackRequest.Builder}. + * @return A {@link SetPlaybackVolumeRequest.Builder}. */ - public SetVolumeForUsersPlaybackRequest.Builder setVolumeForUsersPlayback(int volume_percent) { - return new SetVolumeForUsersPlaybackRequest.Builder(accessToken) + public SetPlaybackVolumeRequest.Builder setPlaybackVolume(int volume_percent) { + return new SetPlaybackVolumeRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .volume_percent(volume_percent); } @@ -1118,10 +1507,10 @@ public SetVolumeForUsersPlaybackRequest.Builder setVolumeForUsersPlayback(int vo /** * Skips to next track in the user's queue. * - * @return A {@link SkipUsersPlaybackToNextTrackRequest.Builder}. + * @return A {@link SkipToNextRequest.Builder}. */ - public SkipUsersPlaybackToNextTrackRequest.Builder skipUsersPlaybackToNextTrack() { - return new SkipUsersPlaybackToNextTrackRequest.Builder(accessToken) + public SkipToNextRequest.Builder skipToNext() { + return new SkipToNextRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -1129,23 +1518,23 @@ public SkipUsersPlaybackToNextTrackRequest.Builder skipUsersPlaybackToNextTrack( * Skips to previous track in the user's queue. *

* Note: This will ALWAYS skip to the previous track, regardless of the current track’s progress. Returning to - * the start of the current track should be performed using the {@link #seekToPositionInCurrentlyPlayingTrack(int)} + * the start of the current track should be performed using the {@link #seekToPosition(int)} * method. * - * @return A {@link SkipUsersPlaybackToPreviousTrackRequest.Builder}. + * @return A {@link SkipToPreviousRequest.Builder}. */ - public SkipUsersPlaybackToPreviousTrackRequest.Builder skipUsersPlaybackToPreviousTrack() { - return new SkipUsersPlaybackToPreviousTrackRequest.Builder(accessToken) + public SkipToPreviousRequest.Builder skipToPrevious() { + return new SkipToPreviousRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } /** * Start a new context or resume current playback on the user's active device. * - * @return A {@link StartResumeUsersPlaybackRequest.Builder}. + * @return A {@link StartResumePlaybackRequest.Builder}. */ - public StartResumeUsersPlaybackRequest.Builder startResumeUsersPlayback() { - return new StartResumeUsersPlaybackRequest.Builder(accessToken) + public StartResumePlaybackRequest.Builder startResumePlayback() { + return new StartResumePlaybackRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -1153,10 +1542,10 @@ public StartResumeUsersPlaybackRequest.Builder startResumeUsersPlayback() { * Toggle shuffle on or off for user's playback. * * @param state true: Shuffle user's playback. false: Do not shuffle user's playback. - * @return A {@link ToggleShuffleForUsersPlaybackRequest.Builder}. + * @return A {@link TogglePlaybackShuffleRequest.Builder}. */ - public ToggleShuffleForUsersPlaybackRequest.Builder toggleShuffleForUsersPlayback(boolean state) { - return new ToggleShuffleForUsersPlaybackRequest.Builder(accessToken) + public TogglePlaybackShuffleRequest.Builder togglePlaybackShuffle(boolean state) { + return new TogglePlaybackShuffleRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .state(state); } @@ -1166,10 +1555,10 @@ public ToggleShuffleForUsersPlaybackRequest.Builder toggleShuffleForUsersPlaybac * * @param device_ids A JSON array containing the ID of the device on which playback should be started/transferred. *
Note: Although an array is accepted, only a single device_id is currently supported. - * @return A {@link TransferUsersPlaybackRequest.Builder}. + * @return A {@link TransferPlaybackRequest.Builder}. */ - public TransferUsersPlaybackRequest.Builder transferUsersPlayback(JsonArray device_ids) { - return new TransferUsersPlaybackRequest.Builder(accessToken) + public TransferPlaybackRequest.Builder transferPlayback(JsonArray device_ids) { + return new TransferPlaybackRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .device_ids(device_ids); } @@ -1178,21 +1567,21 @@ public TransferUsersPlaybackRequest.Builder transferUsersPlayback(JsonArray devi * Add a track or an episode to the end of the user's current playback queue. * * @param uri The uri of the item to add to the queue. Must be a track or an episode uri. - * @return A {@link AddItemToUsersPlaybackQueueRequest.Builder}. + * @return A {@link AddItemToPlaybackQueueRequest.Builder}. * @see Spotify: URLs & IDs */ - public AddItemToUsersPlaybackQueueRequest.Builder addItemToUsersPlaybackQueue(String uri) { - return new AddItemToUsersPlaybackQueueRequest.Builder(accessToken) + public AddItemToPlaybackQueueRequest.Builder addItemToPlaybackQueue(String uri) { + return new AddItemToPlaybackQueueRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .uri(uri); } /** * Receive all items from the user's current playback queue. - * @return An {@link GetTheUsersQueueRequest.Builder}. + * @return An {@link GetUsersQueueRequest.Builder}. */ - public GetTheUsersQueueRequest.Builder getTheUsersQueue() { - return new GetTheUsersQueueRequest.Builder(accessToken) + public GetUsersQueueRequest.Builder getUsersQueue() { + return new GetUsersQueueRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -1228,15 +1617,51 @@ public AddItemsToPlaylistRequest.Builder addItemsToPlaylist(String playlist_id, .uris(uris); } + /** + * @deprecated Use the new endpoints instead. + * Add items to a playlist (deprecated endpoint). + *

+ * Note: If you want to add a large number of items (>50), use {@link #addItemsToPlaylistDeprecated(String, JsonArray)} to not exceed + * the maximum URI length. + * @param playlist_id The playlists ID. + * @param uris URIs of the tracks or episodes to add. Maximum: 100 item URIs. + * @return An {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + * @see Spotify: URLs & IDs + */ + @Deprecated + public AddItemsToPlaylistDeprecatedRequest.Builder addItemsToPlaylistDeprecated(String playlist_id, String[] uris) { + return new AddItemsToPlaylistDeprecatedRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .playlist_id(playlist_id) + .uris(concat(uris, ',')); + } + + /** + * @deprecated Use the new endpoints instead. + * Add items to a playlist (deprecated endpoint). + * + * @param playlist_id The playlists ID. + * @param uris URIs of the tracks or episodes to add. Maximum: 100 item URIs. + * @return An {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + * @see Spotify: URLs & IDs + */ + @Deprecated + public AddItemsToPlaylistDeprecatedRequest.Builder addItemsToPlaylistDeprecated(String playlist_id, JsonArray uris) { + return new AddItemsToPlaylistDeprecatedRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .playlist_id(playlist_id) + .uris(uris); + } + /** * Update a playlists properties. * * @param playlist_id The playlists ID. - * @return A {@link ChangePlaylistsDetailsRequest.Builder}. + * @return A {@link ChangePlaylistDetailsRequest.Builder}. * @see Spotify: URLs & IDs */ - public ChangePlaylistsDetailsRequest.Builder changePlaylistsDetails(String playlist_id) { - return new ChangePlaylistsDetailsRequest.Builder(accessToken) + public ChangePlaylistDetailsRequest.Builder changePlaylistDetails(String playlist_id) { + return new ChangePlaylistDetailsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id); } @@ -1253,13 +1678,45 @@ public CreatePlaylistRequest.Builder createPlaylist(String name) { .name(name); } + /** + * Get a list of the playlists owned or followed by a Spotify user. + * + * @param user_id The user's Spotify user ID. + * @return A {@link GetUsersPlaylistsRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public GetUsersPlaylistsRequest.Builder getUsersPlaylists(String user_id) { + return new GetUsersPlaylistsRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .user_id(user_id); + } + + /** + * Create a playlist for a Spotify user. + * + * @param user_id The user's Spotify user ID. + * @param name The name for the new playlist. + * @return A {@link CreatePlaylistForUserRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public CreatePlaylistForUserRequest.Builder createPlaylistForUser(String user_id, String name) { + return new CreatePlaylistForUserRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .user_id(user_id) + .name(name); + } + /** * Get a list of the playlists owned or followed by the current Spotify user. * - * @return A {@link GetListOfCurrentUsersPlaylistsRequest.Builder}. + * @return A {@link GetCurrentUsersPlaylistsRequest.Builder}. */ - public GetListOfCurrentUsersPlaylistsRequest.Builder getListOfCurrentUsersPlaylists() { - return new GetListOfCurrentUsersPlaylistsRequest.Builder(accessToken) + public GetCurrentUsersPlaylistsRequest.Builder getCurrentUsersPlaylists() { + return new GetCurrentUsersPlaylistsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port); } @@ -1293,11 +1750,11 @@ public GetPlaylistCoverImageRequest.Builder getPlaylistCoverImage(String playlis * Get a playlist's items. * * @param playlist_id The playlists ID. - * @return A {@link GetPlaylistsItemsRequest.Builder}. + * @return A {@link GetPlaylistItemsRequest.Builder}. * @see Spotify: URLs & IDs */ - public GetPlaylistsItemsRequest.Builder getPlaylistsItems(String playlist_id) { - return new GetPlaylistsItemsRequest.Builder(accessToken) + public GetPlaylistItemsRequest.Builder getPlaylistItems(String playlist_id) { + return new GetPlaylistItemsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id); } @@ -1307,12 +1764,12 @@ public GetPlaylistsItemsRequest.Builder getPlaylistsItems(String playlist_id) { * * @param playlist_id The playlists ID. * @param tracks URIs of the items to remove. Maximum: 100 track or episode URIs. - * @return A {@link RemoveItemsFromPlaylistRequest.Builder}. + * @return A {@link RemovePlaylistItemsRequest.Builder}. * @see Spotify: URLs & IDs */ - public RemoveItemsFromPlaylistRequest.Builder removeItemsFromPlaylist( + public RemovePlaylistItemsRequest.Builder removePlaylistItems( String playlist_id, JsonArray tracks) { - return new RemoveItemsFromPlaylistRequest.Builder(accessToken) + return new RemovePlaylistItemsRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id) .tracks(tracks); @@ -1329,11 +1786,11 @@ public RemoveItemsFromPlaylistRequest.Builder removeItemsFromPlaylist( * @param range_start The position of the first item to be reordered. * @param insert_before The position where the items should be inserted. To reorder the items to the end of the * playlist, simply set insert_before to the position after the last item. - * @return A {@link ReorderPlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReorderRequest.Builder}. * @see Spotify: URLs & IDs */ - public ReorderPlaylistsItemsRequest.Builder reorderPlaylistsItems(String playlist_id, int range_start, int insert_before) { - return new ReorderPlaylistsItemsRequest.Builder(accessToken) + public UpdatePlaylistsItemsReorderRequest.Builder updatePlaylistsItemsReorder(String playlist_id, int range_start, int insert_before) { + return new UpdatePlaylistsItemsReorderRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id) .range_start(range_start) @@ -1345,11 +1802,11 @@ public ReorderPlaylistsItemsRequest.Builder reorderPlaylistsItems(String playlis * * @param playlist_id The playlists ID. * @param uris URIs of the items to set. Maximum: 100 track or episode URIs. - * @return A {@link ReplacePlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReplaceRequest.Builder}. * @see Spotify: URLs & IDs */ - public ReplacePlaylistsItemsRequest.Builder replacePlaylistsItems(String playlist_id, String[] uris) { - return new ReplacePlaylistsItemsRequest.Builder(accessToken) + public UpdatePlaylistsItemsReplaceRequest.Builder updatePlaylistsItemsReplace(String playlist_id, String[] uris) { + return new UpdatePlaylistsItemsReplaceRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id) .uris(concat(uris, ',')); @@ -1360,11 +1817,11 @@ public ReplacePlaylistsItemsRequest.Builder replacePlaylistsItems(String playlis * * @param playlist_id The playlists ID. * @param uris URIs of the items to add. Maximum: 100 track or episode URIs. - * @return A {@link ReplacePlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReplaceRequest.Builder}. * @see Spotify: URLs & IDs */ - public ReplacePlaylistsItemsRequest.Builder replacePlaylistsItems(String playlist_id, JsonArray uris) { - return new ReplacePlaylistsItemsRequest.Builder(accessToken) + public UpdatePlaylistsItemsReplaceRequest.Builder updatePlaylistsItemsReplace(String playlist_id, JsonArray uris) { + return new UpdatePlaylistsItemsReplaceRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id) .uris(uris); @@ -1374,11 +1831,11 @@ public ReplacePlaylistsItemsRequest.Builder replacePlaylistsItems(String playlis * Replace the image used to represent a specific playlist. * * @param playlist_id The Spotify ID for the playlist. - * @return An {@link UploadCustomPlaylistCoverImageRequest.Builder}. + * @return An {@link AddCustomPlaylistCoverImageRequest.Builder}. * @see Spotify: URLs & IDs */ - public UploadCustomPlaylistCoverImageRequest.Builder uploadCustomPlaylistCoverImage(String playlist_id) { - return new UploadCustomPlaylistCoverImageRequest.Builder(accessToken) + public AddCustomPlaylistCoverImageRequest.Builder addCustomPlaylistCoverImage(String playlist_id) { + return new AddCustomPlaylistCoverImageRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .playlist_id(playlist_id); } @@ -1389,10 +1846,10 @@ public UploadCustomPlaylistCoverImageRequest.Builder uploadCustomPlaylistCoverIm * @param q The search query's keywords (and optional field filters and operators). * @param type A comma-separated list of item types to search across. Valid types are: album, artist, episode, show, playlist and * track. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. */ - public SearchItemRequest.Builder searchItem(String q, String type) { - return new SearchItemRequest.Builder(accessToken) + public SearchForItemRequest.Builder searchForItem(String q, String type) { + return new SearchForItemRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .q(q) .type(type); @@ -1486,7 +1943,7 @@ public SearchTracksRequest.Builder searchTracks(String q) { } /** - * Get a show. + * Get Spotify catalog information about a show. A show is either 'episodic' (containing episodes) or 'non-episodic' (containing audio only, non-episodic content). * * @param id The Spotify ID of the show. * @return A {@link GetShowRequest.Builder}. @@ -1502,24 +1959,44 @@ public GetShowRequest.Builder getShow(String id) { * Get Spotify catalog information about an show’s episodes. * * @param id The Spotify ID of the show. - * @return A {@link GetShowsEpisodesRequest.Builder}. + * @return A {@link GetShowEpisodesRequest.Builder}. * @see Spotify: URLs & IDs */ - public GetShowsEpisodesRequest.Builder getShowEpisodes(String id) { - return new GetShowsEpisodesRequest.Builder(accessToken) + public GetShowEpisodesRequest.Builder getShowEpisodes(String id) { + return new GetShowEpisodesRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .id(id); } + /** + * Get Spotify catalog information for several shows based on their Spotify IDs. + * + * @param ids A comma-separated list of the Spotify IDs for the shows. Maximum: 50 IDs. + * @return A {@link GetSeveralShowsRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetSeveralShowsRequest.Builder getSeveralShows(String ids) { + return new GetSeveralShowsRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + /** * Get a detailed audio analysis for a single track identified by its unique Spotify ID. * * @param id The Spotify ID for the track. - * @return A {@link GetAudioAnalysisForTrackRequest.Builder}. + * @return A {@link GetTracksAudioAnalysisRequest.Builder}. * @see Spotify: URLs & IDs + + * + * @deprecated This endpoint has been deprecated by Spotify. */ - public GetAudioAnalysisForTrackRequest.Builder getAudioAnalysisForTrack(String id) { - return new GetAudioAnalysisForTrackRequest.Builder(accessToken) + @Deprecated + public GetTracksAudioAnalysisRequest.Builder getTracksAudioAnalysis(String id) { + return new GetTracksAudioAnalysisRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .id(id); } @@ -1528,11 +2005,15 @@ public GetAudioAnalysisForTrackRequest.Builder getAudioAnalysisForTrack(String i * Get audio features for a track based on its Spotify ID. * * @param id The Spotify ID of the track. - * @return A {@link GetAudioFeaturesForTrackRequest.Builder}. + * @return A {@link GetTracksAudioFeaturesRequest.Builder}. * @see Spotify: URLs & IDs + + * + * @deprecated This endpoint has been deprecated by Spotify. */ - public GetAudioFeaturesForTrackRequest.Builder getAudioFeaturesForTrack(String id) { - return new GetAudioFeaturesForTrackRequest.Builder(accessToken) + @Deprecated + public GetTracksAudioFeaturesRequest.Builder getTracksAudioFeatures(String id) { + return new GetTracksAudioFeaturesRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .id(id); } @@ -1541,17 +2022,21 @@ public GetAudioFeaturesForTrackRequest.Builder getAudioFeaturesForTrack(String i * Get audio features for multiple tracks based on their Spotify IDs. * * @param ids A comma-separated list of the Spotify IDs for the tracks. Maximum: 100 IDs. - * @return A {@link GetAudioFeaturesForSeveralTracksRequest.Builder}. + * @return A {@link GetSeveralTracksAudioFeaturesRequest.Builder}. * @see Spotify: URLs & IDs + + * + * @deprecated This endpoint has been deprecated by Spotify. */ - public GetAudioFeaturesForSeveralTracksRequest.Builder getAudioFeaturesForSeveralTracks(String... ids) { - return new GetAudioFeaturesForSeveralTracksRequest.Builder(accessToken) + @Deprecated + public GetSeveralTracksAudioFeaturesRequest.Builder getSeveralTracksAudioFeatures(String... ids) { + return new GetSeveralTracksAudioFeaturesRequest.Builder(accessToken) .setDefaults(httpManager, scheme, host, port) .ids(concat(ids, ',')); } /** - * Get a track. + * Get Spotify catalog information for a single track identified by its unique Spotify ID. * * @param id The Spotify ID of the track. * @return A {@link GetTrackRequest.Builder}. @@ -1563,6 +2048,37 @@ public GetTrackRequest.Builder getTrack(String id) { .id(id); } + /** + * Get Spotify catalog information for multiple tracks based on their Spotify IDs. + * + * @param ids A comma-separated list of the Spotify IDs for the tracks. Maximum: 50 IDs. + * @return A {@link GetSeveralTracksRequest.Builder}. + * @see Spotify: URLs & IDs + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetSeveralTracksRequest.Builder getSeveralTracks(String ids) { + return new GetSeveralTracksRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .ids(ids); + } + + /** + * Get public profile information about a Spotify user. + * + * @param user_id The user's Spotify user ID. + * @return A {@link GetUsersProfileRequest.Builder}. + * @see Spotify: URLs & IDs + * @deprecated This endpoint is deprecated per the Spotify API specification. + */ + @Deprecated + public GetUsersProfileRequest.Builder getUsersProfile(String user_id) { + return new GetUsersProfileRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port) + .user_id(user_id); + } + /** * Get detailed profile information about the current user (including the current user’s username). * @@ -1573,6 +2089,19 @@ public GetCurrentUsersProfileRequest.Builder getCurrentUsersProfile() { .setDefaults(httpManager, scheme, host, port); } + /** + * Get a list of the markets where Spotify is available. + * + * @return A {@link GetAvailableMarketsRequest.Builder}. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ + @Deprecated + public GetAvailableMarketsRequest.Builder getAvailableMarkets() { + return new GetAvailableMarketsRequest.Builder(accessToken) + .setDefaults(httpManager, scheme, host, port); + } + /** * Builder class for building {@link SpotifyApi} instances. */ @@ -1751,4 +2280,3 @@ public SpotifyApi build() { } } } - diff --git a/src/main/java/se/michaelthelin/spotify/enums/ModelObjectType.java b/src/main/java/se/michaelthelin/spotify/enums/ModelObjectType.java index effc511aa..6ba5c7c65 100644 --- a/src/main/java/se/michaelthelin/spotify/enums/ModelObjectType.java +++ b/src/main/java/se/michaelthelin/spotify/enums/ModelObjectType.java @@ -12,6 +12,8 @@ public enum ModelObjectType { ALBUM("album"), /** Artist object type. */ ARTIST("artist"), + /** Audiobook object type. */ + AUDIOBOOK("audiobook"), /** Audio features object type. */ AUDIO_FEATURES("audio_features"), /** Episode object type. */ diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IEpisode.java b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IEpisode.java index 721afee11..a40fd3d95 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IEpisode.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IEpisode.java @@ -57,7 +57,7 @@ public interface IEpisode extends IPlaylistItem { * * @return True if the episode is playable in the given market. Otherwise false. */ - Boolean getPlayable(); + Boolean getIsPlayable(); /** * Get a list of the languages used in the episode, identified by their ISO 639 code. diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IPlaylist.java b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IPlaylist.java index b4eb37c98..384f1247f 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IPlaylist.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IPlaylist.java @@ -91,12 +91,17 @@ public interface IPlaylist { * @see * Spotify: Working With Playlists */ - Boolean getIsPublicAccess(); + Boolean getPublic(); /** - * Get information about the items in the playlist. The concrete type depends on the specific playlist object type. + * Get the track/item metadata for this playlist. + * The concrete type {@code T} is + * {@link se.michaelthelin.spotify.model_objects.specification.Paging} for a full + * {@link Playlist} and + * {@link se.michaelthelin.spotify.model_objects.miscellaneous.PlaylistTracksInformation} + * for a {@link PlaylistSimplified}. * - * @return Item information containing total count. + * @return Track/item metadata for the playlist. */ T getItems(); @@ -105,7 +110,7 @@ public interface IPlaylist { * a specific playlist version. * * @return The version identifier for the current playlist. - * @see se.michaelthelin.spotify.requests.data.playlists.RemoveItemsFromPlaylistRequest + * @see se.michaelthelin.spotify.requests.data.playlists.RemovePlaylistItemsRequest */ String getSnapshotId(); @@ -124,5 +129,3 @@ public interface IPlaylist { */ String getUri(); } - - diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IShow.java b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IShow.java index 1a914c07a..996ab7313 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IShow.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/IShow.java @@ -107,4 +107,3 @@ public interface IShow { */ String getUri(); } - diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/ITrack.java b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/ITrack.java index aaf3b83a5..6c40ccb5d 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/ITrack.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/interfaces/ITrack.java @@ -35,7 +35,7 @@ public interface ITrack extends IPlaylistItem { * @return Whether or not the track has explicit lyrics ({@code true} = yes it does; {@code false} = no it does not * OR unknown). */ - Boolean getIsExplicit(); + Boolean getExplicit(); /** * Check whether the track is playable in the market, which may has been specified somewhere before requesting it. diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/special/SearchResult.java b/src/main/java/se/michaelthelin/spotify/model_objects/special/SearchResult.java index 3a3263749..5906e373f 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/special/SearchResult.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/special/SearchResult.java @@ -4,13 +4,13 @@ import com.google.gson.JsonObject; import se.michaelthelin.spotify.model_objects.AbstractModelObject; import se.michaelthelin.spotify.model_objects.specification.*; -import se.michaelthelin.spotify.requests.data.personalization.interfaces.IArtistTrackModelObject; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; +import se.michaelthelin.spotify.requests.data.users.interfaces.IArtistTrackModelObject; +import se.michaelthelin.spotify.requests.data.search.SearchForItemRequest; import se.michaelthelin.spotify.requests.data.search.interfaces.ISearchModelObject; /** - * Retrieve the searched-for items by building instances from this class. This objects contains - * for every type specified by the {@code type} parameter in the {@link SearchItemRequest} + * Retrieve the searched-for items by building instances from this class. This object contains + * for every type specified by the {@code type} parameter in the {@link SearchForItemRequest} * the searched-for items wrapped in a {@link Paging} object. */ @JsonDeserialize(builder = SearchResult.Builder.class) diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Artist.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Artist.java index 9fea41bee..00e94bfd6 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Artist.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Artist.java @@ -6,7 +6,7 @@ import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.model_objects.AbstractModelObject; import se.michaelthelin.spotify.model_objects.interfaces.IArtist; -import se.michaelthelin.spotify.requests.data.personalization.interfaces.IArtistTrackModelObject; +import se.michaelthelin.spotify.requests.data.users.interfaces.IArtistTrackModelObject; import se.michaelthelin.spotify.requests.data.search.interfaces.ISearchModelObject; import java.util.Arrays; diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Audiobook.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Audiobook.java new file mode 100644 index 000000000..64df1e836 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Audiobook.java @@ -0,0 +1,657 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.enums.ModelObjectType; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Retrieve information about + * Audiobook objects by building instances from this class. + */ +@JsonDeserialize(builder = Audiobook.Builder.class) +public class Audiobook extends AbstractModelObject { + /** The author(s) for the audiobook. */ + private final Author[] authors; + /** A list of the countries in which the audiobook can be played. */ + private final String[] availableMarkets; + /** The copyright statements of the audiobook. */ + private final Copyright[] copyrights; + /** A description of the audiobook. HTML tags are stripped away from this field. */ + private final String description; + /** A description of the audiobook. This field may contain HTML tags. */ + private final String htmlDescription; + /** The edition of the audiobook. */ + private final String edition; + /** Whether or not the audiobook has explicit content. */ + private final Boolean explicit; + /** External URLs for this audiobook. */ + private final ExternalUrl externalUrls; + /** A link to the Web API endpoint providing full details of the audiobook. */ + private final String href; + /** The Spotify ID for the audiobook. */ + private final String id; + /** The cover art for the audiobook in various sizes, widest first. */ + private final Image[] images; + /** A list of the languages used in the audiobook. */ + private final String[] languages; + /** The media type of the audiobook. */ + private final String mediaType; + /** The name of the audiobook. */ + private final String name; + /** The narrator(s) for the audiobook. */ + private final Narrator[] narrators; + /** The publisher of the audiobook. */ + private final String publisher; + /** The object type. Always {@code "audiobook"}. */ + private final ModelObjectType type; + /** The Spotify URI for the audiobook. */ + private final String uri; + /** The number of chapters in this audiobook. */ + private final Integer totalChapters; + /** The chapters of the audiobook. */ + private final Paging chapters; + + private Audiobook(final Builder builder) { + super(builder); + this.authors = builder.authors; + this.availableMarkets = builder.availableMarkets; + this.copyrights = builder.copyrights; + this.description = builder.description; + this.htmlDescription = builder.htmlDescription; + this.edition = builder.edition; + this.explicit = builder.explicit; + this.externalUrls = builder.externalUrls; + this.href = builder.href; + this.id = builder.id; + this.images = builder.images; + this.languages = builder.languages; + this.mediaType = builder.mediaType; + this.name = builder.name; + this.narrators = builder.narrators; + this.publisher = builder.publisher; + this.type = builder.type; + this.uri = builder.uri; + this.totalChapters = builder.totalChapters; + this.chapters = builder.chapters; + } + + /** + * Get the author(s) for the audiobook. + * + * @return An array of {@link Author} objects. + */ + public Author[] getAuthors() { + return authors; + } + + /** + * Get a list of the countries in which the audiobook can be played. + * + * @return An array of ISO 3166-1 alpha-2 country codes. + */ + public String[] getAvailableMarkets() { + return availableMarkets; + } + + /** + * Get the copyright statements of the audiobook. + * + * @return An array of {@link Copyright} objects. + */ + public Copyright[] getCopyrights() { + return copyrights; + } + + /** + * Get a description of the audiobook. HTML tags are stripped away from this field. + * + * @return The description of the audiobook. + */ + public String getDescription() { + return description; + } + + /** + * Get a description of the audiobook. This field may contain HTML tags. + * + * @return The HTML description of the audiobook. + */ + public String getHtmlDescription() { + return htmlDescription; + } + + /** + * Get the edition of the audiobook. + * + * @return The edition of the audiobook. + */ + public String getEdition() { + return edition; + } + + /** + * Check whether the audiobook is explicit or not. + * + * @return Whether or not the audiobook has explicit content. + */ + public Boolean getExplicit() { + return explicit; + } + + /** + * Get the external URLs of the audiobook. + * + * @return An {@link ExternalUrl} object. + */ + public ExternalUrl getExternalUrls() { + return externalUrls; + } + + /** + * Get the full Spotify Web API endpoint URL of the audiobook. + * + * @return A link to the Web API endpoint providing full details of the audiobook. + */ + public String getHref() { + return href; + } + + /** + * Get the Spotify ID of the audiobook. + * + * @return A Spotify audiobook ID. + */ + public String getId() { + return id; + } + + /** + * Get the cover art for the audiobook in various sizes, widest first. + * + * @return An array of {@link Image} objects. + */ + public Image[] getImages() { + return images; + } + + /** + * Get a list of the languages used in the audiobook. + * + * @return An array of ISO 639 language codes. + */ + public String[] getLanguages() { + return languages; + } + + /** + * Get the media type of the audiobook. + * + * @return The media type of the audiobook. + */ + public String getMediaType() { + return mediaType; + } + + /** + * Get the name of the audiobook. + * + * @return The name of the audiobook. + */ + public String getName() { + return name; + } + + /** + * Get the narrator(s) for the audiobook. + * + * @return An array of {@link Narrator} objects. + */ + public Narrator[] getNarrators() { + return narrators; + } + + /** + * Get the publisher of the audiobook. + * + * @return The publisher of the audiobook. + */ + public String getPublisher() { + return publisher; + } + + /** + * Get the model object type. In this case {@code "audiobook"}. + * + * @return A {@link ModelObjectType}. + */ + public ModelObjectType getType() { + return type; + } + + /** + * Get the Spotify URI of the audiobook. + * + * @return Spotify audiobook URI. + */ + public String getUri() { + return uri; + } + + /** + * Get the number of chapters in this audiobook. + * + * @return The number of chapters in this audiobook. + */ + public Integer getTotalChapters() { + return totalChapters; + } + + /** + * Get the chapters of the audiobook. + * + * @return A {@link Paging} object containing {@link ChapterSimplified} objects. + */ + public Paging getChapters() { + return chapters; + } + + @Override + public String toString() { + return "Audiobook(authors=" + Arrays.toString(authors) + ", copyrights=" + Arrays.toString(copyrights) + + ", description=" + description + ", edition=" + edition + ", explicit=" + explicit + + ", externalUrls=" + externalUrls + ", href=" + href + ", id=" + id + ", images=" + Arrays.toString(images) + + ", languages=" + Arrays.toString(languages) + ", mediaType=" + mediaType + ", name=" + name + + ", narrators=" + Arrays.toString(narrators) + ", publisher=" + publisher + ", type=" + type + + ", uri=" + uri + ", totalChapters=" + totalChapters + ", chapters=" + chapters + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link Audiobook} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private Author[] authors; + private String[] availableMarkets; + private Copyright[] copyrights; + private String description; + private String htmlDescription; + private String edition; + private Boolean explicit; + private ExternalUrl externalUrls; + private String href; + private String id; + private Image[] images; + private String[] languages; + private String mediaType; + private String name; + private Narrator[] narrators; + private String publisher; + private ModelObjectType type; + private String uri; + private Integer totalChapters; + private Paging chapters; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the authors. + * + * @param authors The author(s) for the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setAuthors(Author... authors) { + this.authors = authors; + return this; + } + + /** + * Set the available markets. + * + * @param availableMarkets ISO 3166-1 alpha-2 country codes. + * @return A {@link Audiobook.Builder}. + */ + public Builder setAvailableMarkets(String... availableMarkets) { + this.availableMarkets = availableMarkets; + return this; + } + + /** + * Set the copyrights. + * + * @param copyrights The copyright statements of the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setCopyrights(Copyright... copyrights) { + this.copyrights = copyrights; + return this; + } + + /** + * Set the description. + * + * @param description A description of the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setDescription(String description) { + this.description = description; + return this; + } + + /** + * Set the HTML description. + * + * @param htmlDescription A description of the audiobook (may contain HTML tags). + * @return A {@link Audiobook.Builder}. + */ + public Builder setHtmlDescription(String htmlDescription) { + this.htmlDescription = htmlDescription; + return this; + } + + /** + * Set the edition. + * + * @param edition The edition of the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setEdition(String edition) { + this.edition = edition; + return this; + } + + /** + * Set whether the audiobook is explicit. + * + * @param explicit Whether or not the audiobook has explicit content. + * @return A {@link Audiobook.Builder}. + */ + public Builder setExplicit(Boolean explicit) { + this.explicit = explicit; + return this; + } + + /** + * Set the external URLs. + * + * @param externalUrls The {@link ExternalUrl} for the audiobook object. + * @return A {@link Audiobook.Builder}. + */ + public Builder setExternalUrls(ExternalUrl externalUrls) { + this.externalUrls = externalUrls; + return this; + } + + /** + * Set the href. + * + * @param href A link to the Web API endpoint providing full details of the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setHref(String href) { + this.href = href; + return this; + } + + /** + * Set the Spotify ID. + * + * @param id The Spotify ID for the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setId(String id) { + this.id = id; + return this; + } + + /** + * Set the cover art images. + * + * @param images {@link Image} objects. + * @return A {@link Audiobook.Builder}. + */ + public Builder setImages(Image... images) { + this.images = images; + return this; + } + + /** + * Set the languages. + * + * @param languages ISO 639 language codes. + * @return A {@link Audiobook.Builder}. + */ + public Builder setLanguages(String... languages) { + this.languages = languages; + return this; + } + + /** + * Set the media type. + * + * @param mediaType The media type of the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setMediaType(String mediaType) { + this.mediaType = mediaType; + return this; + } + + /** + * Set the name. + * + * @param name The name of the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setName(String name) { + this.name = name; + return this; + } + + /** + * Set the narrators. + * + * @param narrators The narrator(s) for the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setNarrators(Narrator... narrators) { + this.narrators = narrators; + return this; + } + + /** + * Set the publisher. + * + * @param publisher The publisher of the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setPublisher(String publisher) { + this.publisher = publisher; + return this; + } + + /** + * Set the model object type. + * + * @param type The {@link ModelObjectType}. + * @return A {@link Audiobook.Builder}. + */ + public Builder setType(ModelObjectType type) { + this.type = type; + return this; + } + + /** + * Set the Spotify URI. + * + * @param uri The Spotify URI for the audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setUri(String uri) { + this.uri = uri; + return this; + } + + /** + * Set the total number of chapters. + * + * @param totalChapters The number of chapters in this audiobook. + * @return A {@link Audiobook.Builder}. + */ + public Builder setTotalChapters(Integer totalChapters) { + this.totalChapters = totalChapters; + return this; + } + + /** + * Set the chapters paging object. + * + * @param chapters A {@link Paging} object containing {@link ChapterSimplified} objects. + * @return A {@link Audiobook.Builder}. + */ + public Builder setChapters(Paging chapters) { + this.chapters = chapters; + return this; + } + + @Override + public Audiobook build() { + return new Audiobook(this); + } + } + + /** + * JsonUtil class for building {@link Audiobook} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + @Override + public Audiobook createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + return new Builder() + .setAuthors( + hasAndNotNull(jsonObject, "authors") + ? new Author.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("authors")) + : null) + .setAvailableMarkets( + hasAndNotNull(jsonObject, "available_markets") + ? new Gson().fromJson(jsonObject.getAsJsonArray("available_markets"), String[].class) + : null) + .setCopyrights( + hasAndNotNull(jsonObject, "copyrights") + ? new Copyright.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("copyrights")) + : null) + .setDescription( + hasAndNotNull(jsonObject, "description") + ? jsonObject.get("description").getAsString() + : null) + .setHtmlDescription( + hasAndNotNull(jsonObject, "html_description") + ? jsonObject.get("html_description").getAsString() + : null) + .setEdition( + hasAndNotNull(jsonObject, "edition") + ? jsonObject.get("edition").getAsString() + : null) + .setExplicit( + hasAndNotNull(jsonObject, "explicit") + ? jsonObject.get("explicit").getAsBoolean() + : null) + .setExternalUrls( + hasAndNotNull(jsonObject, "external_urls") + ? new ExternalUrl.JsonUtil().createModelObject(jsonObject.getAsJsonObject("external_urls")) + : null) + .setHref( + hasAndNotNull(jsonObject, "href") + ? jsonObject.get("href").getAsString() + : null) + .setId( + hasAndNotNull(jsonObject, "id") + ? jsonObject.get("id").getAsString() + : null) + .setImages( + hasAndNotNull(jsonObject, "images") + ? new Image.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("images")) + : null) + .setLanguages( + hasAndNotNull(jsonObject, "languages") + ? new Gson().fromJson(jsonObject.getAsJsonArray("languages"), String[].class) + : null) + .setMediaType( + hasAndNotNull(jsonObject, "media_type") + ? jsonObject.get("media_type").getAsString() + : null) + .setName( + hasAndNotNull(jsonObject, "name") + ? jsonObject.get("name").getAsString() + : null) + .setNarrators( + hasAndNotNull(jsonObject, "narrators") + ? new Narrator.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("narrators")) + : null) + .setPublisher( + hasAndNotNull(jsonObject, "publisher") + ? jsonObject.get("publisher").getAsString() + : null) + .setType( + hasAndNotNull(jsonObject, "type") + ? ModelObjectType.keyOf(jsonObject.get("type").getAsString().toLowerCase()) + : null) + .setUri( + hasAndNotNull(jsonObject, "uri") + ? jsonObject.get("uri").getAsString() + : null) + .setTotalChapters( + hasAndNotNull(jsonObject, "total_chapters") + ? jsonObject.get("total_chapters").getAsInt() + : null) + .setChapters( + hasAndNotNull(jsonObject, "chapters") + ? new ChapterSimplified.JsonUtil().createModelObjectPaging( + jsonObject.getAsJsonObject("chapters")) + : null) + .build(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Audiobook audiobook = (Audiobook) o; + return Objects.equals(id, audiobook.id) && Objects.equals(name, audiobook.name) + && Objects.equals(uri, audiobook.uri); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, uri); + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/AudiobookSimplified.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/AudiobookSimplified.java new file mode 100644 index 000000000..8d6108efe --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/AudiobookSimplified.java @@ -0,0 +1,628 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.enums.ModelObjectType; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Retrieve information about + * simplified Audiobook objects by building instances from this class. + */ +@JsonDeserialize(builder = AudiobookSimplified.Builder.class) +public class AudiobookSimplified extends AbstractModelObject { + /** The author(s) for the audiobook. */ + private final Author[] authors; + /** A list of the countries in which the audiobook can be played. */ + private final String[] availableMarkets; + /** The copyright statements of the audiobook. */ + private final Copyright[] copyrights; + /** A description of the audiobook. HTML tags are stripped away from this field. */ + private final String description; + /** A description of the audiobook. This field may contain HTML tags. */ + private final String htmlDescription; + /** The edition of the audiobook. */ + private final String edition; + /** Whether or not the audiobook has explicit content. */ + private final Boolean explicit; + /** External URLs for this audiobook. */ + private final ExternalUrl externalUrls; + /** A link to the Web API endpoint providing full details of the audiobook. */ + private final String href; + /** The Spotify ID for the audiobook. */ + private final String id; + /** The cover art for the audiobook in various sizes, widest first. */ + private final Image[] images; + /** A list of the languages used in the audiobook. */ + private final String[] languages; + /** The media type of the audiobook. */ + private final String mediaType; + /** The name of the audiobook. */ + private final String name; + /** The narrator(s) for the audiobook. */ + private final Narrator[] narrators; + /** The publisher of the audiobook. */ + private final String publisher; + /** The object type. Always {@code "audiobook"}. */ + private final ModelObjectType type; + /** The Spotify URI for the audiobook. */ + private final String uri; + /** The number of chapters in this audiobook. */ + private final Integer totalChapters; + + private AudiobookSimplified(final Builder builder) { + super(builder); + this.authors = builder.authors; + this.availableMarkets = builder.availableMarkets; + this.copyrights = builder.copyrights; + this.description = builder.description; + this.htmlDescription = builder.htmlDescription; + this.edition = builder.edition; + this.explicit = builder.explicit; + this.externalUrls = builder.externalUrls; + this.href = builder.href; + this.id = builder.id; + this.images = builder.images; + this.languages = builder.languages; + this.mediaType = builder.mediaType; + this.name = builder.name; + this.narrators = builder.narrators; + this.publisher = builder.publisher; + this.type = builder.type; + this.uri = builder.uri; + this.totalChapters = builder.totalChapters; + } + + /** + * Get the author(s) for the audiobook. + * + * @return An array of {@link Author} objects. + */ + public Author[] getAuthors() { + return authors; + } + + /** + * Get a list of the countries in which the audiobook can be played. + * + * @return An array of ISO 3166-1 alpha-2 country codes. + */ + public String[] getAvailableMarkets() { + return availableMarkets; + } + + /** + * Get the copyright statements of the audiobook. + * + * @return An array of {@link Copyright} objects. + */ + public Copyright[] getCopyrights() { + return copyrights; + } + + /** + * Get a description of the audiobook. HTML tags are stripped away from this field. + * + * @return The description of the audiobook. + */ + public String getDescription() { + return description; + } + + /** + * Get a description of the audiobook. This field may contain HTML tags. + * + * @return The HTML description of the audiobook. + */ + public String getHtmlDescription() { + return htmlDescription; + } + + /** + * Get the edition of the audiobook. + * + * @return The edition of the audiobook. + */ + public String getEdition() { + return edition; + } + + /** + * Check whether the audiobook is explicit or not. + * + * @return Whether or not the audiobook has explicit content. + */ + public Boolean getExplicit() { + return explicit; + } + + /** + * Get the external URLs of the audiobook. + * + * @return An {@link ExternalUrl} object. + */ + public ExternalUrl getExternalUrls() { + return externalUrls; + } + + /** + * Get the full Spotify Web API endpoint URL of the audiobook. + * + * @return A link to the Web API endpoint providing full details of the audiobook. + */ + public String getHref() { + return href; + } + + /** + * Get the Spotify ID of the audiobook. + * + * @return A Spotify audiobook ID. + */ + public String getId() { + return id; + } + + /** + * Get the cover art for the audiobook in various sizes, widest first. + * + * @return An array of {@link Image} objects. + */ + public Image[] getImages() { + return images; + } + + /** + * Get a list of the languages used in the audiobook. + * + * @return An array of ISO 639 language codes. + */ + public String[] getLanguages() { + return languages; + } + + /** + * Get the media type of the audiobook. + * + * @return The media type of the audiobook. + */ + public String getMediaType() { + return mediaType; + } + + /** + * Get the name of the audiobook. + * + * @return The name of the audiobook. + */ + public String getName() { + return name; + } + + /** + * Get the narrator(s) for the audiobook. + * + * @return An array of {@link Narrator} objects. + */ + public Narrator[] getNarrators() { + return narrators; + } + + /** + * Get the publisher of the audiobook. + * + * @return The publisher of the audiobook. + */ + public String getPublisher() { + return publisher; + } + + /** + * Get the model object type. In this case {@code "audiobook"}. + * + * @return A {@link ModelObjectType}. + */ + public ModelObjectType getType() { + return type; + } + + /** + * Get the Spotify URI of the audiobook. + * + * @return Spotify audiobook URI. + */ + public String getUri() { + return uri; + } + + /** + * Get the number of chapters in this audiobook. + * + * @return The number of chapters in this audiobook. + */ + public Integer getTotalChapters() { + return totalChapters; + } + + @Override + public String toString() { + return "AudiobookSimplified(authors=" + Arrays.toString(authors) + ", copyrights=" + Arrays.toString(copyrights) + + ", description=" + description + ", edition=" + edition + ", explicit=" + explicit + + ", externalUrls=" + externalUrls + ", href=" + href + ", id=" + id + ", images=" + Arrays.toString(images) + + ", languages=" + Arrays.toString(languages) + ", mediaType=" + mediaType + ", name=" + name + + ", narrators=" + Arrays.toString(narrators) + ", publisher=" + publisher + ", type=" + type + + ", uri=" + uri + ", totalChapters=" + totalChapters + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link AudiobookSimplified} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private Author[] authors; + private String[] availableMarkets; + private Copyright[] copyrights; + private String description; + private String htmlDescription; + private String edition; + private Boolean explicit; + private ExternalUrl externalUrls; + private String href; + private String id; + private Image[] images; + private String[] languages; + private String mediaType; + private String name; + private Narrator[] narrators; + private String publisher; + private ModelObjectType type; + private String uri; + private Integer totalChapters; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the authors. + * + * @param authors The author(s) for the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setAuthors(Author... authors) { + this.authors = authors; + return this; + } + + /** + * Set the available markets. + * + * @param availableMarkets ISO 3166-1 alpha-2 country codes. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setAvailableMarkets(String... availableMarkets) { + this.availableMarkets = availableMarkets; + return this; + } + + /** + * Set the copyrights. + * + * @param copyrights The copyright statements of the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setCopyrights(Copyright... copyrights) { + this.copyrights = copyrights; + return this; + } + + /** + * Set the description. + * + * @param description A description of the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setDescription(String description) { + this.description = description; + return this; + } + + /** + * Set the HTML description. + * + * @param htmlDescription A description of the audiobook (may contain HTML tags). + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setHtmlDescription(String htmlDescription) { + this.htmlDescription = htmlDescription; + return this; + } + + /** + * Set the edition. + * + * @param edition The edition of the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setEdition(String edition) { + this.edition = edition; + return this; + } + + /** + * Set whether the audiobook is explicit. + * + * @param explicit Whether or not the audiobook has explicit content. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setExplicit(Boolean explicit) { + this.explicit = explicit; + return this; + } + + /** + * Set the external URLs. + * + * @param externalUrls The {@link ExternalUrl} for the audiobook object. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setExternalUrls(ExternalUrl externalUrls) { + this.externalUrls = externalUrls; + return this; + } + + /** + * Set the href. + * + * @param href A link to the Web API endpoint providing full details of the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setHref(String href) { + this.href = href; + return this; + } + + /** + * Set the Spotify ID. + * + * @param id The Spotify ID for the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setId(String id) { + this.id = id; + return this; + } + + /** + * Set the cover art images. + * + * @param images {@link Image} objects. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setImages(Image... images) { + this.images = images; + return this; + } + + /** + * Set the languages. + * + * @param languages ISO 639 language codes. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setLanguages(String... languages) { + this.languages = languages; + return this; + } + + /** + * Set the media type. + * + * @param mediaType The media type of the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setMediaType(String mediaType) { + this.mediaType = mediaType; + return this; + } + + /** + * Set the name. + * + * @param name The name of the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setName(String name) { + this.name = name; + return this; + } + + /** + * Set the narrators. + * + * @param narrators The narrator(s) for the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setNarrators(Narrator... narrators) { + this.narrators = narrators; + return this; + } + + /** + * Set the publisher. + * + * @param publisher The publisher of the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setPublisher(String publisher) { + this.publisher = publisher; + return this; + } + + /** + * Set the model object type. + * + * @param type The {@link ModelObjectType}. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setType(ModelObjectType type) { + this.type = type; + return this; + } + + /** + * Set the Spotify URI. + * + * @param uri The Spotify URI for the audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setUri(String uri) { + this.uri = uri; + return this; + } + + /** + * Set the total number of chapters. + * + * @param totalChapters The number of chapters in this audiobook. + * @return A {@link AudiobookSimplified.Builder}. + */ + public Builder setTotalChapters(Integer totalChapters) { + this.totalChapters = totalChapters; + return this; + } + + @Override + public AudiobookSimplified build() { + return new AudiobookSimplified(this); + } + } + + /** + * JsonUtil class for building {@link AudiobookSimplified} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + @Override + public AudiobookSimplified createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + return new Builder() + .setAuthors( + hasAndNotNull(jsonObject, "authors") + ? new Author.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("authors")) + : null) + .setAvailableMarkets( + hasAndNotNull(jsonObject, "available_markets") + ? new Gson().fromJson(jsonObject.getAsJsonArray("available_markets"), String[].class) + : null) + .setCopyrights( + hasAndNotNull(jsonObject, "copyrights") + ? new Copyright.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("copyrights")) + : null) + .setDescription( + hasAndNotNull(jsonObject, "description") + ? jsonObject.get("description").getAsString() + : null) + .setHtmlDescription( + hasAndNotNull(jsonObject, "html_description") + ? jsonObject.get("html_description").getAsString() + : null) + .setEdition( + hasAndNotNull(jsonObject, "edition") + ? jsonObject.get("edition").getAsString() + : null) + .setExplicit( + hasAndNotNull(jsonObject, "explicit") + ? jsonObject.get("explicit").getAsBoolean() + : null) + .setExternalUrls( + hasAndNotNull(jsonObject, "external_urls") + ? new ExternalUrl.JsonUtil().createModelObject(jsonObject.getAsJsonObject("external_urls")) + : null) + .setHref( + hasAndNotNull(jsonObject, "href") + ? jsonObject.get("href").getAsString() + : null) + .setId( + hasAndNotNull(jsonObject, "id") + ? jsonObject.get("id").getAsString() + : null) + .setImages( + hasAndNotNull(jsonObject, "images") + ? new Image.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("images")) + : null) + .setLanguages( + hasAndNotNull(jsonObject, "languages") + ? new Gson().fromJson(jsonObject.getAsJsonArray("languages"), String[].class) + : null) + .setMediaType( + hasAndNotNull(jsonObject, "media_type") + ? jsonObject.get("media_type").getAsString() + : null) + .setName( + hasAndNotNull(jsonObject, "name") + ? jsonObject.get("name").getAsString() + : null) + .setNarrators( + hasAndNotNull(jsonObject, "narrators") + ? new Narrator.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("narrators")) + : null) + .setPublisher( + hasAndNotNull(jsonObject, "publisher") + ? jsonObject.get("publisher").getAsString() + : null) + .setType( + hasAndNotNull(jsonObject, "type") + ? ModelObjectType.keyOf(jsonObject.get("type").getAsString().toLowerCase()) + : null) + .setUri( + hasAndNotNull(jsonObject, "uri") + ? jsonObject.get("uri").getAsString() + : null) + .setTotalChapters( + hasAndNotNull(jsonObject, "total_chapters") + ? jsonObject.get("total_chapters").getAsInt() + : null) + .build(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AudiobookSimplified audiobook = (AudiobookSimplified) o; + return Objects.equals(id, audiobook.id) && Objects.equals(name, audiobook.name) + && Objects.equals(uri, audiobook.uri); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, uri); + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Author.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Author.java new file mode 100644 index 000000000..7736ccdc6 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Author.java @@ -0,0 +1,115 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.util.Objects; + +/** + * Retrieve information about + * Author objects by building instances from this class. + */ +@JsonDeserialize(builder = Author.Builder.class) +public class Author extends AbstractModelObject { + /** The name of the author. */ + private final String name; + + private Author(final Builder builder) { + super(builder); + this.name = builder.name; + } + + /** + * Get the name of the author. + * + * @return The name of the author. + */ + public String getName() { + return name; + } + + @Override + public String toString() { + return "Author(name=" + name + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link Author} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private String name; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the name of the author to be built. + * + * @param name The name of the author. + * @return An {@link Author.Builder}. + */ + public Builder setName(String name) { + this.name = name; + return this; + } + + @Override + public Author build() { + return new Author(this); + } + } + + /** + * JsonUtil class for building {@link Author} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + @Override + public Author createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + return new Builder() + .setName( + hasAndNotNull(jsonObject, "name") + ? jsonObject.get("name").getAsString() + : null) + .build(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Author author = (Author) o; + return Objects.equals(name, author.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Chapter.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Chapter.java new file mode 100644 index 000000000..81d1126fa --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Chapter.java @@ -0,0 +1,685 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.enums.ModelObjectType; +import se.michaelthelin.spotify.enums.ReleaseDatePrecision; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Retrieve information about + * Chapter objects by building instances from this class. + */ +@JsonDeserialize(builder = Chapter.Builder.class) +public class Chapter extends AbstractModelObject { + /** A URL to a 30 second preview (MP3 format) of the chapter. {@code null} if not available. */ + private final String audioPreviewUrl; + /** A list of the countries in which the chapter can be played. */ + private final String[] availableMarkets; + /** The number of the chapter. */ + private final Integer chapterNumber; + /** A description of the chapter. HTML tags are stripped away from this field. */ + private final String description; + /** A description of the chapter. This field may contain HTML tags. */ + private final String htmlDescription; + /** The chapter length in milliseconds. */ + private final Integer durationMs; + /** Whether or not the chapter has explicit content. */ + private final Boolean explicit; + /** External URLs for this chapter. */ + private final ExternalUrl externalUrls; + /** A link to the Web API endpoint providing full details of the chapter. */ + private final String href; + /** The Spotify ID for the chapter. */ + private final String id; + /** The cover art for the chapter in various sizes, widest first. */ + private final Image[] images; + /** True if the chapter is playable in the given market. Otherwise false. */ + private final Boolean isPlayable; + /** A list of the languages used in the chapter. */ + private final String[] languages; + /** The name of the chapter. */ + private final String name; + /** The date the chapter was first released. */ + private final String releaseDate; + /** The precision with which {@code release_date} value is known. */ + private final ReleaseDatePrecision releaseDatePrecision; + /** The user's most recent position in the chapter. */ + private final ResumePoint resumePoint; + /** The object type. */ + private final ModelObjectType type; + /** The Spotify URI for the chapter. */ + private final String uri; + /** Included in the response when a content restriction is applied. */ + private final ChapterRestriction restrictions; + /** The audiobook for which the chapter belongs. */ + private final AudiobookSimplified audiobook; + + private Chapter(final Builder builder) { + super(builder); + this.audioPreviewUrl = builder.audioPreviewUrl; + this.availableMarkets = builder.availableMarkets; + this.chapterNumber = builder.chapterNumber; + this.description = builder.description; + this.htmlDescription = builder.htmlDescription; + this.durationMs = builder.durationMs; + this.explicit = builder.explicit; + this.externalUrls = builder.externalUrls; + this.href = builder.href; + this.id = builder.id; + this.images = builder.images; + this.isPlayable = builder.isPlayable; + this.languages = builder.languages; + this.name = builder.name; + this.releaseDate = builder.releaseDate; + this.releaseDatePrecision = builder.releaseDatePrecision; + this.resumePoint = builder.resumePoint; + this.type = builder.type; + this.uri = builder.uri; + this.restrictions = builder.restrictions; + this.audiobook = builder.audiobook; + } + + /** + * Get a URL to a 30 second preview (MP3 format) of the chapter. {@code null} if not available. + * + * @return A URL to an audio preview. + */ + public String getAudioPreviewUrl() { + return audioPreviewUrl; + } + + /** + * Get a list of the countries in which the chapter can be played. + * + * @return An array of ISO 3166-1 alpha-2 country codes. + */ + public String[] getAvailableMarkets() { + return availableMarkets; + } + + /** + * Get the number of the chapter. + * + * @return The number of the chapter. + */ + public Integer getChapterNumber() { + return chapterNumber; + } + + /** + * Get a description of the chapter. HTML tags are stripped away from this field. + * + * @return The description of the chapter. + */ + public String getDescription() { + return description; + } + + /** + * Get a description of the chapter. This field may contain HTML tags. + * + * @return The HTML description of the chapter. + */ + public String getHtmlDescription() { + return htmlDescription; + } + + /** + * Get the duration of the chapter in milliseconds. + * + * @return The chapter length in milliseconds. + */ + public Integer getDurationMs() { + return durationMs; + } + + /** + * Check whether the chapter is explicit or not. + * + * @return Whether or not the chapter has explicit content. + */ + public Boolean getExplicit() { + return explicit; + } + + /** + * Get the external URLs of the chapter. + * + * @return An {@link ExternalUrl} object. + */ + public ExternalUrl getExternalUrls() { + return externalUrls; + } + + /** + * Get the full Spotify Web API endpoint URL of the chapter. + * + * @return A link to the Web API endpoint providing full details of the chapter. + */ + public String getHref() { + return href; + } + + /** + * Get the Spotify ID of the chapter. + * + * @return A Spotify chapter ID. + */ + public String getId() { + return id; + } + + /** + * Get the cover art for the chapter in various sizes, widest first. + * + * @return An array of {@link Image} objects. + */ + public Image[] getImages() { + return images; + } + + /** + * Check whether the chapter is playable in the given market. + * + * @return True if the chapter is playable in the given market. Otherwise false. + */ + public Boolean getPlayable() { + return isPlayable; + } + + /** + * Get a list of the languages used in the chapter. + * + * @return An array of ISO 639 language codes. + */ + public String[] getLanguages() { + return languages; + } + + /** + * Get the name of the chapter. + * + * @return The name of the chapter. + */ + public String getName() { + return name; + } + + /** + * Get the release date of the chapter. + * + * @return The date the chapter was first released. + */ + public String getReleaseDate() { + return releaseDate; + } + + /** + * Get the precision of the release date. + * + * @return The precision with which {@code release_date} value is known. + */ + public ReleaseDatePrecision getReleaseDatePrecision() { + return releaseDatePrecision; + } + + /** + * Get the user's most recent position in the chapter. + * + * @return A {@link ResumePoint} object. + */ + public ResumePoint getResumePoint() { + return resumePoint; + } + + /** + * Get the model object type. In this case "episode". + * + * @return A {@link ModelObjectType}. + */ + public ModelObjectType getType() { + return type; + } + + /** + * Get the Spotify URI of the chapter. + * + * @return Spotify chapter URI. + */ + public String getUri() { + return uri; + } + + /** + * Get the content restriction applied, if any. + * + * @return A {@link ChapterRestriction} object, or {@code null}. + */ + public ChapterRestriction getRestrictions() { + return restrictions; + } + + /** + * Get the audiobook for which the chapter belongs. + * + * @return A {@link AudiobookSimplified} object. + */ + public AudiobookSimplified getAudiobook() { + return audiobook; + } + + @Override + public String toString() { + return "Chapter(audioPreviewUrl=" + audioPreviewUrl + ", chapterNumber=" + chapterNumber + + ", description=" + description + ", durationMs=" + durationMs + ", explicit=" + explicit + + ", externalUrls=" + externalUrls + ", href=" + href + ", id=" + id + ", images=" + Arrays.toString(images) + + ", isPlayable=" + isPlayable + ", languages=" + Arrays.toString(languages) + ", name=" + name + + ", releaseDate=" + releaseDate + ", releaseDatePrecision=" + releaseDatePrecision + + ", resumePoint=" + resumePoint + ", type=" + type + ", uri=" + uri + ", audiobook=" + audiobook + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link Chapter} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private String audioPreviewUrl; + private String[] availableMarkets; + private Integer chapterNumber; + private String description; + private String htmlDescription; + private Integer durationMs; + private Boolean explicit; + private ExternalUrl externalUrls; + private String href; + private String id; + private Image[] images; + private Boolean isPlayable; + private String[] languages; + private String name; + private String releaseDate; + private ReleaseDatePrecision releaseDatePrecision; + private ResumePoint resumePoint; + private ModelObjectType type; + private String uri; + private ChapterRestriction restrictions; + private AudiobookSimplified audiobook; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the audio preview URL. + * + * @param audioPreviewUrl A URL to a 30 second preview (MP3 format) of the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setAudioPreviewUrl(String audioPreviewUrl) { + this.audioPreviewUrl = audioPreviewUrl; + return this; + } + + /** + * Set the available markets. + * + * @param availableMarkets ISO 3166-1 alpha-2 country codes. + * @return A {@link Chapter.Builder}. + */ + public Builder setAvailableMarkets(String... availableMarkets) { + this.availableMarkets = availableMarkets; + return this; + } + + /** + * Set the chapter number. + * + * @param chapterNumber The number of the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setChapterNumber(Integer chapterNumber) { + this.chapterNumber = chapterNumber; + return this; + } + + /** + * Set the description. + * + * @param description A description of the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setDescription(String description) { + this.description = description; + return this; + } + + /** + * Set the HTML description. + * + * @param htmlDescription A description of the chapter (may contain HTML tags). + * @return A {@link Chapter.Builder}. + */ + public Builder setHtmlDescription(String htmlDescription) { + this.htmlDescription = htmlDescription; + return this; + } + + /** + * Set the duration in milliseconds. + * + * @param durationMs The chapter length in milliseconds. + * @return A {@link Chapter.Builder}. + */ + public Builder setDurationMs(Integer durationMs) { + this.durationMs = durationMs; + return this; + } + + /** + * Set whether the chapter is explicit. + * + * @param explicit Whether or not the chapter has explicit content. + * @return A {@link Chapter.Builder}. + */ + public Builder setExplicit(Boolean explicit) { + this.explicit = explicit; + return this; + } + + /** + * Set the external URLs. + * + * @param externalUrls The {@link ExternalUrl} for the chapter object. + * @return A {@link Chapter.Builder}. + */ + public Builder setExternalUrls(ExternalUrl externalUrls) { + this.externalUrls = externalUrls; + return this; + } + + /** + * Set the href. + * + * @param href A link to the Web API endpoint providing full details of the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setHref(String href) { + this.href = href; + return this; + } + + /** + * Set the Spotify ID. + * + * @param id The Spotify ID for the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setId(String id) { + this.id = id; + return this; + } + + /** + * Set the cover art images. + * + * @param images {@link Image} objects. + * @return A {@link Chapter.Builder}. + */ + public Builder setImages(Image... images) { + this.images = images; + return this; + } + + /** + * Set whether the chapter is playable. + * + * @param isPlayable True if the chapter is playable in the given market. + * @return A {@link Chapter.Builder}. + */ + public Builder setPlayable(Boolean isPlayable) { + this.isPlayable = isPlayable; + return this; + } + + /** + * Set the languages. + * + * @param languages ISO 639 language codes. + * @return A {@link Chapter.Builder}. + */ + public Builder setLanguages(String... languages) { + this.languages = languages; + return this; + } + + /** + * Set the name. + * + * @param name The name of the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setName(String name) { + this.name = name; + return this; + } + + /** + * Set the release date. + * + * @param releaseDate The date the chapter was first released. + * @return A {@link Chapter.Builder}. + */ + public Builder setReleaseDate(String releaseDate) { + this.releaseDate = releaseDate; + return this; + } + + /** + * Set the release date precision. + * + * @param releaseDatePrecision The precision with which {@code release_date} value is known. + * @return A {@link Chapter.Builder}. + */ + public Builder setReleaseDatePrecision(ReleaseDatePrecision releaseDatePrecision) { + this.releaseDatePrecision = releaseDatePrecision; + return this; + } + + /** + * Set the resume point. + * + * @param resumePoint The user's most recent position in the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setResumePoint(ResumePoint resumePoint) { + this.resumePoint = resumePoint; + return this; + } + + /** + * Set the model object type. + * + * @param type The {@link ModelObjectType}. + * @return A {@link Chapter.Builder}. + */ + public Builder setType(ModelObjectType type) { + this.type = type; + return this; + } + + /** + * Set the Spotify URI. + * + * @param uri The Spotify URI for the chapter. + * @return A {@link Chapter.Builder}. + */ + public Builder setUri(String uri) { + this.uri = uri; + return this; + } + + /** + * Set the content restrictions. + * + * @param restrictions A {@link ChapterRestriction} object. + * @return A {@link Chapter.Builder}. + */ + public Builder setRestrictions(ChapterRestriction restrictions) { + this.restrictions = restrictions; + return this; + } + + /** + * Set the audiobook for which the chapter belongs. + * + * @param audiobook A {@link AudiobookSimplified} object. + * @return A {@link Chapter.Builder}. + */ + public Builder setAudiobook(AudiobookSimplified audiobook) { + this.audiobook = audiobook; + return this; + } + + @Override + public Chapter build() { + return new Chapter(this); + } + } + + /** + * JsonUtil class for building {@link Chapter} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + @Override + public Chapter createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + return new Builder() + .setAudioPreviewUrl( + hasAndNotNull(jsonObject, "audio_preview_url") + ? jsonObject.get("audio_preview_url").getAsString() + : null) + .setAvailableMarkets( + hasAndNotNull(jsonObject, "available_markets") + ? new Gson().fromJson(jsonObject.getAsJsonArray("available_markets"), String[].class) + : null) + .setChapterNumber( + hasAndNotNull(jsonObject, "chapter_number") + ? jsonObject.get("chapter_number").getAsInt() + : null) + .setDescription( + hasAndNotNull(jsonObject, "description") + ? jsonObject.get("description").getAsString() + : null) + .setHtmlDescription( + hasAndNotNull(jsonObject, "html_description") + ? jsonObject.get("html_description").getAsString() + : null) + .setDurationMs( + hasAndNotNull(jsonObject, "duration_ms") + ? jsonObject.get("duration_ms").getAsInt() + : null) + .setExplicit( + hasAndNotNull(jsonObject, "explicit") + ? jsonObject.get("explicit").getAsBoolean() + : null) + .setExternalUrls( + hasAndNotNull(jsonObject, "external_urls") + ? new ExternalUrl.JsonUtil().createModelObject(jsonObject.getAsJsonObject("external_urls")) + : null) + .setHref( + hasAndNotNull(jsonObject, "href") + ? jsonObject.get("href").getAsString() + : null) + .setId( + hasAndNotNull(jsonObject, "id") + ? jsonObject.get("id").getAsString() + : null) + .setImages( + hasAndNotNull(jsonObject, "images") + ? new Image.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("images")) + : null) + .setPlayable( + hasAndNotNull(jsonObject, "is_playable") + ? jsonObject.get("is_playable").getAsBoolean() + : null) + .setLanguages( + hasAndNotNull(jsonObject, "languages") + ? new Gson().fromJson(jsonObject.getAsJsonArray("languages"), String[].class) + : null) + .setName( + hasAndNotNull(jsonObject, "name") + ? jsonObject.get("name").getAsString() + : null) + .setReleaseDate( + hasAndNotNull(jsonObject, "release_date") + ? jsonObject.get("release_date").getAsString() + : null) + .setReleaseDatePrecision( + hasAndNotNull(jsonObject, "release_date_precision") + ? ReleaseDatePrecision.keyOf(jsonObject.get("release_date_precision").getAsString().toLowerCase()) + : null) + .setResumePoint( + hasAndNotNull(jsonObject, "resume_point") + ? new ResumePoint.JsonUtil().createModelObject(jsonObject.getAsJsonObject("resume_point")) + : null) + .setType( + hasAndNotNull(jsonObject, "type") + ? ModelObjectType.keyOf(jsonObject.get("type").getAsString().toLowerCase()) + : null) + .setUri( + hasAndNotNull(jsonObject, "uri") + ? jsonObject.get("uri").getAsString() + : null) + .setRestrictions( + hasAndNotNull(jsonObject, "restrictions") + ? new ChapterRestriction.JsonUtil().createModelObject(jsonObject.getAsJsonObject("restrictions")) + : null) + .setAudiobook( + hasAndNotNull(jsonObject, "audiobook") + ? new AudiobookSimplified.JsonUtil().createModelObject(jsonObject.getAsJsonObject("audiobook")) + : null) + .build(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Chapter chapter = (Chapter) o; + return Objects.equals(id, chapter.id) && Objects.equals(name, chapter.name) + && Objects.equals(uri, chapter.uri); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, uri); + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterRestriction.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterRestriction.java new file mode 100644 index 000000000..e5201e628 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterRestriction.java @@ -0,0 +1,124 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.util.Objects; + +/** + * Retrieve information about + * ChapterRestriction objects by building instances from this class. + * + *

The reason for the restriction. Supported values: + *

    + *
  • {@code market} - The content item is not available in the given market.
  • + *
  • {@code product} - The content item is not available for the user's subscription type.
  • + *
  • {@code explicit} - The content item is explicit and the user's account is set to not play explicit content.
  • + *
  • {@code payment_required} - Payment is required to play the content item.
  • + *
+ * Additional reasons may be added in the future. + */ +@JsonDeserialize(builder = ChapterRestriction.Builder.class) +public class ChapterRestriction extends AbstractModelObject { + /** The reason for the restriction. */ + private final String reason; + + private ChapterRestriction(final Builder builder) { + super(builder); + this.reason = builder.reason; + } + + /** + * Get the reason for the restriction. + * + * @return The restriction reason. + */ + public String getReason() { + return reason; + } + + @Override + public String toString() { + return "ChapterRestriction(reason=" + reason + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link ChapterRestriction} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private String reason; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the restriction reason. + * + * @param reason The restriction reason. + * @return A {@link ChapterRestriction.Builder}. + */ + public Builder setReason(String reason) { + this.reason = reason; + return this; + } + + @Override + public ChapterRestriction build() { + return new ChapterRestriction(this); + } + } + + /** + * JsonUtil class for building {@link ChapterRestriction} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + @Override + public ChapterRestriction createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + return new Builder() + .setReason( + hasAndNotNull(jsonObject, "reason") + ? jsonObject.get("reason").getAsString() + : null) + .build(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ChapterRestriction that = (ChapterRestriction) o; + return Objects.equals(reason, that.reason); + } + + @Override + public int hashCode() { + return Objects.hash(reason); + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterSimplified.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterSimplified.java new file mode 100644 index 000000000..75e9554b9 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/ChapterSimplified.java @@ -0,0 +1,657 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.enums.ModelObjectType; +import se.michaelthelin.spotify.enums.ReleaseDatePrecision; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Retrieve information about + * simplified Chapter objects by building instances from this class. + */ +@JsonDeserialize(builder = ChapterSimplified.Builder.class) +public class ChapterSimplified extends AbstractModelObject { + /** A URL to a 30 second preview (MP3 format) of the chapter. {@code null} if not available. */ + private final String audioPreviewUrl; + /** A list of the countries in which the chapter can be played. */ + private final String[] availableMarkets; + /** The number of the chapter. */ + private final Integer chapterNumber; + /** A description of the chapter. HTML tags are stripped away from this field. */ + private final String description; + /** A description of the chapter. This field may contain HTML tags. */ + private final String htmlDescription; + /** The chapter length in milliseconds. */ + private final Integer durationMs; + /** Whether or not the chapter has explicit content. */ + private final Boolean explicit; + /** External URLs for this chapter. */ + private final ExternalUrl externalUrls; + /** A link to the Web API endpoint providing full details of the chapter. */ + private final String href; + /** The Spotify ID for the chapter. */ + private final String id; + /** The cover art for the chapter in various sizes, widest first. */ + private final Image[] images; + /** True if the chapter is playable in the given market. Otherwise false. */ + private final Boolean isPlayable; + /** A list of the languages used in the chapter. */ + private final String[] languages; + /** The name of the chapter. */ + private final String name; + /** The date the chapter was first released. */ + private final String releaseDate; + /** The precision with which {@code release_date} value is known. */ + private final ReleaseDatePrecision releaseDatePrecision; + /** The user's most recent position in the chapter. */ + private final ResumePoint resumePoint; + /** The object type. */ + private final ModelObjectType type; + /** The Spotify URI for the chapter. */ + private final String uri; + /** Included in the response when a content restriction is applied. */ + private final ChapterRestriction restrictions; + + private ChapterSimplified(final Builder builder) { + super(builder); + this.audioPreviewUrl = builder.audioPreviewUrl; + this.availableMarkets = builder.availableMarkets; + this.chapterNumber = builder.chapterNumber; + this.description = builder.description; + this.htmlDescription = builder.htmlDescription; + this.durationMs = builder.durationMs; + this.explicit = builder.explicit; + this.externalUrls = builder.externalUrls; + this.href = builder.href; + this.id = builder.id; + this.images = builder.images; + this.isPlayable = builder.isPlayable; + this.languages = builder.languages; + this.name = builder.name; + this.releaseDate = builder.releaseDate; + this.releaseDatePrecision = builder.releaseDatePrecision; + this.resumePoint = builder.resumePoint; + this.type = builder.type; + this.uri = builder.uri; + this.restrictions = builder.restrictions; + } + + /** + * Get a URL to a 30 second preview (MP3 format) of the chapter. {@code null} if not available. + * + * @return A URL to an audio preview. + */ + public String getAudioPreviewUrl() { + return audioPreviewUrl; + } + + /** + * Get a list of the countries in which the chapter can be played. + * + * @return An array of ISO 3166-1 alpha-2 country codes. + */ + public String[] getAvailableMarkets() { + return availableMarkets; + } + + /** + * Get the number of the chapter. + * + * @return The number of the chapter. + */ + public Integer getChapterNumber() { + return chapterNumber; + } + + /** + * Get a description of the chapter. HTML tags are stripped away from this field. + * + * @return The description of the chapter. + */ + public String getDescription() { + return description; + } + + /** + * Get a description of the chapter. This field may contain HTML tags. + * + * @return The HTML description of the chapter. + */ + public String getHtmlDescription() { + return htmlDescription; + } + + /** + * Get the duration of the chapter in milliseconds. + * + * @return The chapter length in milliseconds. + */ + public Integer getDurationMs() { + return durationMs; + } + + /** + * Check whether the chapter is explicit or not. + * + * @return Whether or not the chapter has explicit content. + */ + public Boolean getExplicit() { + return explicit; + } + + /** + * Get the external URLs of the chapter. + * + * @return An {@link ExternalUrl} object. + */ + public ExternalUrl getExternalUrls() { + return externalUrls; + } + + /** + * Get the full Spotify Web API endpoint URL of the chapter. + * + * @return A link to the Web API endpoint providing full details of the chapter. + */ + public String getHref() { + return href; + } + + /** + * Get the Spotify ID of the chapter. + * + * @return A Spotify chapter ID. + */ + public String getId() { + return id; + } + + /** + * Get the cover art for the chapter in various sizes, widest first. + * + * @return An array of {@link Image} objects. + */ + public Image[] getImages() { + return images; + } + + /** + * Check whether the chapter is playable in the given market. + * + * @return True if the chapter is playable in the given market. Otherwise false. + */ + public Boolean getPlayable() { + return isPlayable; + } + + /** + * Get a list of the languages used in the chapter. + * + * @return An array of ISO 639 language codes. + */ + public String[] getLanguages() { + return languages; + } + + /** + * Get the name of the chapter. + * + * @return The name of the chapter. + */ + public String getName() { + return name; + } + + /** + * Get the release date of the chapter. + * + * @return The date the chapter was first released. + */ + public String getReleaseDate() { + return releaseDate; + } + + /** + * Get the precision of the release date. + * + * @return The precision with which {@code release_date} value is known. + */ + public ReleaseDatePrecision getReleaseDatePrecision() { + return releaseDatePrecision; + } + + /** + * Get the user's most recent position in the chapter. + * + * @return A {@link ResumePoint} object. + */ + public ResumePoint getResumePoint() { + return resumePoint; + } + + /** + * Get the model object type. In this case "episode". + * + * @return A {@link ModelObjectType}. + */ + public ModelObjectType getType() { + return type; + } + + /** + * Get the Spotify URI of the chapter. + * + * @return Spotify chapter URI. + */ + public String getUri() { + return uri; + } + + /** + * Get the content restriction applied, if any. + * + * @return A {@link ChapterRestriction} object, or {@code null}. + */ + public ChapterRestriction getRestrictions() { + return restrictions; + } + + @Override + public String toString() { + return "ChapterSimplified(audioPreviewUrl=" + audioPreviewUrl + ", chapterNumber=" + chapterNumber + + ", description=" + description + ", durationMs=" + durationMs + ", explicit=" + explicit + + ", externalUrls=" + externalUrls + ", href=" + href + ", id=" + id + ", images=" + Arrays.toString(images) + + ", isPlayable=" + isPlayable + ", languages=" + Arrays.toString(languages) + ", name=" + name + + ", releaseDate=" + releaseDate + ", releaseDatePrecision=" + releaseDatePrecision + + ", resumePoint=" + resumePoint + ", type=" + type + ", uri=" + uri + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link ChapterSimplified} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private String audioPreviewUrl; + private String[] availableMarkets; + private Integer chapterNumber; + private String description; + private String htmlDescription; + private Integer durationMs; + private Boolean explicit; + private ExternalUrl externalUrls; + private String href; + private String id; + private Image[] images; + private Boolean isPlayable; + private String[] languages; + private String name; + private String releaseDate; + private ReleaseDatePrecision releaseDatePrecision; + private ResumePoint resumePoint; + private ModelObjectType type; + private String uri; + private ChapterRestriction restrictions; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the audio preview URL. + * + * @param audioPreviewUrl A URL to a 30 second preview (MP3 format) of the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setAudioPreviewUrl(String audioPreviewUrl) { + this.audioPreviewUrl = audioPreviewUrl; + return this; + } + + /** + * Set the available markets. + * + * @param availableMarkets ISO 3166-1 alpha-2 country codes. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setAvailableMarkets(String... availableMarkets) { + this.availableMarkets = availableMarkets; + return this; + } + + /** + * Set the chapter number. + * + * @param chapterNumber The number of the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setChapterNumber(Integer chapterNumber) { + this.chapterNumber = chapterNumber; + return this; + } + + /** + * Set the description. + * + * @param description A description of the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setDescription(String description) { + this.description = description; + return this; + } + + /** + * Set the HTML description. + * + * @param htmlDescription A description of the chapter (may contain HTML tags). + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setHtmlDescription(String htmlDescription) { + this.htmlDescription = htmlDescription; + return this; + } + + /** + * Set the duration in milliseconds. + * + * @param durationMs The chapter length in milliseconds. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setDurationMs(Integer durationMs) { + this.durationMs = durationMs; + return this; + } + + /** + * Set whether the chapter is explicit. + * + * @param explicit Whether or not the chapter has explicit content. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setExplicit(Boolean explicit) { + this.explicit = explicit; + return this; + } + + /** + * Set the external URLs. + * + * @param externalUrls The {@link ExternalUrl} for the chapter object. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setExternalUrls(ExternalUrl externalUrls) { + this.externalUrls = externalUrls; + return this; + } + + /** + * Set the href. + * + * @param href A link to the Web API endpoint providing full details of the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setHref(String href) { + this.href = href; + return this; + } + + /** + * Set the Spotify ID. + * + * @param id The Spotify ID for the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setId(String id) { + this.id = id; + return this; + } + + /** + * Set the cover art images. + * + * @param images {@link Image} objects. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setImages(Image... images) { + this.images = images; + return this; + } + + /** + * Set whether the chapter is playable. + * + * @param isPlayable True if the chapter is playable in the given market. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setPlayable(Boolean isPlayable) { + this.isPlayable = isPlayable; + return this; + } + + /** + * Set the languages. + * + * @param languages ISO 639 language codes. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setLanguages(String... languages) { + this.languages = languages; + return this; + } + + /** + * Set the name. + * + * @param name The name of the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setName(String name) { + this.name = name; + return this; + } + + /** + * Set the release date. + * + * @param releaseDate The date the chapter was first released. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setReleaseDate(String releaseDate) { + this.releaseDate = releaseDate; + return this; + } + + /** + * Set the release date precision. + * + * @param releaseDatePrecision The precision with which {@code release_date} value is known. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setReleaseDatePrecision(ReleaseDatePrecision releaseDatePrecision) { + this.releaseDatePrecision = releaseDatePrecision; + return this; + } + + /** + * Set the resume point. + * + * @param resumePoint The user's most recent position in the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setResumePoint(ResumePoint resumePoint) { + this.resumePoint = resumePoint; + return this; + } + + /** + * Set the model object type. + * + * @param type The {@link ModelObjectType}. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setType(ModelObjectType type) { + this.type = type; + return this; + } + + /** + * Set the Spotify URI. + * + * @param uri The Spotify URI for the chapter. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setUri(String uri) { + this.uri = uri; + return this; + } + + /** + * Set the content restrictions. + * + * @param restrictions A {@link ChapterRestriction} object. + * @return A {@link ChapterSimplified.Builder}. + */ + public Builder setRestrictions(ChapterRestriction restrictions) { + this.restrictions = restrictions; + return this; + } + + @Override + public ChapterSimplified build() { + return new ChapterSimplified(this); + } + } + + /** + * JsonUtil class for building {@link ChapterSimplified} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + @Override + public ChapterSimplified createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + return new Builder() + .setAudioPreviewUrl( + hasAndNotNull(jsonObject, "audio_preview_url") + ? jsonObject.get("audio_preview_url").getAsString() + : null) + .setAvailableMarkets( + hasAndNotNull(jsonObject, "available_markets") + ? new Gson().fromJson(jsonObject.getAsJsonArray("available_markets"), String[].class) + : null) + .setChapterNumber( + hasAndNotNull(jsonObject, "chapter_number") + ? jsonObject.get("chapter_number").getAsInt() + : null) + .setDescription( + hasAndNotNull(jsonObject, "description") + ? jsonObject.get("description").getAsString() + : null) + .setHtmlDescription( + hasAndNotNull(jsonObject, "html_description") + ? jsonObject.get("html_description").getAsString() + : null) + .setDurationMs( + hasAndNotNull(jsonObject, "duration_ms") + ? jsonObject.get("duration_ms").getAsInt() + : null) + .setExplicit( + hasAndNotNull(jsonObject, "explicit") + ? jsonObject.get("explicit").getAsBoolean() + : null) + .setExternalUrls( + hasAndNotNull(jsonObject, "external_urls") + ? new ExternalUrl.JsonUtil().createModelObject(jsonObject.getAsJsonObject("external_urls")) + : null) + .setHref( + hasAndNotNull(jsonObject, "href") + ? jsonObject.get("href").getAsString() + : null) + .setId( + hasAndNotNull(jsonObject, "id") + ? jsonObject.get("id").getAsString() + : null) + .setImages( + hasAndNotNull(jsonObject, "images") + ? new Image.JsonUtil().createModelObjectArray(jsonObject.getAsJsonArray("images")) + : null) + .setPlayable( + hasAndNotNull(jsonObject, "is_playable") + ? jsonObject.get("is_playable").getAsBoolean() + : null) + .setLanguages( + hasAndNotNull(jsonObject, "languages") + ? new Gson().fromJson(jsonObject.getAsJsonArray("languages"), String[].class) + : null) + .setName( + hasAndNotNull(jsonObject, "name") + ? jsonObject.get("name").getAsString() + : null) + .setReleaseDate( + hasAndNotNull(jsonObject, "release_date") + ? jsonObject.get("release_date").getAsString() + : null) + .setReleaseDatePrecision( + hasAndNotNull(jsonObject, "release_date_precision") + ? ReleaseDatePrecision.keyOf(jsonObject.get("release_date_precision").getAsString().toLowerCase()) + : null) + .setResumePoint( + hasAndNotNull(jsonObject, "resume_point") + ? new ResumePoint.JsonUtil().createModelObject(jsonObject.getAsJsonObject("resume_point")) + : null) + .setType( + hasAndNotNull(jsonObject, "type") + ? ModelObjectType.keyOf(jsonObject.get("type").getAsString().toLowerCase()) + : null) + .setUri( + hasAndNotNull(jsonObject, "uri") + ? jsonObject.get("uri").getAsString() + : null) + .setRestrictions( + hasAndNotNull(jsonObject, "restrictions") + ? new ChapterRestriction.JsonUtil().createModelObject(jsonObject.getAsJsonObject("restrictions")) + : null) + .build(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ChapterSimplified chapter = (ChapterSimplified) o; + return Objects.equals(id, chapter.id) && Objects.equals(name, chapter.name) + && Objects.equals(uri, chapter.uri); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, uri); + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Episode.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Episode.java index ee85a94c0..2252b6902 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Episode.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Episode.java @@ -110,6 +110,7 @@ public Integer getDurationMs() { * @return Whether or not the episode has explicit content ({@code true} = yes it does; {@code false} = no it does not * OR unknown). */ + @Override public Boolean getExplicit() { return explicit; } @@ -168,7 +169,8 @@ public Boolean getExternallyHosted() { * * @return True if the episode is playable in the given market. Otherwise false. */ - public Boolean getPlayable() { + @Override + public Boolean getIsPlayable() { return isPlayable; } diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/EpisodeSimplified.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/EpisodeSimplified.java index 748ad660a..8b20a94ca 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/EpisodeSimplified.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/EpisodeSimplified.java @@ -107,6 +107,7 @@ public Integer getDurationMs() { * @return Whether or not the episode has explicit content ({@code true} = yes it does; {@code false} = no it does not * OR unknown). */ + @Override public Boolean getExplicit() { return explicit; } @@ -162,7 +163,8 @@ public Boolean getExternallyHosted() { * * @return True if the episode is playable in the given market. Otherwise false. */ - public Boolean getPlayable() { + @Override + public Boolean getIsPlayable() { return isPlayable; } diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Narrator.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Narrator.java new file mode 100644 index 000000000..60e5515ca --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Narrator.java @@ -0,0 +1,115 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.util.Objects; + +/** + * Retrieve information about + * Narrator objects by building instances from this class. + */ +@JsonDeserialize(builder = Narrator.Builder.class) +public class Narrator extends AbstractModelObject { + /** The name of the Narrator. */ + private final String name; + + private Narrator(final Builder builder) { + super(builder); + this.name = builder.name; + } + + /** + * Get the name of the Narrator. + * + * @return The name of the Narrator. + */ + public String getName() { + return name; + } + + @Override + public String toString() { + return "Narrator(name=" + name + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link Narrator} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private String name; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the name of the Narrator to be built. + * + * @param name The name of the Narrator. + * @return A {@link Narrator.Builder}. + */ + public Builder setName(String name) { + this.name = name; + return this; + } + + @Override + public Narrator build() { + return new Narrator(this); + } + } + + /** + * JsonUtil class for building {@link Narrator} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + @Override + public Narrator createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + return new Builder() + .setName( + hasAndNotNull(jsonObject, "name") + ? jsonObject.get("name").getAsString() + : null) + .build(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Narrator narrator = (Narrator) o; + return Objects.equals(name, narrator.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Playlist.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Playlist.java index 456cea5da..b4fbbdf4c 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Playlist.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Playlist.java @@ -5,7 +5,7 @@ import se.michaelthelin.spotify.enums.ModelObjectType; import se.michaelthelin.spotify.model_objects.AbstractModelObject; import se.michaelthelin.spotify.model_objects.interfaces.IPlaylist; -import se.michaelthelin.spotify.requests.data.playlists.RemoveItemsFromPlaylistRequest; +import se.michaelthelin.spotify.requests.data.playlists.RemovePlaylistItemsRequest; import java.util.Arrays; import java.util.Objects; @@ -164,7 +164,7 @@ public User getOwner() { * href="https://developer.spotify.com/documentation/web-api/concepts/playlists"> * Spotify: Working With Playlists */ - public Boolean getIsPublicAccess() { + public Boolean getPublic() { return publicAccess; } @@ -173,7 +173,7 @@ public Boolean getIsPublicAccess() { * a specific playlist version. * * @return The version identifier for the current playlist. - * @see RemoveItemsFromPlaylistRequest + * @see RemovePlaylistItemsRequest */ public String getSnapshotId() { return snapshotId; diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/PlaylistSimplified.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/PlaylistSimplified.java index 5c1bc9895..8d71f8265 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/PlaylistSimplified.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/PlaylistSimplified.java @@ -6,7 +6,7 @@ import se.michaelthelin.spotify.model_objects.AbstractModelObject; import se.michaelthelin.spotify.model_objects.interfaces.IPlaylist; import se.michaelthelin.spotify.model_objects.miscellaneous.PlaylistTracksInformation; -import se.michaelthelin.spotify.requests.data.playlists.RemoveItemsFromPlaylistRequest; +import se.michaelthelin.spotify.requests.data.playlists.RemovePlaylistItemsRequest; import se.michaelthelin.spotify.requests.data.search.interfaces.ISearchModelObject; import java.util.Arrays; @@ -153,7 +153,7 @@ public User getOwner() { * href="https://developer.spotify.com/documentation/web-api/concepts/playlists"> * Spotify: Working With Playlists */ - public Boolean getIsPublicAccess() { + public Boolean getPublic() { return publicAccess; } @@ -162,7 +162,7 @@ public Boolean getIsPublicAccess() { * a specific playlist version. * * @return The version identifier for the current playlist. - * @see RemoveItemsFromPlaylistRequest + * @see RemovePlaylistItemsRequest */ public String getSnapshotId() { return snapshotId; diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedAudiobook.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedAudiobook.java new file mode 100644 index 000000000..beac899a0 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedAudiobook.java @@ -0,0 +1,135 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.text.ParseException; +import java.util.Date; +import java.util.logging.Level; + +/** + * Retrieve information about + * Saved Audiobook objects by building instances from this class. + */ +@JsonDeserialize(builder = SavedAudiobook.Builder.class) +public class SavedAudiobook extends AbstractModelObject { + /** The date and time the audiobook was saved. */ + private final Date addedAt; + /** Information about the audiobook. */ + private final AudiobookSimplified audiobook; + + private SavedAudiobook(final Builder builder) { + super(builder); + + this.addedAt = builder.addedAt; + this.audiobook = builder.audiobook; + } + + /** + * Get the date and time the audiobook was saved. + * + * @return The date and time the audiobook was saved. + */ + public Date getAddedAt() { + return addedAt; + } + + /** + * Get information about the audiobook from a saved audiobook object. + * + * @return Information about the audiobook. + */ + public AudiobookSimplified getAudiobook() { + return audiobook; + } + + @Override + public String toString() { + return "SavedAudiobook(addedAt=" + addedAt + ", audiobook=" + audiobook + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link SavedAudiobook} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private Date addedAt; + private AudiobookSimplified audiobook; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the "added at" date of the saved audiobook to be built. + * + * @param addedAt The date and time the audiobook was saved. + * @return A {@link SavedAudiobook.Builder}. + */ + public Builder setAddedAt(Date addedAt) { + this.addedAt = addedAt; + return this; + } + + /** + * Set the simplified audiobook object of the saved audiobook to be built. + * + * @param audiobook Information about the audiobook. + * @return A {@link SavedAudiobook.Builder}. + */ + public Builder setAudiobook(AudiobookSimplified audiobook) { + this.audiobook = audiobook; + return this; + } + + @Override + public SavedAudiobook build() { + return new SavedAudiobook(this); + } + } + + /** + * JsonUtil class for building {@link SavedAudiobook} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + public SavedAudiobook createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + try { + return new Builder() + .setAddedAt( + hasAndNotNull(jsonObject, "added_at") + ? SpotifyApi.parseDefaultDate(jsonObject.get("added_at").getAsString()) + : null) + .setAudiobook( + hasAndNotNull(jsonObject, "audiobook") + ? new AudiobookSimplified.JsonUtil().createModelObject( + jsonObject.getAsJsonObject("audiobook")) + : null) + .build(); + } catch (ParseException e) { + SpotifyApi.LOGGER.log(Level.SEVERE, e.getMessage()); + return null; + } + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedEpisode.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedEpisode.java new file mode 100644 index 000000000..fbc1f36dd --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/SavedEpisode.java @@ -0,0 +1,135 @@ +package se.michaelthelin.spotify.model_objects.specification; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import se.michaelthelin.spotify.SpotifyApi; +import se.michaelthelin.spotify.model_objects.AbstractModelObject; + +import java.text.ParseException; +import java.util.Date; +import java.util.logging.Level; + +/** + * Retrieve information about + * Saved Episode objects by building instances from this class. + */ +@JsonDeserialize(builder = SavedEpisode.Builder.class) +public class SavedEpisode extends AbstractModelObject { + /** The date and time the episode was saved. */ + private final Date addedAt; + /** Information about the episode. */ + private final Episode episode; + + private SavedEpisode(final Builder builder) { + super(builder); + + this.addedAt = builder.addedAt; + this.episode = builder.episode; + } + + /** + * Get the date and time the episode was saved. + * + * @return The date and time the episode was saved. + */ + public Date getAddedAt() { + return addedAt; + } + + /** + * Get information about the episode from a saved episode object. + * + * @return Information about the episode. + */ + public Episode getEpisode() { + return episode; + } + + @Override + public String toString() { + return "SavedEpisode(addedAt=" + addedAt + ", episode=" + episode + ")"; + } + + @Override + public Builder builder() { + return new Builder(); + } + + /** + * Builder class for building {@link SavedEpisode} instances. + */ + public static final class Builder extends AbstractModelObject.Builder { + private Date addedAt; + private Episode episode; + + /** + * Default constructor. + */ + public Builder() { + super(); + } + + /** + * Set the "added at" date of the saved episode to be built. + * + * @param addedAt The date and time the episode was saved. + * @return A {@link SavedEpisode.Builder}. + */ + public Builder setAddedAt(Date addedAt) { + this.addedAt = addedAt; + return this; + } + + /** + * Set the full episode object of the saved episode to be built. + * + * @param episode Information about the episode. + * @return A {@link SavedEpisode.Builder}. + */ + public Builder setEpisode(Episode episode) { + this.episode = episode; + return this; + } + + @Override + public SavedEpisode build() { + return new SavedEpisode(this); + } + } + + /** + * JsonUtil class for building {@link SavedEpisode} instances. + */ + public static final class JsonUtil extends AbstractModelObject.JsonUtil { + + /** + * Default constructor. + */ + public JsonUtil() { + super(); + } + + public SavedEpisode createModelObject(JsonObject jsonObject) { + if (jsonObject == null || jsonObject.isJsonNull()) { + return null; + } + + try { + return new Builder() + .setAddedAt( + hasAndNotNull(jsonObject, "added_at") + ? SpotifyApi.parseDefaultDate(jsonObject.get("added_at").getAsString()) + : null) + .setEpisode( + hasAndNotNull(jsonObject, "episode") + ? new Episode.JsonUtil().createModelObject( + jsonObject.getAsJsonObject("episode")) + : null) + .build(); + } catch (ParseException e) { + SpotifyApi.LOGGER.log(Level.SEVERE, e.getMessage()); + return null; + } + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Show.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Show.java index 868331964..5d90772c2 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Show.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Show.java @@ -92,6 +92,7 @@ public String getDescription() { * @return Whether or not the show has explicit content ({@code true} = yes it does; {@code false} = no it does not * OR unknown). */ + @Override public Boolean getExplicit() { return explicit; } diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/ShowSimplified.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/ShowSimplified.java index 80ededf29..78e05de39 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/ShowSimplified.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/ShowSimplified.java @@ -90,6 +90,7 @@ public String getDescription() { * @return Whether or not the show has explicit content ({@code true} = yes it does; {@code false} = no it does not * OR unknown). */ + @Override public Boolean getExplicit() { return explicit; } diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Track.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Track.java index 17fa6a03f..889d7e749 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/Track.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/Track.java @@ -6,7 +6,7 @@ import se.michaelthelin.spotify.model_objects.AbstractModelObject; import se.michaelthelin.spotify.model_objects.interfaces.ITrack; import se.michaelthelin.spotify.model_objects.miscellaneous.Restrictions; -import se.michaelthelin.spotify.requests.data.personalization.interfaces.IArtistTrackModelObject; +import se.michaelthelin.spotify.requests.data.users.interfaces.IArtistTrackModelObject; import se.michaelthelin.spotify.requests.data.search.interfaces.ISearchModelObject; import java.util.Arrays; @@ -114,7 +114,7 @@ public Integer getDurationMs() { * @return Whether or not the track has explicit lyrics ({@code true} = yes it does; {@code false} = no it does not * OR unknown). */ - public Boolean getIsExplicit() { + public Boolean getExplicit() { return explicit; } diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/specification/TrackSimplified.java b/src/main/java/se/michaelthelin/spotify/model_objects/specification/TrackSimplified.java index 560cd5b84..89f1abc71 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/specification/TrackSimplified.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/specification/TrackSimplified.java @@ -94,7 +94,7 @@ public Integer getDurationMs() { * @return Whether or not the track has explicit lyrics ({@code true} = yes it does; {@code false} = no it does not * OR unknown). */ - public Boolean getIsExplicit() { + public Boolean getExplicit() { return explicit; } diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedAlbumsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/albums/CheckUsersSavedAlbumsRequest.java similarity index 95% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedAlbumsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/albums/CheckUsersSavedAlbumsRequest.java index 399b4d500..f5fb61f57 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedAlbumsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/albums/CheckUsersSavedAlbumsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.albums; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.Gson; @@ -11,7 +11,10 @@ /** * Check if one or more albums is already saved in the current Spotify user’s "Your Music" library. + * + * @deprecated Use {@link CheckLibraryContainsRequest} instead. */ +@Deprecated @JsonDeserialize(builder = CheckUsersSavedAlbumsRequest.Builder.class) public class CheckUsersSavedAlbumsRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumsTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumTracksRequest.java similarity index 80% rename from src/main/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumsTracksRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumTracksRequest.java index 65442e077..4007bcd12 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumsTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumTracksRequest.java @@ -15,15 +15,15 @@ * Get Spotify catalog information about an album's tracks. Optional parameters can be used to limit the number of * tracks returned. */ -@JsonDeserialize(builder = GetAlbumsTracksRequest.Builder.class) -public class GetAlbumsTracksRequest extends AbstractDataRequest> { +@JsonDeserialize(builder = GetAlbumTracksRequest.Builder.class) +public class GetAlbumTracksRequest extends AbstractDataRequest> { /** - * The private {@link GetAlbumsTracksRequest} constructor. + * The private {@link GetAlbumTracksRequest} constructor. * - * @param builder A {@link GetAlbumsTracksRequest.Builder}. + * @param builder A {@link GetAlbumTracksRequest.Builder}. */ - private GetAlbumsTracksRequest(final Builder builder) { + private GetAlbumTracksRequest(final Builder builder) { super(builder); } @@ -42,12 +42,12 @@ public Paging execute() throws } /** - * Builder class for building a {@link GetAlbumsTracksRequest}. + * Builder class for building a {@link GetAlbumTracksRequest}. */ public static final class Builder extends AbstractDataPagingRequest.Builder { /** - * Create a new {@link GetAlbumsTracksRequest.Builder} instance. + * Create a new {@link GetAlbumTracksRequest.Builder} instance. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -59,7 +59,7 @@ public Builder(final String accessToken) { * The ID path parameter setter. * * @param id The Spotify ID for the album. - * @return A {@link GetAlbumsTracksRequest.Builder}. + * @return A {@link GetAlbumTracksRequest.Builder}. * @see Spotify URIs & IDs */ public Builder id(final String id) { @@ -72,7 +72,7 @@ public Builder id(final String id) { * The limit query parameter setter. * * @param limit Optional. The maximum number of tracks to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetAlbumsTracksRequest.Builder}. + * @return A {@link GetAlbumTracksRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -85,7 +85,7 @@ public Builder limit(final Integer limit) { * * @param offset Optional. The index of the first track to return. Default: 0 (the first object). Use with limit to * get the next set of tracks. - * @return A {@link GetAlbumsTracksRequest.Builder}. + * @return A {@link GetAlbumTracksRequest.Builder}. */ @Override public Builder offset(final Integer offset) { @@ -98,7 +98,7 @@ public Builder offset(final Integer offset) { * * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track * Relinking. - * @return A {@link GetAlbumsTracksRequest.Builder}. + * @return A {@link GetAlbumTracksRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes * @see Spotify: Track Relinking Guide */ @@ -110,12 +110,12 @@ public Builder market(final CountryCode market) { /** * The request build method. * - * @return A custom {@link GetAlbumsTracksRequest}. + * @return A custom {@link GetAlbumTracksRequest}. */ @Override - public GetAlbumsTracksRequest build() { + public GetAlbumTracksRequest build() { setPath("/v1/albums/{id}/tracks"); - return new GetAlbumsTracksRequest(this); + return new GetAlbumTracksRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequest.java new file mode 100644 index 000000000..d08cc189c --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequest.java @@ -0,0 +1,102 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.AlbumSimplified; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get a list of new album releases featured in Spotify (shown, for example, on a Spotify player's "Browse" tab). + * + * @deprecated Use the Search API instead. + */ +@Deprecated +@JsonDeserialize(builder = GetNewReleasesRequest.Builder.class) +public class GetNewReleasesRequest extends AbstractDataRequest> { + + /** + * The private {@link GetNewReleasesRequest} constructor. + * + * @param builder A {@link GetNewReleasesRequest.Builder}. + */ + private GetNewReleasesRequest(final Builder builder) { + super(builder); + } + + /** + * Get a paging of new {@link AlbumSimplified} releases. + * + * @return An {@link AlbumSimplified} paging. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Paging execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new AlbumSimplified.JsonUtil().createModelObjectPaging(getJson(), "albums"); + } + + /** + * Builder class for building a {@link GetNewReleasesRequest}. + * + * @deprecated Use the Search API instead. + */ + @Deprecated + public static final class Builder extends AbstractDataPagingRequest.Builder { + + /** + * Create a new {@link GetNewReleasesRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The limit setter. + * + * @param limit Optional. The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + * @return A {@link GetNewReleasesRequest.Builder}. + */ + @Override + public Builder limit(final Integer limit) { + assert (1 <= limit && limit <= 50); + return setQueryParameter("limit", limit); + } + + /** + * The offset setter. + * + * @param offset Optional. The index of the first item to return. Default: 0. + * @return A {@link GetNewReleasesRequest.Builder}. + */ + @Override + public Builder offset(final Integer offset) { + assert (offset >= 0); + return setQueryParameter("offset", offset); + } + + /** + * The request build method. + * + * @return A custom {@link GetNewReleasesRequest}. + */ + @Override + public GetNewReleasesRequest build() { + setPath("/v1/browse/new-releases"); + return new GetNewReleasesRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequest.java new file mode 100644 index 000000000..a2add78aa --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequest.java @@ -0,0 +1,100 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Album; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for several albums identified by their Spotify IDs. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralAlbumsRequest.Builder.class) +public class GetSeveralAlbumsRequest extends AbstractDataRequest { + + /** + * The private {@link GetSeveralAlbumsRequest} constructor. + * + * @param builder A {@link GetSeveralAlbumsRequest.Builder}. + */ + private GetSeveralAlbumsRequest(final Builder builder) { + super(builder); + } + + /** + * Get several {@link Album} objects. + * + * @return Multiple {@link Album} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Album[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Album.JsonUtil().createModelObjectArray(getJson(), "albums"); + } + + /** + * Builder class for building a {@link GetSeveralAlbumsRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSeveralAlbumsRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The album IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the albums. Maximum: 20 IDs. + * @return A {@link GetSeveralAlbumsRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 20); + return setQueryParameter("ids", ids); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply + * Track Relinking. + * @return A {@link GetSeveralAlbumsRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralAlbumsRequest}. + */ + @Override + public GetSeveralAlbumsRequest build() { + setPath("/v1/albums"); + return new GetSeveralAlbumsRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetCurrentUsersSavedAlbumsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetUsersSavedAlbumsRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/GetCurrentUsersSavedAlbumsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/albums/GetUsersSavedAlbumsRequest.java index b114c14d2..2334cb821 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetCurrentUsersSavedAlbumsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/albums/GetUsersSavedAlbumsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.albums; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.neovisionaries.i18n.CountryCode; @@ -14,15 +14,15 @@ /** * Get a list of the albums saved in the current Spotify user’s "Your Music" library. */ -@JsonDeserialize(builder = GetCurrentUsersSavedAlbumsRequest.Builder.class) -public class GetCurrentUsersSavedAlbumsRequest extends AbstractDataRequest> { +@JsonDeserialize(builder = GetUsersSavedAlbumsRequest.Builder.class) +public class GetUsersSavedAlbumsRequest extends AbstractDataRequest> { /** - * The private {@link GetCurrentUsersSavedAlbumsRequest} constructor. + * The private {@link GetUsersSavedAlbumsRequest} constructor. * - * @param builder A {@link GetCurrentUsersSavedAlbumsRequest.Builder}. + * @param builder A {@link GetUsersSavedAlbumsRequest.Builder}. */ - private GetCurrentUsersSavedAlbumsRequest(final Builder builder) { + private GetUsersSavedAlbumsRequest(final Builder builder) { super(builder); } @@ -41,12 +41,12 @@ public Paging execute() throws } /** - * Builder class for building a {@link GetCurrentUsersSavedAlbumsRequest}. + * Builder class for building a {@link GetUsersSavedAlbumsRequest}. */ public static final class Builder extends AbstractDataPagingRequest.Builder { /** - * Create a new {@link GetCurrentUsersSavedAlbumsRequest.Builder} instance. + * Create a new {@link GetUsersSavedAlbumsRequest.Builder} instance. *

* The {@code user-library-read} scope must have been authorized by the user. * @@ -61,7 +61,7 @@ public Builder(final String accessToken) { * The limit setter. * * @param limit Optional. The maximum number of objects to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetCurrentUsersSavedAlbumsRequest.Builder}. + * @return A {@link GetUsersSavedAlbumsRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -74,7 +74,7 @@ public Builder limit(final Integer limit) { * * @param offset Optional. The index of the first object to return. Default: 0 (i.e., the first object). Use with * {@link #limit(Integer)} to get the next set of objects. - * @return A {@link GetCurrentUsersSavedAlbumsRequest.Builder}. + * @return A {@link GetUsersSavedAlbumsRequest.Builder}. */ @Override public Builder offset(final Integer offset) { @@ -87,7 +87,7 @@ public Builder offset(final Integer offset) { * * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply * Track Relinking. - * @return A {@link GetCurrentUsersSavedAlbumsRequest.Builder}. + * @return A {@link GetUsersSavedAlbumsRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes * @see Spotify: Track Relinking Guide */ @@ -99,12 +99,12 @@ public Builder market(final CountryCode market) { /** * The request build method. * - * @return A custom {@link GetCurrentUsersSavedAlbumsRequest}. + * @return A custom {@link GetUsersSavedAlbumsRequest}. */ @Override - public GetCurrentUsersSavedAlbumsRequest build() { + public GetUsersSavedAlbumsRequest build() { setPath("/v1/me/albums"); - return new GetCurrentUsersSavedAlbumsRequest(this); + return new GetUsersSavedAlbumsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequest.java new file mode 100644 index 000000000..0767a6c0b --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequest.java @@ -0,0 +1,92 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Remove one or more albums from the current user's 'Your Music' library. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = RemoveAlbumsForCurrentUserRequest.Builder.class) +public class RemoveAlbumsForCurrentUserRequest extends AbstractDataRequest { + + /** + * The private {@link RemoveAlbumsForCurrentUserRequest} constructor. + * + * @param builder A {@link RemoveAlbumsForCurrentUserRequest.Builder}. + */ + private RemoveAlbumsForCurrentUserRequest(final Builder builder) { + super(builder); + } + + /** + * Remove albums from the current user's library. + * + * @return A string. Note: This endpoint doesn't return something in its response body. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + @Override + public String execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return deleteJson(); + } + + /** + * Builder class for building a {@link RemoveAlbumsForCurrentUserRequest}. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link RemoveAlbumsForCurrentUserRequest.Builder} instance. + *

+ * The {@code user-library-modify} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The album IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the albums. Maximum: 50 IDs. + * @return A {@link RemoveAlbumsForCurrentUserRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link RemoveAlbumsForCurrentUserRequest}. + */ + @Override + public RemoveAlbumsForCurrentUserRequest build() { + setPath("/v1/me/albums"); + return new RemoveAlbumsForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequest.java new file mode 100644 index 000000000..b0210751c --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequest.java @@ -0,0 +1,92 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Save one or more albums to the current user's 'Your Music' library. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = SaveAlbumsForCurrentUserRequest.Builder.class) +public class SaveAlbumsForCurrentUserRequest extends AbstractDataRequest { + + /** + * The private {@link SaveAlbumsForCurrentUserRequest} constructor. + * + * @param builder A {@link SaveAlbumsForCurrentUserRequest.Builder}. + */ + private SaveAlbumsForCurrentUserRequest(final Builder builder) { + super(builder); + } + + /** + * Save albums to the current user's library. + * + * @return A string. Note: This endpoint doesn't return something in its response body. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + @Override + public String execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return putJson(); + } + + /** + * Builder class for building a {@link SaveAlbumsForCurrentUserRequest}. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link SaveAlbumsForCurrentUserRequest.Builder} instance. + *

+ * The {@code user-library-modify} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The album IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the albums. Maximum: 50 IDs. + * @return A {@link SaveAlbumsForCurrentUserRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link SaveAlbumsForCurrentUserRequest}. + */ + @Override + public SaveAlbumsForCurrentUserRequest build() { + setPath("/v1/me/albums"); + return new SaveAlbumsForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsRelatedArtistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsRelatedArtistsRequest.java index 640b411ce..66129deaa 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsRelatedArtistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsRelatedArtistsRequest.java @@ -11,7 +11,10 @@ /** * Get Spotify catalog information about artists similar to a given artist. Similarity is based on analysis of the * Spotify community’s listening history. + * + * @deprecated This endpoint has been deprecated by Spotify. */ +@Deprecated @JsonDeserialize(builder = GetArtistsRelatedArtistsRequest.Builder.class) public class GetArtistsRelatedArtistsRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequest.java new file mode 100644 index 000000000..b244c7748 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequest.java @@ -0,0 +1,100 @@ +package se.michaelthelin.spotify.requests.data.artists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Track; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information about an artist's top tracks by country. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetArtistsTopTracksRequest.Builder.class) +public class GetArtistsTopTracksRequest extends AbstractDataRequest { + + /** + * The private {@link GetArtistsTopTracksRequest} constructor. + * + * @param builder A {@link GetArtistsTopTracksRequest.Builder}. + */ + private GetArtistsTopTracksRequest(final Builder builder) { + super(builder); + } + + /** + * Get an artist's top tracks. + * + * @return Multiple {@link Track} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Track[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Track.JsonUtil().createModelObjectArray(getJson(), "tracks"); + } + + /** + * Builder class for building a {@link GetArtistsTopTracksRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetArtistsTopTracksRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The artist ID path parameter setter. + * + * @param id Required. The Spotify ID for the artist. + * @return A {@link GetArtistsTopTracksRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder id(final String id) { + assert (id != null); + assert (!id.isEmpty()); + return setPathParameter("id", id); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply + * Track Relinking. + * @return A {@link GetArtistsTopTracksRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetArtistsTopTracksRequest}. + */ + @Override + public GetArtistsTopTracksRequest build() { + setPath("/v1/artists/{id}/top-tracks"); + return new GetArtistsTopTracksRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequest.java new file mode 100644 index 000000000..234e5c72f --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequest.java @@ -0,0 +1,86 @@ +package se.michaelthelin.spotify.requests.data.artists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Artist; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for several artists based on their Spotify IDs. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralArtistsRequest.Builder.class) +public class GetSeveralArtistsRequest extends AbstractDataRequest { + + /** + * The private {@link GetSeveralArtistsRequest} constructor. + * + * @param builder A {@link GetSeveralArtistsRequest.Builder}. + */ + private GetSeveralArtistsRequest(final Builder builder) { + super(builder); + } + + /** + * Get several {@link Artist} objects. + * + * @return Multiple {@link Artist} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Artist[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Artist.JsonUtil().createModelObjectArray(getJson(), "artists"); + } + + /** + * Builder class for building a {@link GetSeveralArtistsRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSeveralArtistsRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The artist IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the artists. Maximum: 50 IDs. + * @return A {@link GetSeveralArtistsRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralArtistsRequest}. + */ + @Override + public GetSeveralArtistsRequest build() { + setPath("/v1/artists"); + return new GetSeveralArtistsRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequest.java new file mode 100644 index 000000000..f68c8c708 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequest.java @@ -0,0 +1,90 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.Gson; +import com.google.gson.JsonParser; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Check if one or more audiobooks are already saved in the current Spotify user's library. + * + * @deprecated Use {@link CheckLibraryContainsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = CheckUsersSavedAudiobooksRequest.Builder.class) +public class CheckUsersSavedAudiobooksRequest extends AbstractDataRequest { + + /** + * The private {@link CheckUsersSavedAudiobooksRequest} constructor. + * + * @param builder A {@link CheckUsersSavedAudiobooksRequest.Builder}. + */ + private CheckUsersSavedAudiobooksRequest(final Builder builder) { + super(builder); + } + + /** + * Check whether audiobooks are present in the current user's library. + * + * @return Whether audiobooks are present in the current user's library. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Boolean[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Gson().fromJson(JsonParser.parseString(getJson()).getAsJsonArray(), Boolean[].class); + } + + /** + * Builder class for building a {@link CheckUsersSavedAudiobooksRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link CheckUsersSavedAudiobooksRequest.Builder} instance. + *

+ * The {@code user-library-read} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The audiobook IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link CheckUsersSavedAudiobooksRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link CheckUsersSavedAudiobooksRequest}. + */ + @Override + public CheckUsersSavedAudiobooksRequest build() { + setPath("/v1/me/audiobooks/contains"); + return new CheckUsersSavedAudiobooksRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequest.java new file mode 100644 index 000000000..0ea3d0ddf --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequest.java @@ -0,0 +1,124 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.ChapterSimplified; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information about an audiobook's chapters. + * + *

Note: Audiobooks are only available for the US, UK, Ireland, New Zealand and Australia markets. + */ +@JsonDeserialize(builder = GetAudiobookChaptersRequest.Builder.class) +public class GetAudiobookChaptersRequest extends AbstractDataRequest> { + + /** + * The private {@link GetAudiobookChaptersRequest} constructor. + * + * @param builder A {@link GetAudiobookChaptersRequest.Builder}. + */ + private GetAudiobookChaptersRequest(final Builder builder) { + super(builder); + } + + /** + * Get the chapters from the audiobook. + * + * @return A chapters paging. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Paging execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new ChapterSimplified.JsonUtil().createModelObjectPaging(getJson()); + } + + /** + * Builder class for building a {@link GetAudiobookChaptersRequest}. + */ + public static final class Builder extends AbstractDataPagingRequest.Builder { + + /** + * Create a new {@link GetAudiobookChaptersRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The ID path parameter setter. + * + * @param id The Spotify ID for the audiobook. + * @return A {@link GetAudiobookChaptersRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder id(final String id) { + assert (id != null); + assert (!id.isEmpty()); + return setPathParameter("id", id); + } + + /** + * The limit query parameter setter. + * + * @param limit Optional. The maximum number of chapters to return. Default: 20. Minimum: 1. Maximum: 50. + * @return A {@link GetAudiobookChaptersRequest.Builder}. + */ + @Override + public Builder limit(final Integer limit) { + assert (1 <= limit && limit <= 50); + return setQueryParameter("limit", limit); + } + + /** + * The offset query parameter setter. + * + * @param offset Optional. The index of the first chapter to return. Default: 0 (the first object). + * @return A {@link GetAudiobookChaptersRequest.Builder}. + */ + @Override + public Builder offset(final Integer offset) { + assert (offset >= 0); + return setQueryParameter("offset", offset); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. + * @return A {@link GetAudiobookChaptersRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetAudiobookChaptersRequest}. + */ + @Override + public GetAudiobookChaptersRequest build() { + setPath("/v1/audiobooks/{id}/chapters"); + return new GetAudiobookChaptersRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequest.java new file mode 100644 index 000000000..8b9a77ff2 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequest.java @@ -0,0 +1,98 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Audiobook; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for a single audiobook. + * + *

Note: Audiobooks are only available for the US, UK, Ireland, New Zealand and Australia markets. + */ +@JsonDeserialize(builder = GetAudiobookRequest.Builder.class) +public class GetAudiobookRequest extends AbstractDataRequest { + + /** + * The private {@link GetAudiobookRequest} constructor. + * + * @param builder A {@link GetAudiobookRequest.Builder}. + */ + private GetAudiobookRequest(final Builder builder) { + super(builder); + } + + /** + * Get an {@link Audiobook} synchronously. + * + * @return An {@link Audiobook}. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Audiobook execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Audiobook.JsonUtil().createModelObject(getJson()); + } + + /** + * A builder class for a {@link GetAudiobookRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetAudiobookRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The ID path parameter setter. + * + * @param id The Spotify ID for the audiobook. + * @return A {@link GetAudiobookRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder id(final String id) { + assert (id != null); + assert (!id.isEmpty()); + return setPathParameter("id", id); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. + * @return A {@link GetAudiobookRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetAudiobookRequest}. + */ + @Override + public GetAudiobookRequest build() { + setPath("/v1/audiobooks/{id}"); + return new GetAudiobookRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequest.java new file mode 100644 index 000000000..946d35671 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequest.java @@ -0,0 +1,101 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.AudiobookSimplified; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for several audiobooks identified by their Spotify IDs. + * + *

Note: Audiobooks are only available for the US, UK, Ireland, New Zealand and Australia markets. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralAudiobooksRequest.Builder.class) +public class GetSeveralAudiobooksRequest extends AbstractDataRequest { + + /** + * The private {@link GetSeveralAudiobooksRequest} constructor. + * + * @param builder A {@link GetSeveralAudiobooksRequest.Builder}. + */ + private GetSeveralAudiobooksRequest(final Builder builder) { + super(builder); + } + + /** + * Get several {@link AudiobookSimplified} objects. + * + * @return Multiple {@link AudiobookSimplified} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public AudiobookSimplified[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new AudiobookSimplified.JsonUtil().createModelObjectArray(getJson(), "audiobooks"); + } + + /** + * Builder class for building a {@link GetSeveralAudiobooksRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSeveralAudiobooksRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The audiobook IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link GetSeveralAudiobooksRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. + * @return A {@link GetSeveralAudiobooksRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralAudiobooksRequest}. + */ + @Override + public GetSeveralAudiobooksRequest build() { + setPath("/v1/audiobooks"); + return new GetSeveralAudiobooksRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.java new file mode 100644 index 000000000..9012b7919 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.java @@ -0,0 +1,99 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.model_objects.specification.SavedAudiobook; +import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get a list of the audiobooks saved in the current Spotify user's "Your Music" library. + */ +@JsonDeserialize(builder = GetUsersSavedAudiobooksRequest.Builder.class) +public class GetUsersSavedAudiobooksRequest extends AbstractDataRequest> { + + /** + * The private {@link GetUsersSavedAudiobooksRequest} constructor. + * + * @param builder A {@link GetUsersSavedAudiobooksRequest.Builder}. + */ + private GetUsersSavedAudiobooksRequest(final Builder builder) { + super(builder); + } + + /** + * Get the audiobooks from the current user's "Your Music" library. + * + * @return A {@link SavedAudiobook} paging. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Paging execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new SavedAudiobook.JsonUtil().createModelObjectPaging(getJson()); + } + + /** + * Builder class for building a {@link GetUsersSavedAudiobooksRequest}. + */ + public static final class Builder extends AbstractDataPagingRequest.Builder { + + /** + * Create a new {@link GetUsersSavedAudiobooksRequest.Builder} instance. + *

+ * The {@code user-library-read} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The limit setter. + * + * @param limit Optional. The maximum number of objects to return. Default: 20. Minimum: 1. Maximum: 50. + * @return A {@link GetUsersSavedAudiobooksRequest.Builder}. + */ + @Override + public Builder limit(final Integer limit) { + assert (1 <= limit && limit <= 50); + return setQueryParameter("limit", limit); + } + + /** + * The offset setter. + * + * @param offset Optional. The index of the first object to return. Default: 0. + * @return A {@link GetUsersSavedAudiobooksRequest.Builder}. + */ + @Override + public Builder offset(final Integer offset) { + assert (offset >= 0); + return setQueryParameter("offset", offset); + } + + /** + * The request build method. + * + * @return A custom {@link GetUsersSavedAudiobooksRequest}. + */ + @Override + public GetUsersSavedAudiobooksRequest build() { + setPath("/v1/me/audiobooks"); + return new GetUsersSavedAudiobooksRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.java new file mode 100644 index 000000000..1b1270511 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.java @@ -0,0 +1,89 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Remove one or more audiobooks from the current Spotify user's library. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = RemoveAudiobooksForCurrentUserRequest.Builder.class) +public class RemoveAudiobooksForCurrentUserRequest extends AbstractDataRequest { + + /** + * The private {@link RemoveAudiobooksForCurrentUserRequest} constructor. + * + * @param builder A {@link RemoveAudiobooksForCurrentUserRequest.Builder}. + */ + private RemoveAudiobooksForCurrentUserRequest(final Builder builder) { + super(builder); + } + + /** + * Remove audiobooks from the current user's library. + * + * @return A string. Note: This endpoint doesn't return something in its response body. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + @Override + public String execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return deleteJson(); + } + + /** + * Builder class for building a {@link RemoveAudiobooksForCurrentUserRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link RemoveAudiobooksForCurrentUserRequest.Builder} instance. + *

+ * The {@code user-library-modify} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The audiobook IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link RemoveAudiobooksForCurrentUserRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link RemoveAudiobooksForCurrentUserRequest}. + */ + @Override + public RemoveAudiobooksForCurrentUserRequest build() { + setPath("/v1/me/audiobooks"); + return new RemoveAudiobooksForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.java new file mode 100644 index 000000000..398d16bd4 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.java @@ -0,0 +1,89 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Save one or more audiobooks to the current Spotify user's library. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = SaveAudiobooksForCurrentUserRequest.Builder.class) +public class SaveAudiobooksForCurrentUserRequest extends AbstractDataRequest { + + /** + * The private {@link SaveAudiobooksForCurrentUserRequest} constructor. + * + * @param builder A {@link SaveAudiobooksForCurrentUserRequest.Builder}. + */ + private SaveAudiobooksForCurrentUserRequest(final Builder builder) { + super(builder); + } + + /** + * Save audiobooks to the current user's library. + * + * @return A string. Note: This endpoint doesn't return something in its response body. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + @Override + public String execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return putJson(); + } + + /** + * Builder class for building a {@link SaveAudiobooksForCurrentUserRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link SaveAudiobooksForCurrentUserRequest.Builder} instance. + *

+ * The {@code user-library-modify} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The audiobook IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the audiobooks. Maximum: 50 IDs. + * @return A {@link SaveAudiobooksForCurrentUserRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link SaveAudiobooksForCurrentUserRequest}. + */ + @Override + public SaveAudiobooksForCurrentUserRequest build() { + setPath("/v1/me/audiobooks"); + return new SaveAudiobooksForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSeveralBrowseCategoriesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSeveralBrowseCategoriesRequest.java new file mode 100644 index 000000000..f7d4f0ca9 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSeveralBrowseCategoriesRequest.java @@ -0,0 +1,115 @@ +package se.michaelthelin.spotify.requests.data.categories; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Category; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get a list of categories used to tag items in Spotify (on, for example, the Spotify player's "Browse" tab). + * + * @deprecated Use the Search API instead. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralBrowseCategoriesRequest.Builder.class) +public class GetSeveralBrowseCategoriesRequest extends AbstractDataRequest> { + + /** + * The private {@link GetSeveralBrowseCategoriesRequest} constructor. + * + * @param builder A {@link GetSeveralBrowseCategoriesRequest.Builder}. + */ + private GetSeveralBrowseCategoriesRequest(final Builder builder) { + super(builder); + } + + /** + * Get a paging of {@link Category} objects. + * + * @return A {@link Category} paging. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Paging execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Category.JsonUtil().createModelObjectPaging(getJson(), "categories"); + } + + /** + * Builder class for building a {@link GetSeveralBrowseCategoriesRequest}. + * + * @deprecated Use the Search API instead. + */ + @Deprecated + public static final class Builder extends AbstractDataPagingRequest.Builder { + + /** + * Create a new {@link GetSeveralBrowseCategoriesRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The locale setter. + * + * @param locale Optional. The desired language, consisting of an ISO 639-1 language code and an ISO 3166-1 + * alpha-2 country code, joined by an underscore. For example: {@code es_MX}. Provide this parameter + * if you want the category strings returned in a particular language. + * @return A {@link GetSeveralBrowseCategoriesRequest.Builder}. + */ + public Builder locale(final String locale) { + assert (locale != null); + return setQueryParameter("locale", locale); + } + + /** + * The limit setter. + * + * @param limit Optional. The maximum number of categories to return. Default: 20. Minimum: 1. Maximum: 50. + * @return A {@link GetSeveralBrowseCategoriesRequest.Builder}. + */ + @Override + public Builder limit(final Integer limit) { + assert (1 <= limit && limit <= 50); + return setQueryParameter("limit", limit); + } + + /** + * The offset setter. + * + * @param offset Optional. The index of the first item to return. Default: 0. + * @return A {@link GetSeveralBrowseCategoriesRequest.Builder}. + */ + @Override + public Builder offset(final Integer offset) { + assert (offset >= 0); + return setQueryParameter("offset", offset); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralBrowseCategoriesRequest}. + */ + @Override + public GetSeveralBrowseCategoriesRequest build() { + setPath("/v1/browse/categories"); + return new GetSeveralBrowseCategoriesRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSingleBrowseCategoryRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSingleBrowseCategoryRequest.java new file mode 100644 index 000000000..95481cbf5 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/categories/GetSingleBrowseCategoryRequest.java @@ -0,0 +1,100 @@ +package se.michaelthelin.spotify.requests.data.categories; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Category; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get a single category used to tag items in Spotify (on, for example, the Spotify player's "Browse" tab). + * + * @deprecated Use the Search API instead. + */ +@Deprecated +@JsonDeserialize(builder = GetSingleBrowseCategoryRequest.Builder.class) +public class GetSingleBrowseCategoryRequest extends AbstractDataRequest { + + /** + * The private {@link GetSingleBrowseCategoryRequest} constructor. + * + * @param builder A {@link GetSingleBrowseCategoryRequest.Builder}. + */ + private GetSingleBrowseCategoryRequest(final Builder builder) { + super(builder); + } + + /** + * Get a {@link Category} object. + * + * @return A {@link Category}. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Category execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Category.JsonUtil().createModelObject(getJson()); + } + + /** + * Builder class for building a {@link GetSingleBrowseCategoryRequest}. + * + * @deprecated Use the Search API instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSingleBrowseCategoryRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The category ID path parameter setter. + * + * @param category_id Required. The Spotify category ID for the category. + * @return A {@link GetSingleBrowseCategoryRequest.Builder}. + */ + public Builder category_id(final String category_id) { + assert (category_id != null); + assert (!category_id.isEmpty()); + return setPathParameter("category_id", category_id); + } + + /** + * The locale setter. + * + * @param locale Optional. The desired language, consisting of an ISO 639-1 language code and an ISO 3166-1 + * alpha-2 country code, joined by an underscore. For example: {@code es_MX}. + * @return A {@link GetSingleBrowseCategoryRequest.Builder}. + */ + public Builder locale(final String locale) { + assert (locale != null); + return setQueryParameter("locale", locale); + } + + /** + * The request build method. + * + * @return A custom {@link GetSingleBrowseCategoryRequest}. + */ + @Override + public GetSingleBrowseCategoryRequest build() { + setPath("/v1/browse/categories/{category_id}"); + return new GetSingleBrowseCategoryRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequest.java new file mode 100644 index 000000000..613848430 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequest.java @@ -0,0 +1,97 @@ +package se.michaelthelin.spotify.requests.data.chapters; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Chapter; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for a single audiobook chapter. Chapters are only available within the US, UK, + * Ireland, New Zealand and Australia markets. + */ +@JsonDeserialize(builder = GetChapterRequest.Builder.class) +public class GetChapterRequest extends AbstractDataRequest { + + /** + * The private {@link GetChapterRequest} constructor. + * + * @param builder A {@link GetChapterRequest.Builder}. + */ + private GetChapterRequest(final Builder builder) { + super(builder); + } + + /** + * Get a {@link Chapter} synchronously. + * + * @return A {@link Chapter}. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Chapter execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Chapter.JsonUtil().createModelObject(getJson()); + } + + /** + * A builder class for a {@link GetChapterRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetChapterRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The ID path parameter setter. + * + * @param id The Spotify ID for the chapter. + * @return A {@link GetChapterRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder id(final String id) { + assert (id != null); + assert (!id.isEmpty()); + return setPathParameter("id", id); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. + * @return A {@link GetChapterRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetChapterRequest}. + */ + @Override + public GetChapterRequest build() { + setPath("/v1/chapters/{id}"); + return new GetChapterRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequest.java new file mode 100644 index 000000000..695c18cf2 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequest.java @@ -0,0 +1,100 @@ +package se.michaelthelin.spotify.requests.data.chapters; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Chapter; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for several chapters identified by their Spotify IDs. Chapters are only available + * within the US, UK, Ireland, New Zealand and Australia markets. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralChaptersRequest.Builder.class) +public class GetSeveralChaptersRequest extends AbstractDataRequest { + + /** + * The private {@link GetSeveralChaptersRequest} constructor. + * + * @param builder A {@link GetSeveralChaptersRequest.Builder}. + */ + private GetSeveralChaptersRequest(final Builder builder) { + super(builder); + } + + /** + * Get several {@link Chapter} objects. + * + * @return Multiple {@link Chapter} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Chapter[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Chapter.JsonUtil().createModelObjectArray(getJson(), "chapters"); + } + + /** + * Builder class for building a {@link GetSeveralChaptersRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSeveralChaptersRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The chapter IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the chapters. Maximum: 50 IDs. + * @return A {@link GetSeveralChaptersRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. + * @return A {@link GetSeveralChaptersRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralChaptersRequest}. + */ + @Override + public GetSeveralChaptersRequest build() { + setPath("/v1/chapters"); + return new GetSeveralChaptersRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedEpisodesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/CheckUsersSavedEpisodesRequest.java similarity index 95% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedEpisodesRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/episodes/CheckUsersSavedEpisodesRequest.java index 55c29e247..ec6b8057b 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedEpisodesRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/CheckUsersSavedEpisodesRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.episodes; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.Gson; @@ -11,7 +11,10 @@ /** * Check if one or more episodes is already saved in the current Spotify user's 'Your Episodes' library. + * + * @deprecated Use {@link CheckLibraryContainsRequest} instead. */ +@Deprecated @JsonDeserialize(builder = CheckUsersSavedEpisodesRequest.Builder.class) public class CheckUsersSavedEpisodesRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequest.java new file mode 100644 index 000000000..2f53bf2e1 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequest.java @@ -0,0 +1,99 @@ +package se.michaelthelin.spotify.requests.data.episodes; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Episode; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for several episodes based on their Spotify IDs. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralEpisodesRequest.Builder.class) +public class GetSeveralEpisodesRequest extends AbstractDataRequest { + + /** + * The private {@link GetSeveralEpisodesRequest} constructor. + * + * @param builder A {@link GetSeveralEpisodesRequest.Builder}. + */ + private GetSeveralEpisodesRequest(final Builder builder) { + super(builder); + } + + /** + * Get several {@link Episode} objects. + * + * @return Multiple {@link Episode} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Episode[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Episode.JsonUtil().createModelObjectArray(getJson(), "episodes"); + } + + /** + * Builder class for building a {@link GetSeveralEpisodesRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSeveralEpisodesRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The episode IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the episodes. Maximum: 50 IDs. + * @return A {@link GetSeveralEpisodesRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. + * @return A {@link GetSeveralEpisodesRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralEpisodesRequest}. + */ + @Override + public GetSeveralEpisodesRequest build() { + setPath("/v1/episodes"); + return new GetSeveralEpisodesRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedEpisodesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/GetUsersSavedEpisodesRequest.java similarity index 97% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedEpisodesRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/episodes/GetUsersSavedEpisodesRequest.java index 5c5e87a06..0ad5668ce 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedEpisodesRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/GetUsersSavedEpisodesRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.episodes; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.neovisionaries.i18n.CountryCode; @@ -90,7 +90,7 @@ public GetUsersSavedEpisodesRequest.Builder offset(final Integer offset) { * * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply * Track Relinking. - * @return A {@link GetCurrentUsersSavedAlbumsRequest.Builder}. + * @return A {@link GetUsersSavedEpisodesRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes * @see Spotify: Track Relinking Guide */ diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.java new file mode 100644 index 000000000..128d6bdf8 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.java @@ -0,0 +1,92 @@ +package se.michaelthelin.spotify.requests.data.episodes; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Remove one or more episodes from the current user's library. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = RemoveEpisodesForCurrentUserRequest.Builder.class) +public class RemoveEpisodesForCurrentUserRequest extends AbstractDataRequest { + + /** + * The private {@link RemoveEpisodesForCurrentUserRequest} constructor. + * + * @param builder A {@link RemoveEpisodesForCurrentUserRequest.Builder}. + */ + private RemoveEpisodesForCurrentUserRequest(final Builder builder) { + super(builder); + } + + /** + * Remove episodes from the current user's library. + * + * @return A string. Note: This endpoint doesn't return something in its response body. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + @Override + public String execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return deleteJson(); + } + + /** + * Builder class for building a {@link RemoveEpisodesForCurrentUserRequest}. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link RemoveEpisodesForCurrentUserRequest.Builder} instance. + *

+ * The {@code user-library-modify} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The episode IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the episodes. Maximum: 50 IDs. + * @return A {@link RemoveEpisodesForCurrentUserRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link RemoveEpisodesForCurrentUserRequest}. + */ + @Override + public RemoveEpisodesForCurrentUserRequest build() { + setPath("/v1/me/episodes"); + return new RemoveEpisodesForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequest.java new file mode 100644 index 000000000..524adb5f0 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequest.java @@ -0,0 +1,92 @@ +package se.michaelthelin.spotify.requests.data.episodes; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Save one or more episodes to the current user's library. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = SaveEpisodesForCurrentUserRequest.Builder.class) +public class SaveEpisodesForCurrentUserRequest extends AbstractDataRequest { + + /** + * The private {@link SaveEpisodesForCurrentUserRequest} constructor. + * + * @param builder A {@link SaveEpisodesForCurrentUserRequest.Builder}. + */ + private SaveEpisodesForCurrentUserRequest(final Builder builder) { + super(builder); + } + + /** + * Save episodes to the current user's library. + * + * @return A string. Note: This endpoint doesn't return something in its response body. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + @Override + public String execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return putJson(); + } + + /** + * Builder class for building a {@link SaveEpisodesForCurrentUserRequest}. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link SaveEpisodesForCurrentUserRequest.Builder} instance. + *

+ * The {@code user-library-modify} scope must have been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The episode IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the episodes. Maximum: 50 IDs. + * @return A {@link SaveEpisodesForCurrentUserRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The request build method. + * + * @return A custom {@link SaveEpisodesForCurrentUserRequest}. + */ + @Override + public SaveEpisodesForCurrentUserRequest build() { + setPath("/v1/me/episodes"); + return new SaveEpisodesForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequest.java deleted file mode 100644 index 018ddba75..000000000 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequest.java +++ /dev/null @@ -1,115 +0,0 @@ -package se.michaelthelin.spotify.requests.data.follow.legacy; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.ParseException; -import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.AbstractDataRequest; - -import java.io.IOException; - -/** - * Add the current user as a follower of a playlist. - */ -@JsonDeserialize(builder = FollowPlaylistRequest.Builder.class) -public class FollowPlaylistRequest extends AbstractDataRequest { - - /** - * The private {@link FollowPlaylistRequest} constructor. - * - * @param builder A {@link FollowPlaylistRequest.Builder}. - */ - private FollowPlaylistRequest(final Builder builder) { - super(builder); - } - - /** - * Follow a playlist. - * - * @return A string. Note: This endpoint doesn't return something in its response body. - * @throws IOException In case of networking issues. - * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. - */ - public String execute() throws - IOException, - SpotifyWebApiException, - ParseException { - return putJson(); - } - - /** - * Builder class for building a {@link FollowPlaylistRequest}. - */ - public static final class Builder extends AbstractDataRequest.Builder { - - /** - * Create a new {@link FollowPlaylistRequest} instance. - *

- * Following a playlist publicly requires authorization of the {@code playlist-modify-public} scope; following it - * privately requires the {@code playlist-modify-private} scope. - * - * @param accessToken Required. A valid access token from the Spotify Accounts service. - * @see Spotify: Using Scopes - */ - public Builder(final String accessToken) { - super(accessToken); - } - - /** - * The playlist owner ID setter. - * - * @param owner_id The Spotify user ID of the person who owns the playlist. - * @return A {@link FollowPlaylistRequest.Builder}. - * @see Spotify: URIs & IDs - */ - public Builder owner_id(final String owner_id) { - assert (owner_id != null); - assert (!owner_id.isEmpty()); - return setPathParameter("owner_id", owner_id); - } - - /** - * The playlist ID setter. - * - * @param playlist_id The Spotify ID of the playlist. Any playlist can be followed, regardless of its public/private - * status, as long as you know its playlist ID. - * @return A {@link FollowPlaylistRequest.Builder}. - * @see Spotify: URIs & IDs - */ - public Builder playlist_id(final String playlist_id) { - assert (playlist_id != null); - assert (!playlist_id.isEmpty()); - return setPathParameter("playlist_id", playlist_id); - } - - /** - * The public following state setter. - * - * @param public_ Optional, default {@code true}. If {@code true} the playlist will be included in user's public - * playlists, if {@code false} it will remain private. To be able to follow playlists privately, the - * user must have granted the {@code playlist-modify-private} scope. - * @return A {@link FollowPlaylistRequest.Builder}. - */ - public Builder public_(final Boolean public_) { - assert (public_ != null); - return setBodyParameter("public", public_); - } - - /** - * The request build method. - * - * @return A custom {@link FollowPlaylistRequest}. - */ - @Override - public FollowPlaylistRequest build() { - setContentType(ContentType.APPLICATION_JSON); - setPath("/v1/users/{owner_id}/playlists/{playlist_id}/followers"); - return new FollowPlaylistRequest(this); - } - - @Override - protected Builder self() { - return this; - } - } -} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/UnfollowPlaylistRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/UnfollowPlaylistRequest.java deleted file mode 100644 index cf29b96b9..000000000 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/legacy/UnfollowPlaylistRequest.java +++ /dev/null @@ -1,99 +0,0 @@ -package se.michaelthelin.spotify.requests.data.follow.legacy; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import org.apache.hc.core5.http.ParseException; -import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.AbstractDataRequest; - -import java.io.IOException; - -/** - * Remove the specified user as a follower of a playlist. - */ -@JsonDeserialize(builder = UnfollowPlaylistRequest.Builder.class) -public class UnfollowPlaylistRequest extends AbstractDataRequest { - - /** - * The private {@link UnfollowPlaylistRequest} constructor. - * - * @param builder A {@link UnfollowPlaylistRequest.Builder}. - */ - private UnfollowPlaylistRequest(final Builder builder) { - super(builder); - } - - /** - * Unfollow a playlist. - * - * @return A string. Note: This endpoint doesn't return something in its response body. - * @throws IOException In case of networking issues. - * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. - */ - public String execute() throws - IOException, - SpotifyWebApiException, - ParseException { - return deleteJson(); - } - - /** - * Builder class for building an {@link UnfollowPlaylistRequest}. - */ - public static final class Builder extends AbstractDataRequest.Builder { - - /** - * Create a new {@link UnfollowPlaylistRequest.Builder} instance. - *

- * Unfollowing a publicly followed playlist for a user requires authorization of the {@code playlist-modify-public} - * scope; unfollowing a privately followed playlist requires the {@code playlist-modify-private} scope. - * - * @param accessToken Required. A valid access token from the Spotify Accounts service. - * @see Spotify: Using Scopes - */ - public Builder(final String accessToken) { - super(accessToken); - } - - /** - * The playlist owner ID setter. - * - * @param owner_id The Spotify user ID of the person who owns the playlist. - * @return An {@link UnfollowPlaylistRequest.Builder}. - * @see Spotify: URIs & IDs - */ - public Builder owner_id(final String owner_id) { - assert (owner_id != null); - assert (!owner_id.isEmpty()); - return setPathParameter("owner_id", owner_id); - } - - /** - * The playlist ID setter. - * - * @param playlist_id The Spotify ID of the playlist that is to be no longer followed. - * @return An {@link UnfollowPlaylistRequest.Builder}. - * @see Spotify: URIs & IDs - */ - public Builder playlist_id(final String playlist_id) { - assert (playlist_id != null); - assert (!playlist_id.isEmpty()); - return setPathParameter("playlist_id", playlist_id); - } - - /** - * The request build method. - * - * @return A custom {@link UnfollowPlaylistRequest}. - */ - @Override - public UnfollowPlaylistRequest build() { - setPath("/v1/users/{owner_id}/playlists/{playlist_id}/followers"); - return new UnfollowPlaylistRequest(this); - } - - @Override - protected Builder self() { - return this; - } - } -} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/genres/GetRecommendationGenresRequest.java similarity index 67% rename from src/main/java/se/michaelthelin/spotify/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/genres/GetRecommendationGenresRequest.java index b6dcc3e94..ee2a4a422 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/genres/GetRecommendationGenresRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse.miscellaneous; +package se.michaelthelin.spotify.requests.data.genres; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.Gson; @@ -13,16 +13,19 @@ /** * Retrieve a list of available genres seed parameter values for recommendations. + * + * @deprecated This endpoint has been deprecated by Spotify. */ -@JsonDeserialize(builder = GetAvailableGenreSeedsRequest.Builder.class) -public class GetAvailableGenreSeedsRequest extends AbstractDataRequest { +@Deprecated +@JsonDeserialize(builder = GetRecommendationGenresRequest.Builder.class) +public class GetRecommendationGenresRequest extends AbstractDataRequest { /** - * The private {@link GetAvailableGenreSeedsRequest} constructor. + * The private {@link GetRecommendationGenresRequest} constructor. * - * @param builder A {@link GetAvailableGenreSeedsRequest.Builder}. + * @param builder A {@link GetRecommendationGenresRequest.Builder}. */ - private GetAvailableGenreSeedsRequest(final Builder builder) { + private GetRecommendationGenresRequest(final Builder builder) { super(builder); } @@ -51,12 +54,12 @@ public String[] execute() throws } /** - * Builder class for building a {@link GetAvailableGenreSeedsRequest.Builder}. + * Builder class for building a {@link GetRecommendationGenresRequest.Builder}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetAvailableGenreSeedsRequest.Builder} instance. + * Create a new {@link GetRecommendationGenresRequest.Builder} instance. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -67,12 +70,12 @@ public Builder(final String accessToken) { /** * The request build method. * - * @return A custom {@link GetAvailableGenreSeedsRequest}. + * @return A custom {@link GetRecommendationGenresRequest}. */ @Override - public GetAvailableGenreSeedsRequest build() { + public GetRecommendationGenresRequest build() { setPath("/v1/recommendations/available-genre-seeds"); - return new GetAvailableGenreSeedsRequest(this); + return new GetRecommendationGenresRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedItemsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedItemsRequest.java new file mode 100644 index 000000000..e237eb495 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedItemsRequest.java @@ -0,0 +1,90 @@ +package se.michaelthelin.spotify.requests.data.library; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.Gson; +import com.google.gson.JsonParser; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Check if one or more items are already saved in the current user's library. + * Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, artists, users, and playlists. + */ +@JsonDeserialize(builder = CheckUsersSavedItemsRequest.Builder.class) +public class CheckUsersSavedItemsRequest extends AbstractDataRequest { + + /** + * The private {@link CheckUsersSavedItemsRequest} constructor. + * + * @param builder A {@link CheckUsersSavedItemsRequest.Builder}. + */ + private CheckUsersSavedItemsRequest(final Builder builder) { + super(builder); + } + + /** + * Check whether items are in the current user's library. + * + * @return A {@link Boolean} array. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Boolean[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Gson().fromJson(JsonParser.parseString(getJson()).getAsJsonArray(), Boolean[].class); + } + + /** + * Builder class for building a {@link CheckUsersSavedItemsRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link CheckUsersSavedItemsRequest.Builder} instance. + *

+ * The {@code user-library-read} or {@code user-follow-read} or {@code playlist-read-private} scope must have + * been authorized by the user. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The Spotify URIs setter. + * + * @param uris Required. A comma-separated list of Spotify URIs to check. Maximum: 40 URIs. + * Supported URI types: track, album, episode, show, audiobook, artist, user, playlist. + * @return A {@link CheckUsersSavedItemsRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder uris(final String uris) { + assert (uris != null); + assert (uris.split(",").length <= 40); + return setQueryParameter("uris", uris); + } + + /** + * The request build method. + * + * @return A custom {@link CheckUsersSavedItemsRequest}. + */ + @Override + public CheckUsersSavedItemsRequest build() { + setPath("/v1/me/library/contains"); + return new CheckUsersSavedItemsRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/RemoveFromLibraryRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/library/RemoveItemsFromLibraryRequest.java similarity index 75% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/RemoveFromLibraryRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/library/RemoveItemsFromLibraryRequest.java index 1116a95de..b58a709a4 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/RemoveFromLibraryRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/library/RemoveItemsFromLibraryRequest.java @@ -12,15 +12,15 @@ /** * Remove a list of Spotify URIs from the user's library. */ -@JsonDeserialize(builder = RemoveFromLibraryRequest.Builder.class) -public class RemoveFromLibraryRequest extends AbstractDataRequest { +@JsonDeserialize(builder = RemoveItemsFromLibraryRequest.Builder.class) +public class RemoveItemsFromLibraryRequest extends AbstractDataRequest { /** - * The private {@link RemoveFromLibraryRequest} constructor. + * The private {@link RemoveItemsFromLibraryRequest} constructor. * - * @param builder A {@link RemoveFromLibraryRequest.Builder}. + * @param builder A {@link RemoveItemsFromLibraryRequest.Builder}. */ - private RemoveFromLibraryRequest(final Builder builder) { + private RemoveItemsFromLibraryRequest(final Builder builder) { super(builder); } @@ -40,12 +40,12 @@ public String execute() throws } /** - * Builder class for building a {@link RemoveFromLibraryRequest}. + * Builder class for building a {@link RemoveItemsFromLibraryRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link RemoveFromLibraryRequest.Builder} instance. + * Create a new {@link RemoveItemsFromLibraryRequest.Builder} instance. *

* Modification of the current user's library requires authorization of the * {@code user-library-modify} scope. @@ -61,7 +61,7 @@ public Builder(final String accessToken) { * The URIs setter. * * @param uris Required. A JSON array of Spotify URIs to remove. Maximum: 50 URIs. - * @return A {@link RemoveFromLibraryRequest.Builder}. + * @return A {@link RemoveItemsFromLibraryRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder uris(final JsonArray uris) { @@ -74,13 +74,13 @@ public Builder uris(final JsonArray uris) { /** * The request build method. * - * @return A custom {@link RemoveFromLibraryRequest}. + * @return A custom {@link RemoveItemsFromLibraryRequest}. */ @Override - public RemoveFromLibraryRequest build() { + public RemoveItemsFromLibraryRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/library"); - return new RemoveFromLibraryRequest(this); + return new RemoveItemsFromLibraryRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/SaveToLibraryRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/library/SaveItemsToLibraryRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/SaveToLibraryRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/library/SaveItemsToLibraryRequest.java index 264a4f722..55ffce0cf 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/SaveToLibraryRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/library/SaveItemsToLibraryRequest.java @@ -12,15 +12,15 @@ /** * Save a list of Spotify URIs to the user's library. */ -@JsonDeserialize(builder = SaveToLibraryRequest.Builder.class) -public class SaveToLibraryRequest extends AbstractDataRequest { +@JsonDeserialize(builder = SaveItemsToLibraryRequest.Builder.class) +public class SaveItemsToLibraryRequest extends AbstractDataRequest { /** - * The private {@link SaveToLibraryRequest} constructor. + * The private {@link SaveItemsToLibraryRequest} constructor. * - * @param builder A {@link SaveToLibraryRequest.Builder}. + * @param builder A {@link SaveItemsToLibraryRequest.Builder}. */ - private SaveToLibraryRequest(final Builder builder) { + private SaveItemsToLibraryRequest(final Builder builder) { super(builder); } @@ -40,12 +40,12 @@ public String execute() throws } /** - * Builder class for building a {@link SaveToLibraryRequest}. + * Builder class for building a {@link SaveItemsToLibraryRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link SaveToLibraryRequest.Builder} instance. + * Create a new {@link SaveItemsToLibraryRequest.Builder} instance. *

* Modification of the current user's library requires authorization of the * {@code user-library-modify} scope. @@ -61,7 +61,7 @@ public Builder(final String accessToken) { * The URIs setter. * * @param uris Required. A JSON array of Spotify URIs to save. Maximum: 50 URIs. - * @return A {@link SaveToLibraryRequest.Builder}. + * @return A {@link SaveItemsToLibraryRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder uris(final JsonArray uris) { @@ -74,13 +74,13 @@ public Builder uris(final JsonArray uris) { /** * The request build method. * - * @return A custom {@link SaveToLibraryRequest}. + * @return A custom {@link SaveItemsToLibraryRequest}. */ @Override - public SaveToLibraryRequest build() { + public SaveItemsToLibraryRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/library"); - return new SaveToLibraryRequest(this); + return new SaveItemsToLibraryRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequest.java new file mode 100644 index 000000000..4e6d4519e --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequest.java @@ -0,0 +1,76 @@ +package se.michaelthelin.spotify.requests.data.markets; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get the list of markets where Spotify is available. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetAvailableMarketsRequest.Builder.class) +public class GetAvailableMarketsRequest extends AbstractDataRequest { + + /** + * The private {@link GetAvailableMarketsRequest} constructor. + * + * @param builder A {@link GetAvailableMarketsRequest.Builder}. + */ + private GetAvailableMarketsRequest(final Builder builder) { + super(builder); + } + + /** + * Get the list of available markets. + * + * @return An array of ISO 3166-1 alpha-2 country codes. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public String[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + JsonObject jsonObject = JsonParser.parseString(getJson()).getAsJsonObject(); + return new Gson().fromJson(jsonObject.getAsJsonArray("markets"), String[].class); + } + + /** + * Builder class for building a {@link GetAvailableMarketsRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetAvailableMarketsRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The request build method. + * + * @return A custom {@link GetAvailableMarketsRequest}. + */ + @Override + public GetAvailableMarketsRequest build() { + setPath("/v1/markets"); + return new GetAvailableMarketsRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/AddItemToUsersPlaybackQueueRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/AddItemToPlaybackQueueRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/AddItemToUsersPlaybackQueueRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/AddItemToPlaybackQueueRequest.java index 94515a4d9..ebc652b66 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/AddItemToUsersPlaybackQueueRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/AddItemToPlaybackQueueRequest.java @@ -11,15 +11,15 @@ /** * Add a track or an episode to the end of the user's current playback queue. */ -@JsonDeserialize(builder = AddItemToUsersPlaybackQueueRequest.Builder.class) -public class AddItemToUsersPlaybackQueueRequest extends AbstractDataRequest { +@JsonDeserialize(builder = AddItemToPlaybackQueueRequest.Builder.class) +public class AddItemToPlaybackQueueRequest extends AbstractDataRequest { /** - * The private {@link AddItemToUsersPlaybackQueueRequest} constructor. + * The private {@link AddItemToPlaybackQueueRequest} constructor. * - * @param builder A {@link AddItemToUsersPlaybackQueueRequest.Builder}. + * @param builder A {@link AddItemToPlaybackQueueRequest.Builder}. */ - private AddItemToUsersPlaybackQueueRequest(final Builder builder) { + private AddItemToPlaybackQueueRequest(final Builder builder) { super(builder); } @@ -39,12 +39,12 @@ public String execute() throws } /** - * Builder class for building a {@link AddItemToUsersPlaybackQueueRequest}. + * Builder class for building a {@link AddItemToPlaybackQueueRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link AddItemToUsersPlaybackQueueRequest.Builder}. + * Create a new {@link AddItemToPlaybackQueueRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -60,7 +60,7 @@ public Builder(final String accessToken) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link AddItemToUsersPlaybackQueueRequest.Builder}. + * @return A {@link AddItemToPlaybackQueueRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -74,7 +74,7 @@ public Builder device_id(final String device_id) { * * @param uri Required. The uri of the item to add to the queue. * Must be a track or an episode uri. - * @return A {@link AddItemToUsersPlaybackQueueRequest.Builder}. + * @return A {@link AddItemToPlaybackQueueRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder uri(final String uri) { @@ -87,13 +87,13 @@ public Builder uri(final String uri) { /** * The request build method. * - * @return A custom {@link AddItemToUsersPlaybackQueueRequest}. + * @return A custom {@link AddItemToPlaybackQueueRequest}. */ @Override - public AddItemToUsersPlaybackQueueRequest build() { + public AddItemToPlaybackQueueRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/queue"); - return new AddItemToUsersPlaybackQueueRequest(this); + return new AddItemToPlaybackQueueRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersAvailableDevicesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetAvailableDevicesRequest.java similarity index 71% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersAvailableDevicesRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/GetAvailableDevicesRequest.java index c1867255f..86801e59a 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersAvailableDevicesRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetAvailableDevicesRequest.java @@ -11,15 +11,15 @@ /** * Get information about a user’s available devices. */ -@JsonDeserialize(builder = GetUsersAvailableDevicesRequest.Builder.class) -public class GetUsersAvailableDevicesRequest extends AbstractDataRequest { +@JsonDeserialize(builder = GetAvailableDevicesRequest.Builder.class) +public class GetAvailableDevicesRequest extends AbstractDataRequest { /** - * The private {@link GetUsersAvailableDevicesRequest} constructor. + * The private {@link GetAvailableDevicesRequest} constructor. * - * @param builder A {@link GetUsersAvailableDevicesRequest.Builder}. + * @param builder A {@link GetAvailableDevicesRequest.Builder}. */ - private GetUsersAvailableDevicesRequest(final Builder builder) { + private GetAvailableDevicesRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public Device[] execute() throws } /** - * Builder class for building a {@link GetUsersAvailableDevicesRequest}. + * Builder class for building a {@link GetAvailableDevicesRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetUsersAvailableDevicesRequest.Builder}. + * Create a new {@link GetAvailableDevicesRequest.Builder}. *

* Your access token must have the {@code user-read-playback-state} scope authorized in order to read information. * @@ -57,12 +57,12 @@ public Builder(final String accessToken) { /** * The request build method. * - * @return A custom {@link GetUsersAvailableDevicesRequest}. + * @return A custom {@link GetAvailableDevicesRequest}. */ @Override - public GetUsersAvailableDevicesRequest build() { + public GetAvailableDevicesRequest build() { setPath("/v1/me/player/devices"); - return new GetUsersAvailableDevicesRequest(this); + return new GetAvailableDevicesRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersCurrentlyPlayingTrackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetCurrentlyPlayingTrackRequest.java similarity index 75% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersCurrentlyPlayingTrackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/GetCurrentlyPlayingTrackRequest.java index ef0b5a774..e42c42a03 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersCurrentlyPlayingTrackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetCurrentlyPlayingTrackRequest.java @@ -12,15 +12,15 @@ /** * Get the object currently being played on the user’s Spotify account. */ -@JsonDeserialize(builder = GetUsersCurrentlyPlayingTrackRequest.Builder.class) -public class GetUsersCurrentlyPlayingTrackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = GetCurrentlyPlayingTrackRequest.Builder.class) +public class GetCurrentlyPlayingTrackRequest extends AbstractDataRequest { /** - * The private {@link GetUsersCurrentlyPlayingTrackRequest} constructor. + * The private {@link GetCurrentlyPlayingTrackRequest} constructor. * - * @param builder A {@link GetUsersCurrentlyPlayingTrackRequest.Builder}. + * @param builder A {@link GetCurrentlyPlayingTrackRequest.Builder}. */ - private GetUsersCurrentlyPlayingTrackRequest(final Builder builder) { + private GetCurrentlyPlayingTrackRequest(final Builder builder) { super(builder); } @@ -39,12 +39,12 @@ public CurrentlyPlaying execute() throws } /** - * Builder class for building a {@link GetUsersCurrentlyPlayingTrackRequest}. + * Builder class for building a {@link GetCurrentlyPlayingTrackRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetUsersCurrentlyPlayingTrackRequest.Builder}. + * Create a new {@link GetCurrentlyPlayingTrackRequest.Builder}. *

* Your access token must have the {@code user-read-currently-playing} scope and/or the * {@code user-read-playback-state} authorized in order to read information. @@ -61,7 +61,7 @@ public Builder(final String accessToken) { * * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you * want to apply Track Relinking. - * @return A {@link GetUsersCurrentlyPlayingTrackRequest.Builder}. + * @return A {@link GetCurrentlyPlayingTrackRequest.Builder}. * @see Spotify: Track Relinking Guide * @see Wikipedia: ISO 3166-1 alpha-2 country codes */ @@ -76,9 +76,9 @@ public Builder market(final CountryCode market) { * @param additionalTypes Optional. A comma-separated list of item types that your client supports * besides the default track type. Valid types are: {@code track} and {@code episode}. * An unsupported type in the response is expected to be represented as {@code null} value in the {@code item} field. - * @return A {@link GetUsersCurrentlyPlayingTrackRequest.Builder}. + * @return A {@link GetCurrentlyPlayingTrackRequest.Builder}. */ - public GetUsersCurrentlyPlayingTrackRequest.Builder additionalTypes(final String additionalTypes) { + public GetCurrentlyPlayingTrackRequest.Builder additionalTypes(final String additionalTypes) { assert (additionalTypes != null); assert (additionalTypes.matches("((^|,)(episode|track))+$")); return setQueryParameter("additional_types", additionalTypes); @@ -87,12 +87,12 @@ public GetUsersCurrentlyPlayingTrackRequest.Builder additionalTypes(final String /** * The request build method. * - * @return A custom {@link GetUsersCurrentlyPlayingTrackRequest}. + * @return A custom {@link GetCurrentlyPlayingTrackRequest}. */ @Override - public GetUsersCurrentlyPlayingTrackRequest build() { + public GetCurrentlyPlayingTrackRequest build() { setPath("/v1/me/player/currently-playing"); - return new GetUsersCurrentlyPlayingTrackRequest(this); + return new GetCurrentlyPlayingTrackRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetInformationAboutUsersCurrentPlaybackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetPlaybackStateRequest.java similarity index 75% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/GetInformationAboutUsersCurrentPlaybackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/GetPlaybackStateRequest.java index 3882c9f45..fffd6a6db 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetInformationAboutUsersCurrentPlaybackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetPlaybackStateRequest.java @@ -12,15 +12,15 @@ /** * Get information about the user’s current playback state, including track, track progress, and active device. */ -@JsonDeserialize(builder = GetInformationAboutUsersCurrentPlaybackRequest.Builder.class) -public class GetInformationAboutUsersCurrentPlaybackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = GetPlaybackStateRequest.Builder.class) +public class GetPlaybackStateRequest extends AbstractDataRequest { /** - * The private {@link GetInformationAboutUsersCurrentPlaybackRequest} constructor. + * The private {@link GetPlaybackStateRequest} constructor. * - * @param builder A {@link GetInformationAboutUsersCurrentPlaybackRequest.Builder}. + * @param builder A {@link GetPlaybackStateRequest.Builder}. */ - private GetInformationAboutUsersCurrentPlaybackRequest(final Builder builder) { + private GetPlaybackStateRequest(final Builder builder) { super(builder); } @@ -39,12 +39,12 @@ public CurrentlyPlayingContext execute() throws } /** - * Builder class for building a {@link GetInformationAboutUsersCurrentPlaybackRequest}. + * Builder class for building a {@link GetPlaybackStateRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetInformationAboutUsersCurrentPlaybackRequest.Builder}. + * Create a new {@link GetPlaybackStateRequest.Builder}. *

* Your access token must have the {@code user-read-playback-state} scope authorized in order to read information. * @@ -60,7 +60,7 @@ public Builder(final String accessToken) { * * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you * want to apply Track Relinking. - * @return A {@link GetInformationAboutUsersCurrentPlaybackRequest.Builder}. + * @return A {@link GetPlaybackStateRequest.Builder}. * @see Spotify: Track Relinking Guide * @see Wikipedia: ISO 3166-1 alpha-2 country codes */ @@ -75,7 +75,7 @@ public Builder market(final CountryCode market) { * @param additionalTypes Optional. A comma-separated list of item types that your client supports * besides the default track type. Valid types are: {@code track} and {@code episode}. * An unsupported type in the response is expected to be represented as {@code null} value in the {@code item} field. - * @return A {@link GetInformationAboutUsersCurrentPlaybackRequest.Builder}. + * @return A {@link GetPlaybackStateRequest.Builder}. */ public Builder additionalTypes(final String additionalTypes) { assert (additionalTypes != null); @@ -86,12 +86,12 @@ public Builder additionalTypes(final String additionalTypes) { /** * The request build method. * - * @return A custom {@link GetInformationAboutUsersCurrentPlaybackRequest}. + * @return A custom {@link GetPlaybackStateRequest}. */ @Override - public GetInformationAboutUsersCurrentPlaybackRequest build() { + public GetPlaybackStateRequest build() { setPath("/v1/me/player"); - return new GetInformationAboutUsersCurrentPlaybackRequest(this); + return new GetPlaybackStateRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetRecentlyPlayedTracksRequest.java similarity index 79% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/GetRecentlyPlayedTracksRequest.java index 950f1810b..0d016b794 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetRecentlyPlayedTracksRequest.java @@ -26,15 +26,15 @@ * {@code after} parameter, the endpoint will return the most recently played songs, and the {@code next} * link will page back in time. */ -@JsonDeserialize(builder = GetCurrentUsersRecentlyPlayedTracksRequest.Builder.class) -public class GetCurrentUsersRecentlyPlayedTracksRequest extends AbstractDataRequest> { +@JsonDeserialize(builder = GetRecentlyPlayedTracksRequest.Builder.class) +public class GetRecentlyPlayedTracksRequest extends AbstractDataRequest> { /** - * The private {@link GetCurrentUsersRecentlyPlayedTracksRequest} constructor. + * The private {@link GetRecentlyPlayedTracksRequest} constructor. * - * @param builder A {@link GetCurrentUsersRecentlyPlayedTracksRequest.Builder}. + * @param builder A {@link GetRecentlyPlayedTracksRequest.Builder}. */ - private GetCurrentUsersRecentlyPlayedTracksRequest(final Builder builder) { + private GetRecentlyPlayedTracksRequest(final Builder builder) { super(builder); } @@ -53,12 +53,12 @@ public PagingCursorbased execute() throws } /** - * Builder class for building a {@link GetCurrentUsersRecentlyPlayedTracksRequest}. + * Builder class for building a {@link GetRecentlyPlayedTracksRequest}. */ public static final class Builder extends AbstractDataPagingCursorbasedRequest.Builder { /** - * Create a new {@link GetCurrentUsersRecentlyPlayedTracksRequest.Builder}. + * Create a new {@link GetRecentlyPlayedTracksRequest.Builder}. *

* Your access token must have the {@code user-read-recently-played} scope authorized in order to read * the user's recently played track. @@ -74,7 +74,7 @@ public Builder(final String accessToken) { * The limit setter. * * @param limit Optional. The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetCurrentUsersRecentlyPlayedTracksRequest.Builder}. + * @return A {@link GetRecentlyPlayedTracksRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -88,7 +88,7 @@ public Builder limit(final Integer limit) { * * @param after Optional. A {@link Date} object. Returns all items after (but not including) this cursor position. * If this is specified, {@link #before(Date)} must not be specified. - * @return A {@link GetCurrentUsersRecentlyPlayedTracksRequest.Builder}. + * @return A {@link GetRecentlyPlayedTracksRequest.Builder}. */ @Override public Builder after(final Date after) { @@ -101,7 +101,7 @@ public Builder after(final Date after) { * * @param before Optional. A {@link Date} object. Returns all items before (but not including) this cursor position. * If this is specified, {@link #after(Date)} must not be specified. - * @return A {@link GetCurrentUsersRecentlyPlayedTracksRequest.Builder}. + * @return A {@link GetRecentlyPlayedTracksRequest.Builder}. */ public Builder before(final Date before) { assert (before != null); @@ -111,12 +111,12 @@ public Builder before(final Date before) { /** * The request build method. * - * @return A custom {@link GetCurrentUsersRecentlyPlayedTracksRequest}. + * @return A custom {@link GetRecentlyPlayedTracksRequest}. */ @Override - public GetCurrentUsersRecentlyPlayedTracksRequest build() { + public GetRecentlyPlayedTracksRequest build() { setPath("/v1/me/player/recently-played"); - return new GetCurrentUsersRecentlyPlayedTracksRequest(this); + return new GetRecentlyPlayedTracksRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetTheUsersQueueRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersQueueRequest.java similarity index 75% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/GetTheUsersQueueRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersQueueRequest.java index 5a63b6f23..94e70d456 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/GetTheUsersQueueRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/GetUsersQueueRequest.java @@ -18,15 +18,15 @@ * The endpoint does not support paging since the queue is not expected to be large. * Therefore, the request will return a {@link PlaybackQueue} object including a List of {@link se.michaelthelin.spotify.model_objects.IPlaylistItem}. */ -@JsonDeserialize(builder = GetTheUsersQueueRequest.Builder.class) -public class GetTheUsersQueueRequest extends AbstractDataRequest { +@JsonDeserialize(builder = GetUsersQueueRequest.Builder.class) +public class GetUsersQueueRequest extends AbstractDataRequest { /** - * The private {@link GetTheUsersQueueRequest} constructor. + * The private {@link GetUsersQueueRequest} constructor. * - * @param builder A {@link GetTheUsersQueueRequest.Builder}. + * @param builder A {@link GetUsersQueueRequest.Builder}. */ - private GetTheUsersQueueRequest(final Builder builder) { + private GetUsersQueueRequest(final Builder builder) { super(builder); } @@ -44,12 +44,12 @@ public PlaybackQueue execute() throws IOException, SpotifyWebApiException, Parse } /** - * Builder class for building a {@link GetTheUsersQueueRequest}. + * Builder class for building a {@link GetUsersQueueRequest}. */ - public static final class Builder extends AbstractDataRequest.Builder { + public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetTheUsersQueueRequest.Builder}. + * Create a new {@link GetUsersQueueRequest.Builder}. *

* Your access token must have the {@code user-read-currently-playing} scope and/or the * {@code user-read-playback-state} authorized in order to read information. @@ -64,16 +64,16 @@ public Builder(final String accessToken) { /** * The request build method. * - * @return A custom {@link GetTheUsersQueueRequest}. + * @return A custom {@link GetUsersQueueRequest}. */ @Override - public GetTheUsersQueueRequest build() { + public GetUsersQueueRequest build() { setPath("/v1/me/player/queue"); - return new GetTheUsersQueueRequest(this); + return new GetUsersQueueRequest(this); } @Override - protected GetTheUsersQueueRequest.Builder self() { + protected GetUsersQueueRequest.Builder self() { return this; } } diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/PauseUsersPlaybackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/PausePlaybackRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/PauseUsersPlaybackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/PausePlaybackRequest.java index ff9aa9d56..18c05d200 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/PauseUsersPlaybackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/PausePlaybackRequest.java @@ -11,15 +11,15 @@ /** * Pause playback on the user’s account. */ -@JsonDeserialize(builder = PauseUsersPlaybackRequest.Builder.class) -public class PauseUsersPlaybackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = PausePlaybackRequest.Builder.class) +public class PausePlaybackRequest extends AbstractDataRequest { /** - * The private {@link PauseUsersPlaybackRequest} constructor. + * The private {@link PausePlaybackRequest} constructor. * - * @param builder A {@link PauseUsersPlaybackRequest.Builder}. + * @param builder A {@link PausePlaybackRequest.Builder}. */ - private PauseUsersPlaybackRequest(final Builder builder) { + private PausePlaybackRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public String execute() throws } /** - * Builder class for building a {@link PauseUsersPlaybackRequest}. + * Builder class for building a {@link PausePlaybackRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link PauseUsersPlaybackRequest.Builder}. + * Create a new {@link PausePlaybackRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -59,7 +59,7 @@ public Builder(final String accessToken) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link PauseUsersPlaybackRequest.Builder}. + * @return A {@link PausePlaybackRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -71,13 +71,13 @@ public Builder device_id(final String device_id) { /** * The request build method. * - * @return A custom {@link PauseUsersPlaybackRequest}. + * @return A custom {@link PausePlaybackRequest}. */ @Override - public PauseUsersPlaybackRequest build() { + public PausePlaybackRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/pause"); - return new PauseUsersPlaybackRequest(this); + return new PausePlaybackRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionInCurrentlyPlayingTrackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionRequest.java similarity index 74% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionInCurrentlyPlayingTrackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionRequest.java index b93f32e60..36776ea86 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionInCurrentlyPlayingTrackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionRequest.java @@ -11,15 +11,15 @@ /** * Seeks to the given position in the user’s currently playing track. */ -@JsonDeserialize(builder = SeekToPositionInCurrentlyPlayingTrackRequest.Builder.class) -public class SeekToPositionInCurrentlyPlayingTrackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = SeekToPositionRequest.Builder.class) +public class SeekToPositionRequest extends AbstractDataRequest { /** - * The private {@link SeekToPositionInCurrentlyPlayingTrackRequest} constructor. + * The private {@link SeekToPositionRequest} constructor. * - * @param builder A {@link SeekToPositionInCurrentlyPlayingTrackRequest.Builder}. + * @param builder A {@link SeekToPositionRequest.Builder}. */ - private SeekToPositionInCurrentlyPlayingTrackRequest(final Builder builder) { + private SeekToPositionRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public String execute() throws } /** - * Builder class for building a {@link SeekToPositionInCurrentlyPlayingTrackRequest}. + * Builder class for building a {@link SeekToPositionRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link SeekToPositionInCurrentlyPlayingTrackRequest.Builder}. + * Create a new {@link SeekToPositionRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -60,7 +60,7 @@ public Builder(final String accessToken) { * @param position_ms Required. The position in milliseconds to seek to. Must be a positive number. Passing in a * position that is greater than the length of the track will cause the player to start * playing the next song. - * @return A {@link SeekToPositionInCurrentlyPlayingTrackRequest.Builder}. + * @return A {@link SeekToPositionRequest.Builder}. */ public Builder position_ms(final Integer position_ms) { assert (position_ms != null); @@ -73,7 +73,7 @@ public Builder position_ms(final Integer position_ms) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link SeekToPositionInCurrentlyPlayingTrackRequest.Builder}. + * @return A {@link SeekToPositionRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -85,13 +85,13 @@ public Builder device_id(final String device_id) { /** * The request build method. * - * @return A custom {@link SeekToPositionInCurrentlyPlayingTrackRequest}. + * @return A custom {@link SeekToPositionRequest}. */ @Override - public SeekToPositionInCurrentlyPlayingTrackRequest build() { + public SeekToPositionRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/seek"); - return new SeekToPositionInCurrentlyPlayingTrackRequest(this); + return new SeekToPositionRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/SetVolumeForUsersPlaybackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/SetPlaybackVolumeRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/SetVolumeForUsersPlaybackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/SetPlaybackVolumeRequest.java index 8b56a2377..f4d1d69bc 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/SetVolumeForUsersPlaybackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/SetPlaybackVolumeRequest.java @@ -11,15 +11,15 @@ /** * Set the volume for the user’s current playback device. */ -@JsonDeserialize(builder = SetVolumeForUsersPlaybackRequest.Builder.class) -public class SetVolumeForUsersPlaybackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = SetPlaybackVolumeRequest.Builder.class) +public class SetPlaybackVolumeRequest extends AbstractDataRequest { /** - * The private {@link SetVolumeForUsersPlaybackRequest} constructor. + * The private {@link SetPlaybackVolumeRequest} constructor. * - * @param builder A {@link SetVolumeForUsersPlaybackRequest.Builder}. + * @param builder A {@link SetPlaybackVolumeRequest.Builder}. */ - private SetVolumeForUsersPlaybackRequest(final Builder builder) { + private SetPlaybackVolumeRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public String execute() throws } /** - * Builder class for building a {@link SetVolumeForUsersPlaybackRequest}. + * Builder class for building a {@link SetPlaybackVolumeRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link SetVolumeForUsersPlaybackRequest.Builder}. + * Create a new {@link SetPlaybackVolumeRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -58,7 +58,7 @@ public Builder(final String accessToken) { * The volume percentage setter. * * @param volume_percent Required. The volume to set. Must be a value from 0 to 100 inclusive. - * @return A {@link SetVolumeForUsersPlaybackRequest.Builder}. + * @return A {@link SetPlaybackVolumeRequest.Builder}. */ public Builder volume_percent(final Integer volume_percent) { assert (volume_percent != null); @@ -71,7 +71,7 @@ public Builder volume_percent(final Integer volume_percent) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link SetVolumeForUsersPlaybackRequest.Builder}. + * @return A {@link SetPlaybackVolumeRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -83,13 +83,13 @@ public Builder device_id(final String device_id) { /** * The build method. * - * @return A custom {@link SetVolumeForUsersPlaybackRequest}. + * @return A custom {@link SetPlaybackVolumeRequest}. */ @Override - public SetVolumeForUsersPlaybackRequest build() { + public SetPlaybackVolumeRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/volume"); - return new SetVolumeForUsersPlaybackRequest(this); + return new SetPlaybackVolumeRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeOnUsersPlaybackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeOnUsersPlaybackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeRequest.java index 08d122c1f..351102c92 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeOnUsersPlaybackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeRequest.java @@ -11,15 +11,15 @@ /** * Set the repeat mode for the user’s playback. */ -@JsonDeserialize(builder = SetRepeatModeOnUsersPlaybackRequest.Builder.class) -public class SetRepeatModeOnUsersPlaybackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = SetRepeatModeRequest.Builder.class) +public class SetRepeatModeRequest extends AbstractDataRequest { /** - * The private {@link SetRepeatModeOnUsersPlaybackRequest} constructor. + * The private {@link SetRepeatModeRequest} constructor. * - * @param builder A {@link SetRepeatModeOnUsersPlaybackRequest.Builder}. + * @param builder A {@link SetRepeatModeRequest.Builder}. */ - private SetRepeatModeOnUsersPlaybackRequest(final Builder builder) { + private SetRepeatModeRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public String execute() throws } /** - * Builder class for building a {@link SetRepeatModeOnUsersPlaybackRequest}. + * Builder class for building a {@link SetRepeatModeRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link SetRepeatModeOnUsersPlaybackRequest.Builder}. + * Create a new {@link SetRepeatModeRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -59,7 +59,7 @@ public Builder(final String accessToken) { * * @param state Required. {@code track}, {@code context} or {@code off}. {@code track} will repeat the current * track. {@code context} will repeat the current context. {@code off} will turn repeat off. - * @return A {@link SetRepeatModeOnUsersPlaybackRequest.Builder}. + * @return A {@link SetRepeatModeRequest.Builder}. */ public Builder state(final String state) { assert (state != null); @@ -72,7 +72,7 @@ public Builder state(final String state) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link SetRepeatModeOnUsersPlaybackRequest.Builder}. + * @return A {@link SetRepeatModeRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -84,13 +84,13 @@ public Builder device_id(final String device_id) { /** * The request build method. * - * @return A custom {@link SetRepeatModeOnUsersPlaybackRequest}. + * @return A custom {@link SetRepeatModeRequest}. */ @Override - public SetRepeatModeOnUsersPlaybackRequest build() { + public SetRepeatModeRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/repeat"); - return new SetRepeatModeOnUsersPlaybackRequest(this); + return new SetRepeatModeRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToNextTrackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipToNextRequest.java similarity index 74% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToNextTrackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/SkipToNextRequest.java index 43718e649..03f9d72a8 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToNextTrackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipToNextRequest.java @@ -11,15 +11,15 @@ /** * Skips to next track in the user’s queue. */ -@JsonDeserialize(builder = SkipUsersPlaybackToNextTrackRequest.Builder.class) -public class SkipUsersPlaybackToNextTrackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = SkipToNextRequest.Builder.class) +public class SkipToNextRequest extends AbstractDataRequest { /** - * The private {@link SkipUsersPlaybackToNextTrackRequest} constructor. + * The private {@link SkipToNextRequest} constructor. * - * @param builder A {@link SkipUsersPlaybackToNextTrackRequest.Builder}. + * @param builder A {@link SkipToNextRequest.Builder}. */ - private SkipUsersPlaybackToNextTrackRequest(final Builder builder) { + private SkipToNextRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public String execute() throws } /** - * Builder class for building a {@link SkipUsersPlaybackToNextTrackRequest}. + * Builder class for building a {@link SkipToNextRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link SkipUsersPlaybackToNextTrackRequest.Builder}. + * Create a new {@link SkipToNextRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -59,7 +59,7 @@ public Builder(final String accessToken) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link SkipUsersPlaybackToNextTrackRequest.Builder}. + * @return A {@link SkipToNextRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -71,13 +71,13 @@ public Builder device_id(final String device_id) { /** * The request build method. * - * @return A custom {@link SkipUsersPlaybackToNextTrackRequest}. + * @return A custom {@link SkipToNextRequest}. */ @Override - public SkipUsersPlaybackToNextTrackRequest build() { + public SkipToNextRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/next"); - return new SkipUsersPlaybackToNextTrackRequest(this); + return new SkipToNextRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToPreviousTrackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipToPreviousRequest.java similarity index 73% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToPreviousTrackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/SkipToPreviousRequest.java index 2a8cc944c..e69042e72 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToPreviousTrackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/SkipToPreviousRequest.java @@ -13,17 +13,17 @@ *

* Note: This will ALWAYS skip to the previous track, regardless of the current track’s progress. * Returning to the start of the current track should be performed using a - * {@link SeekToPositionInCurrentlyPlayingTrackRequest}. + * {@link SeekToPositionRequest}. */ -@JsonDeserialize(builder = SkipUsersPlaybackToPreviousTrackRequest.Builder.class) -public class SkipUsersPlaybackToPreviousTrackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = SkipToPreviousRequest.Builder.class) +public class SkipToPreviousRequest extends AbstractDataRequest { /** - * The private {@link SkipUsersPlaybackToPreviousTrackRequest} constructor. + * The private {@link SkipToPreviousRequest} constructor. * - * @param builder A {@link SkipUsersPlaybackToPreviousTrackRequest.Builder}. + * @param builder A {@link SkipToPreviousRequest.Builder}. */ - private SkipUsersPlaybackToPreviousTrackRequest(final Builder builder) { + private SkipToPreviousRequest(final Builder builder) { super(builder); } @@ -42,12 +42,12 @@ public String execute() throws } /** - * Builder class for building a {@link SkipUsersPlaybackToPreviousTrackRequest}. + * Builder class for building a {@link SkipToPreviousRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link SkipUsersPlaybackToPreviousTrackRequest.Builder}. + * Create a new {@link SkipToPreviousRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -63,7 +63,7 @@ public Builder(final String accessToken) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link SkipUsersPlaybackToPreviousTrackRequest.Builder}. + * @return A {@link SkipToPreviousRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -75,13 +75,13 @@ public Builder device_id(final String device_id) { /** * The request build method. * - * @return A custom {@link SkipUsersPlaybackToPreviousTrackRequest}. + * @return A custom {@link SkipToPreviousRequest}. */ @Override - public SkipUsersPlaybackToPreviousTrackRequest build() { + public SkipToPreviousRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/previous"); - return new SkipUsersPlaybackToPreviousTrackRequest(this); + return new SkipToPreviousRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/StartResumePlaybackRequest.java similarity index 83% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/StartResumePlaybackRequest.java index f22b6b85b..4f4dbf41d 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/StartResumePlaybackRequest.java @@ -13,15 +13,15 @@ /** * Start a new context or resume current playback on the user’s active device. */ -@JsonDeserialize(builder = StartResumeUsersPlaybackRequest.Builder.class) -public class StartResumeUsersPlaybackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = StartResumePlaybackRequest.Builder.class) +public class StartResumePlaybackRequest extends AbstractDataRequest { /** - * The private {@link StartResumeUsersPlaybackRequest} constructor. + * The private {@link StartResumePlaybackRequest} constructor. * - * @param builder A {@link StartResumeUsersPlaybackRequest.Builder}. + * @param builder A {@link StartResumePlaybackRequest.Builder}. */ - private StartResumeUsersPlaybackRequest(final Builder builder) { + private StartResumePlaybackRequest(final Builder builder) { super(builder); } @@ -40,12 +40,12 @@ public String execute() throws } /** - * Builder class for building a {@link StartResumeUsersPlaybackRequest}. + * Builder class for building a {@link StartResumePlaybackRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link StartResumeUsersPlaybackRequest.Builder}. + * Create a new {@link StartResumePlaybackRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -61,7 +61,7 @@ public Builder(final String accessToken) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link StartResumeUsersPlaybackRequest.Builder}. + * @return A {@link StartResumePlaybackRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -75,7 +75,7 @@ public Builder device_id(final String device_id) { * * @param context_uri Optional. Spotify URI of the context to play. * Valid contexts are albums, artists and playlists. - * @return A {@link StartResumeUsersPlaybackRequest.Builder}. + * @return A {@link StartResumePlaybackRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder context_uri(final String context_uri) { @@ -88,7 +88,7 @@ public Builder context_uri(final String context_uri) { * The URI setter. * * @param uris Optional. A JSON array of the Spotify track URIs to play. - * @return A {@link StartResumeUsersPlaybackRequest.Builder}. + * @return A {@link StartResumePlaybackRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder uris(final JsonArray uris) { @@ -110,7 +110,7 @@ public Builder uris(final JsonArray uris) { * {@link #uris(JsonArray)} parameter is used.
The {@code position} parameter in the * {@code offset} object is zero based and can’t be negative.
The {@code uri} parameter in the * {@code offset} object is a string representing the URI of the item to start at. - * @return A {@link StartResumeUsersPlaybackRequest.Builder}. + * @return A {@link StartResumePlaybackRequest.Builder}. */ public Builder offset(final JsonObject offset) { assert (offset != null); @@ -124,7 +124,7 @@ public Builder offset(final JsonObject offset) { * @param position_ms Optional. Indicates from what position to start playback. Must be a positive number. Passing * in a position that is greater than the length of the track will cause the player to start * playing the next song. - * @return A {@link StartResumeUsersPlaybackRequest.Builder}. + * @return A {@link StartResumePlaybackRequest.Builder}. */ public Builder position_ms(final Integer position_ms) { assert (position_ms != null); @@ -135,13 +135,13 @@ public Builder position_ms(final Integer position_ms) { /** * The request build method. * - * @return A custom {@link StartResumeUsersPlaybackRequest}. + * @return A custom {@link StartResumePlaybackRequest}. */ @Override - public StartResumeUsersPlaybackRequest build() { + public StartResumePlaybackRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/play"); - return new StartResumeUsersPlaybackRequest(this); + return new StartResumePlaybackRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/ToggleShuffleForUsersPlaybackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/TogglePlaybackShuffleRequest.java similarity index 74% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/ToggleShuffleForUsersPlaybackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/TogglePlaybackShuffleRequest.java index b4cdfbb71..4dd5966b3 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/ToggleShuffleForUsersPlaybackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/TogglePlaybackShuffleRequest.java @@ -11,15 +11,15 @@ /** * Toggle shuffle on or off for user’s playback. */ -@JsonDeserialize(builder = ToggleShuffleForUsersPlaybackRequest.Builder.class) -public class ToggleShuffleForUsersPlaybackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = TogglePlaybackShuffleRequest.Builder.class) +public class TogglePlaybackShuffleRequest extends AbstractDataRequest { /** - * The private {@link ToggleShuffleForUsersPlaybackRequest} constructor. + * The private {@link TogglePlaybackShuffleRequest} constructor. * - * @param builder A {@link ToggleShuffleForUsersPlaybackRequest.Builder}. + * @param builder A {@link TogglePlaybackShuffleRequest.Builder}. */ - private ToggleShuffleForUsersPlaybackRequest(final Builder builder) { + private TogglePlaybackShuffleRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public String execute() throws } /** - * Builder class for building a {@link ToggleShuffleForUsersPlaybackRequest}. + * Builder class for building a {@link TogglePlaybackShuffleRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link ToggleShuffleForUsersPlaybackRequest.Builder}. + * Create a new {@link TogglePlaybackShuffleRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -58,7 +58,7 @@ public Builder(final String accessToken) { * The toggle state setter. * * @param state Required. {@code true}: Shuffle user's playback. {@code false}: Do not shuffle user's playback. - * @return A {@link ToggleShuffleForUsersPlaybackRequest.Builder}. + * @return A {@link TogglePlaybackShuffleRequest.Builder}. */ public Builder state(final Boolean state) { return setQueryParameter("state", state); @@ -69,7 +69,7 @@ public Builder state(final Boolean state) { * * @param device_id Optional. The ID of the device this command is targeting. If not supplied, the * user's currently active device is the target. - * @return A {@link ToggleShuffleForUsersPlaybackRequest.Builder}. + * @return A {@link TogglePlaybackShuffleRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_id(final String device_id) { @@ -81,13 +81,13 @@ public Builder device_id(final String device_id) { /** * The request build method. * - * @return A custom {@link ToggleShuffleForUsersPlaybackRequest}. + * @return A custom {@link TogglePlaybackShuffleRequest}. */ @Override - public ToggleShuffleForUsersPlaybackRequest build() { + public TogglePlaybackShuffleRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player/shuffle"); - return new ToggleShuffleForUsersPlaybackRequest(this); + return new TogglePlaybackShuffleRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/player/TransferUsersPlaybackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/player/TransferPlaybackRequest.java similarity index 78% rename from src/main/java/se/michaelthelin/spotify/requests/data/player/TransferUsersPlaybackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/player/TransferPlaybackRequest.java index 6fa652435..02eeca3de 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/player/TransferUsersPlaybackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/player/TransferPlaybackRequest.java @@ -12,15 +12,15 @@ /** * Transfer playback to a new device and determine if it should start playing. */ -@JsonDeserialize(builder = TransferUsersPlaybackRequest.Builder.class) -public class TransferUsersPlaybackRequest extends AbstractDataRequest { +@JsonDeserialize(builder = TransferPlaybackRequest.Builder.class) +public class TransferPlaybackRequest extends AbstractDataRequest { /** - * The private {@link TransferUsersPlaybackRequest} constructor. + * The private {@link TransferPlaybackRequest} constructor. * - * @param builder A {@link TransferUsersPlaybackRequest.Builder}. + * @param builder A {@link TransferPlaybackRequest.Builder}. */ - private TransferUsersPlaybackRequest(final Builder builder) { + private TransferPlaybackRequest(final Builder builder) { super(builder); } @@ -39,12 +39,12 @@ public String execute() throws } /** - * Builder class for building a {@link TransferUsersPlaybackRequest}. + * Builder class for building a {@link TransferPlaybackRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link TransferUsersPlaybackRequest.Builder}. + * Create a new {@link TransferPlaybackRequest.Builder}. *

* Your access token must have the {@code user-modify-playback-state} scope authorized in order to control playback. * @@ -61,7 +61,7 @@ public Builder(final String accessToken) { * @param device_ids Required. A JSON array containing the ID of the device on which playback should be * started/transferred. Note: Although an array is accepted, only a single * {@code device_id} is currently supported. - * @return A {@link TransferUsersPlaybackRequest.Builder}. + * @return A {@link TransferPlaybackRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder device_ids(final JsonArray device_ids) { @@ -76,7 +76,7 @@ public Builder device_ids(final JsonArray device_ids) { * * @param play Optional. {@code true}: ensure playback happens on new device. * {@code false} or not provided: keep the current playback state. - * @return A {@link TransferUsersPlaybackRequest.Builder}. + * @return A {@link TransferPlaybackRequest.Builder}. */ public Builder play(final Boolean play) { return setBodyParameter("play", play); @@ -85,13 +85,13 @@ public Builder play(final Boolean play) { /** * The request build method. * - * @return A custom {@link TransferUsersPlaybackRequest}. + * @return A custom {@link TransferPlaybackRequest}. */ @Override - public TransferUsersPlaybackRequest build() { + public TransferPlaybackRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/me/player"); - return new TransferUsersPlaybackRequest(this); + return new TransferPlaybackRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UploadCustomPlaylistCoverImageRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddCustomPlaylistCoverImageRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/playlists/UploadCustomPlaylistCoverImageRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddCustomPlaylistCoverImageRequest.java index d998bd98a..4eabd35c2 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UploadCustomPlaylistCoverImageRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddCustomPlaylistCoverImageRequest.java @@ -12,15 +12,15 @@ /** * Replace the image used to represent a specific playlist. */ -@JsonDeserialize(builder = UploadCustomPlaylistCoverImageRequest.Builder.class) -public class UploadCustomPlaylistCoverImageRequest extends AbstractDataRequest { +@JsonDeserialize(builder = AddCustomPlaylistCoverImageRequest.Builder.class) +public class AddCustomPlaylistCoverImageRequest extends AbstractDataRequest { /** - * The private {@link UploadCustomPlaylistCoverImageRequest} constructor. + * The private {@link AddCustomPlaylistCoverImageRequest} constructor. * - * @param builder A {@link UploadCustomPlaylistCoverImageRequest.Builder}. + * @param builder A {@link AddCustomPlaylistCoverImageRequest.Builder}. */ - private UploadCustomPlaylistCoverImageRequest(final Builder builder) { + private AddCustomPlaylistCoverImageRequest(final Builder builder) { super(builder); } @@ -39,12 +39,12 @@ public String execute() throws } /** - * Builder class for building an {@link UploadCustomPlaylistCoverImageRequest}. + * Builder class for building an {@link AddCustomPlaylistCoverImageRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link UploadCustomPlaylistCoverImageRequest.Builder}. + * Create a new {@link AddCustomPlaylistCoverImageRequest.Builder}. *

* This access token must be tied to the user who owns the playlist, and must have the scope * {@code ugc-image-upload} granted. In addition, the token must also contain {@code playlist-modify-public} @@ -61,7 +61,7 @@ public Builder(final String accessToken) { * The playlist ID setter. * * @param playlist_id The Spotify ID for the playlist. - * @return A {@link UploadCustomPlaylistCoverImageRequest.Builder}. + * @return A {@link AddCustomPlaylistCoverImageRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder playlist_id(final String playlist_id) { @@ -74,7 +74,7 @@ public Builder playlist_id(final String playlist_id) { * The image data setter. * * @param image_data Base64 encoded JPEG image data, maximum payload size is 256 KB. - * @return A {@link UploadCustomPlaylistCoverImageRequest.Builder}. + * @return A {@link AddCustomPlaylistCoverImageRequest.Builder}. */ public Builder image_data(final String image_data) { assert (image_data != null); @@ -86,13 +86,13 @@ public Builder image_data(final String image_data) { /** * The request build method. * - * @return A custom {@link UploadCustomPlaylistCoverImageRequest}. + * @return A custom {@link AddCustomPlaylistCoverImageRequest}. */ @Override - public UploadCustomPlaylistCoverImageRequest build() { + public AddCustomPlaylistCoverImageRequest build() { setContentType(ContentType.IMAGE_JPEG); setPath("/v1/playlists/{playlist_id}/images"); - return new UploadCustomPlaylistCoverImageRequest(this); + return new AddCustomPlaylistCoverImageRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistDeprecatedRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistDeprecatedRequest.java new file mode 100644 index 000000000..9bf66c6c9 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistDeprecatedRequest.java @@ -0,0 +1,171 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonArray; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.special.SnapshotResult; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * @deprecated Use the new endpoints instead. + * Add one or more items to a user's playlist. + */ +@Deprecated +@JsonDeserialize(builder = AddItemsToPlaylistDeprecatedRequest.Builder.class) +public class AddItemsToPlaylistDeprecatedRequest extends AbstractDataRequest { + + /** + * @deprecated Use the new endpoints instead. + * The private {@link AddItemsToPlaylistDeprecatedRequest} constructor. + * + * @param builder A {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + */ + private AddItemsToPlaylistDeprecatedRequest(final Builder builder) { + super(builder); + } + + /** + * @deprecated Use the new endpoints instead. + * Add items to playlist. + * + * @return A playlist snapshot ID. The snapshot ID can be used to identify your playlist version in future requests. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + * @see + * Spotify: Version Control and Snapshots + */ + public SnapshotResult execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new SnapshotResult.JsonUtil().createModelObject(postJson()); + } + + /** + * @deprecated Use the new endpoints instead. + * Builder class for building an {@link AddItemsToPlaylistDeprecatedRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * @deprecated Use the new endpoints instead. + * Create a new {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + *

+ * Adding items to the current user's public playlists requires authorization of the {@code playlist-modify-public} + * scope; adding items to the current user's private playlist (including collaborative playlists) requires the + * {@code playlist-modify-private} scope. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * @deprecated Use the new endpoints instead. + * The playlist ID setter. + * + * @param playlist_id The Spotify ID for the playlist. + * @return An {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder playlist_id(final String playlist_id) { + assert (playlist_id != null); + assert (!playlist_id.isEmpty()); + return setPathParameter("playlist_id", playlist_id); + } + + /** + * @deprecated Use the new endpoints instead. + * The item URIs setter. + *

+ * Note: It is likely that passing a large number of item URIs as a query parameter will exceed the maximum + * length of the request URI. When adding a large number of items it is recommended to pass them + * with {@link #uris(JsonArray)}. + * + * @param uris Optional. A comma-separated list of Spotify track or episode URIs to add. Maximum: 100 item URIs. + * @return An {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder uris(final String uris) { + assert (uris != null); + assert (!uris.isEmpty()); + assert (uris.split(",").length <= 100); + return setQueryParameter("uris", uris); + } + + /** + * @deprecated Use the new endpoints instead. + * The position setter. + * + * @param position Optional. The position to insert the items, a zero-based index. If omitted, the + * items will be appended to the playlist. Items are added in the order they are + * listed in the query string or request body. + * @return An {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + */ + public Builder position(final Integer position) { + return position(position, false); + } + + /** + * @deprecated Use the new endpoints instead. + * The item URIs setter. + *

+ * Note: If the URIs already have been set with {@link #uris(String)}, any URIs listed here will be ignored. + * + * @param uris Optional. A JSON array of the Spotify track or episode URIs to add. maximum: 100 item URIs. + * @return An {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder uris(final JsonArray uris) { + assert (uris != null); + assert (!uris.isJsonNull()); + assert (uris.size() <= 100); + return setBodyParameter("uris", uris); + } + + /** + * @deprecated Use the new endpoints instead. + * The position setter. You can set it in the request query string or request body, depending on the + * {@code use_body} parameter. + * + * @param position Optional. The position to insert the items, a zero-based index. If omitted, the + * items will be appended to the playlist. Items are added in the order they are + * listed in the query string or request body. + * @param use_body Whether to include the position in the request query string or body. + * @return An {@link AddItemsToPlaylistDeprecatedRequest.Builder}. + */ + public Builder position(final Integer position, final Boolean use_body) { + assert (position >= 0); + + if (use_body) { + return setBodyParameter("position", position); + } else { + return setQueryParameter("position", position); + } + } + + /** + * @deprecated Use the new endpoints instead. + * The request build method. + * + * @return A custom {@link AddItemsToPlaylistDeprecatedRequest}. + */ + @Override + public AddItemsToPlaylistDeprecatedRequest build() { + setContentType(ContentType.APPLICATION_JSON); + setPath("/v1/playlists/{playlist_id}/tracks"); + return new AddItemsToPlaylistDeprecatedRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequest.java index b404a27d0..9b44dfd86 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequest.java @@ -150,7 +150,7 @@ public Builder position(final Integer position, final Boolean use_body) { @Override public AddItemsToPlaylistRequest build() { setContentType(ContentType.APPLICATION_JSON); - setPath("/v1/playlists/{playlist_id}/tracks"); + setPath("/v1/playlists/{playlist_id}/items"); return new AddItemsToPlaylistRequest(this); } diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistsDetailsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistDetailsRequest.java similarity index 79% rename from src/main/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistsDetailsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistDetailsRequest.java index 8e9f61bcc..c4762215a 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistsDetailsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistDetailsRequest.java @@ -11,15 +11,15 @@ /** * Change a playlist’s name and public/private state. (The user must, of course, own the playlist.) */ -@JsonDeserialize(builder = ChangePlaylistsDetailsRequest.Builder.class) -public class ChangePlaylistsDetailsRequest extends AbstractDataRequest { +@JsonDeserialize(builder = ChangePlaylistDetailsRequest.Builder.class) +public class ChangePlaylistDetailsRequest extends AbstractDataRequest { /** - * The private {@link ChangePlaylistsDetailsRequest} constructor. + * The private {@link ChangePlaylistDetailsRequest} constructor. * - * @param builder A {@link ChangePlaylistsDetailsRequest.Builder}. + * @param builder A {@link ChangePlaylistDetailsRequest.Builder}. */ - private ChangePlaylistsDetailsRequest(final Builder builder) { + private ChangePlaylistDetailsRequest(final Builder builder) { super(builder); } @@ -38,12 +38,12 @@ public String execute() throws } /** - * Builder class for building a {@link ChangePlaylistsDetailsRequest}. + * Builder class for building a {@link ChangePlaylistDetailsRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link ChangePlaylistsDetailsRequest.Builder}. + * Create a new {@link ChangePlaylistDetailsRequest.Builder}. *

* Modifying an user's public playlists requires authorization of the {@code playlist-modify-public} * scope; Modifying an user's private playlist (including collaborative playlists) requires the @@ -60,7 +60,7 @@ public Builder(final String accessToken) { * The playlist ID setter. * * @param playlist_id The Spotify ID for the playlist. - * @return A {@link ChangePlaylistsDetailsRequest.Builder}. + * @return A {@link ChangePlaylistDetailsRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder playlist_id(final String playlist_id) { @@ -73,7 +73,7 @@ public Builder playlist_id(final String playlist_id) { * The playlist name setter. * * @param name Optional. The new name for the playlist. - * @return A {@link ChangePlaylistsDetailsRequest.Builder}. + * @return A {@link ChangePlaylistDetailsRequest.Builder}. */ public Builder name(final String name) { assert (name != null); @@ -85,7 +85,7 @@ public Builder name(final String name) { * The public status setter. * * @param public_ Optional. If {@code true} the playlist will be public, if {@code false} it will be private. - * @return A {@link ChangePlaylistsDetailsRequest.Builder}. + * @return A {@link ChangePlaylistDetailsRequest.Builder}. */ public Builder public_(final Boolean public_) { return setBodyParameter("public", public_); @@ -97,7 +97,7 @@ public Builder public_(final Boolean public_) { * @param collaborative Optional. If {@code true}, the playlist will become collaborative and other users will be * able to modify the playlist in their Spotify client. Note: You can only set * this to {@code true} on non-public playlists. - * @return A {@link ChangePlaylistsDetailsRequest.Builder}. + * @return A {@link ChangePlaylistDetailsRequest.Builder}. */ public Builder collaborative(final Boolean collaborative) { return setBodyParameter("collaborative", collaborative); @@ -107,7 +107,7 @@ public Builder collaborative(final Boolean collaborative) { * The playlist description setter. * * @param description Optional, value for playlist description as displayed in Spotify Clients and in the Web API. - * @return A {@link ChangePlaylistsDetailsRequest.Builder}. + * @return A {@link ChangePlaylistDetailsRequest.Builder}. */ public Builder description(final String description) { assert (description != null); @@ -118,13 +118,13 @@ public Builder description(final String description) { /** * The request build method. * - * @return A custom {@link ChangePlaylistsDetailsRequest}. + * @return A custom {@link ChangePlaylistDetailsRequest}. */ @Override - public ChangePlaylistsDetailsRequest build() { + public ChangePlaylistDetailsRequest build() { setContentType(ContentType.APPLICATION_JSON); setPath("/v1/playlists/{playlist_id}"); - return new ChangePlaylistsDetailsRequest(this); + return new ChangePlaylistDetailsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistForUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistForUserRequest.java new file mode 100644 index 000000000..802832c2c --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistForUserRequest.java @@ -0,0 +1,139 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Playlist; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Create a playlist for a Spotify user. (The playlist will be empty until you add tracks.) + * + * @deprecated This endpoint is deprecated. Use {@link CreatePlaylistRequest} with the current user's ID instead. + */ +@Deprecated +@JsonDeserialize(builder = CreatePlaylistForUserRequest.Builder.class) +public class CreatePlaylistForUserRequest extends AbstractDataRequest { + + /** + * The private {@link CreatePlaylistForUserRequest} constructor. + * + * @param builder A {@link CreatePlaylistForUserRequest.Builder}. + */ + private CreatePlaylistForUserRequest(final Builder builder) { + super(builder); + } + + /** + * Create a new playlist for a user. + * + * @return The newly created {@link Playlist}. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Playlist execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Playlist.JsonUtil().createModelObject(postJson()); + } + + /** + * Builder class for building a {@link CreatePlaylistForUserRequest}. + * + * @deprecated This endpoint is deprecated. Use {@link CreatePlaylistRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link CreatePlaylistForUserRequest.Builder}. + *

+ * Creating a public playlist for a user requires authorization of the {@code playlist-modify-public} scope; + * creating a private playlist requires the {@code playlist-modify-private} scope. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The user ID path parameter setter. + * + * @param user_id Required. The user's Spotify user ID. + * @return A {@link CreatePlaylistForUserRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder user_id(final String user_id) { + assert (user_id != null); + assert (!user_id.isEmpty()); + return setPathParameter("user_id", user_id); + } + + /** + * The playlist name setter. + * + * @param name Required. The name for the new playlist. + * @return A {@link CreatePlaylistForUserRequest.Builder}. + */ + public Builder name(final String name) { + assert (name != null); + assert (!name.isEmpty()); + return setBodyParameter("name", name); + } + + /** + * The public status setter. + * + * @param public_ Optional. Defaults to {@code true}. If {@code true} the playlist will be public. + * @return A {@link CreatePlaylistForUserRequest.Builder}. + */ + public Builder public_(final Boolean public_) { + return setBodyParameter("public", public_); + } + + /** + * The collaborative state setter. + * + * @param collaborative Optional. Defaults to {@code false}. If {@code true} the playlist will be collaborative. + * @return A {@link CreatePlaylistForUserRequest.Builder}. + */ + public Builder collaborative(final Boolean collaborative) { + return setBodyParameter("collaborative", collaborative); + } + + /** + * The playlist description setter. + * + * @param description Optional. Value for playlist description as displayed in Spotify Clients and in the Web API. + * @return A {@link CreatePlaylistForUserRequest.Builder}. + */ + public Builder description(final String description) { + assert (description != null); + assert (!description.isEmpty()); + return setBodyParameter("description", description); + } + + /** + * The request build method. + * + * @return A custom {@link CreatePlaylistForUserRequest}. + */ + @Override + public CreatePlaylistForUserRequest build() { + setContentType(ContentType.APPLICATION_JSON); + setPath("/v1/users/{user_id}/playlists"); + return new CreatePlaylistForUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/browse/GetCategorysPlaylistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetCategoryPlaylistsRequest.java similarity index 75% rename from src/main/java/se/michaelthelin/spotify/requests/data/browse/GetCategorysPlaylistsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetCategoryPlaylistsRequest.java index a9ab956ce..f20e6be77 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/browse/GetCategorysPlaylistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetCategoryPlaylistsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse; +package se.michaelthelin.spotify.requests.data.playlists; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.neovisionaries.i18n.CountryCode; @@ -13,16 +13,19 @@ /** * Get a list of Spotify playlists tagged with a particular category. + * + * @deprecated Use the Search API instead. */ -@JsonDeserialize(builder = GetCategorysPlaylistsRequest.Builder.class) -public class GetCategorysPlaylistsRequest extends AbstractDataRequest> { +@Deprecated +@JsonDeserialize(builder = GetCategoryPlaylistsRequest.Builder.class) +public class GetCategoryPlaylistsRequest extends AbstractDataRequest> { /** - * The private {@link GetCategorysPlaylistsRequest} constructor. + * The private {@link GetCategoryPlaylistsRequest} constructor. * - * @param builder A {@link GetCategorysPlaylistsRequest.Builder}. + * @param builder A {@link GetCategoryPlaylistsRequest.Builder}. */ - private GetCategorysPlaylistsRequest(final Builder builder) { + private GetCategoryPlaylistsRequest(final Builder builder) { super(builder); } @@ -41,12 +44,12 @@ public Paging execute() throws } /** - * Builder class for building a {@link GetCategorysPlaylistsRequest}. + * Builder class for building a {@link GetCategoryPlaylistsRequest}. */ public static final class Builder extends AbstractDataPagingRequest.Builder { /** - * Create a new {@link GetCategorysPlaylistsRequest.Builder} instance. + * Create a new {@link GetCategoryPlaylistsRequest.Builder} instance. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -58,7 +61,7 @@ public Builder(final String accessToken) { * The categroy ID setter. * * @param category_id The Spotify category ID for the category. - * @return A {@link GetCategorysPlaylistsRequest.Builder}. + * @return A {@link GetCategoryPlaylistsRequest.Builder}. * @see Spotify URIs & IDs */ public Builder category_id(final String category_id) { @@ -71,7 +74,7 @@ public Builder category_id(final String category_id) { * The country code setter. * * @param country Optional. A country: an ISO 3166-1 alpha-2 country code. - * @return A {@link GetCategorysPlaylistsRequest.Builder}. + * @return A {@link GetCategoryPlaylistsRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes */ public Builder country(final CountryCode country) { @@ -83,7 +86,7 @@ public Builder country(final CountryCode country) { * The limit setter. * * @param limit Optional. The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetCategorysPlaylistsRequest.Builder}. + * @return A {@link GetCategoryPlaylistsRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -96,7 +99,7 @@ public Builder limit(final Integer limit) { * * @param offset Optional. The index of the first item to return. Default: 0 (the first object). Use with * {@link #limit(Integer)} to get the next set of items. - * @return A {@link GetCategorysPlaylistsRequest.Builder}. + * @return A {@link GetCategoryPlaylistsRequest.Builder}. */ @Override public Builder offset(final Integer offset) { @@ -107,12 +110,12 @@ public Builder offset(final Integer offset) { /** * The request build method. * - * @return A custom {@link GetCategorysPlaylistsRequest}. + * @return A custom {@link GetCategoryPlaylistsRequest}. */ @Override - public GetCategorysPlaylistsRequest build() { + public GetCategoryPlaylistsRequest build() { setPath("/v1/browse/categories/{category_id}/playlists"); - return new GetCategorysPlaylistsRequest(this); + return new GetCategoryPlaylistsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetListOfCurrentUsersPlaylistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetCurrentUsersPlaylistsRequest.java similarity index 77% rename from src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetListOfCurrentUsersPlaylistsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetCurrentUsersPlaylistsRequest.java index d68662a9a..61f71384c 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetListOfCurrentUsersPlaylistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetCurrentUsersPlaylistsRequest.java @@ -13,15 +13,15 @@ /** * Get a list of the playlists owned or followed by the current Spotify user. */ -@JsonDeserialize(builder = GetListOfCurrentUsersPlaylistsRequest.Builder.class) -public class GetListOfCurrentUsersPlaylistsRequest extends AbstractDataRequest> { +@JsonDeserialize(builder = GetCurrentUsersPlaylistsRequest.Builder.class) +public class GetCurrentUsersPlaylistsRequest extends AbstractDataRequest> { /** - * The private {@link GetListOfCurrentUsersPlaylistsRequest} constructor. + * The private {@link GetCurrentUsersPlaylistsRequest} constructor. * - * @param builder A {@link GetListOfCurrentUsersPlaylistsRequest.Builder}. + * @param builder A {@link GetCurrentUsersPlaylistsRequest.Builder}. */ - private GetListOfCurrentUsersPlaylistsRequest(final Builder builder) { + private GetCurrentUsersPlaylistsRequest(final Builder builder) { super(builder); } @@ -40,12 +40,12 @@ public Paging execute() throws } /** - * Builder class for building a {@link GetListOfCurrentUsersPlaylistsRequest} + * Builder class for building a {@link GetCurrentUsersPlaylistsRequest} */ public static final class Builder extends AbstractDataPagingRequest.Builder { /** - * Create a new {@link GetListOfCurrentUsersPlaylistsRequest.Builder}. + * Create a new {@link GetCurrentUsersPlaylistsRequest.Builder}. *

* Private playlists are only retrievable for the current user and requires the {@code playlist-read-private} * scope to have been authorized by the user. Note: This scope alone will not return collaborative playlists, @@ -65,7 +65,7 @@ public Builder(final String accessToken) { * The limit setter. * * @param limit Optional. The maximum number of playlists to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetListOfCurrentUsersPlaylistsRequest.Builder}. + * @return A {@link GetCurrentUsersPlaylistsRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -78,7 +78,7 @@ public Builder limit(final Integer limit) { * * @param offset Optional. The index of the first playlist to return. Default: 0 (the first object). Maximum offset: * 100.000. Use with {@link #limit(Integer)} to get the next set of playlists. - * @return A {@link GetListOfCurrentUsersPlaylistsRequest.Builder}. + * @return A {@link GetCurrentUsersPlaylistsRequest.Builder}. */ @Override public Builder offset(final Integer offset) { @@ -89,12 +89,12 @@ public Builder offset(final Integer offset) { /** * The request build method. * - * @return A custom {@link GetListOfCurrentUsersPlaylistsRequest}. + * @return A custom {@link GetCurrentUsersPlaylistsRequest}. */ @Override - public GetListOfCurrentUsersPlaylistsRequest build() { + public GetCurrentUsersPlaylistsRequest build() { setPath("/v1/me/playlists"); - return new GetListOfCurrentUsersPlaylistsRequest(this); + return new GetCurrentUsersPlaylistsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/browse/GetListOfFeaturedPlaylistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetFeaturedPlaylistsRequest.java similarity index 82% rename from src/main/java/se/michaelthelin/spotify/requests/data/browse/GetListOfFeaturedPlaylistsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetFeaturedPlaylistsRequest.java index 5b8ce7114..9ff217321 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/browse/GetListOfFeaturedPlaylistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetFeaturedPlaylistsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse; +package se.michaelthelin.spotify.requests.data.playlists; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.neovisionaries.i18n.CountryCode; @@ -14,16 +14,19 @@ /** * Get a list of Spotify featured playlists (shown, for example, on a Spotify player’s "Browse" tab). + * + * @deprecated This endpoint has been deprecated by Spotify. */ -@JsonDeserialize(builder = GetListOfFeaturedPlaylistsRequest.Builder.class) -public class GetListOfFeaturedPlaylistsRequest extends AbstractDataRequest { +@Deprecated +@JsonDeserialize(builder = GetFeaturedPlaylistsRequest.Builder.class) +public class GetFeaturedPlaylistsRequest extends AbstractDataRequest { /** - * The private {@link GetListOfFeaturedPlaylistsRequest} constructor. + * The private {@link GetFeaturedPlaylistsRequest} constructor. * - * @param builder A {@link GetListOfFeaturedPlaylistsRequest.Builder}. + * @param builder A {@link GetFeaturedPlaylistsRequest.Builder}. */ - private GetListOfFeaturedPlaylistsRequest(final Builder builder) { + private GetFeaturedPlaylistsRequest(final Builder builder) { super(builder); } @@ -42,12 +45,12 @@ public FeaturedPlaylists execute() throws } /** - * Builder class for building a {@link GetListOfFeaturedPlaylistsRequest}. + * Builder class for building a {@link GetFeaturedPlaylistsRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetListOfFeaturedPlaylistsRequest.Builder} instance. + * Create a new {@link GetFeaturedPlaylistsRequest.Builder} instance. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -66,7 +69,7 @@ public Builder(final String accessToken) { * parameter, may give odd results if not carefully matched. For example * {@code country=SE&locale=de_DE} will return a list of categories relevant to Sweden but as German * language strings. - * @return A {@link GetListOfFeaturedPlaylistsRequest.Builder}. + * @return A {@link GetFeaturedPlaylistsRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes * @see Wikipedia: ISO 639 language code */ @@ -86,7 +89,7 @@ public Builder locale(final String locale) { * @param country Optional. A country: an ISO 3166-1 alpha-2 country code. Provide this parameter if you want to * narrow the list of returned categories to those relevant to a particular country. If omitted, the * returned items will be globally relevant. - * @return A {@link GetListOfFeaturedPlaylistsRequest.Builder}. + * @return A {@link GetFeaturedPlaylistsRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes */ public Builder country(final CountryCode country) { @@ -100,7 +103,7 @@ public Builder country(final CountryCode country) { * @param timestamp Optional. A timestamp in ISO 8601 format. Use this parameter to specify the user's local time to * get results tailored for that specific date and time in the day. If not provided, the response * defaults to the current UTC time. - * @return A {@link GetListOfFeaturedPlaylistsRequest.Builder}. + * @return A {@link GetFeaturedPlaylistsRequest.Builder}. * @see Wikipedia: ISO 8601 timestamps */ public Builder timestamp(final Date timestamp) { @@ -112,7 +115,7 @@ public Builder timestamp(final Date timestamp) { * The limit setter. * * @param limit Optional. The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetListOfFeaturedPlaylistsRequest.Builder}. + * @return A {@link GetFeaturedPlaylistsRequest.Builder}. */ public Builder limit(final Integer limit) { assert (1 <= limit && limit <= 50); @@ -124,7 +127,7 @@ public Builder limit(final Integer limit) { * * @param offset Optional. The index of the first item to return. Default: 0 (the first object). Use with * {@link #limit(Integer)} to get the next set of items. - * @return A {@link GetListOfFeaturedPlaylistsRequest.Builder}. + * @return A {@link GetFeaturedPlaylistsRequest.Builder}. */ public Builder offset(final Integer offset) { assert (offset >= 0); @@ -134,12 +137,12 @@ public Builder offset(final Integer offset) { /** * The request build method. * - * @return A custom {@link GetListOfFeaturedPlaylistsRequest}. + * @return A custom {@link GetFeaturedPlaylistsRequest}. */ @Override - public GetListOfFeaturedPlaylistsRequest build() { + public GetFeaturedPlaylistsRequest build() { setPath("/v1/browse/featured-playlists"); - return new GetListOfFeaturedPlaylistsRequest(this); + return new GetFeaturedPlaylistsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistItemsDeprecatedRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistItemsDeprecatedRequest.java new file mode 100644 index 000000000..0eaf67f31 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistItemsDeprecatedRequest.java @@ -0,0 +1,168 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.model_objects.specification.PlaylistTrack; +import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * @deprecated Use the new endpoints instead. + * Get full details of the tracks or episodes of a playlist owned by a Spotify user. + */ +@Deprecated +@JsonDeserialize(builder = GetPlaylistItemsDeprecatedRequest.Builder.class) +public class GetPlaylistItemsDeprecatedRequest extends AbstractDataRequest> { + + /** + * @deprecated Use the new endpoints instead. + * The private {@link GetPlaylistItemsDeprecatedRequest} constructor. + * + * @param builder A {@link GetPlaylistItemsDeprecatedRequest.Builder}. + */ + private GetPlaylistItemsDeprecatedRequest(final Builder builder) { + super(builder); + } + + /** + * @deprecated Use the new endpoints instead. + * Get a playlist's items. + * + * @return A playlist's items. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Paging execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new PlaylistTrack.JsonUtil().createModelObjectPaging(getJson()); + } + + /** + * @deprecated Use the new endpoints instead. + * Builder class for building a {@link GetPlaylistItemsDeprecatedRequest}. + */ + public static final class Builder extends AbstractDataPagingRequest.Builder { + + /** + * @deprecated Use the new endpoints instead. + * Create a new {@link GetPlaylistItemsDeprecatedRequest.Builder}. + *

+ * Both Public and Private playlists belonging to any user are retrievable on provision of a valid access token. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * @deprecated Use the new endpoints instead. + * The playlist ID setter. + * + * @param playlist_id The Spotify ID for the playlist. + * @return A {@link GetPlaylistItemsDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder playlist_id(final String playlist_id) { + assert (playlist_id != null); + assert (!playlist_id.isEmpty()); + return setPathParameter("playlist_id", playlist_id); + } + + /** + * @deprecated Use the new endpoints instead. + * The fields filter setter. + * + * @param fields Optional. Filters for the query: a comma-separated list of the fields to return. + * If omitted, all fields are returned. + * @return A {@link GetPlaylistItemsDeprecatedRequest.Builder}. + * @see + * Spotify: More Details on Playlist Fields + */ + public Builder fields(final String fields) { + assert (fields != null); + assert (!fields.isEmpty()); + return setQueryParameter("fields", fields); + } + + /** + * @deprecated Use the new endpoints instead. + * The limit setter. + * + * @param limit Optional. The maximum number of items to return. Default: 100. Minimum: 1. Maximum: 100. + * @return A {@link GetPlaylistItemsDeprecatedRequest.Builder}. + */ + @Override + public Builder limit(final Integer limit) { + assert (1 <= limit && limit <= 100); + return setQueryParameter("limit", limit); + } + + /** + * @deprecated Use the new endpoints instead. + * The offset setter. + * + * @param offset Optional. The index of the first item to return. Default: 0 (the first object). + * @return A {@link GetPlaylistItemsDeprecatedRequest.Builder}. + */ + @Override + public Builder offset(final Integer offset) { + assert (offset >= 0); + return setQueryParameter("offset", offset); + } + + /** + * @deprecated Use the new endpoints instead. + * The market country code setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this + * parameter if you want to apply Track Relinking. + * @return A {@link GetPlaylistItemsDeprecatedRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + * @see Spotify: Track Relinking Guide + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * @deprecated Use the new endpoints instead. + * The additional types setter. + * + * @param additionalTypes Optional. A comma-separated list of item types that your client supports + * besides the default track type. Valid types are: {@code track} and {@code episode}. + * An unsupported type in the response is expected to be represented as {@code null} value in the {@code item} field. + * @return A {@link GetPlaylistItemsDeprecatedRequest.Builder}. + */ + public Builder additionalTypes(final String additionalTypes) { + assert (additionalTypes != null); + assert (additionalTypes.matches("((^|,)(episode|track))+$")); + return setQueryParameter("additional_types", additionalTypes); + } + + /** + * @deprecated Use the new endpoints instead. + * The request build method. + * + * @return A custom {@link GetPlaylistItemsDeprecatedRequest}. + */ + @Override + public GetPlaylistItemsDeprecatedRequest build() { + setPath("/v1/playlists/{playlist_id}/tracks"); + return new GetPlaylistItemsDeprecatedRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistsItemsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistItemsRequest.java similarity index 81% rename from src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistsItemsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistItemsRequest.java index 39e835d7a..deeec7bcc 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistsItemsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistItemsRequest.java @@ -14,15 +14,15 @@ /** * Get full details of the tracks or episodes of a playlist owned by a Spotify user. */ -@JsonDeserialize(builder = GetPlaylistsItemsRequest.Builder.class) -public class GetPlaylistsItemsRequest extends AbstractDataRequest> { +@JsonDeserialize(builder = GetPlaylistItemsRequest.Builder.class) +public class GetPlaylistItemsRequest extends AbstractDataRequest> { /** - * The private {@link GetPlaylistsItemsRequest} constructor. + * The private {@link GetPlaylistItemsRequest} constructor. * - * @param builder A {@link GetPlaylistsItemsRequest.Builder}. + * @param builder A {@link GetPlaylistItemsRequest.Builder}. */ - private GetPlaylistsItemsRequest(final Builder builder) { + private GetPlaylistItemsRequest(final Builder builder) { super(builder); } @@ -41,12 +41,12 @@ public Paging execute() throws } /** - * Builder class for building a {@link GetPlaylistsItemsRequest}. + * Builder class for building a {@link GetPlaylistItemsRequest}. */ public static final class Builder extends AbstractDataPagingRequest.Builder { /** - * Create a new {@link GetPlaylistsItemsRequest.Builder}. + * Create a new {@link GetPlaylistItemsRequest.Builder}. *

* Both Public and Private playlists belonging to any user are retrievable on provision of a valid access token. * @@ -60,7 +60,7 @@ public Builder(final String accessToken) { * The playlist ID setter. * * @param playlist_id The Spotify ID for the playlist. - * @return A {@link GetPlaylistsItemsRequest.Builder}. + * @return A {@link GetPlaylistItemsRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder playlist_id(final String playlist_id) { @@ -74,7 +74,7 @@ public Builder playlist_id(final String playlist_id) { * * @param fields Optional. Filters for the query: a comma-separated list of the fields to return. * If omitted, all fields are returned. - * @return A {@link GetPlaylistsItemsRequest.Builder}. + * @return A {@link GetPlaylistItemsRequest.Builder}. * @see * Spotify: More Details on Playlist Fields */ @@ -88,7 +88,7 @@ public Builder fields(final String fields) { * The limit setter. * * @param limit Optional. The maximum number of items to return. Default: 100. Minimum: 1. Maximum: 100. - * @return A {@link GetPlaylistsItemsRequest.Builder}. + * @return A {@link GetPlaylistItemsRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -100,7 +100,7 @@ public Builder limit(final Integer limit) { * The offset setter. * * @param offset Optional. The index of the first item to return. Default: 0 (the first object). - * @return A {@link GetPlaylistsItemsRequest.Builder}. + * @return A {@link GetPlaylistItemsRequest.Builder}. */ @Override public Builder offset(final Integer offset) { @@ -113,7 +113,7 @@ public Builder offset(final Integer offset) { * * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this * parameter if you want to apply Track Relinking. - * @return A {@link GetPlaylistsItemsRequest.Builder}. + * @return A {@link GetPlaylistItemsRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes * @see Spotify: Track Relinking Guide */ @@ -128,7 +128,7 @@ public Builder market(final CountryCode market) { * @param additionalTypes Optional. A comma-separated list of item types that your client supports * besides the default track type. Valid types are: {@code track} and {@code episode}. * An unsupported type in the response is expected to be represented as {@code null} value in the {@code item} field. - * @return A {@link GetPlaylistsItemsRequest.Builder}. + * @return A {@link GetPlaylistItemsRequest.Builder}. */ public Builder additionalTypes(final String additionalTypes) { assert (additionalTypes != null); @@ -139,12 +139,12 @@ public Builder additionalTypes(final String additionalTypes) { /** * The request build method. * - * @return A custom {@link GetPlaylistsItemsRequest}. + * @return A custom {@link GetPlaylistItemsRequest}. */ @Override - public GetPlaylistsItemsRequest build() { - setPath("/v1/playlists/{playlist_id}/tracks"); - return new GetPlaylistsItemsRequest(this); + public GetPlaylistItemsRequest build() { + setPath("/v1/playlists/{playlist_id}/items"); + return new GetPlaylistItemsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequest.java new file mode 100644 index 000000000..2fe640324 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequest.java @@ -0,0 +1,115 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.model_objects.specification.PlaylistSimplified; +import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get a list of the playlists owned or followed by a Spotify user. + * + * @deprecated This endpoint is deprecated. + */ +@Deprecated +@JsonDeserialize(builder = GetUsersPlaylistsRequest.Builder.class) +public class GetUsersPlaylistsRequest extends AbstractDataRequest> { + + /** + * The private {@link GetUsersPlaylistsRequest} constructor. + * + * @param builder A {@link GetUsersPlaylistsRequest.Builder}. + */ + private GetUsersPlaylistsRequest(final Builder builder) { + super(builder); + } + + /** + * Get a paging of {@link PlaylistSimplified} objects for a user. + * + * @return A {@link PlaylistSimplified} paging. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Paging execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new PlaylistSimplified.JsonUtil().createModelObjectPaging(getJson()); + } + + /** + * Builder class for building a {@link GetUsersPlaylistsRequest}. + * + * @deprecated This endpoint is deprecated. + */ + @Deprecated + public static final class Builder extends AbstractDataPagingRequest.Builder { + + /** + * Create a new {@link GetUsersPlaylistsRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The user ID path parameter setter. + * + * @param user_id Required. The user's Spotify user ID. + * @return A {@link GetUsersPlaylistsRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder user_id(final String user_id) { + assert (user_id != null); + assert (!user_id.isEmpty()); + return setPathParameter("user_id", user_id); + } + + /** + * The limit setter. + * + * @param limit Optional. The maximum number of playlists to return. Default: 20. Minimum: 1. Maximum: 50. + * @return A {@link GetUsersPlaylistsRequest.Builder}. + */ + @Override + public Builder limit(final Integer limit) { + assert (1 <= limit && limit <= 50); + return setQueryParameter("limit", limit); + } + + /** + * The offset setter. + * + * @param offset Optional. The index of the first playlist to return. Default: 0. + * @return A {@link GetUsersPlaylistsRequest.Builder}. + */ + @Override + public Builder offset(final Integer offset) { + assert (offset >= 0); + return setQueryParameter("offset", offset); + } + + /** + * The request build method. + * + * @return A custom {@link GetUsersPlaylistsRequest}. + */ + @Override + public GetUsersPlaylistsRequest build() { + setPath("/v1/users/{user_id}/playlists"); + return new GetUsersPlaylistsRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemovePlaylistItemsDeprecatedRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemovePlaylistItemsDeprecatedRequest.java new file mode 100644 index 000000000..64f3b3d77 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemovePlaylistItemsDeprecatedRequest.java @@ -0,0 +1,147 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonArray; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.special.SnapshotResult; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * @deprecated Use the new endpoints instead. + * Remove one or more items from a user’s playlist. + */ +@Deprecated +@JsonDeserialize(builder = RemovePlaylistItemsDeprecatedRequest.Builder.class) +public class RemovePlaylistItemsDeprecatedRequest extends AbstractDataRequest { + + /** + * @deprecated Use the new endpoints instead. + * The private {@link RemovePlaylistItemsDeprecatedRequest} constructor. + * + * @param builder A {@link RemovePlaylistItemsDeprecatedRequest.Builder}. + */ + private RemovePlaylistItemsDeprecatedRequest(final Builder builder) { + super(builder); + } + + /** + * @deprecated Use the new endpoints instead. + * Remove items from a playlist. + * + * @return A playlist snapshot ID. The snapshot ID can be used to identify your playlist version in future requests. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + * @see + * Spotify: Version Control and Snapshots + */ + public SnapshotResult execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new SnapshotResult.JsonUtil().createModelObject(deleteJson()); + } + + /** + * @deprecated Use the new endpoints instead. + * Builder class for building a {@link RemovePlaylistItemsDeprecatedRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * @deprecated Use the new endpoints instead. + * Create a new {@link RemovePlaylistItemsDeprecatedRequest.Builder}. + *

+ * Removing items from an user's public playlists requires authorization of the {@code playlist-modify-public} + * scope; removing items from an user's private playlist (including collaborative playlists) requires the + * {@code playlist-modify-private} scope. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * @deprecated Use the new endpoints instead. + * The playlist ID setter. + * + * @param playlist_id The Spotify ID for the playlist. + * @return An {@link RemovePlaylistItemsDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder playlist_id(final String playlist_id) { + assert (playlist_id != null); + assert (!playlist_id.isEmpty()); + return setPathParameter("playlist_id", playlist_id); + } + + /** + * @deprecated Use the new endpoints instead. + * The item URIs setter. + *

+ * There are several ways to specify which tracks or episodes to remove, determined by the request parameters. + * Removing all occurrences of specific items:
+ * {@code [{ "uri": "spotify:track:4iV5W9uYEdYUVa79Axb7Rh" }, + * {"uri": "spotify:episode:512ojhOuo1ktJprKbVcKyQ" }] }
+ * Removing a specific occurrence of an item:
+ * {@code [{ "uri": "spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "positions": [0,3] }, + * { "uri": "spotify:track:1301WleyT98MSxVHPZCA6M", "positions": [7] }] } + * + * @param tracks Required. An array of objects containing Spotify URIs of the items to remove. A maximum of + * 100 objects can be sent at once + * @return A {@link RemovePlaylistItemsDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder tracks(final JsonArray tracks) { + assert (tracks != null); + assert (!tracks.isJsonNull()); + assert (tracks.size() <= 100); + return setBodyParameter("tracks", tracks); + } + + /** + * @deprecated Use the new endpoints instead. + * The playlist snapshot ID setter. + *

+ * To guard against errors when concurrent edits happen to the same playlist, we recommend specifying a snapshot ID. + * The snapshot ID lets us know which version of the playlist you are trying to edit. Concurrent edits by another + * user will be automatically resolved. If a given item in a given position is not found in the specified snapshot, + * the entire request will fail an no edits will take place. + * + * @param snapshotId Optional. The playlist's snapshot ID against which you want to make the changes. The API will + * validate that the specified items exist and in the specified positions and make the changes, + * even if more recent changes have been made to the playlist. + * @return A {@link RemovePlaylistItemsDeprecatedRequest.Builder}. + * @see + * Spotify: Version Control and Snapshots + */ + public Builder snapshotId(final String snapshotId) { + assert (snapshotId != null); + assert (!snapshotId.isEmpty()); + return setBodyParameter("snapshot_id", snapshotId); + } + + /** + * @deprecated Use the new endpoints instead. + * The request build method. + * + * @return A custom {@link RemovePlaylistItemsDeprecatedRequest}. + */ + @Override + public RemovePlaylistItemsDeprecatedRequest build() { + setContentType(ContentType.APPLICATION_JSON); + setPath("/v1/playlists/{playlist_id}/tracks"); + return new RemovePlaylistItemsDeprecatedRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemoveItemsFromPlaylistRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemovePlaylistItemsRequest.java similarity index 84% rename from src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemoveItemsFromPlaylistRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemovePlaylistItemsRequest.java index 404cbd4f3..93f02ab08 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemoveItemsFromPlaylistRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/RemovePlaylistItemsRequest.java @@ -13,15 +13,15 @@ /** * Remove one or more items from a user’s playlist. */ -@JsonDeserialize(builder = RemoveItemsFromPlaylistRequest.Builder.class) -public class RemoveItemsFromPlaylistRequest extends AbstractDataRequest { +@JsonDeserialize(builder = RemovePlaylistItemsRequest.Builder.class) +public class RemovePlaylistItemsRequest extends AbstractDataRequest { /** - * The private {@link RemoveItemsFromPlaylistRequest} constructor. + * The private {@link RemovePlaylistItemsRequest} constructor. * - * @param builder A {@link RemoveItemsFromPlaylistRequest.Builder}. + * @param builder A {@link RemovePlaylistItemsRequest.Builder}. */ - private RemoveItemsFromPlaylistRequest(final Builder builder) { + private RemovePlaylistItemsRequest(final Builder builder) { super(builder); } @@ -42,12 +42,12 @@ public SnapshotResult execute() throws } /** - * Builder class for building a {@link RemoveItemsFromPlaylistRequest}. + * Builder class for building a {@link RemovePlaylistItemsRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link RemoveItemsFromPlaylistRequest.Builder}. + * Create a new {@link RemovePlaylistItemsRequest.Builder}. *

* Removing items from an user's public playlists requires authorization of the {@code playlist-modify-public} * scope; removing items from an user's private playlist (including collaborative playlists) requires the @@ -64,7 +64,7 @@ public Builder(final String accessToken) { * The playlist ID setter. * * @param playlist_id The Spotify ID for the playlist. - * @return An {@link RemoveItemsFromPlaylistRequest.Builder}. + * @return An {@link RemovePlaylistItemsRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder playlist_id(final String playlist_id) { @@ -86,7 +86,7 @@ public Builder playlist_id(final String playlist_id) { * * @param tracks Required. An array of objects containing Spotify URIs of the items to remove. A maximum of * 100 objects can be sent at once - * @return A {@link RemoveItemsFromPlaylistRequest.Builder}. + * @return A {@link RemovePlaylistItemsRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder tracks(final JsonArray tracks) { @@ -107,7 +107,7 @@ public Builder tracks(final JsonArray tracks) { * @param snapshotId Optional. The playlist's snapshot ID against which you want to make the changes. The API will * validate that the specified items exist and in the specified positions and make the changes, * even if more recent changes have been made to the playlist. - * @return A {@link RemoveItemsFromPlaylistRequest.Builder}. + * @return A {@link RemovePlaylistItemsRequest.Builder}. * @see * Spotify: Version Control and Snapshots */ @@ -120,13 +120,13 @@ public Builder snapshotId(final String snapshotId) { /** * The request build method. * - * @return A custom {@link RemoveItemsFromPlaylistRequest}. + * @return A custom {@link RemovePlaylistItemsRequest}. */ @Override - public RemoveItemsFromPlaylistRequest build() { + public RemovePlaylistItemsRequest build() { setContentType(ContentType.APPLICATION_JSON); - setPath("/v1/playlists/{playlist_id}/tracks"); - return new RemoveItemsFromPlaylistRequest(this); + setPath("/v1/playlists/{playlist_id}/items"); + return new RemovePlaylistItemsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReorderDeprecatedRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReorderDeprecatedRequest.java new file mode 100644 index 000000000..8a5389f3c --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReorderDeprecatedRequest.java @@ -0,0 +1,159 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.special.SnapshotResult; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * @deprecated Use the new endpoints instead. + * Reorder an item or a group of items in a playlist. + *

+ * When reordering items, the timestamp indicating when they were added and the user who added them will + * be kept untouched. In addition, the users following the playlists won’t be notified about changes in + * the playlists when the items are reordered. + */ +@Deprecated +@JsonDeserialize(builder = UpdatePlaylistsItemsReorderDeprecatedRequest.Builder.class) +public class UpdatePlaylistsItemsReorderDeprecatedRequest extends AbstractDataRequest { + + /** + * @deprecated Use the new endpoints instead. + * The private {@link UpdatePlaylistsItemsReorderDeprecatedRequest} constructor. + * + * @param builder A {@link UpdatePlaylistsItemsReorderDeprecatedRequest.Builder}. + */ + private UpdatePlaylistsItemsReorderDeprecatedRequest(final Builder builder) { + super(builder); + } + + /** + * @deprecated Use the new endpoints instead. + * Reorder the items in a playlist. + * + * @return A playlist snapshot ID. The snapshot ID can be used to identify your playlist version in future requests. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + * @see + * Spotify: Version Control and Snapshots + */ + public SnapshotResult execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new SnapshotResult.JsonUtil().createModelObject(putJson()); + } + + /** + * @deprecated Use the new endpoints instead. + * Builder class for building a {@link UpdatePlaylistsItemsReorderDeprecatedRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * @deprecated Use the new endpoints instead. + * Create a new {@link UpdatePlaylistsItemsReorderDeprecatedRequest.Builder}. + *

+ * Reordering items in the current user's public playlists requires authorization of the + * {@code playlist-modify-public} scope; reordering items in the current user's private playlist (including + * collaborative playlists) requires the {@code playlist-modify-private} scope. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * @deprecated Use the new endpoints instead. + * The playlist ID setter. + * + * @param playlist_id The Spotify ID for the playlist. + * @return A {@link UpdatePlaylistsItemsReorderDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder playlist_id(final String playlist_id) { + assert (playlist_id != null); + assert (!playlist_id.isEmpty()); + return setPathParameter("playlist_id", playlist_id); + } + + /** + * @deprecated Use the new endpoints instead. + * The range start setter. + * + * @param range_start Required. The position of the first item to be reordered. + * @return A {@link UpdatePlaylistsItemsReorderDeprecatedRequest.Builder}. + */ + public Builder range_start(final Integer range_start) { + assert (range_start != null); + assert (range_start >= 0); + return setBodyParameter("range_start", range_start); + } + + /** + * @deprecated Use the new endpoints instead. + * The range length setter. + * + * @param range_length Optional. The amount of items to be reordered. Defaults to 1 if not set. + * @return A {@link UpdatePlaylistsItemsReorderDeprecatedRequest.Builder}. + */ + public Builder range_length(final Integer range_length) { + assert (range_length != null); + assert (range_length >= 1); + return setBodyParameter("range_length", range_length); + } + + /** + * @deprecated Use the new endpoints instead. + * The insert before setter. + * + * @param insert_before Required. The position where the items should be inserted. To reorder the items to the + * end of the playlist, simply set insert_before to the position after the last item. + * @return A {@link UpdatePlaylistsItemsReorderDeprecatedRequest.Builder}. + */ + public Builder insert_before(final Integer insert_before) { + assert (insert_before != null); + assert (insert_before >= 0); + return setBodyParameter("insert_before", insert_before); + } + + /** + * @deprecated Use the new endpoints instead. + * The playlist snapshot ID setter. + * + * @param snapshot_id Optional. The playlist's snapshot ID against which you want to make the changes. + * @return A {@link UpdatePlaylistsItemsReorderDeprecatedRequest.Builder}. + * @see + * Spotify: Version Control and Snapshots + */ + public Builder snapshot_id(final String snapshot_id) { + assert (snapshot_id != null); + assert (!snapshot_id.isEmpty()); + return setBodyParameter("snapshot_id", snapshot_id); + } + + /** + * @deprecated Use the new endpoints instead. + * The request build method. + * + * @return A custom {@link UpdatePlaylistsItemsReorderDeprecatedRequest}. + */ + @Override + public UpdatePlaylistsItemsReorderDeprecatedRequest build() { + setContentType(ContentType.APPLICATION_JSON); + setPath("/v1/playlists/{playlist_id}/tracks"); + return new UpdatePlaylistsItemsReorderDeprecatedRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ReorderPlaylistsItemsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReorderRequest.java similarity index 80% rename from src/main/java/se/michaelthelin/spotify/requests/data/playlists/ReorderPlaylistsItemsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReorderRequest.java index 71e9e9905..cbfa4ed32 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ReorderPlaylistsItemsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReorderRequest.java @@ -16,15 +16,15 @@ * be kept untouched. In addition, the users following the playlists won’t be notified about changes in * the playlists when the items are reordered. */ -@JsonDeserialize(builder = ReorderPlaylistsItemsRequest.Builder.class) -public class ReorderPlaylistsItemsRequest extends AbstractDataRequest { +@JsonDeserialize(builder = UpdatePlaylistsItemsReorderRequest.Builder.class) +public class UpdatePlaylistsItemsReorderRequest extends AbstractDataRequest { /** - * The private {@link ReorderPlaylistsItemsRequest} constructor. + * The private {@link UpdatePlaylistsItemsReorderRequest} constructor. * - * @param builder A {@link ReorderPlaylistsItemsRequest.Builder}. + * @param builder A {@link UpdatePlaylistsItemsReorderRequest.Builder}. */ - private ReorderPlaylistsItemsRequest(final Builder builder) { + private UpdatePlaylistsItemsReorderRequest(final Builder builder) { super(builder); } @@ -45,12 +45,12 @@ public SnapshotResult execute() throws } /** - * Builder class for building a {@link ReorderPlaylistsItemsRequest}. + * Builder class for building a {@link UpdatePlaylistsItemsReorderRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link ReorderPlaylistsItemsRequest.Builder}. + * Create a new {@link UpdatePlaylistsItemsReorderRequest.Builder}. *

* Reordering items in the current user's public playlists requires authorization of the * {@code playlist-modify-public} scope; reordering items in the current user's private playlist (including @@ -67,7 +67,7 @@ public Builder(final String accessToken) { * The playlist ID setter. * * @param playlist_id The Spotify ID for the playlist. - * @return A {@link ReorderPlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReorderRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder playlist_id(final String playlist_id) { @@ -80,7 +80,7 @@ public Builder playlist_id(final String playlist_id) { * The range start setter. * * @param range_start Required. The position of the first item to be reordered. - * @return A {@link ReorderPlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReorderRequest.Builder}. */ public Builder range_start(final Integer range_start) { assert (range_start != null); @@ -92,7 +92,7 @@ public Builder range_start(final Integer range_start) { * The range length setter. * * @param range_length Optional. The amount of items to be reordered. Defaults to 1 if not set. - * @return A {@link ReorderPlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReorderRequest.Builder}. */ public Builder range_length(final Integer range_length) { assert (range_length != null); @@ -105,7 +105,7 @@ public Builder range_length(final Integer range_length) { * * @param insert_before Required. The position where the items should be inserted. To reorder the items to the * end of the playlist, simply set insert_before to the position after the last item. - * @return A {@link ReorderPlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReorderRequest.Builder}. */ public Builder insert_before(final Integer insert_before) { assert (insert_before != null); @@ -117,7 +117,7 @@ public Builder insert_before(final Integer insert_before) { * The playlist snapshot ID setter. * * @param snapshot_id Optional. The playlist's snapshot ID against which you want to make the changes. - * @return A {@link ReorderPlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReorderRequest.Builder}. * @see * Spotify: Version Control and Snapshots */ @@ -130,13 +130,13 @@ public Builder snapshot_id(final String snapshot_id) { /** * The request build method. * - * @return A custom {@link ReorderPlaylistsItemsRequest}. + * @return A custom {@link UpdatePlaylistsItemsReorderRequest}. */ @Override - public ReorderPlaylistsItemsRequest build() { + public UpdatePlaylistsItemsReorderRequest build() { setContentType(ContentType.APPLICATION_JSON); - setPath("/v1/playlists/{playlist_id}/tracks"); - return new ReorderPlaylistsItemsRequest(this); + setPath("/v1/playlists/{playlist_id}/items"); + return new UpdatePlaylistsItemsReorderRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReplaceDeprecatedRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReplaceDeprecatedRequest.java new file mode 100644 index 000000000..6a44771e5 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReplaceDeprecatedRequest.java @@ -0,0 +1,131 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonArray; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * @deprecated Use the new endpoints instead. + * Replace all the items in a playlist, overwriting its existing items. This powerful request can be useful for + * replacing items, re-ordering existing items, or clearing the playlist. + */ +@Deprecated +@JsonDeserialize(builder = UpdatePlaylistsItemsReplaceDeprecatedRequest.Builder.class) +public class UpdatePlaylistsItemsReplaceDeprecatedRequest extends AbstractDataRequest { + + /** + * @deprecated Use the new endpoints instead. + * The private {@link UpdatePlaylistsItemsReplaceDeprecatedRequest} constructor. + * + * @param builder A {@link UpdatePlaylistsItemsReplaceDeprecatedRequest.Builder}. + */ + private UpdatePlaylistsItemsReplaceDeprecatedRequest(final Builder builder) { + super(builder); + } + + /** + * @deprecated Use the new endpoints instead. + * Replace items in a playlist. + * + * @return A string. Note: This endpoint doesn't return something in its response body. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public String execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return putJson(); + } + + /** + * @deprecated Use the new endpoints instead. + * Builder class for building a {@link UpdatePlaylistsItemsReplaceDeprecatedRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * @deprecated Use the new endpoints instead. + * Create a new {@link UpdatePlaylistsItemsReplaceDeprecatedRequest.Builder}. + *

+ * Replacing items in the current user's public playlists requires authorization of the + * {@code playlist-modify-public} scope; replacing items in the current user's private playlist (including + * collaborative playlists) requires the {@code playlist-modify-private} scope. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + * @see Spotify: Using Scopes + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * @deprecated Use the new endpoints instead. + * The playlist ID setter. + * + * @param playlist_id The Spotify ID for the playlist. + * @return A {@link UpdatePlaylistsItemsReplaceDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder playlist_id(final String playlist_id) { + assert (playlist_id != null); + assert (!playlist_id.isEmpty()); + return setPathParameter("playlist_id", playlist_id); + } + + /** + * @deprecated Use the new endpoints instead. + * The item URIs setter. + * + * @param uris Optional. A comma-separated list of Spotify track or episode URIs to set. Maximum: 100 track or episode URIs. + * @return A {@link UpdatePlaylistsItemsReplaceDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder uris(final String uris) { + assert (uris != null); + assert (!uris.isEmpty()); + assert (uris.split(",").length <= 100); + return setQueryParameter("uris", uris); + } + + /** + * @deprecated Use the new endpoints instead. + * The item URIs setter. + *

+ * Note: If the URIs have already been set with {@link #uris(String)}, any URIs set here will be ignored. + * + * @param uris Optional. A JSON array of Spotify track or episode URIs to set. Maximum: 100 track or episode URIs. + * @return A {@link UpdatePlaylistsItemsReplaceDeprecatedRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder uris(final JsonArray uris) { + assert (uris != null); + assert (!uris.isJsonNull()); + assert (uris.size() <= 100); + return setBodyParameter("uris", uris); + } + + /** + * @deprecated Use the new endpoints instead. + * The request build method. + * + * @return A custom {@link UpdatePlaylistsItemsReplaceDeprecatedRequest}. + */ + @Override + public UpdatePlaylistsItemsReplaceDeprecatedRequest build() { + setContentType(ContentType.APPLICATION_JSON); + setPath("/v1/playlists/{playlist_id}/tracks"); + return new UpdatePlaylistsItemsReplaceDeprecatedRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ReplacePlaylistsItemsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReplaceRequest.java similarity index 78% rename from src/main/java/se/michaelthelin/spotify/requests/data/playlists/ReplacePlaylistsItemsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReplaceRequest.java index 1d7cb89a1..368324166 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/playlists/ReplacePlaylistsItemsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/playlists/UpdatePlaylistsItemsReplaceRequest.java @@ -13,15 +13,15 @@ * Replace all the items in a playlist, overwriting its existing items. This powerful request can be useful for * replacing items, re-ordering existing items, or clearing the playlist. */ -@JsonDeserialize(builder = ReplacePlaylistsItemsRequest.Builder.class) -public class ReplacePlaylistsItemsRequest extends AbstractDataRequest { +@JsonDeserialize(builder = UpdatePlaylistsItemsReplaceRequest.Builder.class) +public class UpdatePlaylistsItemsReplaceRequest extends AbstractDataRequest { /** - * The private {@link ReplacePlaylistsItemsRequest} constructor. + * The private {@link UpdatePlaylistsItemsReplaceRequest} constructor. * - * @param builder A {@link ReplacePlaylistsItemsRequest.Builder}. + * @param builder A {@link UpdatePlaylistsItemsReplaceRequest.Builder}. */ - private ReplacePlaylistsItemsRequest(final Builder builder) { + private UpdatePlaylistsItemsReplaceRequest(final Builder builder) { super(builder); } @@ -40,12 +40,12 @@ public String execute() throws } /** - * Builder class for building a {@link ReplacePlaylistsItemsRequest}. + * Builder class for building a {@link UpdatePlaylistsItemsReplaceRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link ReplacePlaylistsItemsRequest.Builder}. + * Create a new {@link UpdatePlaylistsItemsReplaceRequest.Builder}. *

* Replacing items in the current user's public playlists requires authorization of the * {@code playlist-modify-public} scope; replacing items in the current user's private playlist (including @@ -62,7 +62,7 @@ public Builder(final String accessToken) { * The playlist ID setter. * * @param playlist_id The Spotify ID for the playlist. - * @return A {@link ReplacePlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReplaceRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder playlist_id(final String playlist_id) { @@ -75,7 +75,7 @@ public Builder playlist_id(final String playlist_id) { * The item URIs setter. * * @param uris Optional. A comma-separated list of Spotify track or episode URIs to set. Maximum: 100 track or episode URIs. - * @return A {@link ReplacePlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReplaceRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder uris(final String uris) { @@ -91,7 +91,7 @@ public Builder uris(final String uris) { * Note: If the URIs have already been set with {@link #uris(String)}, any URIs set here will be ignored. * * @param uris Optional. A JSON array of Spotify track or episode URIs to set. Maximum: 100 track or episode URIs. - * @return A {@link ReplacePlaylistsItemsRequest.Builder}. + * @return A {@link UpdatePlaylistsItemsReplaceRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder uris(final JsonArray uris) { @@ -104,13 +104,13 @@ public Builder uris(final JsonArray uris) { /** * The request build method. * - * @return A custom {@link ReplacePlaylistsItemsRequest}. + * @return A custom {@link UpdatePlaylistsItemsReplaceRequest}. */ @Override - public ReplacePlaylistsItemsRequest build() { + public UpdatePlaylistsItemsReplaceRequest build() { setContentType(ContentType.APPLICATION_JSON); - setPath("/v1/playlists/{playlist_id}/tracks"); - return new ReplacePlaylistsItemsRequest(this); + setPath("/v1/playlists/{playlist_id}/items"); + return new UpdatePlaylistsItemsReplaceRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/search/SearchItemRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/search/SearchForItemRequest.java similarity index 82% rename from src/main/java/se/michaelthelin/spotify/requests/data/search/SearchItemRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/search/SearchForItemRequest.java index 4db0cda5c..d9d197820 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/search/SearchItemRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/search/SearchForItemRequest.java @@ -12,15 +12,15 @@ /** * Get Spotify catalog information about artists, albums, episodes, playlists, shows or tracks that match a keyword string. */ -@JsonDeserialize(builder = SearchItemRequest.Builder.class) -public class SearchItemRequest extends AbstractDataRequest { +@JsonDeserialize(builder = SearchForItemRequest.Builder.class) +public class SearchForItemRequest extends AbstractDataRequest { /** - * The private {@link SearchItemRequest} constructor. + * The private {@link SearchForItemRequest} constructor. * - * @param builder A {@link SearchItemRequest.Builder}. + * @param builder A {@link SearchForItemRequest.Builder}. */ - private SearchItemRequest(final Builder builder) { + private SearchForItemRequest(final Builder builder) { super(builder); } @@ -39,12 +39,12 @@ public SearchResult execute() throws } /** - * Builder class for building a {@link SearchItemRequest}. + * Builder class for building a {@link SearchForItemRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link SearchItemRequest.Builder}. + * Create a new {@link SearchForItemRequest.Builder}. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -56,7 +56,7 @@ public Builder(final String accessToken) { * The search query setter. * * @param q Required. The search query's keywords (and optional field filters and operators). - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. * @see Spotify: Search Query Options */ public Builder q(final String q) { @@ -70,7 +70,7 @@ public Builder q(final String q) { * * @param type Required. A comma-separated list of item types to search across. Valid types are: {@code album}, * {@code artist}, {@code episode}, {@code playlist}, {@code show} and {@code track}. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. */ public Builder type(final String type) { assert (type != null); @@ -84,7 +84,7 @@ public Builder type(final String type) { * @param market Optional. An ISO 3166-1 alpha-2 country code. If a country code is given, only artists, * albums, and tracks with content playable in that market will be returned. (Playlist * results are not affected by the market parameter.) - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes */ public Builder market(final CountryCode market) { @@ -96,7 +96,7 @@ public Builder market(final CountryCode market) { * The limit setter. * * @param limit Optional. The maximum number of results to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. */ public Builder limit(final Integer limit) { assert (limit != null); @@ -109,7 +109,7 @@ public Builder limit(final Integer limit) { * * @param offset Optional. The index of the first result to return. Default: 0 (i.e., the first result). Maximum * offset: 100.000. Use with {@link #limit(Integer)} to get the next page of search results. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. */ public Builder offset(final Integer offset) { assert (offset != null); @@ -123,7 +123,7 @@ public Builder offset(final Integer offset) { * @param includeExternal Optional. Possible values: {@code audio}. If {@code audio} is set * the response will include any relevant audio content that is hosted externally. * By default external content is filtered out from responses. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. */ public Builder includeExternal(String includeExternal) { assert (includeExternal != null); @@ -134,12 +134,12 @@ public Builder includeExternal(String includeExternal) { /** * The request build method. * - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchForItemRequest.Builder}. */ @Override - public SearchItemRequest build() { + public SearchForItemRequest build() { setPath("/v1/search"); - return new SearchItemRequest(this); + return new SearchForItemRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchAlbumsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchAlbumsRequest.java index a6044e0b8..70c5b9962 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchAlbumsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchAlbumsRequest.java @@ -8,7 +8,6 @@ import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; import se.michaelthelin.spotify.requests.data.AbstractDataRequest; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; import java.io.IOException; @@ -115,7 +114,7 @@ public Builder offset(final Integer offset) { * @param includeExternal Optional. Possible values: {@code audio}. If {@code audio} is set * the response will include any relevant audio content that is hosted externally. * By default external content is filtered out from responses. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchAlbumsRequest.Builder}. */ public Builder includeExternal(String includeExternal) { assert (includeExternal != null); diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchArtistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchArtistsRequest.java index 4b31a6546..0e5cbab36 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchArtistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchArtistsRequest.java @@ -8,7 +8,6 @@ import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; import se.michaelthelin.spotify.requests.data.AbstractDataRequest; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; import java.io.IOException; @@ -115,7 +114,7 @@ public Builder offset(final Integer offset) { * @param includeExternal Optional. Possible values: {@code audio}. If {@code audio} is set * the response will include any relevant audio content that is hosted externally. * By default external content is filtered out from responses. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchArtistsRequest.Builder}. */ public Builder includeExternal(String includeExternal) { assert (includeExternal != null); diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchEpisodesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchEpisodesRequest.java index 03744e876..44cae4bb3 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchEpisodesRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchEpisodesRequest.java @@ -8,7 +8,6 @@ import se.michaelthelin.spotify.model_objects.specification.Paging; import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; import se.michaelthelin.spotify.requests.data.AbstractDataRequest; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; import java.io.IOException; @@ -115,7 +114,7 @@ public Builder offset(final Integer offset) { * @param includeExternal Optional. Possible values: {@code audio}. If {@code audio} is set * the response will include any relevant audio content that is hosted externally. * By default external content is filtered out from responses. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchEpisodesRequest.Builder}. */ public Builder includeExternal(String includeExternal) { assert (includeExternal != null); diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchPlaylistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchPlaylistsRequest.java index 6cc95cb8b..bdc58d744 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchPlaylistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchPlaylistsRequest.java @@ -8,7 +8,6 @@ import se.michaelthelin.spotify.model_objects.specification.PlaylistSimplified; import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; import se.michaelthelin.spotify.requests.data.AbstractDataRequest; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; import java.io.IOException; @@ -115,7 +114,7 @@ public Builder offset(final Integer offset) { * @param includeExternal Optional. Possible values: {@code audio}. If {@code audio} is set * the response will include any relevant audio content that is hosted externally. * By default external content is filtered out from responses. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchPlaylistsRequest.Builder}. */ public Builder includeExternal(String includeExternal) { assert (includeExternal != null); diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchShowsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchShowsRequest.java index cbc984c09..c1c7b2be5 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchShowsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchShowsRequest.java @@ -8,7 +8,6 @@ import se.michaelthelin.spotify.model_objects.specification.ShowSimplified; import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; import se.michaelthelin.spotify.requests.data.AbstractDataRequest; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; import java.io.IOException; @@ -116,7 +115,7 @@ public Builder offset(final Integer offset) { * @param includeExternal Optional. Possible values: {@code audio}. If {@code audio} is set * the response will include any relevant audio content that is hosted externally. * By default external content is filtered out from responses. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchShowsRequest.Builder}. */ public Builder includeExternal(String includeExternal) { assert (includeExternal != null); diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchTracksRequest.java index 1ace87ad8..a15712aa0 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/search/simplified/SearchTracksRequest.java @@ -8,7 +8,6 @@ import se.michaelthelin.spotify.model_objects.specification.Track; import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; import se.michaelthelin.spotify.requests.data.AbstractDataRequest; -import se.michaelthelin.spotify.requests.data.search.SearchItemRequest; import java.io.IOException; @@ -115,7 +114,7 @@ public Builder offset(final Integer offset) { * @param includeExternal Optional. Possible values: {@code audio}. If {@code audio} is set * the response will include any relevant audio content that is hosted externally. * By default external content is filtered out from responses. - * @return A {@link SearchItemRequest.Builder}. + * @return A {@link SearchTracksRequest.Builder}. */ public Builder includeExternal(String includeExternal) { assert (includeExternal != null); diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedShowsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/shows/CheckUsersSavedShowsRequest.java similarity index 95% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedShowsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/shows/CheckUsersSavedShowsRequest.java index bbc7d52aa..557cce3e4 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedShowsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/shows/CheckUsersSavedShowsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.shows; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.Gson; @@ -11,7 +11,10 @@ /** * Check if one or more shows is already saved in the current Spotify user’s library. + * + * @deprecated Use {@link CheckLibraryContainsRequest} instead. */ +@Deprecated @JsonDeserialize(builder = CheckUsersSavedShowsRequest.Builder.class) public class CheckUsersSavedShowsRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequest.java new file mode 100644 index 000000000..ea16d2b42 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequest.java @@ -0,0 +1,99 @@ +package se.michaelthelin.spotify.requests.data.shows; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.ShowSimplified; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for several shows based on their Spotify IDs. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralShowsRequest.Builder.class) +public class GetSeveralShowsRequest extends AbstractDataRequest { + + /** + * The private {@link GetSeveralShowsRequest} constructor. + * + * @param builder A {@link GetSeveralShowsRequest.Builder}. + */ + private GetSeveralShowsRequest(final Builder builder) { + super(builder); + } + + /** + * Get several {@link ShowSimplified} objects. + * + * @return Multiple {@link ShowSimplified} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public ShowSimplified[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new ShowSimplified.JsonUtil().createModelObjectArray(getJson(), "shows"); + } + + /** + * Builder class for building a {@link GetSeveralShowsRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSeveralShowsRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The show IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the shows. Maximum: 50 IDs. + * @return A {@link GetSeveralShowsRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. + * @return A {@link GetSeveralShowsRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralShowsRequest}. + */ + @Override + public GetSeveralShowsRequest build() { + setPath("/v1/shows"); + return new GetSeveralShowsRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetShowsEpisodesRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetShowEpisodesRequest.java similarity index 82% rename from src/main/java/se/michaelthelin/spotify/requests/data/shows/GetShowsEpisodesRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/shows/GetShowEpisodesRequest.java index f3dd77313..2103d6ce1 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetShowsEpisodesRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetShowEpisodesRequest.java @@ -14,15 +14,15 @@ /** * Get Spotify catalog information about an show’s episodes. */ -@JsonDeserialize(builder = GetShowsEpisodesRequest.Builder.class) -public class GetShowsEpisodesRequest extends AbstractDataRequest> { +@JsonDeserialize(builder = GetShowEpisodesRequest.Builder.class) +public class GetShowEpisodesRequest extends AbstractDataRequest> { /** - * The private {@link GetShowsEpisodesRequest} constructor. + * The private {@link GetShowEpisodesRequest} constructor. * - * @param builder A {@link GetShowsEpisodesRequest.Builder}. + * @param builder A {@link GetShowEpisodesRequest.Builder}. */ - private GetShowsEpisodesRequest(Builder builder) { + private GetShowEpisodesRequest(Builder builder) { super(builder); } @@ -42,12 +42,12 @@ public Paging execute() throws } /** - * Builder class for building a {@link GetShowsEpisodesRequest}. + * Builder class for building a {@link GetShowEpisodesRequest}. */ public static final class Builder extends AbstractDataPagingRequest.Builder { /** - * Create a new {@link GetShowsEpisodesRequest.Builder} instance. + * Create a new {@link GetShowEpisodesRequest.Builder} instance. *

* Reading the user’s resume points on episode objects requires the {@code user-read-playback-position} scope. * @@ -62,7 +62,7 @@ public Builder(final String accessToken) { * The show ID setter. * * @param id The Spotify ID for the show. - * @return A {@link GetShowsEpisodesRequest.Builder}. + * @return A {@link GetShowEpisodesRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder id(final String id) { @@ -75,7 +75,7 @@ public Builder id(final String id) { * The limit setter. * * @param limit Optional. The maximum number of episodes to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetShowsEpisodesRequest.Builder}. + * @return A {@link GetShowEpisodesRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -88,7 +88,7 @@ public Builder limit(final Integer limit) { * * @param offset Optional. The index of the first episode to return. Default: 0 (i.e., the first object). Use with * {@link #limit(Integer)} to get the next set of objects. - * @return A {@link GetShowsEpisodesRequest.Builder}. + * @return A {@link GetShowEpisodesRequest.Builder}. */ @Override public Builder offset(final Integer offset) { @@ -104,7 +104,7 @@ public Builder offset(final Integer offset) { * Users can view the country that is associated with their account in the account settings. * * @param market Optional. An ISO 3166-1 alpha-2 country code. - * @return A {@link GetShowsEpisodesRequest.Builder}. + * @return A {@link GetShowEpisodesRequest.Builder}. * @see Wikipedia: ISO 3166-1 alpha-2 country codes */ public Builder market(final CountryCode market) { @@ -115,12 +115,12 @@ public Builder market(final CountryCode market) { /** * The request build method. * - * @return A custom {@link GetShowsEpisodesRequest}. + * @return A custom {@link GetShowEpisodesRequest}. */ @Override - public GetShowsEpisodesRequest build() { + public GetShowEpisodesRequest build() { setPath("/v1/shows/{id}/episodes"); - return new GetShowsEpisodesRequest(this); + return new GetShowEpisodesRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedShowsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetUsersSavedShowsRequest.java similarity index 98% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedShowsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/shows/GetUsersSavedShowsRequest.java index f230f285b..7d418e093 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedShowsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/shows/GetUsersSavedShowsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.shows; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ParseException; diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/shows/RemoveShowsForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/shows/RemoveShowsForCurrentUserRequest.java new file mode 100644 index 000000000..2fda54c91 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/shows/RemoveShowsForCurrentUserRequest.java @@ -0,0 +1,57 @@ +package se.michaelthelin.spotify.requests.data.shows; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Remove one or more shows from the current user's library. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = RemoveShowsForCurrentUserRequest.Builder.class) +public class RemoveShowsForCurrentUserRequest extends AbstractDataRequest { + + private RemoveShowsForCurrentUserRequest(final Builder builder) { + super(builder); + } + + @Override + public String execute() throws IOException, SpotifyWebApiException, ParseException { + return deleteJson(); + } + + /** + * Builder class for building a {@link RemoveShowsForCurrentUserRequest}. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + public Builder(final String accessToken) { + super(accessToken); + } + + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + @Override + public RemoveShowsForCurrentUserRequest build() { + setPath("/v1/me/shows"); + return new RemoveShowsForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequest.java new file mode 100644 index 000000000..e39c5fdd7 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequest.java @@ -0,0 +1,57 @@ +package se.michaelthelin.spotify.requests.data.shows; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Save one or more shows to the current user's library. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = SaveShowsForCurrentUserRequest.Builder.class) +public class SaveShowsForCurrentUserRequest extends AbstractDataRequest { + + private SaveShowsForCurrentUserRequest(final Builder builder) { + super(builder); + } + + @Override + public String execute() throws IOException, SpotifyWebApiException, ParseException { + return putJson(); + } + + /** + * Builder class for building a {@link SaveShowsForCurrentUserRequest}. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + public Builder(final String accessToken) { + super(accessToken); + } + + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + @Override + public SaveShowsForCurrentUserRequest build() { + setPath("/v1/me/shows"); + return new SaveShowsForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/CheckUsersSavedTracksRequest.java similarity index 95% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedTracksRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/tracks/CheckUsersSavedTracksRequest.java index 6ce3f2e3c..407c0374a 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/CheckUsersSavedTracksRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.tracks; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.Gson; @@ -11,7 +11,10 @@ /** * Check if one or more tracks is already saved in the current Spotify user’s "Your Music" library. + * + * @deprecated Use {@link CheckLibraryContainsRequest} instead. */ +@Deprecated @JsonDeserialize(builder = CheckUsersSavedTracksRequest.Builder.class) public class CheckUsersSavedTracksRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/browse/GetRecommendationsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetRecommendationsRequest.java similarity index 99% rename from src/main/java/se/michaelthelin/spotify/requests/data/browse/GetRecommendationsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetRecommendationsRequest.java index 180eb2b52..0cb4b74a6 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/browse/GetRecommendationsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetRecommendationsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse; +package se.michaelthelin.spotify.requests.data.tracks; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.neovisionaries.i18n.CountryCode; @@ -17,7 +17,10 @@ * together with pool size details.

*

* For artists and tracks that are very new or obscure there might not be enough data to generate a list of tracks. + * + * @deprecated This endpoint has been deprecated by Spotify. */ +@Deprecated @JsonDeserialize(builder = GetRecommendationsRequest.Builder.class) public class GetRecommendationsRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksAudioFeaturesRequest.java similarity index 69% rename from src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksAudioFeaturesRequest.java index 5f56dd6b3..52127e78f 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksAudioFeaturesRequest.java @@ -10,16 +10,19 @@ /** * Get audio features for multiple tracks based on their Spotify IDs. + * + * @deprecated This endpoint has been deprecated by Spotify. */ -@JsonDeserialize(builder = GetAudioFeaturesForSeveralTracksRequest.Builder.class) -public class GetAudioFeaturesForSeveralTracksRequest extends AbstractDataRequest { +@Deprecated +@JsonDeserialize(builder = GetSeveralTracksAudioFeaturesRequest.Builder.class) +public class GetSeveralTracksAudioFeaturesRequest extends AbstractDataRequest { /** - * The private {@link GetAudioFeaturesForSeveralTracksRequest} constructor. + * The private {@link GetSeveralTracksAudioFeaturesRequest} constructor. * - * @param builder A {@link GetAudioFeaturesForSeveralTracksRequest.Builder}. + * @param builder A {@link GetSeveralTracksAudioFeaturesRequest.Builder}. */ - private GetAudioFeaturesForSeveralTracksRequest(final Builder builder) { + private GetSeveralTracksAudioFeaturesRequest(final Builder builder) { super(builder); } @@ -38,12 +41,12 @@ public AudioFeatures[] execute() throws } /** - * Builder class for building a {@link GetAudioFeaturesForSeveralTracksRequest}. + * Builder class for building a {@link GetSeveralTracksAudioFeaturesRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetAudioFeaturesForSeveralTracksRequest.Builder}. + * Create a new {@link GetSeveralTracksAudioFeaturesRequest.Builder}. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -55,7 +58,7 @@ public Builder(final String accessToken) { * The track IDs setter. * * @param ids Required. A comma-separated list of the Spotify IDs for the tracks. Maximum: 100 IDs. - * @return A {@link GetAudioFeaturesForSeveralTracksRequest.Builder}. + * @return A {@link GetSeveralTracksAudioFeaturesRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder ids(final String ids) { @@ -67,12 +70,12 @@ public Builder ids(final String ids) { /** * The request build method. * - * @return A custom {@link GetAudioFeaturesForSeveralTracksRequest}. + * @return A custom {@link GetSeveralTracksAudioFeaturesRequest}. */ @Override - public GetAudioFeaturesForSeveralTracksRequest build() { + public GetSeveralTracksAudioFeaturesRequest build() { setPath("/v1/audio-features"); - return new GetAudioFeaturesForSeveralTracksRequest(this); + return new GetSeveralTracksAudioFeaturesRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequest.java new file mode 100644 index 000000000..de32799cb --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequest.java @@ -0,0 +1,100 @@ +package se.michaelthelin.spotify.requests.data.tracks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.neovisionaries.i18n.CountryCode; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Track; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get Spotify catalog information for multiple tracks based on their Spotify IDs. + * + * @deprecated This endpoint has been deprecated by Spotify. + */ +@Deprecated +@JsonDeserialize(builder = GetSeveralTracksRequest.Builder.class) +public class GetSeveralTracksRequest extends AbstractDataRequest { + + /** + * The private {@link GetSeveralTracksRequest} constructor. + * + * @param builder A {@link GetSeveralTracksRequest.Builder}. + */ + private GetSeveralTracksRequest(final Builder builder) { + super(builder); + } + + /** + * Get several {@link Track} objects. + * + * @return Multiple {@link Track} objects. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public Track[] execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new Track.JsonUtil().createModelObjectArray(getJson(), "tracks"); + } + + /** + * Builder class for building a {@link GetSeveralTracksRequest}. + */ + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetSeveralTracksRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The track IDs setter. + * + * @param ids Required. A comma-separated list of the Spotify IDs for the tracks. Maximum: 50 IDs. + * @return A {@link GetSeveralTracksRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + /** + * The market query parameter setter. + * + * @param market Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply + * Track Relinking. + * @return A {@link GetSeveralTracksRequest.Builder}. + * @see Wikipedia: ISO 3166-1 alpha-2 country codes + */ + public Builder market(final CountryCode market) { + assert (market != null); + return setQueryParameter("market", market); + } + + /** + * The request build method. + * + * @return A custom {@link GetSeveralTracksRequest}. + */ + @Override + public GetSeveralTracksRequest build() { + setPath("/v1/tracks"); + return new GetSeveralTracksRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisForTrackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetTracksAudioAnalysisRequest.java similarity index 70% rename from src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisForTrackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetTracksAudioAnalysisRequest.java index eb3b514e5..b9f19f27f 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisForTrackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetTracksAudioAnalysisRequest.java @@ -10,16 +10,19 @@ /** * Get a detailed audio analysis for a single track identified by its unique Spotify ID. + * + * @deprecated This endpoint has been deprecated by Spotify. */ -@JsonDeserialize(builder = GetAudioAnalysisForTrackRequest.Builder.class) -public class GetAudioAnalysisForTrackRequest extends AbstractDataRequest { +@Deprecated +@JsonDeserialize(builder = GetTracksAudioAnalysisRequest.Builder.class) +public class GetTracksAudioAnalysisRequest extends AbstractDataRequest { /** - * The private {@link GetAudioAnalysisForTrackRequest} constructor. + * The private {@link GetTracksAudioAnalysisRequest} constructor. * - * @param builder A {@link GetAudioAnalysisForTrackRequest.Builder}. + * @param builder A {@link GetTracksAudioAnalysisRequest.Builder}. */ - private GetAudioAnalysisForTrackRequest(final Builder builder) { + private GetTracksAudioAnalysisRequest(final Builder builder) { super(builder); } @@ -38,12 +41,12 @@ public AudioAnalysis execute() throws } /** - * Builder class for building a {@link GetAudioAnalysisForTrackRequest}. + * Builder class for building a {@link GetTracksAudioAnalysisRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetAudioAnalysisForTrackRequest.Builder}. + * Create a new {@link GetTracksAudioAnalysisRequest.Builder}. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -55,7 +58,7 @@ public Builder(final String accessToken) { * The track ID setter. * * @param id Required. The Spotify ID for the track. - * @return A {@link GetAudioAnalysisForTrackRequest.Builder}. + * @return A {@link GetTracksAudioAnalysisRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder id(final String id) { @@ -67,12 +70,12 @@ public Builder id(final String id) { /** * The request build method. * - * @return A custom {@link GetAudioAnalysisForTrackRequest}. + * @return A custom {@link GetTracksAudioAnalysisRequest}. */ @Override - public GetAudioAnalysisForTrackRequest build() { + public GetTracksAudioAnalysisRequest build() { setPath("/v1/audio-analysis/{id}"); - return new GetAudioAnalysisForTrackRequest(this); + return new GetTracksAudioAnalysisRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForTrackRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetTracksAudioFeaturesRequest.java similarity index 70% rename from src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForTrackRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetTracksAudioFeaturesRequest.java index 36b58acd8..a35c98a62 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForTrackRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetTracksAudioFeaturesRequest.java @@ -10,16 +10,19 @@ /** * Get audio feature information for a single track identified by its unique Spotify ID. + * + * @deprecated This endpoint has been deprecated by Spotify. */ -@JsonDeserialize(builder = GetAudioFeaturesForTrackRequest.Builder.class) -public class GetAudioFeaturesForTrackRequest extends AbstractDataRequest { +@Deprecated +@JsonDeserialize(builder = GetTracksAudioFeaturesRequest.Builder.class) +public class GetTracksAudioFeaturesRequest extends AbstractDataRequest { /** - * The private {@link GetAudioFeaturesForTrackRequest} constructor. + * The private {@link GetTracksAudioFeaturesRequest} constructor. * - * @param builder A {@link GetAudioFeaturesForTrackRequest.Builder}. + * @param builder A {@link GetTracksAudioFeaturesRequest.Builder}. */ - private GetAudioFeaturesForTrackRequest(final Builder builder) { + private GetTracksAudioFeaturesRequest(final Builder builder) { super(builder); } @@ -38,12 +41,12 @@ public AudioFeatures execute() throws } /** - * Builder class for building a {@link GetAudioFeaturesForTrackRequest}. + * Builder class for building a {@link GetTracksAudioFeaturesRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link GetAudioFeaturesForTrackRequest.Builder}. + * Create a new {@link GetTracksAudioFeaturesRequest.Builder}. * * @param accessToken Required. A valid access token from the Spotify Accounts service. */ @@ -55,7 +58,7 @@ public Builder(final String accessToken) { * The track ID setter. * * @param id Required. The Spotify ID for the track. - * @return A {@link GetAudioFeaturesForTrackRequest.Builder}.. + * @return A {@link GetTracksAudioFeaturesRequest.Builder}.. * @see Spotify: URIs & IDs */ public Builder id(final String id) { @@ -67,12 +70,12 @@ public Builder id(final String id) { /** * The request build method. * - * @return A custom {@link GetAudioFeaturesForTrackRequest}. + * @return A custom {@link GetTracksAudioFeaturesRequest}. */ @Override - public GetAudioFeaturesForTrackRequest build() { + public GetTracksAudioFeaturesRequest build() { setPath("/v1/audio-features/{id}"); - return new GetAudioFeaturesForTrackRequest(this); + return new GetTracksAudioFeaturesRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetUsersSavedTracksRequest.java similarity index 98% rename from src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedTracksRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetUsersSavedTracksRequest.java index 346b4a3ca..8f25065b2 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/GetUsersSavedTracksRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.tracks; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.neovisionaries.i18n.CountryCode; diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/RemoveUsersSavedTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/RemoveUsersSavedTracksRequest.java new file mode 100644 index 000000000..517c87d99 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/RemoveUsersSavedTracksRequest.java @@ -0,0 +1,57 @@ +package se.michaelthelin.spotify.requests.data.tracks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Remove one or more tracks from the current user's 'Your Music' library. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = RemoveUsersSavedTracksRequest.Builder.class) +public class RemoveUsersSavedTracksRequest extends AbstractDataRequest { + + private RemoveUsersSavedTracksRequest(final Builder builder) { + super(builder); + } + + @Override + public String execute() throws IOException, SpotifyWebApiException, ParseException { + return deleteJson(); + } + + /** + * Builder class for building a {@link RemoveUsersSavedTracksRequest}. + * + * @deprecated Use {@link RemoveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + public Builder(final String accessToken) { + super(accessToken); + } + + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + @Override + public RemoveUsersSavedTracksRequest build() { + setPath("/v1/me/tracks"); + return new RemoveUsersSavedTracksRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequest.java new file mode 100644 index 000000000..4ff37e192 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequest.java @@ -0,0 +1,57 @@ +package se.michaelthelin.spotify.requests.data.tracks; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Save one or more tracks to the current user's 'Your Music' library. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ +@Deprecated +@JsonDeserialize(builder = SaveTracksForCurrentUserRequest.Builder.class) +public class SaveTracksForCurrentUserRequest extends AbstractDataRequest { + + private SaveTracksForCurrentUserRequest(final Builder builder) { + super(builder); + } + + @Override + public String execute() throws IOException, SpotifyWebApiException, ParseException { + return putJson(); + } + + /** + * Builder class for building a {@link SaveTracksForCurrentUserRequest}. + * + * @deprecated Use {@link SaveLibraryItemsRequest} instead. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + public Builder(final String accessToken) { + super(accessToken); + } + + public Builder ids(final String ids) { + assert (ids != null); + assert (ids.split(",").length <= 50); + return setQueryParameter("ids", ids); + } + + @Override + public SaveTracksForCurrentUserRequest build() { + setPath("/v1/me/tracks"); + return new SaveTracksForCurrentUserRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequest.java similarity index 96% rename from src/main/java/se/michaelthelin/spotify/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequest.java index 0e9fee6c1..2e869c4a9 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.Gson; @@ -12,7 +12,10 @@ /** * Check to see if the current user is following one or more artists or other Spotify users. + * + * @deprecated This endpoint has been deprecated by Spotify. */ +@Deprecated @JsonDeserialize(builder = CheckCurrentUserFollowsArtistsOrUsersRequest.Builder.class) public class CheckCurrentUserFollowsArtistsOrUsersRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/CheckUsersFollowPlaylistRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/CheckIfUserFollowsPlaylistRequest.java similarity index 67% rename from src/main/java/se/michaelthelin/spotify/requests/data/follow/CheckUsersFollowPlaylistRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/CheckIfUserFollowsPlaylistRequest.java index 951d7aea7..522cb5733 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/CheckUsersFollowPlaylistRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/CheckIfUserFollowsPlaylistRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.Gson; @@ -11,16 +11,19 @@ /** * Check to see if one or more Spotify users are following a specified playlist. + * + * @deprecated This endpoint has been deprecated by Spotify. */ -@JsonDeserialize(builder = CheckUsersFollowPlaylistRequest.Builder.class) -public class CheckUsersFollowPlaylistRequest extends AbstractDataRequest { +@Deprecated +@JsonDeserialize(builder = CheckIfUserFollowsPlaylistRequest.Builder.class) +public class CheckIfUserFollowsPlaylistRequest extends AbstractDataRequest { /** - * The private {@link CheckUsersFollowPlaylistRequest} constructor. + * The private {@link CheckIfUserFollowsPlaylistRequest} constructor. * - * @param builder A {@link CheckUsersFollowPlaylistRequest.Builder}. + * @param builder A {@link CheckIfUserFollowsPlaylistRequest.Builder}. */ - private CheckUsersFollowPlaylistRequest(final Builder builder) { + private CheckIfUserFollowsPlaylistRequest(final Builder builder) { super(builder); } @@ -39,12 +42,12 @@ public Boolean[] execute() throws } /** - * Builder class for building a {@link CheckUsersFollowPlaylistRequest}. + * Builder class for building a {@link CheckIfUserFollowsPlaylistRequest}. */ public static final class Builder extends AbstractDataRequest.Builder { /** - * Create a new {@link CheckUsersFollowPlaylistRequest.Builder} instance. + * Create a new {@link CheckIfUserFollowsPlaylistRequest.Builder} instance. *

* Following a playlist can be done publicly or privately. Checking if a user publicly follows a playlist doesn't * require any scopes; if the user is publicly following the playlist, this endpoint returns {@code true}. @@ -59,27 +62,11 @@ public Builder(final String accessToken) { super(accessToken); } - /** - * The playlists owner ID setter. - * - * @param owner_id The Spotify user ID of the person who owns the playlist. - * @return A {@link CheckUsersFollowPlaylistRequest.Builder}. - * @see Spotify: URIs & IDs - * - * @deprecated since the endpoint no longer needs it. - */ - @Deprecated(since = "8.3.7") - public Builder owner_id(final String owner_id) { - assert (owner_id != null); - assert (!owner_id.isEmpty()); - return setPathParameter("owner_id", owner_id); - } - /** * The playlist ID setter. * * @param playlist_id The Spotify ID of the playlist. - * @return A {@link CheckUsersFollowPlaylistRequest.Builder}. + * @return A {@link CheckIfUserFollowsPlaylistRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder playlist_id(final String playlist_id) { @@ -93,7 +80,7 @@ public Builder playlist_id(final String playlist_id) { * * @param ids Required. A comma-separated list of Spotify User IDs; the ids of the users that you want to check to * see if they follow the playlist. Maximum: 5 ids. - * @return A {@link CheckUsersFollowPlaylistRequest.Builder}. + * @return A {@link CheckIfUserFollowsPlaylistRequest.Builder}. * @see Spotify: URIs & IDs */ public Builder ids(final String ids) { @@ -105,12 +92,12 @@ public Builder ids(final String ids) { /** * The request build method. * - * @return A custom {@link CheckUsersFollowPlaylistRequest}. + * @return A custom {@link CheckIfUserFollowsPlaylistRequest}. */ @Override - public CheckUsersFollowPlaylistRequest build() { + public CheckIfUserFollowsPlaylistRequest build() { setPath("/v1/playlists/{playlist_id}/followers/contains"); - return new CheckUsersFollowPlaylistRequest(this); + return new CheckIfUserFollowsPlaylistRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/FollowArtistsOrUsersRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/FollowArtistsOrUsersRequest.java similarity index 96% rename from src/main/java/se/michaelthelin/spotify/requests/data/follow/FollowArtistsOrUsersRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/FollowArtistsOrUsersRequest.java index 2c4d5c344..efd72f408 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/FollowArtistsOrUsersRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/FollowArtistsOrUsersRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.JsonArray; @@ -12,7 +12,10 @@ /** * Add the current user as a follower of one or more artists or other Spotify users. + * + * @deprecated This endpoint has been deprecated by Spotify. */ +@Deprecated @JsonDeserialize(builder = FollowArtistsOrUsersRequest.Builder.class) public class FollowArtistsOrUsersRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/FollowPlaylistRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/FollowPlaylistRequest.java similarity index 96% rename from src/main/java/se/michaelthelin/spotify/requests/data/follow/FollowPlaylistRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/FollowPlaylistRequest.java index be41d25e1..b1f6e52b4 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/FollowPlaylistRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/FollowPlaylistRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ContentType; @@ -10,7 +10,10 @@ /** * Add the current user as a follower of a playlist. + * + * @deprecated This endpoint has been deprecated by Spotify. */ +@Deprecated @JsonDeserialize(builder = FollowPlaylistRequest.Builder.class) public class FollowPlaylistRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/users_profile/GetCurrentUsersProfileRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetCurrentUsersProfileRequest.java similarity index 97% rename from src/main/java/se/michaelthelin/spotify/requests/data/users_profile/GetCurrentUsersProfileRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/GetCurrentUsersProfileRequest.java index 8d5a4e6e2..6fb556091 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/users_profile/GetCurrentUsersProfileRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetCurrentUsersProfileRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.users_profile; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ParseException; diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/GetUsersFollowedArtistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetFollowedArtistsRequest.java similarity index 76% rename from src/main/java/se/michaelthelin/spotify/requests/data/follow/GetUsersFollowedArtistsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/GetFollowedArtistsRequest.java index e13d39696..04068d927 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/GetUsersFollowedArtistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetFollowedArtistsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ParseException; @@ -14,15 +14,15 @@ /** * Get the current user’s followed artists. */ -@JsonDeserialize(builder = GetUsersFollowedArtistsRequest.Builder.class) -public class GetUsersFollowedArtistsRequest extends AbstractDataRequest> { +@JsonDeserialize(builder = GetFollowedArtistsRequest.Builder.class) +public class GetFollowedArtistsRequest extends AbstractDataRequest> { /** - * The private {@link GetUsersFollowedArtistsRequest} constructor. + * The private {@link GetFollowedArtistsRequest} constructor. * - * @param builder A {@link GetUsersFollowedArtistsRequest.Builder}. + * @param builder A {@link GetFollowedArtistsRequest.Builder}. */ - private GetUsersFollowedArtistsRequest(final Builder builder) { + private GetFollowedArtistsRequest(final Builder builder) { super(builder); } @@ -41,12 +41,12 @@ public PagingCursorbased execute() throws } /** - * Builder class for building a {@link GetUsersFollowedArtistsRequest}. + * Builder class for building a {@link GetFollowedArtistsRequest}. */ public static final class Builder extends AbstractDataPagingCursorbasedRequest.Builder { /** - * Create a new {@link GetUsersFollowedArtistsRequest.Builder} instance. + * Create a new {@link GetFollowedArtistsRequest.Builder} instance. *

* Getting details of the artists or users the current user follows requires authorization of the * {@code user-follow-read} scope. @@ -62,7 +62,7 @@ public Builder(final String accessToken) { * The type setter. * * @param type Required. The ID type: currently only {@code artist} is supported. - * @return A {@link GetUsersFollowedArtistsRequest.Builder}. + * @return A {@link GetFollowedArtistsRequest.Builder}. */ public Builder type(final ModelObjectType type) { assert (type != null); @@ -74,7 +74,7 @@ public Builder type(final ModelObjectType type) { * The limit setter. * * @param limit Optional. The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. - * @return A {@link GetUsersFollowedArtistsRequest.Builder}. + * @return A {@link GetFollowedArtistsRequest.Builder}. */ @Override public Builder limit(final Integer limit) { @@ -87,7 +87,7 @@ public Builder limit(final Integer limit) { * The after value setter. * * @param after Optional. The last artist ID retrieved from the previous request. - * @return A {@link GetUsersFollowedArtistsRequest.Builder}. + * @return A {@link GetFollowedArtistsRequest.Builder}. * @see Spotify: URIs & IDs */ @Override @@ -99,12 +99,12 @@ public Builder after(final String after) { /** * The request build method. * - * @return A custom {@link GetUsersFollowedArtistsRequest}. + * @return A custom {@link GetFollowedArtistsRequest}. */ @Override - public GetUsersFollowedArtistsRequest build() { + public GetFollowedArtistsRequest build() { setPath("/v1/me/following"); - return new GetUsersFollowedArtistsRequest(this); + return new GetFollowedArtistsRequest(this); } @Override diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequest.java new file mode 100644 index 000000000..a897cc846 --- /dev/null +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequest.java @@ -0,0 +1,89 @@ +package se.michaelthelin.spotify.requests.data.users; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.apache.hc.core5.http.ParseException; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.User; +import se.michaelthelin.spotify.requests.data.AbstractDataRequest; + +import java.io.IOException; + +/** + * Get public profile information about a Spotify user. + * + * @deprecated This endpoint is deprecated. + */ +@Deprecated +@JsonDeserialize(builder = GetUsersProfileRequest.Builder.class) +public class GetUsersProfileRequest extends AbstractDataRequest { + + /** + * The private {@link GetUsersProfileRequest} constructor. + * + * @param builder A {@link GetUsersProfileRequest.Builder}. + */ + private GetUsersProfileRequest(final Builder builder) { + super(builder); + } + + /** + * Get the user's profile. + * + * @return A {@link User} object. + * @throws IOException In case of networking issues. + * @throws SpotifyWebApiException The Web API returned an error further specified in this exception's root cause. + */ + public User execute() throws + IOException, + SpotifyWebApiException, + ParseException { + return new User.JsonUtil().createModelObject(getJson()); + } + + /** + * Builder class for building a {@link GetUsersProfileRequest}. + * + * @deprecated This endpoint is deprecated. + */ + @Deprecated + public static final class Builder extends AbstractDataRequest.Builder { + + /** + * Create a new {@link GetUsersProfileRequest.Builder} instance. + * + * @param accessToken Required. A valid access token from the Spotify Accounts service. + */ + public Builder(final String accessToken) { + super(accessToken); + } + + /** + * The user ID path parameter setter. + * + * @param user_id Required. The user's Spotify user ID. + * @return A {@link GetUsersProfileRequest.Builder}. + * @see Spotify: URIs & IDs + */ + public Builder user_id(final String user_id) { + assert (user_id != null); + assert (!user_id.isEmpty()); + return setPathParameter("user_id", user_id); + } + + /** + * The request build method. + * + * @return A custom {@link GetUsersProfileRequest}. + */ + @Override + public GetUsersProfileRequest build() { + setPath("/v1/users/{user_id}"); + return new GetUsersProfileRequest(this); + } + + @Override + protected Builder self() { + return this; + } + } +} diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/GetUsersTopArtistsAndTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetUsersTopArtistsAndTracksRequest.java similarity index 94% rename from src/main/java/se/michaelthelin/spotify/requests/data/personalization/GetUsersTopArtistsAndTracksRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/GetUsersTopArtistsAndTracksRequest.java index 6938ab676..a87577d02 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/GetUsersTopArtistsAndTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/GetUsersTopArtistsAndTracksRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.personalization; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ParseException; @@ -10,9 +10,9 @@ import se.michaelthelin.spotify.model_objects.specification.Track; import se.michaelthelin.spotify.requests.data.AbstractDataPagingRequest; import se.michaelthelin.spotify.requests.data.AbstractDataRequest; -import se.michaelthelin.spotify.requests.data.personalization.interfaces.IArtistTrackModelObject; -import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopArtistsRequest; -import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopTracksRequest; +import se.michaelthelin.spotify.requests.data.users.interfaces.IArtistTrackModelObject; +import se.michaelthelin.spotify.requests.data.users.simplified.GetUsersTopArtistsRequest; +import se.michaelthelin.spotify.requests.data.users.simplified.GetUsersTopTracksRequest; import java.io.IOException; diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/UnfollowArtistsOrUsersRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/UnfollowArtistsOrUsersRequest.java similarity index 96% rename from src/main/java/se/michaelthelin/spotify/requests/data/follow/UnfollowArtistsOrUsersRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/UnfollowArtistsOrUsersRequest.java index 72dcb63ce..f12f198cf 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/UnfollowArtistsOrUsersRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/UnfollowArtistsOrUsersRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.gson.JsonArray; @@ -12,7 +12,10 @@ /** * Remove the current user as a follower of one or more artists or other Spotify users. + * + * @deprecated This endpoint has been deprecated by Spotify. */ +@Deprecated @JsonDeserialize(builder = UnfollowArtistsOrUsersRequest.Builder.class) public class UnfollowArtistsOrUsersRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/follow/UnfollowPlaylistRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/UnfollowPlaylistRequest.java similarity index 95% rename from src/main/java/se/michaelthelin/spotify/requests/data/follow/UnfollowPlaylistRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/UnfollowPlaylistRequest.java index 47c282036..c3f90692b 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/follow/UnfollowPlaylistRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/UnfollowPlaylistRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ParseException; @@ -9,7 +9,10 @@ /** * Remove the current user as a follower of a playlist. + * + * @deprecated This endpoint has been deprecated by Spotify. */ +@Deprecated @JsonDeserialize(builder = UnfollowPlaylistRequest.Builder.class) public class UnfollowPlaylistRequest extends AbstractDataRequest { diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/interfaces/IArtistTrackModelObject.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/interfaces/IArtistTrackModelObject.java similarity index 81% rename from src/main/java/se/michaelthelin/spotify/requests/data/personalization/interfaces/IArtistTrackModelObject.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/interfaces/IArtistTrackModelObject.java index f074f959c..2a3bbabcb 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/interfaces/IArtistTrackModelObject.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/interfaces/IArtistTrackModelObject.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.personalization.interfaces; +package se.michaelthelin.spotify.requests.data.users.interfaces; import se.michaelthelin.spotify.model_objects.IModelObject; diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopArtistsRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopArtistsRequest.java similarity index 98% rename from src/main/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopArtistsRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopArtistsRequest.java index 5103a8f73..b4c184528 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopArtistsRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopArtistsRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.personalization.simplified; +package se.michaelthelin.spotify.requests.data.users.simplified; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ParseException; diff --git a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopTracksRequest.java b/src/main/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopTracksRequest.java similarity index 98% rename from src/main/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopTracksRequest.java rename to src/main/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopTracksRequest.java index b489177b2..a9b6044cb 100644 --- a/src/main/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopTracksRequest.java +++ b/src/main/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopTracksRequest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.personalization.simplified; +package se.michaelthelin.spotify.requests.data.users.simplified; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.hc.core5.http.ParseException; diff --git a/src/test/fixtures/open-api-schema.yaml b/src/test/fixtures/open-api-schema.yaml new file mode 100644 index 000000000..e1d766c6c --- /dev/null +++ b/src/test/fixtures/open-api-schema.yaml @@ -0,0 +1,7523 @@ +openapi: '3.0.3' +info: + description: | + You can use Spotify's Web API to discover music and podcasts, manage your Spotify library, control audio playback, and much more. Browse our available Web API endpoints using the sidebar at left, or via the navigation bar on top of this page on smaller screens. + + In order to make successful Web API requests your app will need a valid access token. One can be obtained through OAuth 2.0. + + The base URI for all Web API requests is `https://api.spotify.com/v1`. + + Need help? See our Web API guides for more information, or visit the Spotify for Developers community forum to ask questions and connect with other developers. + version: '1.0.0' + title: 'Spotify Web API' + termsOfService: 'https://developer.spotify.com/terms/' + contact: + name: Spotify for Developers Community + url: https://community.spotify.com/t5/Spotify-for-Developers/bd-p/Spotify_Developer +servers: + - url: https://api.spotify.com/v1 +tags: + - name: Albums + - name: Artists + - name: Audiobooks + - name: Categories + - name: Chapters + - name: Episodes + - name: Library + - name: Genres + - name: Markets + - name: Player + - name: Playlists + - name: Search + - name: Shows + - name: Tracks + - name: Users +paths: + /albums/{id}: + get: + operationId: get-an-album + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Albums + summary: | + Get Album + description: | + Get Spotify catalog information for a single album. + parameters: + - $ref: '#/components/parameters/PathAlbumId' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/OneAlbum' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /albums: + get: + deprecated: true + operationId: get-multiple-albums + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Albums + summary: | + Get Several Albums + description: | + Get Spotify catalog information for multiple albums identified by their Spotify IDs. + parameters: + - $ref: '#/components/parameters/QueryAlbumIds' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/ManyAlbums' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /albums/{id}/tracks: + get: + operationId: get-an-albums-tracks + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Albums + - Tracks + summary: | + Get Album Tracks + description: | + Get Spotify catalog information about an album’s tracks. + Optional parameters can be used to limit the number of tracks returned. + parameters: + - $ref: '#/components/parameters/PathAlbumId' + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingSimplifiedTrackObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /artists/{id}: + get: + tags: + - Artists + operationId: get-an-artist + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Artist + description: | + Get Spotify catalog information for a single artist identified by their unique Spotify ID. + parameters: + - $ref: '#/components/parameters/PathArtistId' + responses: + '200': + $ref: '#/components/responses/OneArtist' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /artists: + get: + deprecated: true + tags: + - Artists + operationId: get-multiple-artists + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Several Artists + description: | + Get Spotify catalog information for several artists based on their Spotify IDs. + parameters: + - name: ids + required: true + in: query + schema: + title: Spotify Artist IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) for the artists. Maximum: 50 IDs. + example: 2CIMQHirSU0MQqyYHq0eOx,57dN52uHvrHOxijzpIgu3E,1vCWHaC5f2uS3yhpwWbIA6 + type: string + responses: + '200': + $ref: '#/components/responses/ManyArtists' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /artists/{id}/albums: + get: + tags: + - Artists + - Albums + operationId: get-an-artists-albums + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Artist's Albums + description: | + Get Spotify catalog information about an artist's albums. + parameters: + - $ref: '#/components/parameters/PathArtistId' + - $ref: '#/components/parameters/QueryIncludeGroups' + - $ref: '#/components/parameters/QueryMarket' + - name: limit + required: false + in: query + schema: + title: Limit + description: | + The maximum number of items to return. Default: 5. Minimum: 1. Maximum: 10. + default: 5 + example: 5 + type: integer + minimum: 0 + maximum: 10 + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingArtistDiscographyAlbumObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /artists/{id}/top-tracks: + get: + deprecated: true + tags: + - Artists + - Tracks + operationId: get-an-artists-top-tracks + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Artist's Top Tracks + description: | + Get Spotify catalog information about an artist's top tracks by country. + parameters: + - $ref: '#/components/parameters/PathArtistId' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/ManyTracks' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /artists/{id}/related-artists: + get: + deprecated: true + tags: + - Artists + operationId: get-an-artists-related-artists + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Artist's Related Artists + description: | + Get Spotify catalog information about artists similar to a given artist. Similarity is based on analysis of the Spotify community's listening history. + parameters: + - $ref: '#/components/parameters/PathArtistId' + responses: + '200': + $ref: '#/components/responses/ManyArtists' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /shows/{id}: + get: + tags: + - Shows + operationId: get-a-show + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Show + description: | + Get Spotify catalog information for a single show identified by its + unique Spotify ID. + parameters: + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/PathShowId' + responses: + '200': + $ref: '#/components/responses/OneShow' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-playback-position + /shows: + get: + deprecated: true + tags: + - Shows + operationId: get-multiple-shows + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Several Shows + description: | + Get Spotify catalog information for several shows based on their Spotify IDs. + parameters: + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryShowIds' + responses: + '200': + $ref: '#/components/responses/ManySimplifiedShows' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /shows/{id}/episodes: + get: + tags: + - Shows + - Episodes + operationId: get-a-shows-episodes + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Show Episodes + description: | + Get Spotify catalog information about an show’s episodes. Optional parameters can be used to limit the number of episodes returned. + parameters: + - $ref: '#/components/parameters/PathShowId' + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingSimplifiedEpisodeObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-playback-position + /episodes/{id}: + get: + tags: + - Episodes + operationId: get-an-episode + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Episode + description: | + Get Spotify catalog information for a single episode identified by its + unique Spotify ID. + parameters: + - name: id + required: true + in: path + schema: + title: Get an Episode + description: + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) + for the episode. + example: 512ojhOuo1ktJprKbVcKyQ + type: string + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/OneEpisode' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-playback-position + /episodes: + get: + deprecated: true + tags: + - Episodes + operationId: get-multiple-episodes + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + summary: | + Get Several Episodes + description: | + Get Spotify catalog information for several episodes based on their Spotify IDs. + parameters: + - name: ids + required: true + in: query + schema: + title: Ids + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) for the episodes. Maximum: 50 IDs. + example: 77o6BIVlYM3msb4MMIL1jH,0Q86acNRm6V9GYx55SXKwf + type: string + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/ManyEpisodes' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-playback-position + /audiobooks/{id}: + get: + operationId: get-an-audiobook + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Audiobooks + summary: | + Get an Audiobook + description: | + Get Spotify catalog information for a single audiobook. Audiobooks are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets. + parameters: + - $ref: '#/components/parameters/PathAudiobookId' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/OneAudiobook' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /audiobooks: + get: + deprecated: true + operationId: get-multiple-audiobooks + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Audiobooks + summary: | + Get Several Audiobooks + description: | + Get Spotify catalog information for several audiobooks identified by their Spotify IDs. Audiobooks are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets. + parameters: + - $ref: '#/components/parameters/QueryAudiobookIds' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/ManyAudiobooks' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /audiobooks/{id}/chapters: + get: + operationId: get-audiobook-chapters + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Audiobooks + - Chapters + summary: | + Get Audiobook Chapters + description: | + Get Spotify catalog information about an audiobook's chapters. Audiobooks are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets. + parameters: + - $ref: '#/components/parameters/PathAudiobookId' + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingSimplifiedChapterObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /me/audiobooks: + get: + tags: + - Audiobooks + - Library + operationId: get-users-saved-audiobooks + summary: | + Get User's Saved Audiobooks + description: | + Get a list of the audiobooks saved in the current Spotify user's 'Your Music' library. + parameters: + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingSimplifiedAudiobookObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + put: + deprecated: true + tags: + - Audiobooks + - Library + operationId: save-audiobooks-user + summary: | + Save Audiobooks for Current User + description: | + Save one or more audiobooks to the current Spotify user's library. + + **Note:** This endpoint is deprecated. Use [Save Items to Library](/documentation/web-api/reference/save-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryAudiobookIds' + responses: + '200': + description: Audiobook(s) are saved to the library + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + delete: + deprecated: true + tags: + - Audiobooks + - Library + operationId: remove-audiobooks-user + summary: | + Remove User's Saved Audiobooks + description: | + Remove one or more audiobooks from the Spotify user's library. + + **Note:** This endpoint is deprecated. Use [Remove Items from Library](/documentation/web-api/reference/remove-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryAudiobookIds' + responses: + '200': + description: Audiobook(s) have been removed from the library + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + /me/audiobooks/contains: + get: + tags: + - Audiobooks + - Library + operationId: check-users-saved-audiobooks + summary: | + Check User's Saved Audiobooks + deprecated: true + description: | + Check if one or more audiobooks are already saved in the current Spotify user's library. + + **Note:** This endpoint is deprecated. Use [Check User's Saved Items](/documentation/web-api/reference/check-library-contains) instead. + parameters: + - $ref: '#/components/parameters/QueryAudiobookIds' + responses: + '200': + $ref: '#/components/responses/ArrayOfBooleans' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + /chapters/{id}: + get: + operationId: get-a-chapter + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Chapters + summary: | + Get a Chapter + description: | + Get Spotify catalog information for a single audiobook chapter. Chapters are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets. + parameters: + - $ref: '#/components/parameters/PathChapterId' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/OneChapter' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /chapters: + get: + deprecated: true + operationId: get-several-chapters + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataPolicyList' + tags: + - Chapters + summary: | + Get Several Chapters + description: | + Get Spotify catalog information for several audiobook chapters identified by their Spotify IDs. Chapters are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets. + parameters: + - $ref: '#/components/parameters/QueryChapterIds' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/ManyChapters' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /tracks/{id}: + get: + tags: + - Tracks + operationId: get-track + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataWithMachineLearningPolicyList' + summary: | + Get Track + description: | + Get Spotify catalog information for a single track identified by its + unique Spotify ID. + parameters: + - name: id + required: true + in: path + schema: + title: Spotify Track ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) + for the track. + example: 11dFghVXANMlKmJXsNCbNl + type: string + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/OneTrack' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /tracks: + get: + deprecated: true + tags: + - Tracks + operationId: get-several-tracks + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataWithMachineLearningPolicyList' + summary: | + Get Several Tracks + description: | + Get Spotify catalog information for multiple tracks based on their Spotify IDs. + parameters: + - $ref: '#/components/parameters/QueryMarket' + - name: ids + required: true + in: query + schema: + title: Spotify Track IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `ids=4iV5W9uYEdYUVa79Axb7Rh,1301WleyT98MSxVHPZCA6M`. Maximum: 50 IDs. + example: 7ouMYWpwJ422jRcDASZB7P,4VqPOruhp5EdPBeR92t6lQ,2takcwOaAZWiXQijPHIx7B + type: string + responses: + '200': + $ref: '#/components/responses/ManyTracks' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /search: + get: + tags: + - Search + operationId: search + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/MachineLearning' + summary: | + Search for Item + description: | + Get Spotify catalog information about albums, artists, playlists, tracks, shows, episodes or audiobooks + that match a keyword string. Audiobooks are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets. + parameters: + - name: q + required: true + in: query + schema: + title: Query + description: | + Your search query. + + You can narrow down your search using field filters. The available filters are `album`, `artist`, `track`, `year`, `upc`, `tag:hipster`, `tag:new`, `isrc`, and `genre`. Each field filter only applies to certain result types. + + The `artist` and `year` filters can be used while searching albums, artists and tracks. You can filter on a single `year` or a range (e.g. 1955-1960).
+ The `album` filter can be used while searching albums and tracks.
+ The `genre` filter can be used while searching artists and tracks.
+ The `isrc` and `track` filters can be used while searching tracks.
+ The `upc`, `tag:new` and `tag:hipster` filters can only be used while searching albums. The `tag:new` filter will return albums released in the past two weeks and `tag:hipster` can be used to return only albums with the lowest 10% popularity.
+ + example: remaster%20track:Doxy%20artist:Miles%20Davis + type: string + - name: type + required: true + explode: false + in: query + schema: + title: Item type + description: | + A comma-separated list of item types to search across. Search results include hits + from all the specified item types. For example: `q=abacab&type=album,track` returns + both albums and tracks matching "abacab". + items: + type: string + enum: + - album + - artist + - playlist + - track + - show + - episode + - audiobook + type: array + - $ref: '#/components/parameters/QueryMarket' + - name: limit + required: false + in: query + schema: + title: Limit + description: | + The maximum number of results to return in each item type. + default: 5 + example: 10 + type: integer + minimum: 0 + maximum: 10 + - name: offset + required: false + in: query + schema: + title: Offset + description: | + The index of the first result to return. Use + with limit to get the next page of search results. + default: 0 + minimum: 0 + maximum: 1000 + example: 5 + type: integer + - name: include_external + required: false + in: query + schema: + title: Include External + description: | + If `include_external=audio` is specified it signals that the client can play externally hosted audio content, and marks + the content as playable in the response. By default externally hosted audio content is marked as unplayable in the response. + type: string + enum: + - audio + responses: + '200': + $ref: '#/components/responses/SearchItems' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /me: + get: + tags: + - Users + operationId: get-current-users-profile + summary: | + Get Current User's Profile + description: | + Get detailed profile information about the current user (including the + current user's username). + responses: + '200': + $ref: '#/components/responses/OnePrivateUser' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-private + - user-read-email + /playlists/{playlist_id}: + get: + tags: + - Playlists + operationId: get-playlist + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataWithMachineLearningPolicyList' + summary: | + Get Playlist + description: | + Get a playlist owned by a Spotify user. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - $ref: '#/components/parameters/QueryMarket' + - name: fields + required: false + in: query + schema: + title: Fields + description: | + Filters for the query: a comma-separated list of the + fields to return. If omitted, all fields are returned. For example, to get + just the playlist''s description and URI: `fields=description,uri`. A dot + separator can be used to specify non-reoccurring fields, while parentheses + can be used to specify reoccurring fields within objects. For example, to + get just the added date and user ID of the adder: `fields=tracks.items(added_at,added_by.id)`. + Use multiple parentheses to drill down into nested objects, for example: `fields=tracks.items(track(name,href,album(name,href)))`. + Fields can be excluded by prefixing them with an exclamation mark, for example: + `fields=tracks.items(track(name,href,album(!name,href)))` + example: items(added_by.id,track(name,href,album(name,href))) + type: string + - $ref: '#/components/parameters/QueryAdditionalTypes' + responses: + '200': + $ref: '#/components/responses/OnePlaylist' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + put: + tags: + - Playlists + - Library + operationId: change-playlist-details + summary: | + Change Playlist Details + description: | + Change a playlist's name and public/private state. (The user must, of + course, own the playlist.) + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + requestBody: + content: + application/json: + schema: + example: + name: Updated Playlist Name + description: Updated playlist description + public: false + type: object + additionalProperties: true + properties: + name: + type: string + description: | + The new name for the playlist, for example `"My New Playlist Title"` + public: + type: boolean + description: | + The playlist's public/private status (if it should be added to the user's profile or not): `true` the playlist will be public, `false` the playlist will be private, `null` the playlist status is not relevant. For more about public/private status, see [Working with Playlists](/documentation/web-api/concepts/playlists) + collaborative: + type: boolean + description: | + If `true`, the playlist will become collaborative and other users will be able to modify the playlist in their Spotify client.
+ _**Note**: You can only set `collaborative` to `true` on non-public playlists._ + description: + type: string + description: | + Value for playlist description as displayed in Spotify Clients and in the Web API. + responses: + '200': + description: Playlist updated + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + /playlists/{playlist_id}/tracks: + get: + tags: + - Playlists + - Tracks + operationId: get-playlists-tracks + deprecated: true + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataWithMachineLearningPolicyList' + summary: | + Get Playlist Items [DEPRECATED] + description: | + **Deprecated:** Use [Get Playlist Items](/documentation/web-api/reference/get-playlists-items) instead. + + Get full details of the items of a playlist owned by a Spotify user. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - $ref: '#/components/parameters/QueryMarket' + - name: fields + required: false + in: query + schema: + title: Fields + description: | + Filters for the query: a comma-separated list of the + fields to return. If omitted, all fields are returned. For example, to get + just the total number of items and the request limit:
`fields=total,limit`
A + dot separator can be used to specify non-reoccurring fields, while parentheses + can be used to specify reoccurring fields within objects. For example, to + get just the added date and user ID of the adder:
`fields=items(added_at,added_by.id)`
Use + multiple parentheses to drill down into nested objects, for example:
`fields=items(track(name,href,album(name,href)))`
Fields + can be excluded by prefixing them with an exclamation mark, for example:
`fields=items.track.album(!external_urls,images)` + example: items(added_by.id,track(name,href,album(name,href))) + type: string + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + - $ref: '#/components/parameters/QueryAdditionalTypes' + responses: + '200': + $ref: '#/components/responses/PagingPlaylistTrackObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-read-private + post: + tags: + - Playlists + - Tracks + operationId: add-tracks-to-playlist + deprecated: true + summary: | + Add Items to Playlist [DEPRECATED] + description: | + **Deprecated:** Use [Add Items to Playlist](/documentation/web-api/reference/add-items-to-playlist) instead. + + Add one or more items to a user's playlist. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - name: position + required: false + in: query + schema: + title: Position (append by default) + description: | + The position to insert the items, a zero-based index. For example, to insert the items in the first position: `position=0`; to insert the items in the third position: `position=2`. If omitted, the items will be appended to the playlist. Items are added in the order they are listed in the query string or request body. + example: 0 + type: integer + - name: uris + required: false + in: query + schema: + title: Spotify Track URIs + description: | + A comma-separated list of [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) to add, can be track or episode URIs. For example:
`uris=spotify:track:4iV5W9uYEdYUVa79Axb7Rh, spotify:track:1301WleyT98MSxVHPZCA6M, spotify:episode:512ojhOuo1ktJprKbVcKyQ`
A maximum of 100 items can be added in one request.
+ _**Note**: it is likely that passing a large number of item URIs as a query parameter will exceed the maximum length of the request URI. When adding a large number of items, it is recommended to pass them in the request body, see below._ + example: spotify:track:4iV5W9uYEdYUVa79Axb7Rh,spotify:track:1301WleyT98MSxVHPZCA6M + type: string + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + uris: + description: | + A JSON array of the [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) to add. For example: `{"uris": ["spotify:track:4iV5W9uYEdYUVa79Axb7Rh","spotify:track:1301WleyT98MSxVHPZCA6M", "spotify:episode:512ojhOuo1ktJprKbVcKyQ"]}`
A maximum of 100 items can be added in one request. _**Note**: if the `uris` parameter is present in the query string, any URIs listed here in the body will be ignored._ + type: array + items: + type: string + position: + description: | + The position to insert the items, a zero-based index. For example, to insert the items in the first position: `position=0` ; to insert the items in the third position: `position=2`. If omitted, the items will be appended to the playlist. Items are added in the order they appear in the uris array. For example: `{"uris": ["spotify:track:4iV5W9uYEdYUVa79Axb7Rh","spotify:track:1301WleyT98MSxVHPZCA6M"], "position": 3}` + type: integer + responses: + '201': + $ref: '#/components/responses/PlaylistSnapshotId' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + put: + tags: + - Playlists + - Tracks + operationId: reorder-or-replace-playlists-tracks + deprecated: true + summary: | + Update Playlist Items [DEPRECATED] + description: | + **Deprecated:** Use [Update Playlist Items](/documentation/web-api/reference/reorder-or-replace-playlists-items) instead. + + Either reorder or replace items in a playlist depending on the request's parameters. + To reorder items, include `range_start`, `insert_before`, `range_length` and `snapshot_id` in the request's body. + To replace items, include `uris` as either a query parameter or in the request's body. + Replacing items in a playlist will overwrite its existing items. This operation can be used for replacing or clearing items in a playlist. +
+ **Note**: Replace and reorder are mutually exclusive operations which share the same endpoint, but have different parameters. + These operations can't be applied together in a single request. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - name: uris + required: false + in: query + schema: + title: Spotify Track URIs + description: | + A comma-separated list of [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) to set, can be track or episode URIs. For example: `uris=spotify:track:4iV5W9uYEdYUVa79Axb7Rh,spotify:track:1301WleyT98MSxVHPZCA6M,spotify:episode:512ojhOuo1ktJprKbVcKyQ`
A maximum of 100 items can be set in one request. + type: string + requestBody: + content: + application/json: + schema: + example: + range_start: 1 + insert_before: 3 + range_length: 2 + type: object + additionalProperties: true + properties: + uris: + type: array + items: + type: string + range_start: + type: integer + description: | + The position of the first item to be reordered. + insert_before: + type: integer + description: | + The position where the items should be inserted.
To reorder the items to the end of the playlist, simply set _insert_before_ to the position after the last item.
Examples:
To reorder the first item to the last position in a playlist with 10 items, set _range_start_ to 0, and _insert_before_ to 10.
To reorder the last item in a playlist with 10 items to the start of the playlist, set _range_start_ to 9, and _insert_before_ to 0. + range_length: + type: integer + description: | + The amount of items to be reordered. Defaults to 1 if not set.
The range of items to be reordered begins from the _range_start_ position, and includes the _range_length_ subsequent items.
Example:
To move the items at index 9-10 to the start of the playlist, _range_start_ is set to 9, and _range_length_ is set to 2. + snapshot_id: + type: string + description: | + The playlist's snapshot ID against which you want to make the changes. + responses: + '200': + $ref: '#/components/responses/PlaylistSnapshotId' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + delete: + tags: + - Playlists + - Tracks + operationId: remove-tracks-playlist + deprecated: true + summary: | + Remove Playlist Items [DEPRECATED] + description: | + **Deprecated:** Use [Remove Playlist Items](/documentation/web-api/reference/remove-items-playlist) instead. + + Remove one or more items from a user's playlist. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + requestBody: # Request body in DELETE is allowed, but discouraged (https://github.com/OAI/OpenAPI-Specification/pull/2117). + content: + application/json: + schema: + type: object + required: + - tracks + properties: + tracks: + type: array + description: | + An array of objects containing [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) of the tracks or episodes to remove. + For example: `{ "tracks": [{ "uri": "spotify:track:4iV5W9uYEdYUVa79Axb7Rh" },{ "uri": "spotify:track:1301WleyT98MSxVHPZCA6M" }] }`. A maximum of 100 objects can be sent at once. + items: + type: object + properties: + uri: + type: string + description: Spotify URI + snapshot_id: + type: string + description: | + The playlist's snapshot ID against which you want to make the changes. + The API will validate that the specified items exist and in the specified positions and make the changes, + even if more recent changes have been made to the playlist. + responses: + '200': + $ref: '#/components/responses/PlaylistSnapshotId' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + /playlists/{playlist_id}/items: + get: + tags: + - Playlists + - Tracks + operationId: get-playlists-items + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataWithMachineLearningPolicyList' + summary: | + Get Playlist Items + description: | + Get full details of the items of a playlist owned by a Spotify user. + + **Note**: This endpoint is only accessible for playlists owned by the current user or playlists the user is a collaborator of. A `403 Forbidden` status code will be returned if the user is neither the owner nor a collaborator of the playlist. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - $ref: '#/components/parameters/QueryMarket' + - name: fields + required: false + in: query + schema: + title: Fields + description: | + Filters for the query: a comma-separated list of the + fields to return. If omitted, all fields are returned. For example, to get + just the total number of items and the request limit:
`fields=total,limit`
A + dot separator can be used to specify non-reoccurring fields, while parentheses + can be used to specify reoccurring fields within objects. For example, to + get just the added date and user ID of the adder:
`fields=items(added_at,added_by.id)`
Use + multiple parentheses to drill down into nested objects, for example:
`fields=items(track(name,href,album(name,href)))`
Fields + can be excluded by prefixing them with an exclamation mark, for example:
`fields=items.track.album(!external_urls,images)` + example: items(added_by.id,track(name,href,album(name,href))) + type: string + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + - $ref: '#/components/parameters/QueryAdditionalTypes' + responses: + '200': + $ref: '#/components/responses/PagingPlaylistTrackObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-read-private + post: + tags: + - Playlists + - Tracks + operationId: add-items-to-playlist + summary: | + Add Items to Playlist + description: | + Add one or more items to a user's playlist. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - name: position + required: false + in: query + schema: + title: Position (append by default) + description: | + The position to insert the items, a zero-based index. For example, to insert the items in the first position: `position=0`; to insert the items in the third position: `position=2`. If omitted, the items will be appended to the playlist. Items are added in the order they are listed in the query string or request body. + example: 0 + type: integer + - name: uris + required: false + in: query + schema: + title: Spotify Track URIs + description: | + A comma-separated list of [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) to add, can be track or episode URIs. For example:
`uris=spotify:track:4iV5W9uYEdYUVa79Axb7Rh, spotify:track:1301WleyT98MSxVHPZCA6M, spotify:episode:512ojhOuo1ktJprKbVcKyQ`
A maximum of 100 items can be added in one request.
+ _**Note**: it is likely that passing a large number of item URIs as a query parameter will exceed the maximum length of the request URI. When adding a large number of items, it is recommended to pass them in the request body, see below._ + example: spotify:track:4iV5W9uYEdYUVa79Axb7Rh,spotify:track:1301WleyT98MSxVHPZCA6M + type: string + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + uris: + description: | + A JSON array of the [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) to add. For example: `{"uris": ["spotify:track:4iV5W9uYEdYUVa79Axb7Rh","spotify:track:1301WleyT98MSxVHPZCA6M", "spotify:episode:512ojhOuo1ktJprKbVcKyQ"]}`
A maximum of 100 items can be added in one request. _**Note**: if the `uris` parameter is present in the query string, any URIs listed here in the body will be ignored._ + type: array + items: + type: string + position: + description: | + The position to insert the items, a zero-based index. For example, to insert the items in the first position: `position=0` ; to insert the items in the third position: `position=2`. If omitted, the items will be appended to the playlist. Items are added in the order they appear in the uris array. For example: `{"uris": ["spotify:track:4iV5W9uYEdYUVa79Axb7Rh","spotify:track:1301WleyT98MSxVHPZCA6M"], "position": 3}` + type: integer + responses: + '201': + $ref: '#/components/responses/PlaylistSnapshotId' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + put: + tags: + - Playlists + - Tracks + operationId: reorder-or-replace-playlists-items + summary: | + Update Playlist Items + description: | + Either reorder or replace items in a playlist depending on the request's parameters. + To reorder items, include `range_start`, `insert_before`, `range_length` and `snapshot_id` in the request's body. + To replace items, include `uris` as either a query parameter or in the request's body. + Replacing items in a playlist will overwrite its existing items. This operation can be used for replacing or clearing items in a playlist. +
+ **Note**: Replace and reorder are mutually exclusive operations which share the same endpoint, but have different parameters. + These operations can't be applied together in a single request. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - name: uris + required: false + in: query + schema: + title: Spotify Track URIs + description: | + A comma-separated list of [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) to set, can be track or episode URIs. For example: `uris=spotify:track:4iV5W9uYEdYUVa79Axb7Rh,spotify:track:1301WleyT98MSxVHPZCA6M,spotify:episode:512ojhOuo1ktJprKbVcKyQ`
A maximum of 100 items can be set in one request. + type: string + requestBody: + content: + application/json: + schema: + example: + range_start: 1 + insert_before: 3 + range_length: 2 + type: object + additionalProperties: true + properties: + uris: + type: array + items: + type: string + range_start: + type: integer + description: | + The position of the first item to be reordered. + insert_before: + type: integer + description: | + The position where the items should be inserted.
To reorder the items to the end of the playlist, simply set _insert_before_ to the position after the last item.
Examples:
To reorder the first item to the last position in a playlist with 10 items, set _range_start_ to 0, and _insert_before_ to 10.
To reorder the last item in a playlist with 10 items to the start of the playlist, set _range_start_ to 9, and _insert_before_ to 0. + range_length: + type: integer + description: | + The amount of items to be reordered. Defaults to 1 if not set.
The range of items to be reordered begins from the _range_start_ position, and includes the _range_length_ subsequent items.
Example:
To move the items at index 9-10 to the start of the playlist, _range_start_ is set to 9, and _range_length_ is set to 2. + snapshot_id: + type: string + description: | + The playlist's snapshot ID against which you want to make the changes. + responses: + '200': + $ref: '#/components/responses/PlaylistSnapshotId' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + delete: + tags: + - Playlists + - Tracks + operationId: remove-items-playlist + summary: | + Remove Playlist Items + description: | + Remove one or more items from a user's playlist. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + requestBody: + content: + application/json: + schema: + type: object + required: + - items + properties: + items: + type: array + description: | + An array of objects containing [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids) of the tracks or episodes to remove. + For example: `{ "items": [{ "uri": "spotify:track:4iV5W9uYEdYUVa79Axb7Rh" },{ "uri": "spotify:track:1301WleyT98MSxVHPZCA6M" }] }`. A maximum of 100 objects can be sent at once. + items: + type: object + properties: + uri: + type: string + description: Spotify URI + snapshot_id: + type: string + description: | + The playlist's snapshot ID against which you want to make the changes. + The API will validate that the specified items exist and in the specified positions and make the changes, + even if more recent changes have been made to the playlist. + responses: + '200': + $ref: '#/components/responses/PlaylistSnapshotId' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + /me/playlists: + get: + tags: + - Playlists + - Library + operationId: get-a-list-of-current-users-playlists + summary: | + Get Current User's Playlists + description: | + Get a list of the playlists owned or followed by the current Spotify + user. + parameters: + - $ref: '#/components/parameters/QueryLimit' + - name: offset + required: false + in: query + schema: + title: Offset + description: | + 'The index of the first playlist to return. Default: + 0 (the first object). Maximum offset: 100.000\. Use with `limit` to get the + next set of playlists.' + default: 0 + example: 5 + type: integer + responses: + '200': + $ref: '#/components/responses/PagedPlaylists' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-read-private + post: + tags: + - Playlists + - Library + operationId: create-playlist + summary: | + Create Playlist + description: | + Create a playlist for the current Spotify user. (The playlist will be empty until + you [add tracks](/documentation/web-api/reference/add-tracks-to-playlist).) + Each user is generally limited to a maximum of 11000 playlists. + requestBody: + content: + application/json: + schema: + example: + name: New Playlist + description: New playlist description + public: false + type: object + additionalProperties: true + required: + - name + properties: + name: + type: string + description: | + The name for the new playlist, for example `"Your Coolest Playlist"`. This name does not need to be unique; a user may have several playlists with the same name. + public: + type: boolean + description: | + Defaults to `true`. The playlist's public/private status (if it should be added to the user's profile or not): `true` the playlist will be public, `false` the playlist will be private. To be able to create private playlists, the user must have granted the `playlist-modify-private` [scope](/documentation/web-api/concepts/scopes/#list-of-scopes). For more about public/private status, see [Working with Playlists](/documentation/web-api/concepts/playlists) + collaborative: + type: boolean + description: | + Defaults to `false`. If `true` the playlist will be collaborative. _**Note**: to create a collaborative playlist you must also set `public` to `false`. To create collaborative playlists you must have granted `playlist-modify-private` and `playlist-modify-public` [scopes](/documentation/web-api/concepts/scopes/#list-of-scopes)._ + description: + type: string + description: | + value for playlist description as displayed in Spotify Clients and in the Web API. + responses: + '201': + $ref: '#/components/responses/OnePlaylist' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + /me/library: + put: + tags: + - Library + operationId: save-library-items + summary: | + Save Items to Library + description: | + Add one or more items to the current user's library. Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, users, and playlists. + parameters: + - name: uris + required: true + in: query + schema: + title: Spotify URIs + description: | + A comma-separated list of [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids). Maximum: 40 URIs. + + Supported URI types: + - `spotify:track:{id}` + - `spotify:album:{id}` + - `spotify:episode:{id}` + - `spotify:show:{id}` + - `spotify:audiobook:{id}` + - `spotify:user:{id}` + - `spotify:playlist:{id}` + example: spotify:track:7a3LWj5xSFhFRYmztS8wgK,spotify:album:4aawyAB9vmqN3uQ7FjRGTy + type: string + responses: + '200': + description: Items saved to library + '400': + description: | + Bad Request. Possible reasons: missing `uris` parameter, invalid URI format, unsupported URI type, or more than 40 URIs provided. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + - user-follow-modify + - playlist-modify-public + delete: + tags: + - Library + operationId: remove-library-items + summary: | + Remove Items from Library + description: | + Remove one or more items from the current user's library. Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, users, and playlists. + parameters: + - name: uris + required: true + in: query + schema: + title: Spotify URIs + description: | + A comma-separated list of [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids). Maximum: 40 URIs. + + Supported URI types: + - `spotify:track:{id}` + - `spotify:album:{id}` + - `spotify:episode:{id}` + - `spotify:show:{id}` + - `spotify:audiobook:{id}` + - `spotify:user:{id}` + - `spotify:playlist:{id}` + example: spotify:track:7a3LWj5xSFhFRYmztS8wgK,spotify:album:4aawyAB9vmqN3uQ7FjRGTy + type: string + responses: + '200': + description: Items removed from library + '400': + description: | + Bad Request. Possible reasons: missing `uris` parameter, invalid URI format, unsupported URI type, or more than 40 URIs provided. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + - user-follow-modify + - playlist-modify-public + /me/library/contains: + get: + tags: + - Library + operationId: check-library-contains + summary: | + Check User's Saved Items + description: | + Check if one or more items are already saved in the current user's library. Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, artists, users, and playlists. + parameters: + - name: uris + required: true + in: query + schema: + title: Spotify URIs + description: | + A comma-separated list of [Spotify URIs](/documentation/web-api/concepts/spotify-uris-ids). Maximum: 40 URIs. + + Supported URI types: + - `spotify:track:{id}` + - `spotify:album:{id}` + - `spotify:episode:{id}` + - `spotify:show:{id}` + - `spotify:audiobook:{id}` + - `spotify:artist:{id}` + - `spotify:user:{id}` + - `spotify:playlist:{id}` + example: spotify:track:7a3LWj5xSFhFRYmztS8wgK,spotify:album:4aawyAB9vmqN3uQ7FjRGTy,spotify:artist:2takcwOaAZWiXQijPHIx7B + type: string + responses: + '200': + $ref: '#/components/responses/ArrayOfBooleans' + '400': + description: | + Bad Request. Possible reasons: missing `uris` parameter, invalid URI format, unsupported URI type, or more than 40 URIs provided. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + - user-follow-read + - playlist-read-private + /me/albums: + get: + tags: + - Albums + - Library + operationId: get-users-saved-albums + summary: | + Get User's Saved Albums + description: | + Get a list of the albums saved in the current Spotify user's 'Your Music' library. + parameters: + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + $ref: '#/components/responses/PagingSavedAlbumObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + put: + deprecated: true + tags: + - Albums + - Library + operationId: save-albums-user + summary: | + Save Albums for Current User + description: | + Save one or more albums to the current user's 'Your Music' library. + + **Note:** This endpoint is deprecated. Use [Save Items to Library](/documentation/web-api/reference/save-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryAlbumIds' + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + ids: + type: array + description: | + A JSON array of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `["4iV5W9uYEdYUVa79Axb7Rh", "1301WleyT98MSxVHPZCA6M"]`
A maximum of 50 items can be specified in one request. _**Note**: if the `ids` parameter is present in the query string, any IDs listed here in the body will be ignored._ + items: + type: string + responses: + '200': + description: The album is saved + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + delete: + deprecated: true + tags: + - Albums + - Library + operationId: remove-albums-user + summary: | + Remove Users' Saved Albums + description: | + Remove one or more albums from the current user's 'Your Music' library. + + **Note:** This endpoint is deprecated. Use [Remove Items from Library](/documentation/web-api/reference/remove-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryAlbumIds' + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + ids: + type: array + description: | + A JSON array of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `["4iV5W9uYEdYUVa79Axb7Rh", "1301WleyT98MSxVHPZCA6M"]`
A maximum of 50 items can be specified in one request. _**Note**: if the `ids` parameter is present in the query string, any IDs listed here in the body will be ignored._ + items: + type: string + responses: + '200': + description: Album(s) have been removed from the library + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + /me/albums/contains: + get: + tags: + - Albums + - Library + operationId: check-users-saved-albums + summary: | + Check User's Saved Albums + deprecated: true + description: | + Check if one or more albums is already saved in the current Spotify user's 'Your Music' library. + + **Note:** This endpoint is deprecated. Use [Check User's Saved Items](/documentation/web-api/reference/check-library-contains) instead. + parameters: + - $ref: '#/components/parameters/QueryAlbumIds' + responses: + '200': + $ref: '#/components/responses/ArrayOfBooleans' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + /me/tracks: + get: + tags: + - Tracks + - Library + operationId: get-users-saved-tracks + summary: | + Get User's Saved Tracks + description: | + Get a list of the songs saved in the current Spotify user's 'Your Music' library. + parameters: + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingSavedTrackObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + put: + deprecated: true + tags: + - Tracks + - Library + operationId: save-tracks-user + summary: | + Save Tracks for Current User + description: | + Save one or more tracks to the current user's 'Your Music' library. + + **Note:** This endpoint is deprecated. Use [Save Items to Library](/documentation/web-api/reference/save-library-items) instead. + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + required: + - uris + properties: + ids: + type: array + description: | + A JSON array of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `["4iV5W9uYEdYUVa79Axb7Rh", "1301WleyT98MSxVHPZCA6M"]`
A maximum of 50 items can be specified in one request. _**Note**: if the `timestamped_ids` is present in the body, any IDs listed in the query parameters (deprecated) or the `ids` field in the body will be ignored._ + items: + type: string + timestamped_ids: + type: array + description: | + A JSON array of objects containing track IDs with their corresponding timestamps. Each object must include a track ID and an `added_at` timestamp. This allows you to specify when tracks were added to maintain a specific chronological order in the user's library.
A maximum of 50 items can be specified in one request. _**Note**: if the `timestamped_ids` is present in the body, any IDs listed in the query parameters (deprecated) or the `ids` field in the body will be ignored._ + items: + type: object + required: + - id + - added_at + properties: + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the track. + added_at: + type: string + format: date-time + x-spotify-docs-type: Timestamp + description: | + The timestamp when the track was added to the library. Use ISO 8601 format with UTC timezone (e.g., `2023-01-15T14:30:00Z`). You can specify past timestamps to insert tracks at specific positions in the library's chronological order. The API uses minute-level granularity for ordering, though the timestamp supports millisecond precision. + responses: + '200': + description: Track saved + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + delete: + deprecated: true + tags: + - Tracks + - Library + operationId: remove-tracks-user + summary: | + Remove User's Saved Tracks + description: | + Remove one or more tracks from the current user's 'Your Music' library. + + **Note:** This endpoint is deprecated. Use [Remove Items from Library](/documentation/web-api/reference/remove-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryTrackIds' + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + ids: + type: array + description: | + A JSON array of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `["4iV5W9uYEdYUVa79Axb7Rh", "1301WleyT98MSxVHPZCA6M"]`
A maximum of 50 items can be specified in one request. _**Note**: if the `ids` parameter is present in the query string, any IDs listed here in the body will be ignored._ + items: + type: string + responses: + '200': + description: Track removed + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + /me/tracks/contains: + get: + tags: + - Tracks + - Library + operationId: check-users-saved-tracks + summary: | + Check User's Saved Tracks + deprecated: true + description: | + Check if one or more tracks is already saved in the current Spotify user's 'Your Music' library. + + **Note:** This endpoint is deprecated. Use [Check User's Saved Items](/documentation/web-api/reference/check-library-contains) instead. + parameters: + - $ref: '#/components/parameters/QueryTrackIds' + responses: + '200': + $ref: '#/components/responses/ArrayOfBooleans' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + /me/episodes: + get: + tags: + - Episodes + - Library + operationId: get-users-saved-episodes + summary: | + Get User's Saved Episodes + description: | + Get a list of the episodes saved in the current Spotify user's library. + parameters: + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingSavedEpisodeObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + - user-read-playback-position + put: + deprecated: true + tags: + - Episodes + - Library + operationId: save-episodes-user + summary: | + Save Episodes for Current User + description: | + Save one or more episodes to the current user's library. + + **Note:** This endpoint is deprecated. Use [Save Items to Library](/documentation/web-api/reference/save-library-items) instead. + parameters: + - name: ids + required: true + in: query + schema: + title: Spotify Episodes IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). Maximum: 50 IDs. + example: 77o6BIVlYM3msb4MMIL1jH,0Q86acNRm6V9GYx55SXKwf + type: string + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + required: + - uris + properties: + ids: + type: array + description: | + A JSON array of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids).
A maximum of 50 items can be specified in one request. _**Note**: if the `ids` parameter is present in the query string, any IDs listed here in the body will be ignored._ + items: + type: string + responses: + '200': + description: Episode saved + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + delete: + deprecated: true + tags: + - Episodes + - Library + operationId: remove-episodes-user + summary: | + Remove User's Saved Episodes + description: | + Remove one or more episodes from the current user's library. + + **Note:** This endpoint is deprecated. Use [Remove Items from Library](/documentation/web-api/reference/remove-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryTrackIds' + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + ids: + type: array + description: | + A JSON array of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids).
A maximum of 50 items can be specified in one request. _**Note**: if the `ids` parameter is present in the query string, any IDs listed here in the body will be ignored._ + items: + type: string + responses: + '200': + description: Episode removed + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + /me/episodes/contains: + get: + tags: + - Episodes + - Library + operationId: check-users-saved-episodes + summary: | + Check User's Saved Episodes + deprecated: true + description: | + Check if one or more episodes is already saved in the current Spotify user's 'Your Episodes' library. + + **Note:** This endpoint is deprecated. Use [Check User's Saved Items](/documentation/web-api/reference/check-library-contains) instead. + parameters: + - name: ids + required: true + in: query + schema: + title: Spotify Episode IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) for the episodes. Maximum: 50 IDs. + example: 77o6BIVlYM3msb4MMIL1jH,0Q86acNRm6V9GYx55SXKwf + type: string + responses: + '200': + $ref: '#/components/responses/ArrayOfBooleans' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + /me/shows: + get: + tags: + - Shows + - Library + operationId: get-users-saved-shows + summary: | + Get User's Saved Shows + description: | + Get a list of shows saved in the current Spotify user's library. Optional parameters can be used to limit the number of shows returned. + parameters: + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + '200': + $ref: '#/components/responses/PagingSavedShowObject' + security: + - oauth_2_0: + - user-library-read + put: + deprecated: true + tags: + - Shows + - Library + operationId: save-shows-user + summary: | + Save Shows for Current User + description: | + Save one or more shows to current Spotify user's library. + + **Note:** This endpoint is deprecated. Use [Save Items to Library](/documentation/web-api/reference/save-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryShowIds' + responses: + '200': + description: Show saved + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + delete: + deprecated: true + tags: + - Shows + - Library + operationId: remove-shows-user + summary: | + Remove User's Saved Shows + description: | + Delete one or more shows from current Spotify user's library. + + **Note:** This endpoint is deprecated. Use [Remove Items from Library](/documentation/web-api/reference/remove-library-items) instead. + parameters: + - $ref: '#/components/parameters/QueryShowIds' + - $ref: '#/components/parameters/QueryMarket' + responses: + '200': + description: Show removed + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-modify + /me/shows/contains: + get: + tags: + - Shows + - Library + operationId: check-users-saved-shows + summary: | + Check User's Saved Shows + deprecated: true + description: | + Check if one or more shows is already saved in the current Spotify user's library. + + **Note:** This endpoint is deprecated. Use [Check User's Saved Items](/documentation/web-api/reference/check-library-contains) instead. + parameters: + - $ref: '#/components/parameters/QueryShowIds' + responses: + '200': + $ref: '#/components/responses/ArrayOfBooleans' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-library-read + /me/top/{type}: + get: + tags: + - Users + - Tracks + - Library + operationId: get-users-top-artists-and-tracks + summary: | + Get User's Top Items + description: | + Get the current user's top artists or tracks based on calculated affinity. + parameters: + - name: type + required: true + in: path + schema: + title: Type + description: | + The type of entity to return. Valid values: `artists` or `tracks` + enum: ['artists', 'tracks'] + type: string + - name: time_range + required: false + in: query + schema: + title: Time Range + description: | + Over what time frame the affinities are computed. Valid values: `long_term` (calculated from ~1 year of data and including all new data as it becomes available), `medium_term` (approximately last 6 months), `short_term` (approximately last 4 weeks). Default: `medium_term` + default: medium_term + example: medium_term + type: string + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagingArtistOrTrackObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-top-read + /users/{user_id}: + get: + deprecated: true + tags: + - Users + operationId: get-users-profile + summary: | + Get User's Profile + description: | + Get public profile information about a Spotify user. + parameters: + - $ref: '#/components/parameters/PathUserId' + responses: + '200': + $ref: '#/components/responses/OnePublicUser' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /users/{user_id}/playlists: + get: + deprecated: true + tags: + - Playlists + - Users + operationId: get-list-users-playlists + summary: | + Get User's Playlists + description: | + Get a list of the playlists owned or followed by a Spotify user. + parameters: + - $ref: '#/components/parameters/PathUserId' + - $ref: '#/components/parameters/QueryLimit' + - name: offset + required: false + in: query + schema: + title: Offset + description: | + The index of the first playlist to return. Default: + 0 (the first object). Maximum offset: 100.000\. Use with `limit` to get the + next set of playlists. + default: 0 + example: 5 + type: integer + responses: + '200': + $ref: '#/components/responses/PagedPlaylists' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-read-private + - playlist-read-collaborative + post: + tags: + - Playlists + - Library + operationId: create-playlist-for-user + deprecated: true + summary: | + Create Playlist for user + description: | + **Deprecated**: Use [Create Playlist](/documentation/web-api/reference/create-playlist) instead. + + Create a playlist for a Spotify user. (The playlist will be empty until + you [add tracks](/documentation/web-api/reference/add-tracks-to-playlist).) + Each user is generally limited to a maximum of 11000 playlists. + parameters: + - $ref: '#/components/parameters/PathUserId' + requestBody: + content: + application/json: + schema: + example: + name: New Playlist + description: New playlist description + public: false + type: object + additionalProperties: true + required: + - name + properties: + name: + type: string + description: | + The name for the new playlist, for example `"Your Coolest Playlist"`. This name does not need to be unique; a user may have several playlists with the same name. + public: + type: boolean + description: | + Defaults to `true`. The playlist's public/private status (if it should be added to the user's profile or not): `true` the playlist will be public, `false` the playlist will be private. To be able to create private playlists, the user must have granted the `playlist-modify-private` [scope](/documentation/web-api/concepts/scopes/#list-of-scopes). For more about public/private status, see [Working with Playlists](/documentation/web-api/concepts/playlists) + collaborative: + type: boolean + description: | + Defaults to `false`. If `true` the playlist will be collaborative. _**Note**: to create a collaborative playlist you must also set `public` to `false`. To create collaborative playlists you must have granted `playlist-modify-private` and `playlist-modify-public` [scopes](/documentation/web-api/concepts/scopes/#list-of-scopes)._ + description: + type: string + description: | + value for playlist description as displayed in Spotify Clients and in the Web API. + responses: + '201': + $ref: '#/components/responses/OnePlaylist' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + /playlists/{playlist_id}/followers: + put: + deprecated: true + tags: + - Users + - Playlists + operationId: follow-playlist + description: | + Add the current user as a follower of a playlist. + + **Note:** This endpoint is deprecated. Use [Save Items to Library](/documentation/web-api/reference/save-library-items) instead. + summary: | + Follow Playlist + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + requestBody: + content: + application/json: + schema: + example: + public: false + type: object + additionalProperties: true + properties: + public: + type: boolean + description: | + Defaults to `true`. If `true` the playlist will be included in user's public playlists (added to profile), if `false` it will remain private. For more about public/private status, see [Working with Playlists](/documentation/web-api/concepts/playlists) + responses: + '200': + description: Playlist followed + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + delete: + deprecated: true + tags: + - Users + - Playlists + operationId: unfollow-playlist + summary: | + Unfollow Playlist + description: | + Remove the current user as a follower of a playlist. + + **Note:** This endpoint is deprecated. Use [Remove Items from Library](/documentation/web-api/reference/remove-library-items) instead. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + responses: + '200': + description: Playlist unfollowed + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - playlist-modify-public + - playlist-modify-private + /browse/featured-playlists: + get: + deprecated: true + tags: + - Playlists + operationId: get-featured-playlists + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/MultipleIntegrations' + summary: | + Get Featured Playlists + description: | + Get a list of Spotify featured playlists (shown, for example, on a Spotify player's 'Browse' tab). + parameters: + - name: locale + required: false + in: query + schema: + title: Locale + description: | + The desired language, consisting of an [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code and an [ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2), joined by an underscore. For example: `es_MX`, meaning "Spanish (Mexico)". Provide this parameter if you want the category strings returned in a particular language.
_**Note**: if `locale` is not supplied, or if the specified language is not available, the category strings returned will be in the Spotify default language (American English)._ + example: sv_SE + type: string + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagedFeaturedPlaylists' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /browse/categories: + get: + deprecated: true + tags: + - Categories + operationId: get-categories + summary: | + Get Several Browse Categories + description: | + Get a list of categories used to tag items in Spotify (on, for example, the Spotify player’s “Browse” tab). + parameters: + - name: locale + required: false + in: query + schema: + title: Locale + description: | + The desired language, consisting of an [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code and an [ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2), joined by an underscore. For example: `es_MX`, meaning "Spanish (Mexico)". Provide this parameter if you want the category strings returned in a particular language.
_**Note**: if `locale` is not supplied, or if the specified language is not available, the category strings returned will be in the Spotify default language (American English)._ + example: sv_SE + type: string + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagedCategories' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /browse/categories/{category_id}: + get: + deprecated: true + tags: + - Categories + operationId: get-a-category + summary: | + Get Single Browse Category + description: | + Get a single category used to tag items in Spotify (on, for example, the Spotify player’s “Browse” tab). + parameters: + - name: category_id + required: true + in: path + schema: + title: Category ID + description: | + The [Spotify category ID](/documentation/web-api/concepts/spotify-uris-ids) for the category. + example: dinner + type: string + - name: locale + required: false + in: query + schema: + title: Locale + description: | + The desired language, consisting of an [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code and an [ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2), joined by an underscore. For example: `es_MX`, meaning "Spanish (Mexico)". Provide this parameter if you want the category strings returned in a particular language.
_**Note**: if `locale` is not supplied, or if the specified language is not available, the category strings returned will be in the Spotify default language (American English)._ + example: sv_SE + type: string + responses: + '200': + $ref: '#/components/responses/OneCategory' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /browse/categories/{category_id}/playlists: + get: + deprecated: true + tags: + - Playlists + - Categories + operationId: get-a-categories-playlists + summary: | + Get Category's Playlists + description: | + Get a list of Spotify playlists tagged with a particular category. + parameters: + - name: category_id + required: true + in: path + schema: + title: Category ID + description: | + The [Spotify category ID](/documentation/web-api/concepts/spotify-uris-ids) for the category. + example: dinner + type: string + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagedFeaturedPlaylists' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /playlists/{playlist_id}/images: + get: + tags: + - Playlists + operationId: get-playlist-cover + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/metadataWithMachineLearningPolicyList' + summary: | + Get Playlist Cover Image + description: | + Get the current image associated with a specific playlist. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + responses: + '200': + $ref: '#/components/responses/ArrayOfImages' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + put: + tags: + - Playlists + operationId: upload-custom-playlist-cover + summary: | + Add Custom Playlist Cover Image + description: | + Replace the image used to represent a specific playlist. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + requestBody: + content: + image/jpeg: + schema: + example: /9j/2wCEABoZGSccJz4lJT5CLy8vQkc9Ozs9R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0cBHCcnMyYzPSYmPUc9Mj1HR0dEREdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR//dAAQAAf/uAA5BZG9iZQBkwAAAAAH/wAARCAABAAEDACIAAREBAhEB/8QASwABAQAAAAAAAAAAAAAAAAAAAAYBAQAAAAAAAAAAAAAAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAARAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwAAARECEQA/AJgAH//Z + format: byte + type: string + required: true + description: Base64 encoded JPEG image data, maximum payload size is 256 KB. + responses: + '202': + description: Image uploaded + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - ugc-image-upload + - playlist-modify-public + - playlist-modify-private + /browse/new-releases: + get: + deprecated: true + tags: + - Albums + operationId: get-new-releases + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/MultipleIntegrations' + summary: | + Get New Releases + description: | + Get a list of new album releases featured in Spotify (shown, for example, on a Spotify player’s “Browse” tab). + parameters: + - $ref: '#/components/parameters/QueryLimit' + - $ref: '#/components/parameters/QueryOffset' + responses: + '200': + $ref: '#/components/responses/PagedAlbums' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /me/following: + get: + tags: + - Users + - Library + - Artists + operationId: get-followed + summary: | + Get Followed Artists + description: | + Get the current user's followed artists. + parameters: + - name: type + required: true + in: query + schema: + title: Item Type + description: | + The ID type: currently only `artist` is supported. + enum: + - artist + example: artist + type: string + - name: after + required: false + in: query + schema: + title: After + description: | + The last artist ID retrieved from the previous request. + example: 0I2XqVXqHScXjHhk6AYYRe + type: string + - name: limit + required: false + in: query + schema: + title: Limit + description: | + The maximum number of items to return. Default: 20\. Minimum: 1\. Maximum: 50\. + default: 20 + example: 10 + type: integer + minimum: 0 + maximum: 50 + responses: + '200': + $ref: '#/components/responses/CursorPagedArtists' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-follow-read + put: + deprecated: true + tags: + - Users + - Artists + - Library + operationId: follow-artists-users + summary: | + Follow Artists or Users + description: | + Add the current user as a follower of one or more artists or other Spotify users. + + **Note:** This endpoint is deprecated. Use [Save Items to Library](/documentation/web-api/reference/save-library-items) instead. + parameters: + - name: type + required: true + in: query + schema: + title: Item Type + description: | + The ID type. + enum: + - artist + - user + example: artist + type: string + - name: ids + required: true + in: query + schema: + title: Spotify IDs + description: | + A comma-separated list of the artist or the user [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). + A maximum of 50 IDs can be sent in one request. + example: 2CIMQHirSU0MQqyYHq0eOx,57dN52uHvrHOxijzpIgu3E,1vCWHaC5f2uS3yhpwWbIA6 + type: string + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + required: + - ids + properties: + ids: + type: array + description: | + A JSON array of the artist or user [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). + For example: `{ids:["74ASZWbe4lXaubB36ztrGX", "08td7MxkoHQkXnWAYD8d6Q"]}`. A maximum of 50 IDs can be sent in one request. _**Note**: if the `ids` parameter is present in the query string, any IDs listed here in the body will be ignored._ + items: + type: string + + responses: + '204': + description: Artist or user followed + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-follow-modify + delete: + deprecated: true + tags: + - Users + - Artists + - Library + operationId: unfollow-artists-users + summary: | + Unfollow Artists or Users + description: | + Remove the current user as a follower of one or more artists or other Spotify users. + + **Note:** This endpoint is deprecated. Use [Remove Items from Library](/documentation/web-api/reference/remove-library-items) instead. + parameters: + - name: type + required: true + in: query + schema: + title: Item Type + description: | + The ID type: either `artist` or `user`. + enum: + - artist + - user + example: artist + type: string + - name: ids + required: true + in: query + schema: + title: Spotify IDs + description: | + A comma-separated list of the artist or the user [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `ids=74ASZWbe4lXaubB36ztrGX,08td7MxkoHQkXnWAYD8d6Q`. A maximum of 50 IDs can be sent in one request. + example: 2CIMQHirSU0MQqyYHq0eOx,57dN52uHvrHOxijzpIgu3E,1vCWHaC5f2uS3yhpwWbIA6 + type: string + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + ids: + type: array + description: | + A JSON array of the artist or user [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `{ids:["74ASZWbe4lXaubB36ztrGX", "08td7MxkoHQkXnWAYD8d6Q"]}`. A maximum of 50 IDs can be sent in one request. _**Note**: if the `ids` parameter is present in the query string, any IDs listed here in the body will be ignored._ + items: + type: string + responses: + '204': + description: Artist or user unfollowed + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-follow-modify + /me/following/contains: + get: + tags: + - Users + - Artists + - Library + operationId: check-current-user-follows + summary: | + Check If User Follows Artists or Users + deprecated: true + description: | + Check to see if the current user is following one or more artists or other Spotify users. + + **Note:** This endpoint is deprecated. Use [Check User's Saved Items](/documentation/web-api/reference/check-library-contains) instead. + parameters: + - name: type + required: true + in: query + schema: + title: Item Type + description: | + The ID type: either `artist` or `user`. + enum: + - artist + - user + example: artist + type: string + - name: ids + required: true + in: query + schema: + title: Spotify IDs + description: | + A comma-separated list of the artist or the user [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) to check. For example: `ids=74ASZWbe4lXaubB36ztrGX,08td7MxkoHQkXnWAYD8d6Q`. A maximum of 50 IDs can be sent in one request. + example: 2CIMQHirSU0MQqyYHq0eOx,57dN52uHvrHOxijzpIgu3E,1vCWHaC5f2uS3yhpwWbIA6 + type: string + responses: + '200': + $ref: '#/components/responses/ArrayOfBooleans' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-follow-read + /playlists/{playlist_id}/followers/contains: + get: + tags: + - Users + - Playlists + operationId: check-if-user-follows-playlist + summary: | + Check if Current User Follows Playlist + deprecated: true + description: | + Check to see if the current user is following a specified playlist. + + **Note:** This endpoint is deprecated. Use [Check User's Saved Items](/documentation/web-api/reference/check-library-contains) instead. + parameters: + - $ref: '#/components/parameters/PathPlaylistId' + - name: ids + required: false + in: query + schema: + title: Spotify user IDs + description: | + **Deprecated** A single item list containing current user's [Spotify Username](/documentation/web-api/concepts/spotify-uris-ids). Maximum: 1 id. + example: jmperezperez + type: string + responses: + '200': + $ref: '#/components/responses/SingletonArrayOfBoolean' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /audio-features: + get: + deprecated: true + tags: + - Tracks + operationId: get-several-audio-features + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/MachineLearning' + summary: | + Get Several Tracks' Audio Features + description: | + Get audio features for multiple tracks based on their Spotify IDs. + parameters: + - name: ids + required: true + in: query + schema: + title: Spotify Track IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) + for the tracks. Maximum: 100 IDs. + example: 7ouMYWpwJ422jRcDASZB7P,4VqPOruhp5EdPBeR92t6lQ,2takcwOaAZWiXQijPHIx7B + type: string + responses: + '200': + $ref: '#/components/responses/ManyAudioFeatures' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /audio-features/{id}: + get: + deprecated: true + tags: + - Tracks + operationId: get-audio-features + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/MachineLearning' + summary: | + Get Track's Audio Features + description: | + Get audio feature information for a single track identified by its unique + Spotify ID. + parameters: + - name: id + required: true + in: path + schema: + title: Spotify Track ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the track. + example: 11dFghVXANMlKmJXsNCbNl + type: string + responses: + '200': + $ref: '#/components/responses/OneAudioFeatures' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /audio-analysis/{id}: + get: + deprecated: true + tags: + - Tracks + operationId: get-audio-analysis + summary: | + Get Track's Audio Analysis + description: | + Get a low-level audio analysis for a track in the Spotify catalog. The audio analysis describes the track’s structure and musical content, including rhythm, pitch, and timbre. + parameters: + - name: id + required: true + in: path + schema: + title: Spotify Track ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) + for the track. + example: 11dFghVXANMlKmJXsNCbNl + type: string + responses: + '200': + $ref: '#/components/responses/OneAudioAnalysis' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /recommendations: + get: + deprecated: true + tags: + - Tracks + operationId: get-recommendations + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/MachineLearning' + summary: | + Get Recommendations + description: | + Recommendations are generated based on the available information for a given seed entity and matched against similar artists and tracks. If there is sufficient information about the provided seeds, a list of tracks will be returned together with pool size details. + + For artists and tracks that are very new or obscure there might not be enough data to generate a list of tracks. + parameters: + - name: limit + required: false + in: query + schema: + title: Limit + description: | + The target size of the list of recommended tracks. For seeds with unusually small pools or when highly restrictive filtering is applied, it may be impossible to generate the requested number of recommended tracks. Debugging information for such cases is available in the response. Default: 20\. Minimum: 1\. Maximum: 100. + default: 20 + example: 10 + type: integer + minimum: 1 + maximum: 100 + - $ref: '#/components/parameters/QueryMarket' + - name: seed_artists + required: true + in: query + schema: + title: Spotify Artist ID Seeds + description: | + A comma separated list of [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) for seed artists. Up to 5 seed values may be provided in any combination of `seed_artists`, `seed_tracks` and `seed_genres`.
_**Note**: only required if `seed_genres` and `seed_tracks` are not set_. + example: 4NHQUGzhtTLFvgF5SZesLK + type: string + - name: seed_genres + required: true + in: query + schema: + title: Genres Seeds + description: | + A comma separated list of any genres in the set of [available genre seeds](/documentation/web-api/reference/get-recommendation-genres). Up to 5 seed values may be provided in any combination of `seed_artists`, `seed_tracks` and `seed_genres`.
_**Note**: only required if `seed_artists` and `seed_tracks` are not set_. + example: classical,country + type: string + - name: seed_tracks + required: true + in: query + schema: + title: Spotify Track ID Seeds + description: | + A comma separated list of [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) for a seed track. Up to 5 seed values may be provided in any combination of `seed_artists`, `seed_tracks` and `seed_genres`.
_**Note**: only required if `seed_artists` and `seed_genres` are not set_. + example: 0c6xIDDpzE81m2q797ordA + type: string + - name: min_acousticness + required: false + in: query + schema: + title: Min. Acousticness + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + minimum: 0 + maximum: 1 + - name: max_acousticness + required: false + in: query + schema: + title: Max. Acousticness + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + minimum: 0 + maximum: 1 + - name: target_acousticness + required: false + in: query + schema: + title: Target Acousticness + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + minimum: 0 + maximum: 1 + - name: min_danceability + required: false + in: query + schema: + title: Min. Danceability + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + minimum: 0 + maximum: 1 + - name: max_danceability + required: false + in: query + schema: + title: Max. Danceability + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + minimum: 0 + maximum: 1 + - name: target_danceability + required: false + in: query + schema: + title: Target Danceability + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + minimum: 0 + maximum: 1 + - name: min_duration_ms + required: false + in: query + schema: + title: Min. Duration (ms) + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: integer + - name: max_duration_ms + required: false + in: query + schema: + title: Max. Duration (ms) + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: integer + - name: target_duration_ms + required: false + in: query + schema: + title: Target Duration (ms) + description: Target duration of the track (ms) + type: integer + - name: min_energy + required: false + in: query + schema: + title: Min. Energy + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + minimum: 0 + maximum: 1 + - name: max_energy + required: false + in: query + schema: + title: Max. Energy + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + minimum: 0 + maximum: 1 + - name: target_energy + required: false + in: query + schema: + title: Target Energy + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + minimum: 0 + maximum: 1 + - name: min_instrumentalness + required: false + in: query + schema: + title: Min. Instrumentalness + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + minimum: 0 + maximum: 1 + - name: max_instrumentalness + required: false + in: query + schema: + title: Max. Instrumentalness + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + minimum: 0 + maximum: 1 + - name: target_instrumentalness + required: false + in: query + schema: + title: Target Instrumentalness + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + minimum: 0 + maximum: 1 + - name: min_key + required: false + in: query + schema: + title: Min. Key + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: integer + minimum: 0 + maximum: 11 + - name: max_key + required: false + in: query + schema: + title: Max. Key + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: integer + minimum: 0 + maximum: 11 + - name: target_key + required: false + in: query + schema: + title: Target Key + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: integer + minimum: 0 + maximum: 11 + - name: min_liveness + required: false + in: query + schema: + title: Min. Liveness + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + minimum: 0 + maximum: 1 + - name: max_liveness + required: false + in: query + schema: + title: Max. Liveness + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + minimum: 0 + maximum: 1 + - name: target_liveness + required: false + in: query + schema: + title: Target Liveness + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + minimum: 0 + maximum: 1 + - name: min_loudness + required: false + in: query + schema: + title: Min. Loudness + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + - name: max_loudness + required: false + in: query + schema: + title: Max. Loudness + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + - name: target_loudness + required: false + in: query + schema: + title: Target Loudness + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + - name: min_mode + required: false + in: query + schema: + title: Min. Mode + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: integer + minimum: 0 + maximum: 1 + - name: max_mode + required: false + in: query + schema: + title: Max. Mode + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: integer + minimum: 0 + maximum: 1 + - name: target_mode + required: false + in: query + schema: + title: Target Mode + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: integer + minimum: 0 + maximum: 1 + - name: min_popularity + required: false + in: query + schema: + title: Min. Popularity + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: integer + minimum: 0 + maximum: 100 + - name: max_popularity + required: false + in: query + schema: + title: Max. Popularity + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: integer + minimum: 0 + maximum: 100 + - name: target_popularity + required: false + in: query + schema: + title: Target Popularity + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: integer + minimum: 0 + maximum: 100 + - name: min_speechiness + required: false + in: query + schema: + title: Min. Speechiness + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + minimum: 0 + maximum: 1 + - name: max_speechiness + required: false + in: query + schema: + title: Max. Speechiness + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + minimum: 0 + maximum: 1 + - name: target_speechiness + required: false + in: query + schema: + title: Target Speechiness + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + minimum: 0 + maximum: 1 + - name: min_tempo + required: false + in: query + schema: + title: Min. Tempo + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + - name: max_tempo + required: false + in: query + schema: + title: Max. Tempo + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + - name: target_tempo + required: false + in: query + schema: + title: Target Tempo + description: Target tempo (BPM) + type: number + - name: min_time_signature + required: false + in: query + schema: + title: Min. Time Signature + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: integer + maximum: 11 + - name: max_time_signature + required: false + in: query + schema: + title: Max. Time Signature + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: integer + - name: target_time_signature + required: false + in: query + schema: + title: Target Time Signature + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: integer + - name: min_valence + required: false + in: query + schema: + title: Min. Valence + description: | + For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `min_tempo=140` would restrict results to only those tracks with a tempo of greater than 140 beats per minute. + type: number + minimum: 0 + maximum: 1 + - name: max_valence + required: false + in: query + schema: + title: Max. Valence + description: | + For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided. See tunable track attributes below for the list of available options. For example, `max_instrumentalness=0.35` would filter out most tracks that are likely to be instrumental. + type: number + minimum: 0 + maximum: 1 + - name: target_valence + required: false + in: query + schema: + title: Target Valence + description: | + For each of the tunable track attributes (below) a target value may be provided. Tracks with the attribute values nearest to the target values will be preferred. For example, you might request `target_energy=0.6` and `target_danceability=0.8`. All target values will be weighed equally in ranking results. + type: number + minimum: 0 + maximum: 1 + responses: + '200': + $ref: '#/components/responses/OneRecommendations' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /recommendations/available-genre-seeds: + get: + deprecated: true + tags: + - Genres + operationId: get-recommendation-genres + summary: | + Get Available Genre Seeds + description: | + Retrieve a list of available genres seed parameter values for [recommendations](/documentation/web-api/reference/get-recommendations). + responses: + '200': + $ref: '#/components/responses/ManyGenres' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + /me/player: + get: + tags: + - Player + operationId: get-information-about-the-users-current-playback + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Get Playback State + description: | + Get information about the user’s current playback state, including track or episode, progress, and active device. + parameters: + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryAdditionalTypes' + responses: + '200': + $ref: '#/components/responses/OneCurrentlyPlaying' + '204': + description: Playback not available or active + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-playback-state + put: + tags: + - Player + operationId: transfer-a-users-playback + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Transfer Playback + description: | + Transfer playback to a new device and optionally begin playback. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + requestBody: + content: + application/json: + schema: + example: + device_ids: + - 74ASZWbe4lXaubB36ztrGX + type: object + additionalProperties: true + required: + - device_ids + properties: + device_ids: + type: array + description: | + A JSON array containing the ID of the device on which playback should be started/transferred.
For example:`{device_ids:["74ASZWbe4lXaubB36ztrGX"]}`
_**Note**: Although an array is accepted, only a single device_id is currently supported. Supplying more than one will return `400 Bad Request`_ + items: + type: string + play: + type: boolean + description: | + **true**: ensure playback happens on new device.
**false** or not provided: keep the current playback state. + additionalProperties: true + responses: + '204': + description: Playback transferred + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/devices: + get: + tags: + - Player + operationId: get-a-users-available-devices + summary: | + Get Available Devices + description: | + Get information about a user’s available Spotify Connect devices. Some device models are not supported and will not be listed in the API response. + responses: + '200': + $ref: '#/components/responses/ManyDevices' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-playback-state + /me/player/currently-playing: + get: + tags: + - Player + operationId: get-the-users-currently-playing-track + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Get Currently Playing Track + description: | + Get the object currently being played on the user's Spotify account. + parameters: + - $ref: '#/components/parameters/QueryMarket' + - $ref: '#/components/parameters/QueryAdditionalTypes' + responses: + '200': + $ref: '#/components/responses/OneCurrentlyPlayingTrack' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-currently-playing + + /me/player/play: + put: + tags: + - Player + operationId: start-a-users-playback + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Start/Resume Playback + description: | + Start a new context or resume current playback on the user's active device. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: device_id + required: false + in: query + schema: + title: Device ID + description: The id of the device this command is targeting. If + not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + requestBody: + content: + application/json: + schema: + example: + context_uri: spotify:album:5ht7ItJgpBH7W6vJ5BqpPr + offset: + position: 5 + position_ms: 0 + type: object + additionalProperties: true + properties: + context_uri: + type: string + description: | + Optional. Spotify URI of the context to play. + Valid contexts are albums, artists & playlists. + `{context_uri:"spotify:album:1Je1IMUlBXcx1Fz0WE7oPT"}` + additionalProperties: true + uris: + type: array + description: | + Optional. A JSON array of the Spotify track URIs to play. + For example: `{"uris": ["spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "spotify:track:1301WleyT98MSxVHPZCA6M"]}` + items: + type: string + offset: + type: object + description: | + Optional. Indicates from where in the context playback should start. Only available when context_uri corresponds to an album or playlist object + "position" is zero based and can’t be negative. Example: `"offset": {"position": 5}` + "uri" is a string representing the uri of the item to start at. Example: `"offset": {"uri": "spotify:track:1301WleyT98MSxVHPZCA6M"}` + additionalProperties: true + position_ms: + type: integer + description: integer + additionalProperties: true + responses: + '204': + description: Playback started + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/pause: + put: + tags: + - Player + operationId: pause-a-users-playback + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Pause Playback + description: | + Pause playback on the user's account. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: device_id + required: false + in: query + schema: + title: Device ID + description: | + The id of the device this command is targeting. If not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Playback paused + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/next: + post: + tags: + - Player + operationId: skip-users-playback-to-next-track + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Skip To Next + description: | + Skips to next track in the user’s queue. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: device_id + required: false + in: query + schema: + title: Device ID + description: The id of the device this command is targeting. If + not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Command sent + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/previous: + post: + tags: + - Player + operationId: skip-users-playback-to-previous-track + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Skip To Previous + description: | + Skips to previous track in the user’s queue. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: device_id + required: false + in: query + schema: + title: Device ID + description: | + The id of the device this command is targeting. If + not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Command sent + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/seek: + put: + tags: + - Player + operationId: seek-to-position-in-currently-playing-track + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Seek To Position + description: | + Seeks to the given position in the user’s currently playing track. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: position_ms + required: true + in: query + schema: + title: Position (ms) + description: | + The position in milliseconds to seek to. Must be a + positive number. Passing in a position that is greater than the length of + the track will cause the player to start playing the next song. + example: 25000 + type: integer + - name: device_id + required: false + in: query + schema: + title: Device ID + description: | + The id of the device this command is targeting. If + not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Command sent + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/repeat: + put: + tags: + - Player + operationId: set-repeat-mode-on-users-playback + summary: | + Set Repeat Mode + description: | + Set the repeat mode for the user's playback. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: state + required: true + in: query + schema: + title: State + description: | + **track**, **context** or **off**.
+ **track** will repeat the current track.
+ **context** will repeat the current context.
+ **off** will turn repeat off. + example: context + type: string + - name: device_id + required: false + in: query + schema: + title: Device ID + description: | + The id of the device this command is targeting. If + not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Command sent + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/volume: + put: + tags: + - Player + operationId: set-volume-for-users-playback + summary: | + Set Playback Volume + description: | + Set the volume for the user’s current playback device. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: volume_percent + required: true + in: query + schema: + title: Volume % + description: | + The volume to set. Must be a value from 0 to 100 inclusive. + example: 50 + type: integer + - name: device_id + required: false + in: query + schema: + title: Device ID + description: | + The id of the device this command is targeting. If not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Command sent + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/shuffle: + put: + tags: + - Player + operationId: toggle-shuffle-for-users-playback + summary: | + Toggle Playback Shuffle + description: | + Toggle shuffle on or off for user’s playback. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: state + required: true + in: query + schema: + title: State + description: | + **true** : Shuffle user's playback.
+ **false** : Do not shuffle user's playback. + example: true + type: boolean + - name: device_id + required: false + in: query + schema: + title: Device ID + description: | + The id of the device this command is targeting. If + not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Command sent + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /me/player/recently-played: + get: + tags: + - Player + operationId: get-recently-played + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Get Recently Played Tracks + description: | + Get tracks from the current user's recently played tracks. + _**Note**: Currently doesn't support podcast episodes._ + parameters: + - name: limit + required: false + in: query + schema: + title: Limit + description: | + The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + default: 20 + example: 10 + type: integer + minimum: 0 + maximum: 50 + - name: after + required: false + in: query + schema: + title: After + description: | + A Unix timestamp in milliseconds. Returns all items + after (but not including) this cursor position. If `after` is specified, `before` + must not be specified. + example: 1484811043508 + type: integer + - name: before + required: false + in: query + schema: + title: Before + description: | + A Unix timestamp in milliseconds. Returns all items + before (but not including) this cursor position. If `before` is specified, + `after` must not be specified. + type: integer + responses: + '200': + $ref: '#/components/responses/CursorPagedPlayHistory' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-recently-played + /me/player/queue: + get: + tags: + - Player + operationId: get-queue + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Get the User's Queue + description: | + Get the list of objects that make up the user's queue. + responses: + '200': + $ref: '#/components/responses/Queue' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-read-currently-playing + - user-read-playback-state + post: + tags: + - Player + operationId: add-to-queue + x-spotify-policy-list: + $ref: '#/components/x-spotify-policy/playerPolicyList' + summary: | + Add Item to Playback Queue + description: | + Add an item to be played next in the user's current playback queue. This API only works for users who have Spotify Premium. The order of execution is not guaranteed when you use this API with other Player API endpoints. + parameters: + - name: uri + required: true + in: query + schema: + title: Spotify URI + description: | + The uri of the item to add to the queue. Must be a track or an episode uri. + example: spotify:track:4iV5W9uYEdYUVa79Axb7Rh + type: string + - name: device_id + required: false + in: query + schema: + title: Device ID + description: | + The id of the device this command is targeting. If + not supplied, the user's currently active device is the target. + example: 0d1841b0976bae2a3a310dd74c0f3df354899bc8 + type: string + responses: + '204': + description: Command received + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: + - user-modify-playback-state + /markets: + get: + deprecated: true + tags: + - Markets + operationId: get-available-markets + summary: | + Get Available Markets + description: | + Get the list of markets where Spotify is available. + responses: + '200': + description: A markets object with an array of country codes + content: + application/json: + schema: + type: object + properties: + markets: + type: array + items: + type: string + example: ['CA', 'BR', 'IT'] + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '429': + $ref: '#/components/responses/TooManyRequests' + security: + - oauth_2_0: [] + +components: + securitySchemes: + oauth_2_0: + type: oauth2 + description: Spotify supports OAuth 2.0 for authenticating all API requests. + flows: + authorizationCode: + authorizationUrl: https://accounts.spotify.com/authorize + tokenUrl: https://accounts.spotify.com/api/token + scopes: + app-remote-control: | + Communicate with the Spotify app on your device. + playlist-read-private: | + Access your private playlists. + playlist-read-collaborative: | + Access your collaborative playlists. + playlist-modify-public: | + Manage your public playlists. + playlist-modify-private: | + Manage your private playlists. + user-library-read: | + Access your saved content. + user-library-modify: | + Manage your saved content. + user-read-private: | + Access your subscription details. + user-read-email: | + Get your real email address. + user-follow-read: | + Access your followers and who you are following. + user-follow-modify: | + Manage your saved content. + user-top-read: | + Read your top artists and content. + user-read-playback-position: | + Read your position in content you have played. + user-read-playback-state: | + Read your currently playing content and Spotify Connect devices information. + user-read-recently-played: | + Access your recently played items. + user-read-currently-playing: | + Read your currently playing content. + user-modify-playback-state: | + Control playback on your Spotify clients and Spotify Connect devices. + ugc-image-upload: | + Upload images to Spotify on your behalf. + streaming: | + Play content and control playback on your other devices. + x-spotify-policy: + policies: + $ref: '../policies.yaml' + metadataPolicyList: + - $ref: '#/components/x-spotify-policy/policies/Downloading' + - $ref: '#/components/x-spotify-policy/policies/VisualAlteration' + - $ref: '#/components/x-spotify-policy/policies/Attribution' + metadataWithMachineLearningPolicyList: + - $ref: '#/components/x-spotify-policy/policies/Downloading' + - $ref: '#/components/x-spotify-policy/policies/VisualAlteration' + - $ref: '#/components/x-spotify-policy/policies/Attribution' + - $ref: '#/components/x-spotify-policy/policies/MachineLearning' + playerPolicyList: + - $ref: '#/components/x-spotify-policy/policies/CommercialStreaming' + - $ref: '#/components/x-spotify-policy/policies/ContentAlteration' + - $ref: '#/components/x-spotify-policy/policies/Synchronization' + - $ref: '#/components/x-spotify-policy/policies/Broadcasting' + downloading: + $ref: '#/components/x-spotify-policy/policies/Downloading' + responses: + Unauthorized: + description: | + Bad or expired token. This can happen if the user revoked a token or + the access token has expired. You should re-authenticate the user. + content: + application/json: + schema: + type: object + required: + - error + properties: + error: + $ref: '#/components/schemas/ErrorObject' + + Forbidden: + description: | + Bad OAuth request (wrong consumer key, bad nonce, expired + timestamp...). Unfortunately, re-authenticating the user won't help here. + content: + application/json: + schema: + type: object + required: + - error + properties: + error: + $ref: '#/components/schemas/ErrorObject' + + NotFound: + description: | + The requested resource cannot be found. + content: + application/json: + schema: + type: object + required: + - error + properties: + error: + $ref: '#/components/schemas/ErrorObject' + + BadRequest: + description: | + The request contains malformed data in path, query parameters, or body. + content: + application/json: + schema: + type: object + required: + - error + properties: + error: + $ref: '#/components/schemas/ErrorObject' + + TooManyRequests: + description: | + The app has exceeded its rate limits. + content: + application/json: + schema: + type: object + required: + - error + properties: + error: + $ref: '#/components/schemas/ErrorObject' + + ManyAlbums: + description: A set of albums + content: + application/json: + schema: + type: object + required: + - albums + properties: + albums: + type: array + items: + $ref: '#/components/schemas/AlbumObject' + + ManyAudiobooks: + description: A set of audiobooks. If one of the requested audiobooks is unavailable then you'll find a `null` item in the `audiobooks` array where the audiobook object would otherwise be. + content: + application/json: + schema: + type: object + required: + - audiobooks + properties: + audiobooks: + type: array + items: + $ref: '#/components/schemas/AudiobookObject' + + ManyChapters: + description: A set of chapters + content: + application/json: + schema: + type: object + required: + - chapters + properties: + chapters: + type: array + items: + $ref: '#/components/schemas/ChapterObject' + + ManyDevices: + description: A set of devices + content: + application/json: + schema: + type: object + required: + - devices + properties: + devices: + type: array + items: + $ref: '#/components/schemas/DeviceObject' + + PagedAlbums: + description: A paged set of albums + content: + application/json: + schema: + type: object + required: + - albums + properties: + albums: + $ref: '#/components/schemas/PagingSimplifiedAlbumObject' + + PagedPlaylists: + description: A paged set of playlists + content: + application/json: + schema: + $ref: '#/components/schemas/PagingPlaylistObject' + + PagedFeaturedPlaylists: + description: A paged set of playlists + content: + application/json: + schema: + $ref: '#/components/schemas/PagingFeaturedPlaylistObject' + + PagedCategories: + description: A paged set of categories + content: + application/json: + schema: + type: object + required: + - categories + properties: + categories: + type: object + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/CategoryObject' + + CursorPagedArtists: + description: A paged set of artists + content: + application/json: + schema: + type: object + required: + - artists + properties: + artists: + $ref: '#/components/schemas/CursorPagingSimplifiedArtistObject' + + CursorPagedPlayHistory: + description: A paged set of tracks + content: + application/json: + schema: + $ref: '#/components/schemas/CursorPagingPlayHistoryObject' + + ManyArtists: + description: A set of artists + content: + application/json: + schema: + type: object + required: + - artists + properties: + artists: + type: array + items: + $ref: '#/components/schemas/ArtistObject' + + ManyAudioFeatures: + description: A set of audio features + content: + application/json: + schema: + type: object + required: + - audio_features + properties: + audio_features: + type: array + items: + $ref: '#/components/schemas/AudioFeaturesObject' + + ManyEpisodes: + description: A set of episodes + content: + application/json: + schema: + type: object + required: + - episodes + properties: + episodes: + type: array + items: + $ref: '#/components/schemas/EpisodeObject' + + ManyGenres: + description: A set of genres + content: + application/json: + schema: + type: object + required: + - genres + properties: + genres: + type: array + example: ['alternative', 'samba'] + items: + type: string + + OneEpisode: + description: An episode + content: + application/json: + schema: + $ref: '#/components/schemas/EpisodeObject' + + OneChapter: + description: A Chapter + content: + application/json: + schema: + $ref: '#/components/schemas/ChapterObject' + + OneAudiobook: + description: An Audiobook + content: + application/json: + schema: + $ref: '#/components/schemas/AudiobookObject' + + OneAlbum: + description: An album + content: + application/json: + schema: + $ref: '#/components/schemas/AlbumObject' + + ArrayOfImages: + description: A set of images + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ImageObject' + + OnePrivateUser: + description: A user + content: + application/json: + schema: + $ref: '#/components/schemas/PrivateUserObject' + + OnePublicUser: + description: A user + content: + application/json: + schema: + $ref: '#/components/schemas/PublicUserObject' + + OneTrack: + description: A track + content: + application/json: + schema: + $ref: '#/components/schemas/TrackObject' + + OneShow: + description: A show + content: + application/json: + schema: + $ref: '#/components/schemas/ShowObject' + + OneCategory: + description: A category + content: + application/json: + schema: + $ref: '#/components/schemas/CategoryObject' + + OnePlaylist: + description: A playlist + content: + application/json: + schema: + $ref: '#/components/schemas/PlaylistObject' + + OneAudioFeatures: + description: Audio features for one track + content: + application/json: + schema: + $ref: '#/components/schemas/AudioFeaturesObject' + + OneAudioAnalysis: + description: Audio analysis for one track + content: + application/json: + schema: + $ref: '#/components/schemas/AudioAnalysisObject' + + OneArtist: + description: An artist + content: + application/json: + schema: + $ref: '#/components/schemas/ArtistObject' + + ManyTracks: + description: A set of tracks + content: + application/json: + schema: + type: object + required: + - tracks + properties: + tracks: + type: array + items: + $ref: '#/components/schemas/TrackObject' + + ManySimplifiedShows: + description: A set of shows + content: + application/json: + schema: + type: object + required: + - shows + properties: + shows: + type: array + items: + $ref: '#/components/schemas/SimplifiedShowObject' + + PagingSimplifiedTrackObject: + description: Pages of tracks + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSimplifiedTrackObject' + + PagingSavedTrackObject: + description: Pages of tracks + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSavedTrackObject' + + PagingPlaylistTrackObject: + description: Pages of tracks + content: + application/json: + schema: + $ref: '#/components/schemas/PagingPlaylistTrackObject' + + PagingArtistDiscographyAlbumObject: + description: Pages of albums + content: + application/json: + schema: + $ref: '#/components/schemas/PagingArtistDiscographyAlbumObject' + + PagingSavedAlbumObject: + description: Pages of albums + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSavedAlbumObject' + + PagingSavedShowObject: + description: Pages of shows + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSavedShowObject' + + PagingSimplifiedEpisodeObject: + description: Pages of episodes + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSimplifiedEpisodeObject' + + PagingSavedEpisodeObject: + description: Pages of episodes + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSavedEpisodeObject' + + PagingSimplifiedAudiobookObject: + description: Pages of audiobooks + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSimplifiedAudiobookObject' + + PagingSimplifiedChapterObject: + description: Pages of chapters + content: + application/json: + schema: + $ref: '#/components/schemas/PagingSimplifiedChapterObject' + + PagingArtistOrTrackObject: + description: Pages of artists or tracks + content: + application/json: + schema: + type: object + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + type: object + oneOf: + - $ref: '#/components/schemas/ArtistObject' + - $ref: '#/components/schemas/TrackObject' + discriminator: + propertyName: type + + SearchItems: + description: Search response + content: + application/json: + schema: + type: object + properties: + tracks: + $ref: '#/components/schemas/PagingTrackObject' + artists: + $ref: '#/components/schemas/PagingArtistObject' + albums: + $ref: '#/components/schemas/PagingSimplifiedAlbumObject' + playlists: + $ref: '#/components/schemas/PagingPlaylistObject' + shows: + $ref: '#/components/schemas/PagingSimplifiedShowObject' + episodes: + $ref: '#/components/schemas/PagingSimplifiedEpisodeObject' + audiobooks: + $ref: '#/components/schemas/PagingSimplifiedAudiobookObject' + + OneRecommendations: + description: A set of recommendations + content: + application/json: + schema: + $ref: '#/components/schemas/RecommendationsObject' + + ArrayOfBooleans: + description: Array of booleans + content: + application/json: + schema: + type: array + example: [false, true] + items: + type: boolean + + SingletonArrayOfBoolean: + description: Array of boolean, containing a single boolean + content: + application/json: + schema: + type: array + example: [true] + items: + type: boolean + + Queue: + description: Information about the queue + content: + application/json: + schema: + $ref: '#/components/schemas/QueueObject' + + OneCurrentlyPlaying: + description: Information about playback + content: + application/json: + schema: + $ref: '#/components/schemas/CurrentlyPlayingContextObject' + + OneCurrentlyPlayingTrack: + description: Information about the currently playing track + content: + application/json: + schema: + $ref: '#/components/schemas/CurrentlyPlayingContextObject' + + PlaylistSnapshotId: + description: A snapshot ID for the playlist + content: + application/json: + schema: + type: object + properties: + snapshot_id: + type: string + example: 'abc' + + #------------------------------- + # Reusable schemas (data models) + #------------------------------- + schemas: + LinkedTrackObject: + type: object + x-spotify-docs-type: LinkedTrackObject + properties: + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known external URLs for this track. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the track. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the track. + type: + type: string + description: | + The object type: "track". + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the track. + + TrackRestrictionObject: + type: object + x-spotify-docs-type: TrackRestrictionObject + properties: + reason: + type: string + description: | + The reason for the restriction. Supported values: + - `market` - The content item is not available in the given market. + - `product` - The content item is not available for the user's subscription type. + - `explicit` - The content item is explicit and the user's account is set to not play explicit content. + + Additional reasons may be added in the future. + **Note**: If you use this field, make sure that your application safely handles unknown values. + + AlbumRestrictionObject: + type: object + x-spotify-docs-type: AlbumRestrictionObject + properties: + reason: + type: string + enum: ['market', 'product', 'explicit'] + description: | + The reason for the restriction. Albums may be restricted if the content is not available in a given market, to the user's subscription type, or when the user's account is set to not play explicit content. + Additional reasons may be added in the future. + + EpisodeRestrictionObject: + type: object + x-spotify-docs-type: EpisodeRestrictionObject + properties: + reason: + type: string + description: | + The reason for the restriction. Supported values: + - `market` - The content item is not available in the given market. + - `product` - The content item is not available for the user's subscription type. + - `explicit` - The content item is explicit and the user's account is set to not play explicit content. + + Additional reasons may be added in the future. + **Note**: If you use this field, make sure that your application safely handles unknown values. + + ChapterRestrictionObject: + type: object + x-spotify-docs-type: ChapterRestrictionObject + properties: + reason: + type: string + description: | + The reason for the restriction. Supported values: + - `market` - The content item is not available in the given market. + - `product` - The content item is not available for the user's subscription type. + - `explicit` - The content item is explicit and the user's account is set to not play explicit content. + - `payment_required` - Payment is required to play the content item. + + Additional reasons may be added in the future. + **Note**: If you use this field, make sure that your application safely handles unknown values. + + ArtistObject: + type: object + x-spotify-docs-type: ArtistObject + properties: + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known external URLs for this artist. + followers: + deprecated: true + allOf: + - $ref: '#/components/schemas/FollowersObject' + description: | + Information about the followers of the artist. + genres: + deprecated: true + type: array + items: + type: string + example: ['Prog rock', 'Grunge'] + description: | + A list of the genres the artist is associated with. If not yet classified, the array is empty. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the artist. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the artist. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + Images of the artist in various sizes, widest first. + name: + type: string + description: | + The name of the artist. + popularity: + deprecated: true + type: integer + description: | + The popularity of the artist. The value will be between 0 and 100, with 100 being the most popular. The artist's popularity is calculated from the popularity of all the artist's tracks. + type: + type: string + enum: ['artist'] + description: | + The object type. + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the artist. + + SimplifiedArtistObject: + type: object + x-spotify-docs-type: SimplifiedArtistObject + properties: + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known external URLs for this artist. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the artist. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the artist. + name: + type: string + description: | + The name of the artist. + type: + type: string + enum: ['artist'] + description: | + The object type. + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the artist. + + PlayHistoryObject: + type: object + x-spotify-docs-type: PlayHistoryObject + properties: + track: + allOf: + - $ref: '#/components/schemas/TrackObject' + description: The track the user listened to. + played_at: + type: string + format: date-time + x-spotify-docs-type: Timestamp + description: The date and time the track was played. + context: + allOf: + - $ref: '#/components/schemas/ContextObject' + description: The context the track was played from. + + PlaylistTrackObject: + type: object + x-spotify-docs-type: PlaylistTrackObject + properties: + added_at: + type: string + format: date-time + x-spotify-docs-type: Timestamp + description: | + The date and time the track or episode was added. _**Note**: some very old playlists may return `null` in this field._ + added_by: + allOf: + - $ref: '#/components/schemas/PlaylistUserObject' + description: | + The Spotify user who added the track or episode. _**Note**: some very old playlists may return `null` in this field._ + is_local: + type: boolean + description: | + Whether this track or episode is a [local file](/documentation/web-api/concepts/playlists/#local-files) or not. + item: + oneOf: + - $ref: '#/components/schemas/TrackObject' + - $ref: '#/components/schemas/EpisodeObject' + x-spotify-docs-type: TrackObject | EpisodeObject + description: Information about the track or episode. + discriminator: + propertyName: type + track: + oneOf: + - $ref: '#/components/schemas/TrackObject' + - $ref: '#/components/schemas/EpisodeObject' + x-spotify-docs-type: TrackObject | EpisodeObject + deprecated: true + description: | + **Deprecated:** Use `item` instead. Information about the track or episode. + discriminator: + propertyName: type + + QueueObject: + type: object + x-spotify-docs-type: QueueObject + properties: + currently_playing: + oneOf: + - $ref: '#/components/schemas/TrackObject' + - $ref: '#/components/schemas/EpisodeObject' + discriminator: + propertyName: type + x-spotify-docs-type: TrackObject | EpisodeObject + description: The currently playing track or episode. Can be `null`. + queue: + type: array + items: + oneOf: + - $ref: '#/components/schemas/TrackObject' + - $ref: '#/components/schemas/EpisodeObject' + discriminator: + propertyName: type + x-spotify-docs-type: TrackObject | EpisodeObject + description: The tracks or episodes in the queue. Can be empty. + + CurrentlyPlayingContextObject: + type: object + x-spotify-docs-type: CurrentlyPlayingContextObject + properties: + device: + allOf: + - $ref: '#/components/schemas/DeviceObject' + description: | + The device that is currently active. + repeat_state: + type: string + description: off, track, context + shuffle_state: + type: boolean + description: If shuffle is on or off. + context: + allOf: + - $ref: '#/components/schemas/ContextObject' + description: A Context Object. Can be `null`. + timestamp: + type: integer + description: Unix Millisecond Timestamp when playback state was last changed (play, pause, skip, scrub, new song, etc.). + progress_ms: + type: integer + description: Progress into the currently playing track or episode. Can be `null`. + is_playing: + type: boolean + description: If something is currently playing, return `true`. + item: + oneOf: + - $ref: '#/components/schemas/TrackObject' + - $ref: '#/components/schemas/EpisodeObject' + discriminator: + propertyName: type + x-spotify-docs-type: TrackObject | EpisodeObject + description: The currently playing track or episode. Can be `null`. + currently_playing_type: + type: string + description: | + The object type of the currently playing item. Can be one of `track`, `episode`, `ad` or `unknown`. + actions: + allOf: + - $ref: '#/components/schemas/DisallowsObject' + description: | + Allows to update the user interface based on which playback actions are available within the current context. + + DisallowsObject: + type: object + x-spotify-docs-type: DisallowsObject + properties: + interrupting_playback: + type: boolean + description: Interrupting playback. Optional field. + pausing: + type: boolean + description: Pausing. Optional field. + resuming: + type: boolean + description: Resuming. Optional field. + seeking: + type: boolean + description: Seeking playback location. Optional field. + skipping_next: + type: boolean + description: Skipping to the next context. Optional field. + skipping_prev: + type: boolean + description: Skipping to the previous context. Optional field. + toggling_repeat_context: + type: boolean + description: Toggling repeat context flag. Optional field. + toggling_shuffle: + type: boolean + description: Toggling shuffle flag. Optional field. + toggling_repeat_track: + type: boolean + description: Toggling repeat track flag. Optional field. + transferring_playback: + type: boolean + description: Transfering playback between devices. Optional field. + + ErrorObject: + type: object + x-spotify-docs-type: ErrorObject + required: + - status + - message + properties: + status: + type: integer + minimum: 400 + maximum: 599 + description: | + The HTTP status code (also returned in the response header; see [Response Status Codes](/documentation/web-api/concepts/api-calls#response-status-codes) for more information). + message: + type: string + description: | + A short description of the cause of the error. + + PrivateUserObject: + type: object + x-spotify-docs-type: PrivateUserObject + properties: + country: + deprecated: true + type: string + description: | + The country of the user, as set in the user's account profile. An [ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). _This field is only available when the current user has granted access to the [user-read-private](/documentation/web-api/concepts/scopes/#list-of-scopes) scope._ + display_name: + type: string + description: | + The name displayed on the user's profile. `null` if not available. + email: + deprecated: true + type: string + description: | + The user's email address, as entered by the user when creating their account. _**Important!** This email address is unverified; there is no proof that it actually belongs to the user._ _This field is only available when the current user has granted access to the [user-read-email](/documentation/web-api/concepts/scopes/#list-of-scopes) scope._ + explicit_content: + deprecated: true + allOf: + - $ref: '#/components/schemas/ExplicitContentSettingsObject' + description: | + The user's explicit content settings. _This field is only available when the current user has granted access to the [user-read-private](/documentation/web-api/concepts/scopes/#list-of-scopes) scope._ + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: Known external URLs for this user. + followers: + deprecated: true + allOf: + - $ref: '#/components/schemas/FollowersObject' + description: Information about the followers of the user. + href: + type: string + description: | + A link to the Web API endpoint for this user. + id: + type: string + description: | + The [Spotify user ID](/documentation/web-api/concepts/spotify-uris-ids) for the user. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: The user's profile image. + product: + deprecated: true + type: string + description: | + The user's Spotify subscription level: "premium", "free", etc. (The subscription level "open" can be considered the same as "free".) _This field is only available when the current user has granted access to the [user-read-private](/documentation/web-api/concepts/scopes/#list-of-scopes) scope._ + type: + type: string + description: | + The object type: "user" + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the user. + + PublicUserObject: + type: object + x-spotify-docs-type: PublicUserObject + properties: + display_name: + type: string + nullable: true + description: | + The name displayed on the user's profile. `null` if not available. + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known public external URLs for this user. + followers: + deprecated: true + allOf: + - $ref: '#/components/schemas/FollowersObject' + description: | + Information about the followers of this user. + href: + type: string + description: | + A link to the Web API endpoint for this user. + id: + type: string + description: | + The [Spotify user ID](/documentation/web-api/concepts/spotify-uris-ids) for this user. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + The user's profile image. + type: + type: string + enum: ['user'] + description: | + The object type. + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for this user. + + AudioAnalysisObject: + type: object + x-spotify-docs-type: AudioAnalysisObject + properties: + meta: + type: object + properties: + analyzer_version: + type: string + example: '4.0.0' + description: The version of the Analyzer used to analyze this track. + platform: + type: string + example: 'Linux' + description: The platform used to read the track's audio data. + detailed_status: + type: string + example: 'OK' + description: A detailed status code for this track. If analysis data is missing, this code may explain why. + status_code: + type: integer + example: 0 + description: The return code of the analyzer process. 0 if successful, 1 if any errors occurred. + timestamp: + type: integer + example: 1495193577 + description: The Unix timestamp (in seconds) at which this track was analyzed. + analysis_time: + type: number + example: 6.93906 + description: The amount of time taken to analyze this track. + input_process: + type: string + example: libvorbisfile L+R 44100->22050 + description: The method used to read the track's audio data. + track: + type: object + properties: + num_samples: + type: integer + example: 4585515 + description: The exact number of audio samples analyzed from this track. See also `analysis_sample_rate`. + duration: + type: number + description: Length of the track in seconds. + example: 207.95985 + sample_md5: + type: string + description: This field will always contain the empty string. + offset_seconds: + type: integer + example: 0 + description: An offset to the start of the region of the track that was analyzed. (As the entire track is analyzed, this should always be 0.) + window_seconds: + type: integer + example: 0 + description: The length of the region of the track was analyzed, if a subset of the track was analyzed. (As the entire track is analyzed, this should always be 0.) + analysis_sample_rate: + type: integer + example: 22050 + description: The sample rate used to decode and analyze this track. May differ from the actual sample rate of this track available on Spotify. + analysis_channels: + type: integer + example: 1 + description: The number of channels used for analysis. If 1, all channels are summed together to mono before analysis. + end_of_fade_in: + type: number + example: 0.0 + description: The time, in seconds, at which the track's fade-in period ends. If the track has no fade-in, this will be 0.0. + start_of_fade_out: + type: number + example: 201.13705 + description: The time, in seconds, at which the track's fade-out period starts. If the track has no fade-out, this should match the track's length. + loudness: + $ref: '#/components/schemas/Loudness' + tempo: + $ref: '#/components/schemas/Tempo' + tempo_confidence: + type: number + example: 0.73 + minimum: 0 + maximum: 1 + description: The confidence, from 0.0 to 1.0, of the reliability of the `tempo`. + time_signature: + $ref: '#/components/schemas/TimeSignature' + time_signature_confidence: + type: number + example: 0.994 + minimum: 0 + maximum: 1 + description: The confidence, from 0.0 to 1.0, of the reliability of the `time_signature`. + key: + $ref: '#/components/schemas/Key' + key_confidence: + type: number + example: 0.408 + minimum: 0 + maximum: 1 + description: The confidence, from 0.0 to 1.0, of the reliability of the `key`. + mode: + $ref: '#/components/schemas/Mode' + mode_confidence: + type: number + example: 0.485 + minimum: 0 + maximum: 1 + description: The confidence, from 0.0 to 1.0, of the reliability of the `mode`. + codestring: + type: string + description: An [Echo Nest Musical Fingerprint (ENMFP)](https://academiccommons.columbia.edu/doi/10.7916/D8Q248M4) codestring for this track. + code_version: + type: number + example: 3.15 + description: A version number for the Echo Nest Musical Fingerprint format used in the codestring field. + echoprintstring: + type: string + description: An [EchoPrint](https://github.com/spotify/echoprint-codegen) codestring for this track. + echoprint_version: + type: number + example: 4.15 + description: A version number for the EchoPrint format used in the echoprintstring field. + synchstring: + type: string + description: A [Synchstring](https://github.com/echonest/synchdata) for this track. + synch_version: + type: number + example: 1.0 + description: A version number for the Synchstring used in the synchstring field. + rhythmstring: + type: string + description: A Rhythmstring for this track. The format of this string is similar to the Synchstring. + rhythm_version: + type: number + example: 1.0 + description: A version number for the Rhythmstring used in the rhythmstring field. + bars: + type: array + description: The time intervals of the bars throughout the track. A bar (or measure) is a segment of time defined as a given number of beats. + items: + $ref: '#/components/schemas/TimeIntervalObject' + beats: + type: array + description: The time intervals of beats throughout the track. A beat is the basic time unit of a piece of music; for example, each tick of a metronome. Beats are typically multiples of tatums. + items: + $ref: '#/components/schemas/TimeIntervalObject' + sections: + type: array + description: Sections are defined by large variations in rhythm or timbre, e.g. chorus, verse, bridge, guitar solo, etc. Each section contains its own descriptions of tempo, key, mode, time_signature, and loudness. + items: + $ref: '#/components/schemas/SectionObject' + segments: + type: array + description: Each segment contains a roughly conisistent sound throughout its duration. + items: + $ref: '#/components/schemas/SegmentObject' + tatums: + type: array + description: A tatum represents the lowest regular pulse train that a listener intuitively infers from the timing of perceived musical events (segments). + items: + $ref: '#/components/schemas/TimeIntervalObject' + + TimeIntervalObject: + type: object + properties: + start: + type: number + description: The starting point (in seconds) of the time interval. + example: 0.49567 + duration: + type: number + description: The duration (in seconds) of the time interval. + example: 2.18749 + confidence: + type: number + description: The confidence, from 0.0 to 1.0, of the reliability of the interval. + example: 0.925 + minimum: 0 + maximum: 1 + + SectionObject: + type: object + properties: + start: + type: number + description: The starting point (in seconds) of the section. + example: 0.0 + duration: + type: number + description: The duration (in seconds) of the section. + example: 6.97092 + confidence: + type: number + description: The confidence, from 0.0 to 1.0, of the reliability of the section's "designation". + example: 1.0 + minimum: 0 + maximum: 1 + loudness: + type: number + description: The overall loudness of the section in decibels (dB). Loudness values are useful for comparing relative loudness of sections within tracks. + example: -14.938 + tempo: + type: number + description: The overall estimated tempo of the section in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration. + example: 113.178 + tempo_confidence: + type: number + description: The confidence, from 0.0 to 1.0, of the reliability of the tempo. Some tracks contain tempo changes or sounds which don't contain tempo (like pure speech) which would correspond to a low value in this field. + example: 0.647 + minimum: 0 + maximum: 1 + key: + type: integer + description: The estimated overall key of the section. The values in this field ranging from 0 to 11 mapping to pitches using standard Pitch Class notation (E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on). If no key was detected, the value is -1. + example: 9 + key_confidence: + type: number + description: The confidence, from 0.0 to 1.0, of the reliability of the key. Songs with many key changes may correspond to low values in this field. + example: 0.297 + minimum: 0 + maximum: 1 + mode: + type: number + description: Indicates the modality (major or minor) of a section, the type of scale from which its melodic content is derived. This field will contain a 0 for "minor", a 1 for "major", or a -1 for no result. Note that the major key (e.g. C major) could more likely be confused with the minor key at 3 semitones lower (e.g. A minor) as both keys carry the same pitches. + enum: + - -1 + - 0 + - 1 + mode_confidence: + type: number + description: The confidence, from 0.0 to 1.0, of the reliability of the `mode`. + example: 0.471 + minimum: 0 + maximum: 1 + time_signature: + $ref: '#/components/schemas/TimeSignature' + time_signature_confidence: + type: number + description: The confidence, from 0.0 to 1.0, of the reliability of the `time_signature`. Sections with time signature changes may correspond to low values in this field. + example: 1.0 + minimum: 0 + maximum: 1 + + SegmentObject: + type: object + properties: + start: + type: number + description: The starting point (in seconds) of the segment. + example: 0.70154 + duration: + type: number + description: The duration (in seconds) of the segment. + example: 0.19891 + confidence: + type: number + example: 0.435 + minimum: 0 + maximum: 1 + description: | + The confidence, from 0.0 to 1.0, of the reliability of the segmentation. Segments of the song which are difficult to logically segment (e.g: noise) may correspond to low values in this field. + loudness_start: + type: number + description: The onset loudness of the segment in decibels (dB). Combined with `loudness_max` and `loudness_max_time`, these components can be used to describe the "attack" of the segment. + example: -23.053 + loudness_max: + type: number + description: The peak loudness of the segment in decibels (dB). Combined with `loudness_start` and `loudness_max_time`, these components can be used to describe the "attack" of the segment. + example: -14.25 + loudness_max_time: + type: number + description: The segment-relative offset of the segment peak loudness in seconds. Combined with `loudness_start` and `loudness_max`, these components can be used to desctibe the "attack" of the segment. + example: 0.07305 + loudness_end: + type: number + description: The offset loudness of the segment in decibels (dB). This value should be equivalent to the loudness_start of the following segment. + example: 0.0 + pitches: + type: array + description: | + Pitch content is given by a “chroma” vector, corresponding to the 12 pitch classes C, C#, D to B, with values ranging from 0 to 1 that describe the relative dominance of every pitch in the chromatic scale. For example a C Major chord would likely be represented by large values of C, E and G (i.e. classes 0, 4, and 7). + + Vectors are normalized to 1 by their strongest dimension, therefore noisy sounds are likely represented by values that are all close to 1, while pure tones are described by one value at 1 (the pitch) and others near 0. + As can be seen below, the 12 vector indices are a combination of low-power spectrum values at their respective pitch frequencies. + ![pitch vector](/assets/audio/Pitch_vector.png) + items: + type: number + minimum: 0 + maximum: 1 + example: [0.212, 0.141, 0.294] + timbre: + type: array + description: | + Timbre is the quality of a musical note or sound that distinguishes different types of musical instruments, or voices. It is a complex notion also referred to as sound color, texture, or tone quality, and is derived from the shape of a segment’s spectro-temporal surface, independently of pitch and loudness. The timbre feature is a vector that includes 12 unbounded values roughly centered around 0. Those values are high level abstractions of the spectral surface, ordered by degree of importance. + + For completeness however, the first dimension represents the average loudness of the segment; second emphasizes brightness; third is more closely correlated to the flatness of a sound; fourth to sounds with a stronger attack; etc. See an image below representing the 12 basis functions (i.e. template segments). + ![timbre basis functions](/assets/audio/Timbre_basis_functions.png) + + The actual timbre of the segment is best described as a linear combination of these 12 basis functions weighted by the coefficient values: timbre = c1 x b1 + c2 x b2 + ... + c12 x b12, where c1 to c12 represent the 12 coefficients and b1 to b12 the 12 basis functions as displayed below. Timbre vectors are best used in comparison with each other. + items: + type: number + example: [42.115, 64.373, -0.233] + + TimeSignature: + type: integer + description: An estimated time signature. The time signature (meter) is a notational convention to specify how many beats are in each bar (or measure). The time signature ranges from 3 to 7 indicating time signatures of "3/4", to "7/4". + example: 4 + minimum: 3 + maximum: 7 + + Tempo: + type: number + example: 118.211 + format: float + x-spotify-docs-type: Float + description: | + The overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration. + + Loudness: + type: number + example: -5.883 + format: float + x-spotify-docs-type: Float + description: | + The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typically range between -60 and 0 db. + + Key: + type: integer + example: 9 + minimum: -1 + maximum: 11 + description: | + The key the track is in. Integers map to pitches using standard [Pitch Class notation](https://en.wikipedia.org/wiki/Pitch_class). E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on. If no key was detected, the value is -1. + + Mode: + type: integer + example: 0 + description: | + Mode indicates the modality (major or minor) of a track, the type of scale from which its melodic content is derived. Major is represented by 1 and minor is 0. + + AudioFeaturesObject: + type: object + x-spotify-docs-type: AudioFeaturesObject + properties: + acousticness: + type: number + format: float + example: 0.00242 + minimum: 0.0 + maximum: 1.0 + x-spotify-docs-type: Float + description: | + A confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic. + analysis_url: + type: string + example: | + https://api.spotify.com/v1/audio-analysis/2takcwOaAZWiXQijPHIx7B + description: | + A URL to access the full audio analysis of this track. An access token is required to access this data. + danceability: + type: number + example: 0.585 + format: float + x-spotify-docs-type: Float + description: | + Danceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable. + duration_ms: + type: integer + example: 237040 + description: | + The duration of the track in milliseconds. + energy: + type: number + example: 0.842 + format: float + x-spotify-docs-type: Float + description: | + Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy. + id: + type: string + example: 2takcwOaAZWiXQijPHIx7B + description: | + The Spotify ID for the track. + instrumentalness: + type: number + example: 0.00686 + format: float + x-spotify-docs-type: Float + description: | + Predicts whether a track contains no vocals. "Ooh" and "aah" sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly "vocal". The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0. + key: + $ref: '#/components/schemas/Key' + liveness: + type: number + example: 0.0866 + format: float + x-spotify-docs-type: Float + description: | + Detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live. + loudness: + $ref: '#/components/schemas/Loudness' + mode: + $ref: '#/components/schemas/Mode' + speechiness: + type: number + example: 0.0556 + format: float + x-spotify-docs-type: Float + description: | + Speechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks. + tempo: + $ref: '#/components/schemas/Tempo' + time_signature: + $ref: '#/components/schemas/TimeSignature' + track_href: + type: string + example: | + https://api.spotify.com/v1/tracks/2takcwOaAZWiXQijPHIx7B + description: | + A link to the Web API endpoint providing full details of the track. + type: + type: string + enum: ['audio_features'] + description: | + The object type. + uri: + type: string + example: spotify:track:2takcwOaAZWiXQijPHIx7B + description: | + The Spotify URI for the track. + valence: + type: number + example: 0.428 + minimum: 0 + maximum: 1 + format: float + x-spotify-docs-type: Float + description: | + A measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry). + + SimplifiedTrackObject: + type: object + x-spotify-docs-type: SimplifiedTrackObject + properties: + artists: + type: array + items: + $ref: '#/components/schemas/SimplifiedArtistObject' + description: The artists who performed the track. Each artist object includes a link in `href` to more detailed information about the artist. + available_markets: + deprecated: true + type: array + items: + type: string + description: | + A list of the countries in which the track can be played, identified by their [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code. + disc_number: + type: integer + description: The disc number (usually `1` unless the album consists of more than one disc). + duration_ms: + type: integer + description: The track length in milliseconds. + explicit: + type: boolean + description: Whether or not the track has explicit lyrics ( `true` = yes it does; `false` = no it does not OR unknown). + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + External URLs for this track. + href: + type: string + description: A link to the Web API endpoint providing full details of the track. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the track. + is_playable: + type: boolean + description: | + Part of the response when [Track Relinking](/documentation/web-api/concepts/track-relinking/) is applied. If `true`, the track is playable in the given market. Otherwise `false`. + linked_from: + deprecated: true + allOf: + - $ref: '#/components/schemas/LinkedTrackObject' + description: Part of the response when [Track Relinking](/documentation/web-api/concepts/track-relinking/) is applied and is only part of the response if the track linking, in fact, exists. The requested track has been replaced with a different track. The track in the `linked_from` object contains information about the originally requested track. + restrictions: + allOf: + - $ref: '#/components/schemas/TrackRestrictionObject' + description: | + Included in the response when a content restriction is applied. + name: + type: string + description: The name of the track. + preview_url: + deprecated: true + type: string + nullable: true + description: | + A URL to a 30 second preview (MP3 format) of the track. + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/StandalonePreview' + track_number: + type: integer + description: | + The number of the track. If an album has several discs, the track number is the number on the specified disc. + type: + type: string + description: | + The object type: "track". + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the track. + is_local: + type: boolean + description: | + Whether or not the track is from a local file. + + DeviceObject: + type: object + x-spotify-docs-type: DeviceObject + properties: + id: + type: string + nullable: true + description: The device ID. This ID is unique and persistent to some extent. However, this is not guaranteed and any cached `device_id` should periodically be cleared out and refetched as necessary. + is_active: + type: boolean + description: If this device is the currently active device. + is_private_session: + type: boolean + description: If this device is currently in a private session. + is_restricted: + type: boolean + description: Whether controlling this device is restricted. At present if this is "true" then no Web API commands will be accepted by this device. + name: + type: string + example: 'Kitchen speaker' + description: A human-readable name for the device. Some devices have a name that the user can configure (e.g. \"Loudest speaker\") and some devices have a generic name associated with the manufacturer or device model. + type: + type: string + example: 'computer' + description: Device type, such as "computer", "smartphone" or "speaker". + volume_percent: + type: integer + minimum: 0 + example: 59 + maximum: 100 + nullable: true + description: The current volume in percent. + supports_volume: + type: boolean + description: If this device can be used to set the volume. + + CursorObject: + type: object + x-spotify-docs-type: CursorObject + properties: + after: + type: string + description: The cursor to use as key to find the next page of items. + before: + type: string + description: The cursor to use as key to find the previous page of items. + + # CursorPagingObject must be part of an allOf which defines the items property as an array + CursorPagingObject: + type: object + x-spotify-docs-type: CursorPagingObject + properties: + href: + type: string + description: A link to the Web API endpoint returning the full result of the request. + limit: + type: integer + description: The maximum number of items in the response (as set in the query or by default). + next: + type: string + description: URL to the next page of items. ( `null` if none) + cursors: + allOf: + - $ref: '#/components/schemas/CursorObject' + description: The cursors used to find the next set of items. + total: + type: integer + description: The total number of items available to return. + + CursorPagingPlayHistoryObject: + type: object + x-spotify-docs-type: PagingTrackObject + allOf: + - $ref: '#/components/schemas/CursorPagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/PlayHistoryObject' + + CursorPagingSimplifiedArtistObject: + type: object + x-spotify-docs-type: PagingArtistObject + allOf: + - $ref: '#/components/schemas/CursorPagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/ArtistObject' + + # PagingObject must be part of an allOf which defines the items property as an array + PagingObject: + type: object + x-spotify-docs-type: PagingObject + required: + - href + - items + - limit + - next + - offset + - previous + - total + properties: + href: + type: string + example: | + https://api.spotify.com/v1/me/shows?offset=0&limit=20 + description: | + A link to the Web API endpoint returning the full result of the request + limit: + type: integer + example: 20 + description: | + The maximum number of items in the response (as set in the query or by default). + next: + type: string + example: https://api.spotify.com/v1/me/shows?offset=1&limit=1 + nullable: true + description: | + URL to the next page of items. ( `null` if none) + offset: + type: integer + example: 0 + description: | + The offset of the items returned (as set in the query or by default) + previous: + type: string + example: https://api.spotify.com/v1/me/shows?offset=1&limit=1 + nullable: true + description: | + URL to the previous page of items. ( `null` if none) + total: + type: integer + example: 4 + description: | + The total number of items available to return. + + PagingPlaylistObject: + type: object + x-spotify-docs-type: PagingPlaylistObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SimplifiedPlaylistObject' + + PagingFeaturedPlaylistObject: + type: object + x-spotify-docs-type: PagingFeaturedPlaylistObject + properties: + message: + type: string + description: | + The localized message of a playlist. + example: Popular Playlists + playlists: + $ref: '#/components/schemas/PagingPlaylistObject' + + PagingArtistDiscographyAlbumObject: + type: object + x-spotify-docs-type: PagingArtistDiscographyAlbumObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/ArtistDiscographyAlbumObject' + + PagingSimplifiedAlbumObject: + type: object + x-spotify-docs-type: PagingAlbumObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SimplifiedAlbumObject' + + PagingSavedAlbumObject: + type: object + x-spotify-docs-type: PagingSavedAlbumObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SavedAlbumObject' + + PagingSimplifiedTrackObject: + type: object + x-spotify-docs-type: PagingTrackObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SimplifiedTrackObject' + + PagingSavedTrackObject: + type: object + x-spotify-docs-type: PagingTrackObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SavedTrackObject' + + PagingTrackObject: + type: object + x-spotify-docs-type: PagingTrackObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/TrackObject' + + PagingPlaylistTrackObject: + type: object + x-spotify-docs-type: PagingPlaylistTrackObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/PlaylistTrackObject' + + PagingSimplifiedShowObject: + type: object + x-spotify-docs-type: PagingShowObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SimplifiedShowObject' + + PagingSavedShowObject: + type: object + x-spotify-docs-type: PagingShowObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SavedShowObject' + + PagingSimplifiedEpisodeObject: + type: object + x-spotify-docs-type: PagingEpisodeObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SimplifiedEpisodeObject' + + PagingSavedEpisodeObject: + type: object + x-spotify-docs-type: PagingEpisodeObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SavedEpisodeObject' + + PagingSimplifiedAudiobookObject: + type: object + x-spotify-docs-type: PagingAudiobookObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SimplifiedAudiobookObject' + + PagingArtistObject: + type: object + x-spotify-docs-type: PagingArtistObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/ArtistObject' + + PagingSimplifiedChapterObject: + type: object + x-spotify-docs-type: PagingSimplifiedChapterObject + allOf: + - $ref: '#/components/schemas/PagingObject' + - type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/SimplifiedChapterObject' + + RecommendationsObject: + type: object + x-spotify-docs-type: RecommendationsObject + required: + - seeds + - tracks + properties: + seeds: + type: array + items: + $ref: '#/components/schemas/RecommendationSeedObject' + description: | + An array of recommendation seed objects. + tracks: + type: array + items: + $ref: '#/components/schemas/TrackObject' + description: | + An array of track object (simplified) ordered according to the parameters supplied. + + RecommendationSeedObject: + type: object + x-spotify-docs-type: RecommendationSeedObject + properties: + afterFilteringSize: + type: integer + description: | + The number of tracks available after min\_\* and max\_\* filters have been applied. + afterRelinkingSize: + type: integer + description: | + The number of tracks available after relinking for regional availability. + href: + type: string + description: | + A link to the full track or artist data for this seed. For tracks this will be a link to a Track Object. For artists a link to an Artist Object. For genre seeds, this value will be `null`. + id: + type: string + description: | + The id used to select this seed. This will be the same as the string used in the `seed_artists`, `seed_tracks` or `seed_genres` parameter. + initialPoolSize: + type: integer + description: | + The number of recommended tracks available for this seed. + type: + type: string + description: | + The entity type of this seed. One of `artist`, `track` or `genre`. + + SavedAlbumObject: + type: object + x-spotify-docs-type: SavedAlbumObject + properties: + added_at: + type: string + format: date-time + x-spotify-docs-type: Timestamp + description: | + The date and time the album was saved + Timestamps are returned in ISO 8601 format as Coordinated Universal Time (UTC) with a zero offset: YYYY-MM-DDTHH:MM:SSZ. + If the time is imprecise (for example, the date/time of an album release), an additional field indicates the precision; see for example, release_date in an album object. + album: + allOf: + - $ref: '#/components/schemas/AlbumObject' + description: Information about the album. + + SavedTrackObject: + type: object + x-spotify-docs-type: SavedTrackObject + properties: + added_at: + type: string + format: date-time + x-spotify-docs-type: Timestamp + description: | + The date and time the track was saved. + Timestamps are returned in ISO 8601 format as Coordinated Universal Time (UTC) with a zero offset: YYYY-MM-DDTHH:MM:SSZ. + If the time is imprecise (for example, the date/time of an album release), an additional field indicates the precision; see for example, release_date in an album object. + track: + allOf: + - $ref: '#/components/schemas/TrackObject' + description: Information about the track. + + SavedEpisodeObject: + type: object + x-spotify-docs-type: SavedEpisodeObject + properties: + added_at: + type: string + format: date-time + x-spotify-docs-type: Timestamp + description: | + The date and time the episode was saved. + Timestamps are returned in ISO 8601 format as Coordinated Universal Time (UTC) with a zero offset: YYYY-MM-DDTHH:MM:SSZ. + episode: + allOf: + - $ref: '#/components/schemas/EpisodeObject' + description: Information about the episode. + + SavedShowObject: + type: object + x-spotify-docs-type: SavedShowObject + properties: + added_at: + type: string + format: date-time + x-spotify-docs-type: Timestamp + description: | + The date and time the show was saved. + Timestamps are returned in ISO 8601 format as Coordinated Universal Time (UTC) with a zero offset: YYYY-MM-DDTHH:MM:SSZ. + If the time is imprecise (for example, the date/time of an album release), an additional field indicates the precision; see for example, release_date in an album object. + show: + allOf: + - $ref: '#/components/schemas/SimplifiedShowObject' + description: Information about the show. + + PlaylistObject: + type: object + x-spotify-docs-type: PlaylistObject + properties: + collaborative: + type: boolean + description: | + `true` if the owner allows other users to modify the playlist. + description: + type: string + nullable: true + description: | + The playlist description. _Only returned for modified, verified playlists, otherwise_ `null`. + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known external URLs for this playlist. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the playlist. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the playlist. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + Images for the playlist. The array may be empty or contain up to three images. The images are returned by size in descending order. See [Working with Playlists](/documentation/web-api/concepts/playlists). _**Note**: If returned, the source URL for the image (`url`) is temporary and will expire in less than a day._ + name: + type: string + description: | + The name of the playlist. + owner: + allOf: + - $ref: '#/components/schemas/PlaylistOwnerObject' + description: | + The user who owns the playlist + public: + type: boolean + description: | + The playlist's public/private status (if it is added to the user's profile): `true` the playlist is public, `false` the playlist is private, `null` the playlist status is not relevant. For more about public/private status, see [Working with Playlists](/documentation/web-api/concepts/playlists) + snapshot_id: + type: string + description: | + The version identifier for the current playlist. Can be supplied in other requests to target a specific playlist version + items: + type: object + allOf: + - $ref: '#/components/schemas/PagingPlaylistTrackObject' + description: | + The items of the playlist. _**Note**: This field is only available for playlists owned by the current user or playlists the user is a collaborator of._ + tracks: + type: object + allOf: + - $ref: '#/components/schemas/PagingPlaylistTrackObject' + deprecated: true + description: | + **Deprecated:** Use `items` instead. The tracks of the playlist. + type: + type: string + description: | + The object type: "playlist" + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the playlist. + + SimplifiedPlaylistObject: + type: object + x-spotify-docs-type: SimplifiedPlaylistObject + properties: + collaborative: + type: boolean + description: | + `true` if the owner allows other users to modify the playlist. + description: + type: string + description: | + The playlist description. _Only returned for modified, verified playlists, otherwise_ `null`. + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known external URLs for this playlist. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the playlist. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the playlist. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + Images for the playlist. The array may be empty or contain up to three images. The images are returned by size in descending order. See [Working with Playlists](/documentation/web-api/concepts/playlists). _**Note**: If returned, the source URL for the image (`url`) is temporary and will expire in less than a day._ + name: + type: string + description: | + The name of the playlist. + owner: + allOf: + - $ref: '#/components/schemas/PlaylistOwnerObject' + description: | + The user who owns the playlist + public: + type: boolean + description: | + The playlist's public/private status (if it is added to the user's profile): `true` the playlist is public, `false` the playlist is private, `null` the playlist status is not relevant. For more about public/private status, see [Working with Playlists](/documentation/web-api/concepts/playlists) + snapshot_id: + type: string + description: | + The version identifier for the current playlist. Can be supplied in other requests to target a specific playlist version + items: + allOf: + - $ref: '#/components/schemas/PlaylistTracksRefObject' + description: | + A collection containing a link ( `href` ) to the Web API endpoint where full details of the playlist's items can be retrieved, along with the `total` number of items in the playlist. Note, a track object may be `null`. This can happen if a track is no longer available. + tracks: + allOf: + - $ref: '#/components/schemas/PlaylistTracksRefObject' + deprecated: true + description: | + **Deprecated:** Use `items` instead. A collection containing a link ( `href` ) to the Web API endpoint where full details of the playlist's tracks can be retrieved, along with the `total` number of tracks in the playlist. Note, a track object may be `null`. This can happen if a track is no longer available. + type: + type: string + description: | + The object type: "playlist" + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the playlist. + + PlaylistTracksRefObject: + type: object + x-spotify-docs-type: PlaylistTracksRefObject + properties: + href: + type: string + description: | + A link to the Web API endpoint where full details of the playlist's tracks can be retrieved. + total: + type: integer + description: | + Number of tracks in the playlist. + + PlaylistUserObject: + type: object + x-spotify-docs-type: PlaylistUserObject + properties: + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known public external URLs for this user. + href: + type: string + description: | + A link to the Web API endpoint for this user. + id: + type: string + description: | + The [Spotify user ID](/documentation/web-api/concepts/spotify-uris-ids) for this user. + type: + type: string + enum: ['user'] + description: | + The object type. + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for this user. + + PlaylistOwnerObject: + allOf: + - $ref: '#/components/schemas/PlaylistUserObject' + - type: object + properties: + display_name: + type: string + nullable: true + description: | + The name displayed on the user's profile. `null` if not available. + + CategoryObject: + type: object + x-spotify-docs-type: CategoryObject + required: + - href + - icons + - id + - name + properties: + href: + type: string + description: | + A link to the Web API endpoint returning full details of the category. + icons: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + The category icon, in various sizes. + id: + type: string + example: equal + description: | + The [Spotify category ID](/documentation/web-api/concepts/spotify-uris-ids) of the category. + name: + type: string + example: EQUAL + description: | + The name of the category. + + TrackObject: + type: object + x-spotify-docs-type: TrackObject + properties: + album: + allOf: + - $ref: '#/components/schemas/SimplifiedAlbumObject' + description: | + The album on which the track appears. The album object includes a link in `href` to full information about the album. + artists: + type: array + items: + $ref: '#/components/schemas/SimplifiedArtistObject' + description: | + The artists who performed the track. Each artist object includes a link in `href` to more detailed information about the artist. + available_markets: + deprecated: true + type: array + items: + type: string + description: | + A list of the countries in which the track can be played, identified by their [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code. + disc_number: + type: integer + description: | + The disc number (usually `1` unless the album consists of more than one disc). + duration_ms: + type: integer + description: | + The track length in milliseconds. + explicit: + type: boolean + description: | + Whether or not the track has explicit lyrics ( `true` = yes it does; `false` = no it does not OR unknown). + external_ids: + allOf: + - $ref: '#/components/schemas/ExternalIdObject' + description: | + Known external IDs for the track. + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known external URLs for this track. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the track. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the track. + is_playable: + type: boolean + description: | + Part of the response when [Track Relinking](/documentation/web-api/concepts/track-relinking) is applied. If `true`, the track is playable in the given market. Otherwise `false`. + linked_from: + deprecated: true + type: object + description: | + Part of the response when [Track Relinking](/documentation/web-api/concepts/track-relinking) is applied, and the requested track has been replaced with different track. The track in the `linked_from` object contains information about the originally requested track. + restrictions: + allOf: + - $ref: '#/components/schemas/TrackRestrictionObject' + description: | + Included in the response when a content restriction is applied. + name: + type: string + description: | + The name of the track. + popularity: + deprecated: true + type: integer + description: | + The popularity of the track. The value will be between 0 and 100, with 100 being the most popular.
The popularity of a track is a value between 0 and 100, with 100 being the most popular. The popularity is calculated by algorithm and is based, in the most part, on the total number of plays the track has had and how recent those plays are.
Generally speaking, songs that are being played a lot now will have a higher popularity than songs that were played a lot in the past. Duplicate tracks (e.g. the same track from a single and an album) are rated independently. Artist and album popularity is derived mathematically from track popularity. _**Note**: the popularity value may lag actual popularity by a few days: the value is not updated in real time._ + preview_url: + deprecated: true + type: string + nullable: true + description: | + A link to a 30 second preview (MP3 format) of the track. Can be `null` + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/StandalonePreview' + track_number: + type: integer + description: | + The number of the track. If an album has several discs, the track number is the number on the specified disc. + type: + type: string + description: | + The object type: "track". + enum: ['track'] + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the track. + is_local: + type: boolean + description: | + Whether or not the track is from a local file. + + EpisodeObject: + x-spotify-docs-type: EpisodeObject + type: object + allOf: + - $ref: '#/components/schemas/EpisodeBase' + - type: object + required: + - show + properties: + show: + allOf: + - $ref: '#/components/schemas/SimplifiedShowObject' + description: | + The show on which the episode belongs. + + SimplifiedEpisodeObject: + x-spotify-docs-type: SimplifiedEpisodeObject + type: object + allOf: + - $ref: '#/components/schemas/EpisodeBase' + - type: object + + EpisodeBase: + type: object + required: + - audio_preview_url + - description + - html_description + - duration_ms + - explicit + - external_urls + - href + - id + - images + - is_externally_hosted + - is_playable + - languages + - name + - release_date + - release_date_precision + - type + - uri + properties: + audio_preview_url: + deprecated: true + type: string + nullable: true + example: https://p.scdn.co/mp3-preview/2f37da1d4221f40b9d1a98cd191f4d6f1646ad17 + description: | + A URL to a 30 second preview (MP3 format) of the episode. `null` if not available. + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/StandalonePreview' + description: + type: string + example: | + A Spotify podcast sharing fresh insights on important topics of the moment—in a way only Spotify can. You’ll hear from experts in the music, podcast and tech industries as we discover and uncover stories about our work and the world around us. + description: | + A description of the episode. HTML tags are stripped away from this field, use `html_description` field in case HTML tags are needed. + html_description: + type: string + example: | +

A Spotify podcast sharing fresh insights on important topics of the moment—in a way only Spotify can. You’ll hear from experts in the music, podcast and tech industries as we discover and uncover stories about our work and the world around us.

+ description: | + A description of the episode. This field may contain HTML tags. + duration_ms: + type: integer + example: 1686230 + description: | + The episode length in milliseconds. + explicit: + type: boolean + description: | + Whether or not the episode has explicit content (true = yes it does; false = no it does not OR unknown). + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + External URLs for this episode. + href: + type: string + example: https://api.spotify.com/v1/episodes/5Xt5DXGzch68nYYamXrNxZ + description: | + A link to the Web API endpoint providing full details of the episode. + id: + type: string + example: 5Xt5DXGzch68nYYamXrNxZ + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the episode. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + The cover art for the episode in various sizes, widest first. + is_externally_hosted: + type: boolean + description: | + True if the episode is hosted outside of Spotify's CDN. + is_playable: + type: boolean + description: | + True if the episode is playable in the given market. Otherwise false. + language: + type: string + deprecated: true + example: en + description: | + The language used in the episode, identified by a [ISO 639](https://en.wikipedia.org/wiki/ISO_639) code. This field is deprecated and might be removed in the future. Please use the `languages` field instead. + languages: + type: array + items: + type: string + example: ['fr', 'en'] + description: | + A list of the languages used in the episode, identified by their [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639) code. + name: + type: string + example: | + Starting Your Own Podcast: Tips, Tricks, and Advice From Anchor Creators + description: | + The name of the episode. + release_date: + type: string + example: '1981-12-15' + description: | + The date the episode was first released, for example `"1981-12-15"`. Depending on the precision, it might be shown as `"1981"` or `"1981-12"`. + release_date_precision: + type: string + example: day + enum: ['year', 'month', 'day'] + description: | + The precision with which `release_date` value is known. + resume_point: + allOf: + - $ref: '#/components/schemas/ResumePointObject' + description: | + The user's most recent position in the episode. Set if the supplied access token is a user token and has the scope 'user-read-playback-position'. + type: + type: string + enum: ['episode'] + description: | + The object type. + uri: + type: string + example: spotify:episode:0zLhl3WsOCQHbe1BPTiHgr + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the episode. + restrictions: + allOf: + - $ref: '#/components/schemas/EpisodeRestrictionObject' + description: | + Included in the response when a content restriction is applied. + + ResumePointObject: + type: object + x-spotify-docs-type: ResumePointObject + properties: + fully_played: + type: boolean + description: | + Whether or not the episode has been fully played by the user. + resume_position_ms: + type: integer + description: | + The user's most recent position in the episode in milliseconds. + + ShowBase: + type: object + required: + - available_markets + - copyrights + - description + - explicit + - external_urls + - href + - html_description + - id + - images + - is_externally_hosted + - languages + - media_type + - name + - publisher + - total_episodes + - type + - uri + properties: + available_markets: + deprecated: true + type: array + items: + type: string + description: | + A list of the countries in which the show can be played, identified by their [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code. + copyrights: + type: array + items: + $ref: '#/components/schemas/CopyrightObject' + description: | + The copyright statements of the show. + description: + type: string + description: | + A description of the show. HTML tags are stripped away from this field, use `html_description` field in case HTML tags are needed. + html_description: + type: string + description: | + A description of the show. This field may contain HTML tags. + explicit: + type: boolean + description: | + Whether or not the show has explicit content (true = yes it does; false = no it does not OR unknown). + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + External URLs for this show. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the show. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the show. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + The cover art for the show in various sizes, widest first. + is_externally_hosted: + type: boolean + description: | + True if all of the shows episodes are hosted outside of Spotify's CDN. This field might be `null` in some cases. + languages: + type: array + items: + type: string + description: | + A list of the languages used in the show, identified by their [ISO 639](https://en.wikipedia.org/wiki/ISO_639) code. + media_type: + type: string + description: | + The media type of the show. + name: + type: string + description: | + The name of the episode. + publisher: + deprecated: true + type: string + description: | + The publisher of the show. + type: + type: string + enum: ['show'] + description: | + The object type. + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the show. + total_episodes: + type: integer + description: | + The total number of episodes in the show. + + ShowObject: + x-spotify-docs-type: ShowObject + allOf: + - $ref: '#/components/schemas/ShowBase' + - type: object + required: + - episodes + properties: + episodes: + type: object + allOf: + - $ref: '#/components/schemas/PagingSimplifiedEpisodeObject' + description: | + The episodes of the show. + + SimplifiedShowObject: + x-spotify-docs-type: SimplifiedShowObject + allOf: + - $ref: '#/components/schemas/ShowBase' + - type: object + + AudiobookBase: + type: object + required: + - authors + - available_markets + - copyrights + - description + - explicit + - external_urls + - href + - html_description + - id + - images + - languages + - media_type + - name + - narrators + - publisher + - total_chapters + - type + - uri + properties: + authors: + type: array + items: + $ref: '#/components/schemas/AuthorObject' + description: | + The author(s) for the audiobook. + available_markets: + deprecated: true + type: array + items: + type: string + description: | + A list of the countries in which the audiobook can be played, identified by their [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code. + copyrights: + type: array + items: + $ref: '#/components/schemas/CopyrightObject' + description: | + The copyright statements of the audiobook. + description: + type: string + description: | + A description of the audiobook. HTML tags are stripped away from this field, use `html_description` field in case HTML tags are needed. + html_description: + type: string + description: | + A description of the audiobook. This field may contain HTML tags. + edition: + type: string + description: | + The edition of the audiobook. + example: 'Unabridged' + explicit: + type: boolean + description: | + Whether or not the audiobook has explicit content (true = yes it does; false = no it does not OR unknown). + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + External URLs for this audiobook. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the audiobook. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the audiobook. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + The cover art for the audiobook in various sizes, widest first. + languages: + type: array + items: + type: string + description: | + A list of the languages used in the audiobook, identified by their [ISO 639](https://en.wikipedia.org/wiki/ISO_639) code. + media_type: + type: string + description: | + The media type of the audiobook. + name: + type: string + description: | + The name of the audiobook. + narrators: + type: array + items: + $ref: '#/components/schemas/NarratorObject' + description: | + The narrator(s) for the audiobook. + publisher: + deprecated: true + type: string + description: | + The publisher of the audiobook. + type: + type: string + enum: ['audiobook'] + description: | + The object type. + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the audiobook. + total_chapters: + type: integer + description: | + The number of chapters in this audiobook. + + AudiobookObject: + x-spotify-docs-type: AudiobookObject + allOf: + - $ref: '#/components/schemas/AudiobookBase' + - type: object + required: + - chapters + properties: + chapters: + type: object + allOf: + - $ref: '#/components/schemas/PagingSimplifiedChapterObject' + description: | + The chapters of the audiobook. + + SimplifiedAudiobookObject: + x-spotify-docs-type: SimplifiedAudiobookObject + allOf: + - $ref: '#/components/schemas/AudiobookBase' + - type: object + + AlbumBase: + type: object + required: + - album_type + - total_tracks + - available_markets + - external_urls + - href + - id + - images + - name + - release_date + - release_date_precision + - type + - uri + properties: + album_type: + type: string + description: | + The type of the album. + enum: [album, single, compilation] + example: compilation + total_tracks: + type: integer + description: The number of tracks in the album. + example: 9 + available_markets: + deprecated: true + type: array + items: + type: string + example: ['CA', 'BR', 'IT'] + description: | + The markets in which the album is available: [ISO 3166-1 alpha-2 country codes](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). _**NOTE**: an album is considered available in a market when at least 1 of its tracks is available in that market._ + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + Known external URLs for this album. + href: + type: string + description: | + A link to the Web API endpoint providing full details of the album. + id: + type: string + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the album. + example: 2up3OPMp9Tb4dAKM2erWXQ + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + The cover art for the album in various sizes, widest first. + name: + type: string + description: | + The name of the album. In case of an album takedown, the value may be an empty string. + release_date: + type: string + example: '1981-12' + description: | + The date the album was first released. + release_date_precision: + type: string + enum: ['year', 'month', 'day'] + example: 'year' + description: | + The precision with which `release_date` value is known. + restrictions: + allOf: + - $ref: '#/components/schemas/AlbumRestrictionObject' + description: | + Included in the response when a content restriction is applied. + type: + type: string + enum: ['album'] + description: | + The object type. + uri: + type: string + example: 'spotify:album:2up3OPMp9Tb4dAKM2erWXQ' + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the album. + + SimplifiedAlbumObject: + x-spotify-docs-type: SimplifiedAlbumObject + allOf: + - $ref: '#/components/schemas/AlbumBase' + - type: object + required: + - artists + properties: + artists: + type: array + items: + $ref: '#/components/schemas/SimplifiedArtistObject' + description: | + The artists of the album. Each artist object includes a link in `href` to more detailed information about the artist. + + ArtistDiscographyAlbumObject: + x-spotify-docs-type: ArtistDiscographyAlbumObject + allOf: + - $ref: '#/components/schemas/SimplifiedAlbumObject' + - type: object + required: + - album_group + properties: + album_group: + deprecated: true + type: string + enum: [album, single, compilation, appears_on] + example: compilation + description: | + This field describes the relationship between the artist and the album. + + ChapterObject: + x-spotify-docs-type: ChapterObject + type: object + allOf: + - $ref: '#/components/schemas/ChapterBase' + - type: object + required: + - audiobook + properties: + audiobook: + allOf: + - $ref: '#/components/schemas/SimplifiedAudiobookObject' + description: | + The audiobook for which the chapter belongs. + + SimplifiedChapterObject: + x-spotify-docs-type: SimplifiedChapterObject + type: object + allOf: + - $ref: '#/components/schemas/ChapterBase' + - type: object + + ChapterBase: + type: object + required: + - audio_preview_url + - chapter_number + - description + - html_description + - duration_ms + - explicit + - external_urls + - href + - id + - images + - is_playable + - languages + - name + - release_date + - release_date_precision + - type + - uri + properties: + audio_preview_url: + deprecated: true + type: string + nullable: true + example: https://p.scdn.co/mp3-preview/2f37da1d4221f40b9d1a98cd191f4d6f1646ad17 + description: | + A URL to a 30 second preview (MP3 format) of the chapter. `null` if not available. + x-spotify-policy-list: + - $ref: '#/components/x-spotify-policy/policies/StandalonePreview' + available_markets: + deprecated: true + type: array + items: + type: string + description: | + A list of the countries in which the chapter can be played, identified by their [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code. + chapter_number: + type: integer + example: 1 + description: | + The number of the chapter + description: + type: string + example: | + We kept on ascending, with occasional periods of quick descent, but in the main always ascending. Suddenly, I became conscious of the fact that the driver was in the act of pulling up the horses in the courtyard of a vast ruined castle, from whose tall black windows came no ray of light, and whose broken battlements showed a jagged line against the moonlit sky. + description: | + A description of the chapter. HTML tags are stripped away from this field, use `html_description` field in case HTML tags are needed. + html_description: + type: string + example: | +

We kept on ascending, with occasional periods of quick descent, but in the main always ascending. Suddenly, I became conscious of the fact that the driver was in the act of pulling up the horses in the courtyard of a vast ruined castle, from whose tall black windows came no ray of light, and whose broken battlements showed a jagged line against the moonlit sky.

+ description: | + A description of the chapter. This field may contain HTML tags. + duration_ms: + type: integer + example: 1686230 + description: | + The chapter length in milliseconds. + explicit: + type: boolean + description: | + Whether or not the chapter has explicit content (true = yes it does; false = no it does not OR unknown). + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: | + External URLs for this chapter. + href: + type: string + example: https://api.spotify.com/v1/episodes/5Xt5DXGzch68nYYamXrNxZ + description: | + A link to the Web API endpoint providing full details of the chapter. + id: + type: string + example: 5Xt5DXGzch68nYYamXrNxZ + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) for the chapter. + images: + type: array + items: + $ref: '#/components/schemas/ImageObject' + description: | + The cover art for the chapter in various sizes, widest first. + is_playable: + type: boolean + description: | + True if the chapter is playable in the given market. Otherwise false. + languages: + type: array + items: + type: string + example: ['fr', 'en'] + description: | + A list of the languages used in the chapter, identified by their [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639) code. + name: + type: string + example: | + Starting Your Own Podcast: Tips, Tricks, and Advice From Anchor Creators + description: | + The name of the chapter. + release_date: + type: string + example: '1981-12-15' + description: | + The date the chapter was first released, for example `"1981-12-15"`. Depending on the precision, it might be shown as `"1981"` or `"1981-12"`. + release_date_precision: + type: string + example: day + enum: ['year', 'month', 'day'] + description: | + The precision with which `release_date` value is known. + resume_point: + allOf: + - $ref: '#/components/schemas/ResumePointObject' + description: | + The user's most recent position in the chapter. Set if the supplied access token is a user token and has the scope 'user-read-playback-position'. + type: + type: string + enum: ['episode'] + description: | + The object type. + uri: + type: string + example: spotify:episode:0zLhl3WsOCQHbe1BPTiHgr + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the chapter. + restrictions: + allOf: + - $ref: '#/components/schemas/ChapterRestrictionObject' + description: | + Included in the response when a content restriction is applied. + + AlbumObject: + x-spotify-docs-type: AlbumObject + required: + - artists + - tracks + - copyrights + - external_ids + - genres + - label + - popularity + allOf: + - $ref: '#/components/schemas/AlbumBase' + - type: object + properties: + artists: + type: array + items: + $ref: '#/components/schemas/SimplifiedArtistObject' + description: | + The artists of the album. Each artist object includes a link in `href` to more detailed information about the artist. + tracks: + allOf: + - $ref: '#/components/schemas/PagingSimplifiedTrackObject' + description: | + The tracks of the album. + copyrights: + type: array + items: + $ref: '#/components/schemas/CopyrightObject' + description: | + The copyright statements of the album. + external_ids: + allOf: + - $ref: '#/components/schemas/ExternalIdObject' + description: | + Known external IDs for the album. + genres: + type: array + items: + type: string + deprecated: true + example: [] + description: | + **Deprecated** The array is always empty. + label: + deprecated: true + type: string + description: | + The label associated with the album. + popularity: + deprecated: true + type: integer + description: | + The popularity of the album. The value will be between 0 and 100, with 100 being the most popular. + + ContextObject: + type: object + x-spotify-docs-type: ContextObject + properties: + type: + type: string + description: | + The object type, e.g. "artist", "playlist", "album", "show". + href: + type: string + description: A link to the Web API endpoint providing full details of the track. + external_urls: + allOf: + - $ref: '#/components/schemas/ExternalUrlObject' + description: External URLs for this context. + uri: + type: string + description: | + The [Spotify URI](/documentation/web-api/concepts/spotify-uris-ids) for the context. + + CopyrightObject: + type: object + x-spotify-docs-type: CopyrightObject + properties: + text: + type: string + description: | + The copyright text for this content. + type: + type: string + description: | + The type of copyright: `C` = the copyright, `P` = the sound recording (performance) copyright. + + AuthorObject: + type: object + x-spotify-docs-type: AuthorObject + properties: + name: + type: string + description: | + The name of the author. + + NarratorObject: + type: object + x-spotify-docs-type: NarratorObject + properties: + name: + type: string + description: | + The name of the Narrator. + + ExternalIdObject: + type: object + x-spotify-docs-type: ExternalIdObject + properties: + isrc: + type: string + description: | + [International Standard Recording Code](http://en.wikipedia.org/wiki/International_Standard_Recording_Code) + ean: + type: string + description: | + [International Article Number](http://en.wikipedia.org/wiki/International_Article_Number_%28EAN%29) + upc: + type: string + description: | + [Universal Product Code](http://en.wikipedia.org/wiki/Universal_Product_Code) + + ExternalUrlObject: + type: object + x-spotify-docs-type: ExternalUrlObject + properties: + spotify: + type: string + description: | + The [Spotify URL](/documentation/web-api/concepts/spotify-uris-ids) for the object. + + FollowersObject: + type: object + x-spotify-docs-type: FollowersObject + properties: + href: + type: string + nullable: true + description: | + This will always be set to null, as the Web API does not support it at the moment. + total: + type: integer + description: | + The total number of followers. + + ImageObject: + type: object + x-spotify-docs-type: ImageObject + required: + - url + - height + - width + properties: + url: + type: string + example: | + https://i.scdn.co/image/ab67616d00001e02ff9ca10b55ce82ae553c8228 + description: | + The source URL of the image. + height: + type: integer + example: 300 + nullable: true + description: | + The image height in pixels. + width: + type: integer + example: 300 + nullable: true + description: | + The image width in pixels. + + ExplicitContentSettingsObject: + type: object + x-spotify-docs-type: ExplicitContentSettingsObject + properties: + filter_enabled: + type: boolean + description: | + When `true`, indicates that explicit content should not be played. + filter_locked: + type: boolean + description: | + When `true`, indicates that the explicit content setting is locked and can't be changed by the user. + parameters: + PathAlbumId: + in: path + name: id + required: true + schema: + title: Spotify Album ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) of the album. + example: 4aawyAB9vmqN3uQ7FjRGTy + type: string + PathPlaylistId: + name: playlist_id + required: true + in: path + schema: + title: Playlist ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) of the playlist. + example: 3cEYpjA9oz9GiPac4AsH4n + type: string + QueryMarket: + name: market + required: false + in: query + schema: + title: Market + description: | + An [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). + If a country code is specified, only content that is available in that market will be returned.
+ If a valid user access token is specified in the request header, the country associated with + the user account will take priority over this parameter.
+ _**Note**: If neither market or user country are provided, the content is considered unavailable for the client._
+ Users can view the country that is associated with their account in the [account settings](https://www.spotify.com/account/overview/). + example: ES + type: string + QueryLimit: + name: limit + required: false + in: query + schema: + title: Limit + description: | + The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + default: 20 + example: 10 + type: integer + minimum: 0 + maximum: 50 + QueryOffset: + name: offset + required: false + in: query + schema: + title: Offset + description: | + The index of the first item to return. Default: 0 (the first item). Use with limit to get the next set of items. + default: 0 + example: 5 + type: integer + QueryAdditionalTypes: + name: additional_types + required: false + in: query + schema: + title: Additional Types + description: | + A comma-separated list of item types that your client supports besides the default `track` type. Valid types are: `track` and `episode`.
+ _**Note**: This parameter was introduced to allow existing clients to maintain their current behaviour and might be deprecated in the future._
+ In addition to providing this parameter, make sure that your client properly handles cases of new types in the future by checking against the `type` field of each object. + type: string + QueryAlbumIds: + name: ids + required: true + in: query + schema: + title: Spotify Album IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) for the albums. Maximum: 20 IDs. + example: 382ObEPsp2rxGrnsizN5TX,1A2GTWGtFfWp7KSQTwWOyo,2noRn2Aes5aoNVsU6iWThc + type: string + PathArtistId: + name: id + required: true + in: path + schema: + title: Spotify Artist ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) of the artist. + example: 0TnOYISbd1XYRBk9myaseg + type: string + PathShowId: + name: id + required: true + in: path + schema: + title: Spotify Show ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) + for the show. + example: 38bS44xjbVVZ3No3ByF1dJ + type: string + PathAudiobookId: + name: id + required: true + in: path + schema: + title: Spotify Audiobook ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) + for the audiobook. + example: 7iHfbu1YPACw6oZPAFJtqe + type: string + QueryAudiobookIds: + name: ids + required: true + in: query + schema: + title: Spotify Audiobook IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `ids=18yVqkdbdRvS24c0Ilj2ci,1HGw3J3NxZO1TP1BTtVhpZ`. Maximum: 50 IDs. + example: 18yVqkdbdRvS24c0Ilj2ci,1HGw3J3NxZO1TP1BTtVhpZ,7iHfbu1YPACw6oZPAFJtqe + type: string + PathChapterId: + name: id + required: true + in: path + schema: + title: Spotify Chapter ID + description: | + The [Spotify ID](/documentation/web-api/concepts/spotify-uris-ids) + for the chapter. + example: 0D5wENdkdwbqlrHoaJ9g29 + type: string + QueryChapterIds: + name: ids + required: true + in: query + schema: + title: Spotify Chapter IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `ids=0IsXVP0JmcB2adSE338GkK,3ZXb8FKZGU0EHALYX6uCzU`. Maximum: 50 IDs. + example: 0IsXVP0JmcB2adSE338GkK,3ZXb8FKZGU0EHALYX6uCzU,0D5wENdkdwbqlrHoaJ9g29 + type: string + QueryTrackIds: + name: ids + required: true + in: query + schema: + title: Spotify Track IDs + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids). For example: `ids=4iV5W9uYEdYUVa79Axb7Rh,1301WleyT98MSxVHPZCA6M`. Maximum: 50 IDs. + example: 7ouMYWpwJ422jRcDASZB7P,4VqPOruhp5EdPBeR92t6lQ,2takcwOaAZWiXQijPHIx7B + type: string + QueryIncludeGroups: + name: include_groups + required: false + in: query + schema: + title: Groups to include (single, album, appears_on, compilation) + description: | + A comma-separated list of keywords that will be used to filter the response. If not supplied, all album types will be returned.
+ Valid values are:
- `album`
- `single`
- `appears_on`
- `compilation`
For example: `include_groups=album,single`. + example: single,appears_on + type: string + QueryShowIds: + name: ids + required: true + in: query + schema: + title: Ids + description: | + A comma-separated list of the [Spotify IDs](/documentation/web-api/concepts/spotify-uris-ids) for the shows. Maximum: 50 IDs. + example: 5CfCWKI5pZ28U0uOzXkDHe,5as3aKmN2k11yfDDDSrvaZ + type: string + PathUserId: + name: user_id + required: true + in: path + schema: + title: User ID + description: | + The user's [Spotify user ID](/documentation/web-api/concepts/spotify-uris-ids). + example: smedjan + type: string diff --git a/src/test/fixtures/requests/data/library/CheckUsersSavedAlbumsRequest.json b/src/test/fixtures/requests/data/albums/CheckUsersSavedAlbumsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/CheckUsersSavedAlbumsRequest.json rename to src/test/fixtures/requests/data/albums/CheckUsersSavedAlbumsRequest.json diff --git a/src/test/fixtures/requests/data/albums/GetNewReleasesRequest.json b/src/test/fixtures/requests/data/albums/GetNewReleasesRequest.json new file mode 100644 index 000000000..39a8abd0c --- /dev/null +++ b/src/test/fixtures/requests/data/albums/GetNewReleasesRequest.json @@ -0,0 +1,45 @@ +{ + "albums": { + "href": "https://api.spotify.com/v1/browse/new-releases?country=SE&offset=0&limit=2", + "items": [ + { + "album_type": "SINGLE", + "artists": [ + { + "external_urls": { + "spotify": "https://open.spotify.com/artist/2RdwBSPQiwcmiDo9kixcl8" + }, + "href": "https://api.spotify.com/v1/artists/2RdwBSPQiwcmiDo9kixcl8", + "id": "2RdwBSPQiwcmiDo9kixcl8", + "name": "Pharrell Williams", + "type": "artist", + "uri": "spotify:artist:2RdwBSPQiwcmiDo9kixcl8" + } + ], + "available_markets": ["SE"], + "external_urls": { + "spotify": "https://open.spotify.com/album/5ZX4m5aVSmWQ5iHAPQpT71" + }, + "href": "https://api.spotify.com/v1/albums/5ZX4m5aVSmWQ5iHAPQpT71", + "id": "5ZX4m5aVSmWQ5iHAPQpT71", + "images": [ + { + "height": 640, + "url": "https://i.scdn.co/image/e6b635ebe3ef4ba22492f5698a7b5d417f78b88a", + "width": 640 + } + ], + "name": "Runnin'", + "release_date": "2016-03-18", + "release_date_precision": "day", + "type": "album", + "uri": "spotify:album:5ZX4m5aVSmWQ5iHAPQpT71" + } + ], + "limit": 2, + "next": null, + "offset": 0, + "previous": null, + "total": 1 + } +} diff --git a/src/test/fixtures/requests/data/albums/GetSeveralAlbumsRequest.json b/src/test/fixtures/requests/data/albums/GetSeveralAlbumsRequest.json new file mode 100644 index 000000000..672ffa667 --- /dev/null +++ b/src/test/fixtures/requests/data/albums/GetSeveralAlbumsRequest.json @@ -0,0 +1,32 @@ +{ + "albums": [ + { + "album_type": "album", + "artists": [ + { + "external_urls": { + "spotify": "https://open.spotify.com/artist/2BTZIqw0ntH9MvilQ3ewNY" + }, + "href": "https://api.spotify.com/v1/artists/2BTZIqw0ntH9MvilQ3ewNY", + "id": "2BTZIqw0ntH9MvilQ3ewNY", + "name": "Cyndi Lauper", + "type": "artist", + "uri": "spotify:artist:2BTZIqw0ntH9MvilQ3ewNY" + } + ], + "available_markets": ["US", "GB"], + "external_urls": { + "spotify": "https://open.spotify.com/album/0sNOF9WDwhWunNAHPD3Baj" + }, + "href": "https://api.spotify.com/v1/albums/0sNOF9WDwhWunNAHPD3Baj", + "id": "0sNOF9WDwhWunNAHPD3Baj", + "images": [], + "name": "She's So Unusual", + "release_date": "1983", + "release_date_precision": "year", + "total_tracks": 12, + "type": "album", + "uri": "spotify:album:0sNOF9WDwhWunNAHPD3Baj" + } + ] +} diff --git a/src/test/fixtures/requests/data/library/GetCurrentUsersSavedAlbumsRequest.json b/src/test/fixtures/requests/data/albums/GetUsersSavedAlbumsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/GetCurrentUsersSavedAlbumsRequest.json rename to src/test/fixtures/requests/data/albums/GetUsersSavedAlbumsRequest.json diff --git a/src/test/fixtures/requests/data/albums/RemoveAlbumsForCurrentUserRequest.json b/src/test/fixtures/requests/data/albums/RemoveAlbumsForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/albums/RemoveAlbumsForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/albums/SaveAlbumsForCurrentUserRequest.json b/src/test/fixtures/requests/data/albums/SaveAlbumsForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/albums/SaveAlbumsForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/artists/GetArtistsTopTracksRequest.json b/src/test/fixtures/requests/data/artists/GetArtistsTopTracksRequest.json new file mode 100644 index 000000000..27ef9f484 --- /dev/null +++ b/src/test/fixtures/requests/data/artists/GetArtistsTopTracksRequest.json @@ -0,0 +1,65 @@ +{ + "tracks": [ + { + "album": { + "album_type": "album", + "artists": [ + { + "external_urls": { + "spotify": "https://open.spotify.com/artist/0OdUWJ0sBjDrqHygGUXeCF" + }, + "href": "https://api.spotify.com/v1/artists/0OdUWJ0sBjDrqHygGUXeCF", + "id": "0OdUWJ0sBjDrqHygGUXeCF", + "name": "Band of Horses", + "type": "artist", + "uri": "spotify:artist:0OdUWJ0sBjDrqHygGUXeCF" + } + ], + "available_markets": ["US"], + "external_urls": { + "spotify": "https://open.spotify.com/album/1oR3KrPIp4CbagPa3PhtPp" + }, + "href": "https://api.spotify.com/v1/albums/1oR3KrPIp4CbagPa3PhtPp", + "id": "1oR3KrPIp4CbagPa3PhtPp", + "images": [], + "name": "Everything All the Time", + "release_date": "2006-03-21", + "release_date_precision": "day", + "total_tracks": 10, + "type": "album", + "uri": "spotify:album:1oR3KrPIp4CbagPa3PhtPp" + }, + "artists": [ + { + "external_urls": { + "spotify": "https://open.spotify.com/artist/0OdUWJ0sBjDrqHygGUXeCF" + }, + "href": "https://api.spotify.com/v1/artists/0OdUWJ0sBjDrqHygGUXeCF", + "id": "0OdUWJ0sBjDrqHygGUXeCF", + "name": "Band of Horses", + "type": "artist", + "uri": "spotify:artist:0OdUWJ0sBjDrqHygGUXeCF" + } + ], + "available_markets": ["US"], + "disc_number": 1, + "duration_ms": 252040, + "explicit": false, + "external_ids": { + "isrc": "USSM10600772" + }, + "external_urls": { + "spotify": "https://open.spotify.com/track/6hDH3YWFdse1K7GPSGZPen" + }, + "href": "https://api.spotify.com/v1/tracks/6hDH3YWFdse1K7GPSGZPen", + "id": "6hDH3YWFdse1K7GPSGZPen", + "is_local": false, + "name": "The Funeral", + "popularity": 72, + "preview_url": null, + "track_number": 2, + "type": "track", + "uri": "spotify:track:6hDH3YWFdse1K7GPSGZPen" + } + ] +} diff --git a/src/test/fixtures/requests/data/artists/GetSeveralArtistsRequest.json b/src/test/fixtures/requests/data/artists/GetSeveralArtistsRequest.json new file mode 100644 index 000000000..917304c7f --- /dev/null +++ b/src/test/fixtures/requests/data/artists/GetSeveralArtistsRequest.json @@ -0,0 +1,30 @@ +{ + "artists": [ + { + "external_urls": { + "spotify": "https://open.spotify.com/artist/0OdUWJ0sBjDrqHygGUXeCF" + }, + "followers": { + "href": null, + "total": 306565 + }, + "genres": [ + "indie folk", + "indie pop" + ], + "href": "https://api.spotify.com/v1/artists/0OdUWJ0sBjDrqHygGUXeCF", + "id": "0OdUWJ0sBjDrqHygGUXeCF", + "images": [ + { + "height": 816, + "url": "https://i.scdn.co/image/eb266625dab075341e8c4378a177a27370f91903", + "width": 1000 + } + ], + "name": "Band of Horses", + "popularity": 59, + "type": "artist", + "uri": "spotify:artist:0OdUWJ0sBjDrqHygGUXeCF" + } + ] +} diff --git a/src/test/fixtures/requests/data/library/CheckUsersSavedEpisodesRequest.json b/src/test/fixtures/requests/data/audiobooks/CheckUsersSavedAudiobooksRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/CheckUsersSavedEpisodesRequest.json rename to src/test/fixtures/requests/data/audiobooks/CheckUsersSavedAudiobooksRequest.json diff --git a/src/test/fixtures/requests/data/audiobooks/GetAudiobookChaptersRequest.json b/src/test/fixtures/requests/data/audiobooks/GetAudiobookChaptersRequest.json new file mode 100644 index 000000000..9bce189a4 --- /dev/null +++ b/src/test/fixtures/requests/data/audiobooks/GetAudiobookChaptersRequest.json @@ -0,0 +1,37 @@ +{ + "href": "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV/chapters?offset=0&limit=20", + "items": [ + { + "audio_preview_url": null, + "available_markets": ["US"], + "chapter_number": 1, + "description": "Chapter 1: Loomings.", + "html_description": "

Chapter 1: Loomings.

", + "duration_ms": 540000, + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/episode/2kFJSKFOkDUEXFOh7WFJUv" + }, + "href": "https://api.spotify.com/v1/chapters/2kFJSKFOkDUEXFOh7WFJUv", + "id": "2kFJSKFOkDUEXFOh7WFJUv", + "images": [], + "is_playable": true, + "languages": ["en"], + "name": "Chapter 1: Loomings.", + "release_date": "2020-01-01", + "release_date_precision": "day", + "resume_point": { + "fully_played": false, + "resume_position_ms": 0 + }, + "type": "episode", + "uri": "spotify:episode:2kFJSKFOkDUEXFOh7WFJUv", + "restrictions": null + } + ], + "limit": 20, + "next": null, + "offset": 0, + "previous": null, + "total": 135 +} diff --git a/src/test/fixtures/requests/data/audiobooks/GetAudiobookRequest.json b/src/test/fixtures/requests/data/audiobooks/GetAudiobookRequest.json new file mode 100644 index 000000000..28f94518f --- /dev/null +++ b/src/test/fixtures/requests/data/audiobooks/GetAudiobookRequest.json @@ -0,0 +1,46 @@ +{ + "authors": [ + { + "name": "Herman Melville" + } + ], + "available_markets": ["US", "GB"], + "chapters": { + "href": "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV/chapters?offset=0&limit=20", + "items": [], + "limit": 20, + "next": null, + "offset": 0, + "previous": null, + "total": 135 + }, + "copyrights": [], + "description": "Moby Dick; or, The Whale is an 1851 novel by American writer Herman Melville.", + "html_description": "

Moby Dick; or, The Whale is an 1851 novel by American writer Herman Melville.

", + "edition": "Unabridged", + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/show/7isl4tFkclqCygPqGxX8FV" + }, + "href": "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV", + "id": "7isl4tFkclqCygPqGxX8FV", + "images": [ + { + "height": 300, + "url": "https://i.scdn.co/image/ab676663000022a8f60bf7a19640f3f3ec9af37f", + "width": 300 + } + ], + "languages": ["en"], + "media_type": "audio", + "name": "Moby-Dick", + "narrators": [ + { + "name": "Frank Muller" + } + ], + "publisher": "Blackstone Audio", + "total_chapters": 135, + "type": "audiobook", + "uri": "spotify:show:7isl4tFkclqCygPqGxX8FV" +} diff --git a/src/test/fixtures/requests/data/audiobooks/GetSeveralAudiobooksRequest.json b/src/test/fixtures/requests/data/audiobooks/GetSeveralAudiobooksRequest.json new file mode 100644 index 000000000..0d586d0da --- /dev/null +++ b/src/test/fixtures/requests/data/audiobooks/GetSeveralAudiobooksRequest.json @@ -0,0 +1,35 @@ +{ + "audiobooks": [ + { + "authors": [ + { + "name": "Herman Melville" + } + ], + "available_markets": ["US", "GB"], + "copyrights": [], + "description": "Moby Dick; or, The Whale is an 1851 novel by American writer Herman Melville.", + "html_description": "

Moby Dick; or, The Whale is an 1851 novel by American writer Herman Melville.

", + "edition": "Unabridged", + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/show/7isl4tFkclqCygPqGxX8FV" + }, + "href": "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV", + "id": "7isl4tFkclqCygPqGxX8FV", + "images": [], + "languages": ["en"], + "media_type": "audio", + "name": "Moby-Dick", + "narrators": [ + { + "name": "Frank Muller" + } + ], + "publisher": "Blackstone Audio", + "total_chapters": 135, + "type": "audiobook", + "uri": "spotify:show:7isl4tFkclqCygPqGxX8FV" + } + ] +} diff --git a/src/test/fixtures/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.json b/src/test/fixtures/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.json new file mode 100644 index 000000000..f9a86c197 --- /dev/null +++ b/src/test/fixtures/requests/data/audiobooks/GetUsersSavedAudiobooksRequest.json @@ -0,0 +1,44 @@ +{ + "href": "https://api.spotify.com/v1/me/audiobooks?offset=0&limit=20", + "items": [ + { + "added_at": "2022-01-01T00:00:00Z", + "audiobook": { + "authors": [ + { + "name": "Herman Melville" + } + ], + "available_markets": ["US"], + "copyrights": [], + "description": "Moby Dick", + "html_description": "

Moby Dick

", + "edition": "Unabridged", + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/show/7isl4tFkclqCygPqGxX8FV" + }, + "href": "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV", + "id": "7isl4tFkclqCygPqGxX8FV", + "images": [], + "languages": ["en"], + "media_type": "audio", + "name": "Moby-Dick", + "narrators": [ + { + "name": "Frank Muller" + } + ], + "publisher": "Blackstone Audio", + "total_chapters": 135, + "type": "audiobook", + "uri": "spotify:show:7isl4tFkclqCygPqGxX8FV" + } + } + ], + "limit": 20, + "next": null, + "offset": 0, + "previous": null, + "total": 1 +} diff --git a/src/test/fixtures/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.json b/src/test/fixtures/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.json b/src/test/fixtures/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/categories/GetCategoriesRequest.json b/src/test/fixtures/requests/data/categories/GetCategoriesRequest.json new file mode 100644 index 000000000..2210d3fd7 --- /dev/null +++ b/src/test/fixtures/requests/data/categories/GetCategoriesRequest.json @@ -0,0 +1,36 @@ +{ + "categories": { + "href": "https://api.spotify.com/v1/browse/categories?offset=0&limit=2", + "items": [ + { + "href": "https://api.spotify.com/v1/browse/categories/toplists", + "icons": [ + { + "height": 275, + "url": "https://datsnxq1rwndn.cloudfront.net/media/derived/toplists_11160599e6a04ac5d6132b366af6f729_0_0_275_275.jpg", + "width": 275 + } + ], + "id": "toplists", + "name": "Top Lists" + }, + { + "href": "https://api.spotify.com/v1/browse/categories/mood", + "icons": [ + { + "height": 274, + "url": "https://datsnxq1rwndn.cloudfront.net/media/original/mood-274x274_976986a31ac8c49794cbdc35c3d12afe_274x274.jpg", + "width": 274 + } + ], + "id": "mood", + "name": "Mood" + } + ], + "limit": 2, + "next": "https://api.spotify.com/v1/browse/categories?offset=2&limit=2", + "offset": 0, + "previous": null, + "total": 31 + } +} diff --git a/src/test/fixtures/requests/data/categories/GetCategoryRequest.json b/src/test/fixtures/requests/data/categories/GetCategoryRequest.json new file mode 100644 index 000000000..14aeab075 --- /dev/null +++ b/src/test/fixtures/requests/data/categories/GetCategoryRequest.json @@ -0,0 +1,12 @@ +{ + "href": "https://api.spotify.com/v1/browse/categories/toplists", + "icons": [ + { + "height": 275, + "url": "https://datsnxq1rwndn.cloudfront.net/media/derived/toplists_11160599e6a04ac5d6132b366af6f729_0_0_275_275.jpg", + "width": 275 + } + ], + "id": "toplists", + "name": "Top Lists" +} diff --git a/src/test/fixtures/requests/data/chapters/GetChapterRequest.json b/src/test/fixtures/requests/data/chapters/GetChapterRequest.json new file mode 100644 index 000000000..2509dd655 --- /dev/null +++ b/src/test/fixtures/requests/data/chapters/GetChapterRequest.json @@ -0,0 +1,58 @@ +{ + "audio_preview_url": null, + "audiobook": { + "authors": [ + { + "name": "Herman Melville" + } + ], + "available_markets": ["US"], + "copyrights": [], + "description": "Moby Dick", + "html_description": "

Moby Dick

", + "edition": "Unabridged", + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/show/7isl4tFkclqCygPqGxX8FV" + }, + "href": "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV", + "id": "7isl4tFkclqCygPqGxX8FV", + "images": [], + "languages": ["en"], + "media_type": "audio", + "name": "Moby-Dick", + "narrators": [ + { + "name": "Frank Muller" + } + ], + "publisher": "Blackstone Audio", + "total_chapters": 135, + "type": "audiobook", + "uri": "spotify:show:7isl4tFkclqCygPqGxX8FV" + }, + "available_markets": ["US"], + "chapter_number": 1, + "description": "Chapter 1: Loomings.", + "html_description": "

Chapter 1: Loomings.

", + "duration_ms": 540000, + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/episode/2kFJSKFOkDUEXFOh7WFJUv" + }, + "href": "https://api.spotify.com/v1/chapters/2kFJSKFOkDUEXFOh7WFJUv", + "id": "2kFJSKFOkDUEXFOh7WFJUv", + "images": [], + "is_playable": true, + "languages": ["en"], + "name": "Chapter 1: Loomings.", + "release_date": "2020-01-01", + "release_date_precision": "day", + "resume_point": { + "fully_played": false, + "resume_position_ms": 0 + }, + "type": "episode", + "uri": "spotify:episode:2kFJSKFOkDUEXFOh7WFJUv", + "restrictions": null +} diff --git a/src/test/fixtures/requests/data/chapters/GetSeveralChaptersRequest.json b/src/test/fixtures/requests/data/chapters/GetSeveralChaptersRequest.json new file mode 100644 index 000000000..55207177b --- /dev/null +++ b/src/test/fixtures/requests/data/chapters/GetSeveralChaptersRequest.json @@ -0,0 +1,62 @@ +{ + "chapters": [ + { + "audio_preview_url": null, + "audiobook": { + "authors": [ + { + "name": "Herman Melville" + } + ], + "available_markets": ["US"], + "copyrights": [], + "description": "Moby Dick", + "html_description": "

Moby Dick

", + "edition": "Unabridged", + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/show/7isl4tFkclqCygPqGxX8FV" + }, + "href": "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV", + "id": "7isl4tFkclqCygPqGxX8FV", + "images": [], + "languages": ["en"], + "media_type": "audio", + "name": "Moby-Dick", + "narrators": [ + { + "name": "Frank Muller" + } + ], + "publisher": "Blackstone Audio", + "total_chapters": 135, + "type": "audiobook", + "uri": "spotify:show:7isl4tFkclqCygPqGxX8FV" + }, + "available_markets": ["US"], + "chapter_number": 1, + "description": "Chapter 1: Loomings.", + "html_description": "

Chapter 1: Loomings.

", + "duration_ms": 540000, + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/episode/2kFJSKFOkDUEXFOh7WFJUv" + }, + "href": "https://api.spotify.com/v1/chapters/2kFJSKFOkDUEXFOh7WFJUv", + "id": "2kFJSKFOkDUEXFOh7WFJUv", + "images": [], + "is_playable": true, + "languages": ["en"], + "name": "Chapter 1: Loomings.", + "release_date": "2020-01-01", + "release_date_precision": "day", + "resume_point": { + "fully_played": false, + "resume_position_ms": 0 + }, + "type": "episode", + "uri": "spotify:episode:2kFJSKFOkDUEXFOh7WFJUv", + "restrictions": null + } + ] +} diff --git a/src/test/fixtures/requests/data/episodes/CheckUsersSavedEpisodesRequest.json b/src/test/fixtures/requests/data/episodes/CheckUsersSavedEpisodesRequest.json new file mode 100644 index 000000000..0f4d57ab5 --- /dev/null +++ b/src/test/fixtures/requests/data/episodes/CheckUsersSavedEpisodesRequest.json @@ -0,0 +1,4 @@ +[ + true, + false +] diff --git a/src/test/fixtures/requests/data/episodes/GetSeveralEpisodesRequest.json b/src/test/fixtures/requests/data/episodes/GetSeveralEpisodesRequest.json new file mode 100644 index 000000000..b2be30570 --- /dev/null +++ b/src/test/fixtures/requests/data/episodes/GetSeveralEpisodesRequest.json @@ -0,0 +1,30 @@ +{ + "episodes": [ + { + "audio_preview_url": "https://p.scdn.co/mp3-preview/9b0ebffde166917f35f9eab25af874e765261776", + "description": "A sample episode description.", + "html_description": "

A sample episode description.

", + "duration_ms": 8052140, + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/episode/4GI3dxEafwap1sFiTGPKd1" + }, + "href": "https://api.spotify.com/v1/episodes/4GI3dxEafwap1sFiTGPKd1", + "id": "4GI3dxEafwap1sFiTGPKd1", + "images": [], + "is_externally_hosted": false, + "is_playable": true, + "language": "en-US", + "languages": ["en-US"], + "name": "Sample Episode", + "release_date": "2020-01-01", + "release_date_precision": "day", + "resume_point": { + "fully_played": false, + "resume_position_ms": 0 + }, + "type": "episode", + "uri": "spotify:episode:4GI3dxEafwap1sFiTGPKd1" + } + ] +} diff --git a/src/test/fixtures/requests/data/library/GetUsersSavedEpisodesRequest.json b/src/test/fixtures/requests/data/episodes/GetUsersSavedEpisodesRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/GetUsersSavedEpisodesRequest.json rename to src/test/fixtures/requests/data/episodes/GetUsersSavedEpisodesRequest.json diff --git a/src/test/fixtures/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.json b/src/test/fixtures/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/episodes/RemoveEpisodesForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/episodes/SaveEpisodesForCurrentUserRequest.json b/src/test/fixtures/requests/data/episodes/SaveEpisodesForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/episodes/SaveEpisodesForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequest.json b/src/test/fixtures/requests/data/genres/GetRecommendationGenresRequest.json similarity index 100% rename from src/test/fixtures/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequest.json rename to src/test/fixtures/requests/data/genres/GetRecommendationGenresRequest.json diff --git a/src/test/fixtures/requests/data/library/CheckLibraryContainsRequest.json b/src/test/fixtures/requests/data/library/CheckLibraryContainsRequest.json new file mode 100644 index 000000000..0f4d57ab5 --- /dev/null +++ b/src/test/fixtures/requests/data/library/CheckLibraryContainsRequest.json @@ -0,0 +1,4 @@ +[ + true, + false +] diff --git a/src/test/fixtures/requests/data/markets/GetAvailableMarketsRequest.json b/src/test/fixtures/requests/data/markets/GetAvailableMarketsRequest.json new file mode 100644 index 000000000..10914312e --- /dev/null +++ b/src/test/fixtures/requests/data/markets/GetAvailableMarketsRequest.json @@ -0,0 +1,190 @@ +{ + "markets": [ + "AD", + "AE", + "AG", + "AL", + "AM", + "AO", + "AR", + "AT", + "AU", + "AZ", + "BA", + "BB", + "BD", + "BE", + "BF", + "BG", + "BH", + "BI", + "BJ", + "BN", + "BO", + "BR", + "BS", + "BT", + "BW", + "BY", + "BZ", + "CA", + "CD", + "CG", + "CH", + "CI", + "CL", + "CM", + "CO", + "CR", + "CV", + "CW", + "CY", + "CZ", + "DE", + "DJ", + "DK", + "DM", + "DO", + "DZ", + "EC", + "EE", + "EG", + "ES", + "ET", + "FI", + "FJ", + "FM", + "FR", + "GA", + "GB", + "GD", + "GE", + "GH", + "GM", + "GN", + "GQ", + "GR", + "GT", + "GW", + "GY", + "HK", + "HN", + "HR", + "HT", + "HU", + "ID", + "IE", + "IL", + "IN", + "IQ", + "IS", + "IT", + "JM", + "JO", + "JP", + "KE", + "KG", + "KH", + "KI", + "KM", + "KN", + "KR", + "KW", + "KZ", + "LA", + "LB", + "LC", + "LI", + "LK", + "LR", + "LS", + "LT", + "LU", + "LV", + "LY", + "MA", + "MC", + "MD", + "ME", + "MG", + "MH", + "MK", + "ML", + "MN", + "MO", + "MR", + "MT", + "MU", + "MV", + "MW", + "MX", + "MY", + "MZ", + "NA", + "NE", + "NG", + "NI", + "NL", + "NO", + "NP", + "NR", + "NZ", + "OM", + "PA", + "PE", + "PG", + "PH", + "PK", + "PL", + "PR", + "PS", + "PT", + "PW", + "PY", + "QA", + "RO", + "RS", + "RW", + "SA", + "SB", + "SC", + "SE", + "SG", + "SI", + "SK", + "SL", + "SM", + "SN", + "SR", + "ST", + "SV", + "SZ", + "TD", + "TG", + "TH", + "TJ", + "TL", + "TM", + "TN", + "TO", + "TR", + "TT", + "TV", + "TW", + "TZ", + "UA", + "UG", + "US", + "UY", + "UZ", + "VC", + "VE", + "VN", + "VU", + "WS", + "XK", + "ZA", + "ZM", + "ZW" + ] +} diff --git a/src/test/fixtures/requests/data/player/GetTheUsersQueueRequest.json b/src/test/fixtures/requests/data/player/GetQueueRequest.json similarity index 100% rename from src/test/fixtures/requests/data/player/GetTheUsersQueueRequest.json rename to src/test/fixtures/requests/data/player/GetQueueRequest.json diff --git a/src/test/fixtures/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequest.json b/src/test/fixtures/requests/data/player/GetRecentlyPlayedRequest.json similarity index 100% rename from src/test/fixtures/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequest.json rename to src/test/fixtures/requests/data/player/GetRecentlyPlayedRequest.json diff --git a/src/test/fixtures/requests/data/playlists/CreatePlaylistForUserRequest.json b/src/test/fixtures/requests/data/playlists/CreatePlaylistForUserRequest.json new file mode 100644 index 000000000..6dfb7d2ba --- /dev/null +++ b/src/test/fixtures/requests/data/playlists/CreatePlaylistForUserRequest.json @@ -0,0 +1,42 @@ +{ + "collaborative": false, + "description": "New playlist description", + "external_urls": { + "spotify": "https://open.spotify.com/playlist/3cEYpjA9oz9GiPac4AsH4n" + }, + "href": "https://api.spotify.com/v1/playlists/3cEYpjA9oz9GiPac4AsH4n", + "id": "3cEYpjA9oz9GiPac4AsH4n", + "images": [], + "name": "New Playlist", + "owner": { + "external_urls": { + "spotify": "https://open.spotify.com/user/jmperezperez" + }, + "href": "https://api.spotify.com/v1/users/jmperezperez", + "id": "jmperezperez", + "type": "user", + "uri": "spotify:user:jmperezperez" + }, + "public": false, + "snapshot_id": "JbtmHBDBAkMzFjnFzSP0aeYCCMP1XSIY5VHZT_jUGrFTzNTa6tnPiSzeBMFIcH2", + "items": { + "href": "https://api.spotify.com/v1/playlists/3cEYpjA9oz9GiPac4AsH4n/tracks", + "limit": 100, + "next": null, + "offset": 0, + "previous": null, + "total": 0, + "items": [] + }, + "tracks": { + "href": "https://api.spotify.com/v1/playlists/3cEYpjA9oz9GiPac4AsH4n/tracks", + "limit": 100, + "next": null, + "offset": 0, + "previous": null, + "total": 0, + "items": [] + }, + "type": "playlist", + "uri": "spotify:playlist:3cEYpjA9oz9GiPac4AsH4n" +} diff --git a/src/test/fixtures/requests/data/browse/GetCategorysPlaylistsRequest.json b/src/test/fixtures/requests/data/playlists/GetCategoryPlaylistsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/browse/GetCategorysPlaylistsRequest.json rename to src/test/fixtures/requests/data/playlists/GetCategoryPlaylistsRequest.json diff --git a/src/test/fixtures/requests/data/browse/GetListOfFeaturedPlaylistsRequest.json b/src/test/fixtures/requests/data/playlists/GetFeaturedPlaylistsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/browse/GetListOfFeaturedPlaylistsRequest.json rename to src/test/fixtures/requests/data/playlists/GetFeaturedPlaylistsRequest.json diff --git a/src/test/fixtures/requests/data/playlists/GetListOfUsersPlaylistsRequest_UserWith$.json b/src/test/fixtures/requests/data/playlists/GetListUsersPlaylistsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/playlists/GetListOfUsersPlaylistsRequest_UserWith$.json rename to src/test/fixtures/requests/data/playlists/GetListUsersPlaylistsRequest.json diff --git a/src/test/fixtures/requests/data/playlists/GetListUsersPlaylistsRequest_UserWith$.json b/src/test/fixtures/requests/data/playlists/GetListUsersPlaylistsRequest_UserWith$.json new file mode 100644 index 000000000..095712593 --- /dev/null +++ b/src/test/fixtures/requests/data/playlists/GetListUsersPlaylistsRequest_UserWith$.json @@ -0,0 +1,64 @@ +{ + "href": "https://api.spotify.com/v1/users/%24wizzler%24/playlists", + "items": [ + { + "collaborative": false, + "external_urls": { + "spotify": "https://open.spotify.com/user/%24wizzler%24/playlists/53Y8wT46QIMz5H4WQ8O22c" + }, + "href": "https://api.spotify.com/v1/users/%24wizzler%24/playlists/53Y8wT46QIMz5H4WQ8O22c", + "id": "53Y8wT46QIMz5H4WQ8O22c", + "images": [], + "name": "Wizzlers Big Playlist", + "owner": { + "external_urls": { + "spotify": "https://open.spotify.com/user/wizzler" + }, + "href": "https://api.spotify.com/v1/users/wizzler", + "id": "$wizzler$", + "type": "user", + "uri": "spotify:user:%24wizzler%24" + }, + "public": true, + "snapshot_id": "bNLWdmhh+HDsbHzhckXeDC0uyKyg4FjPI/KEsKjAE526usnz2LxwgyBoMShVL+z+", + "items": { + "href": "https://api.spotify.com/v1/users/wizzler/playlists/53Y8wT46QIMz5H4WQ8O22c/tracks", + "total": 30 + }, + "type": "playlist", + "uri": "spotify:user:%24wizzler%24:playlist:53Y8wT46QIMz5H4WQ8O22c" + }, + { + "collaborative": false, + "external_urls": { + "spotify": "https://open.spotify.com/user/wizzlersmate/playlists/1AVZz0mBuGbCEoNRQdYQju" + }, + "href": "https://api.spotify.com/v1/users/wizzlersmate/playlists/1AVZz0mBuGbCEoNRQdYQju", + "id": "1AVZz0mBuGbCEoNRQdYQju", + "images": [], + "name": "Another Playlist", + "owner": { + "external_urls": { + "spotify": "https://open.spotify.com/user/wizzlersmate" + }, + "href": "https://api.spotify.com/v1/users/wizzlersmate", + "id": "wizzlersmate", + "type": "user", + "uri": "spotify:user:wizzlersmate" + }, + "public": true, + "snapshot_id": "Y0qg/IT5T02DKpw4uQKc/9RUrqQJ07hbTKyEeDRPOo9LU0g0icBrIXwVkHfQZ/aD", + "items": { + "href": "https://api.spotify.com/v1/users/wizzlersmate/playlists/1AVZz0mBuGbCEoNRQdYQju/tracks", + "total": 58 + }, + "type": "playlist", + "uri": "spotify:user:wizzlersmate:playlist:1AVZz0mBuGbCEoNRQdYQju" + } + ], + "limit": 9, + "next": null, + "offset": 0, + "previous": null, + "total": 9 +} diff --git a/src/test/fixtures/requests/data/playlists/GetPlaylistCoverImageRequest.json b/src/test/fixtures/requests/data/playlists/GetPlaylistCoverRequest.json similarity index 100% rename from src/test/fixtures/requests/data/playlists/GetPlaylistCoverImageRequest.json rename to src/test/fixtures/requests/data/playlists/GetPlaylistCoverRequest.json diff --git a/src/test/fixtures/requests/data/playlists/GetPlaylistsItemsRequest_Episode.json b/src/test/fixtures/requests/data/playlists/GetPlaylistsItemsRequest_Episode.json index 77afccf23..8f84722d6 100644 --- a/src/test/fixtures/requests/data/playlists/GetPlaylistsItemsRequest_Episode.json +++ b/src/test/fixtures/requests/data/playlists/GetPlaylistsItemsRequest_Episode.json @@ -1,5 +1,5 @@ { - "href": "https://api.spotify.com/v1/playlists/21THa8j9TaSGuXYNBU5tsC/tracks?offset=0&limit=100&additional_types=episode", + "href": "https://api.spotify.com/v1/playlists/21THa8j9TaSGuXYNBU5tsC/items?offset=0&limit=100&additional_types=episode", "items": [ { "added_at": "2016-10-11T13:44:40Z", diff --git a/src/test/fixtures/requests/data/playlists/RemoveItemsPlaylistRequest.json b/src/test/fixtures/requests/data/playlists/RemoveItemsPlaylistRequest.json new file mode 100644 index 000000000..9a0e7c58a --- /dev/null +++ b/src/test/fixtures/requests/data/playlists/RemoveItemsPlaylistRequest.json @@ -0,0 +1,3 @@ +{ + "snapshot_id": "JbtmHBDBAYu3/bt8BOXKjzKx3i0b6LCa/wVjyl6qQ2Yf6nFXkbmzuEa+ZI/U1yF+" +} \ No newline at end of file diff --git a/src/test/fixtures/requests/data/playlists/ReplacePlaylistsItemsRequest.json b/src/test/fixtures/requests/data/playlists/ReplacePlaylistsItemsRequest.json new file mode 100644 index 000000000..9a0e7c58a --- /dev/null +++ b/src/test/fixtures/requests/data/playlists/ReplacePlaylistsItemsRequest.json @@ -0,0 +1,3 @@ +{ + "snapshot_id": "JbtmHBDBAYu3/bt8BOXKjzKx3i0b6LCa/wVjyl6qQ2Yf6nFXkbmzuEa+ZI/U1yF+" +} \ No newline at end of file diff --git a/src/test/fixtures/requests/data/search/SearchItemRequest.json b/src/test/fixtures/requests/data/search/SearchRequest.json similarity index 100% rename from src/test/fixtures/requests/data/search/SearchItemRequest.json rename to src/test/fixtures/requests/data/search/SearchRequest.json diff --git a/src/test/fixtures/requests/data/library/CheckUsersSavedShowsRequest.json b/src/test/fixtures/requests/data/shows/CheckUsersSavedShowsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/CheckUsersSavedShowsRequest.json rename to src/test/fixtures/requests/data/shows/CheckUsersSavedShowsRequest.json diff --git a/src/test/fixtures/requests/data/shows/GetSeveralShowsRequest.json b/src/test/fixtures/requests/data/shows/GetSeveralShowsRequest.json new file mode 100644 index 000000000..9de4b7a6f --- /dev/null +++ b/src/test/fixtures/requests/data/shows/GetSeveralShowsRequest.json @@ -0,0 +1,25 @@ +{ + "shows": [ + { + "available_markets": ["US", "GB"], + "copyrights": [], + "description": "A sample podcast description.", + "html_description": "

A sample podcast description.

", + "explicit": false, + "external_urls": { + "spotify": "https://open.spotify.com/show/7iZEp9f2Gg8JvKNqK3t905" + }, + "href": "https://api.spotify.com/v1/shows/7iZEp9f2Gg8JvKNqK3t905", + "id": "7iZEp9f2Gg8JvKNqK3t905", + "images": [], + "is_externally_hosted": false, + "languages": ["de"], + "media_type": "audio", + "name": "Acht Milliarden – Der Auslands-Podcast", + "publisher": "DER SPIEGEL", + "total_episodes": 20, + "type": "show", + "uri": "spotify:show:7iZEp9f2Gg8JvKNqK3t905" + } + ] +} diff --git a/src/test/fixtures/requests/data/library/GetUsersSavedShowsRequest.json b/src/test/fixtures/requests/data/shows/GetUsersSavedShowsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/GetUsersSavedShowsRequest.json rename to src/test/fixtures/requests/data/shows/GetUsersSavedShowsRequest.json diff --git a/src/test/fixtures/requests/data/shows/RemoveShowsForCurrentUserRequest.json b/src/test/fixtures/requests/data/shows/RemoveShowsForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/shows/RemoveShowsForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/shows/SaveShowsForCurrentUserRequest.json b/src/test/fixtures/requests/data/shows/SaveShowsForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/shows/SaveShowsForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/library/CheckUsersSavedTracksRequest.json b/src/test/fixtures/requests/data/tracks/CheckUsersSavedTracksRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/CheckUsersSavedTracksRequest.json rename to src/test/fixtures/requests/data/tracks/CheckUsersSavedTracksRequest.json diff --git a/src/test/fixtures/requests/data/tracks/GetAudioAnalysisForTrackRequest.json b/src/test/fixtures/requests/data/tracks/GetAudioAnalysisRequest.json similarity index 100% rename from src/test/fixtures/requests/data/tracks/GetAudioAnalysisForTrackRequest.json rename to src/test/fixtures/requests/data/tracks/GetAudioAnalysisRequest.json diff --git a/src/test/fixtures/requests/data/tracks/GetAudioFeaturesForTrackRequest.json b/src/test/fixtures/requests/data/tracks/GetAudioFeaturesRequest.json similarity index 100% rename from src/test/fixtures/requests/data/tracks/GetAudioFeaturesForTrackRequest.json rename to src/test/fixtures/requests/data/tracks/GetAudioFeaturesRequest.json diff --git a/src/test/fixtures/requests/data/browse/GetRecommendationsRequest.json b/src/test/fixtures/requests/data/tracks/GetRecommendationsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/browse/GetRecommendationsRequest.json rename to src/test/fixtures/requests/data/tracks/GetRecommendationsRequest.json diff --git a/src/test/fixtures/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequest.json b/src/test/fixtures/requests/data/tracks/GetSeveralAudioFeaturesRequest.json similarity index 100% rename from src/test/fixtures/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequest.json rename to src/test/fixtures/requests/data/tracks/GetSeveralAudioFeaturesRequest.json diff --git a/src/test/fixtures/requests/data/tracks/GetSeveralTracksRequest.json b/src/test/fixtures/requests/data/tracks/GetSeveralTracksRequest.json new file mode 100644 index 000000000..0e2e5687c --- /dev/null +++ b/src/test/fixtures/requests/data/tracks/GetSeveralTracksRequest.json @@ -0,0 +1,65 @@ +{ + "tracks": [ + { + "album": { + "album_type": "album", + "artists": [ + { + "external_urls": { + "spotify": "https://open.spotify.com/artist/0C0XlULifJtAgn6ZNCW2eu" + }, + "href": "https://api.spotify.com/v1/artists/0C0XlULifJtAgn6ZNCW2eu", + "id": "0C0XlULifJtAgn6ZNCW2eu", + "name": "The Killers", + "type": "artist", + "uri": "spotify:artist:0C0XlULifJtAgn6ZNCW2eu" + } + ], + "available_markets": ["US"], + "external_urls": { + "spotify": "https://open.spotify.com/album/3JUNfTWU5QUkDG4c8e7PVW" + }, + "href": "https://api.spotify.com/v1/albums/3JUNfTWU5QUkDG4c8e7PVW", + "id": "3JUNfTWU5QUkDG4c8e7PVW", + "images": [], + "name": "Hot Fuss", + "release_date": "2004-06-14", + "release_date_precision": "day", + "total_tracks": 11, + "type": "album", + "uri": "spotify:album:3JUNfTWU5QUkDG4c8e7PVW" + }, + "artists": [ + { + "external_urls": { + "spotify": "https://open.spotify.com/artist/0C0XlULifJtAgn6ZNCW2eu" + }, + "href": "https://api.spotify.com/v1/artists/0C0XlULifJtAgn6ZNCW2eu", + "id": "0C0XlULifJtAgn6ZNCW2eu", + "name": "The Killers", + "type": "artist", + "uri": "spotify:artist:0C0XlULifJtAgn6ZNCW2eu" + } + ], + "available_markets": ["US"], + "disc_number": 1, + "duration_ms": 222586, + "explicit": false, + "external_ids": { + "isrc": "GBUM70400251" + }, + "external_urls": { + "spotify": "https://open.spotify.com/track/0eGsygTp906u18L0Oimnem" + }, + "href": "https://api.spotify.com/v1/tracks/0eGsygTp906u18L0Oimnem", + "id": "0eGsygTp906u18L0Oimnem", + "is_local": false, + "name": "Mr. Brightside", + "popularity": 85, + "preview_url": null, + "track_number": 2, + "type": "track", + "uri": "spotify:track:0eGsygTp906u18L0Oimnem" + } + ] +} diff --git a/src/test/fixtures/requests/data/library/GetUsersSavedTracksRequest.json b/src/test/fixtures/requests/data/tracks/GetUsersSavedTracksRequest.json similarity index 100% rename from src/test/fixtures/requests/data/library/GetUsersSavedTracksRequest.json rename to src/test/fixtures/requests/data/tracks/GetUsersSavedTracksRequest.json diff --git a/src/test/fixtures/requests/data/tracks/RemoveTracksForCurrentUserRequest.json b/src/test/fixtures/requests/data/tracks/RemoveTracksForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/tracks/RemoveTracksForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/tracks/SaveTracksForCurrentUserRequest.json b/src/test/fixtures/requests/data/tracks/SaveTracksForCurrentUserRequest.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/fixtures/requests/data/tracks/SaveTracksForCurrentUserRequest.json @@ -0,0 +1 @@ +{} diff --git a/src/test/fixtures/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequest.json b/src/test/fixtures/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequest.json similarity index 100% rename from src/test/fixtures/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequest.json rename to src/test/fixtures/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequest.json diff --git a/src/test/fixtures/requests/data/follow/CheckUsersFollowPlaylistRequest.json b/src/test/fixtures/requests/data/users/CheckIfUserFollowsPlaylistRequest.json similarity index 100% rename from src/test/fixtures/requests/data/follow/CheckUsersFollowPlaylistRequest.json rename to src/test/fixtures/requests/data/users/CheckIfUserFollowsPlaylistRequest.json diff --git a/src/test/fixtures/requests/data/users_profile/GetCurrentUsersProfileRequest.json b/src/test/fixtures/requests/data/users/GetCurrentUsersProfileRequest.json similarity index 100% rename from src/test/fixtures/requests/data/users_profile/GetCurrentUsersProfileRequest.json rename to src/test/fixtures/requests/data/users/GetCurrentUsersProfileRequest.json diff --git a/src/test/fixtures/requests/data/follow/GetUsersFollowedArtistsRequest.json b/src/test/fixtures/requests/data/users/GetFollowedRequest.json similarity index 100% rename from src/test/fixtures/requests/data/follow/GetUsersFollowedArtistsRequest.json rename to src/test/fixtures/requests/data/users/GetFollowedRequest.json diff --git a/src/test/fixtures/requests/data/follow/GetUsersFollowedArtistsRequest_None.json b/src/test/fixtures/requests/data/users/GetFollowedRequest_None.json similarity index 100% rename from src/test/fixtures/requests/data/follow/GetUsersFollowedArtistsRequest_None.json rename to src/test/fixtures/requests/data/users/GetFollowedRequest_None.json diff --git a/src/test/fixtures/requests/data/users/GetUsersProfileRequest.json b/src/test/fixtures/requests/data/users/GetUsersProfileRequest.json new file mode 100644 index 000000000..39fb4f4af --- /dev/null +++ b/src/test/fixtures/requests/data/users/GetUsersProfileRequest.json @@ -0,0 +1,25 @@ +{ + "birthdate": "1937-06-01", + "country": "SE", + "display_name": "JM Wizzler", + "email": "email@example.com", + "external_urls": { + "spotify": "https://open.spotify.com/user/wizzler" + }, + "followers": { + "href": null, + "total": 3829 + }, + "href": "https://api.spotify.com/v1/users/wizzler", + "id": "wizzler", + "images": [ + { + "height": null, + "url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-frc3/t1.0-1/1970403_10152215092574354_1798272330_n.jpg", + "width": null + } + ], + "product": "premium", + "type": "user", + "uri": "spotify:user:wizzler" +} \ No newline at end of file diff --git a/src/test/fixtures/requests/data/personalization/simplified/GetUsersTopArtistsRequest.json b/src/test/fixtures/requests/data/users/simplified/GetUsersTopArtistsRequest.json similarity index 100% rename from src/test/fixtures/requests/data/personalization/simplified/GetUsersTopArtistsRequest.json rename to src/test/fixtures/requests/data/users/simplified/GetUsersTopArtistsRequest.json diff --git a/src/test/fixtures/requests/data/personalization/simplified/GetUsersTopTracksRequest.json b/src/test/fixtures/requests/data/users/simplified/GetUsersTopTracksRequest.json similarity index 100% rename from src/test/fixtures/requests/data/personalization/simplified/GetUsersTopTracksRequest.json rename to src/test/fixtures/requests/data/users/simplified/GetUsersTopTracksRequest.json diff --git a/src/test/java/se/michaelthelin/spotify/ITest.java b/src/test/java/se/michaelthelin/spotify/ITest.java index cbbc0b624..e040bf523 100644 --- a/src/test/java/se/michaelthelin/spotify/ITest.java +++ b/src/test/java/se/michaelthelin/spotify/ITest.java @@ -45,6 +45,8 @@ public interface ITest { String ADDITIONAL_TYPES = "track,episode"; String ID_ALBUM = "5zT1JLIj9E57p3e1rFm9Uq"; String ID_ARTIST = "0LcJLqbBmaGUft1e9Mm8HV"; + String ID_AUDIOBOOK = "7isl4tFkclqCygPqGxX8FV"; + String ID_CHAPTER = "2kFJSKFOkDUEXFOh7WFJUv"; String ID_EPISODE = "4GI3dxEafwap1sFiTGPKd1"; String ID_PLAYLIST = "3AGOiaoRXMSjswCLtuNqv5"; String ID_SHOW = "5AvwZVawapvyhJUIx71pdJ"; diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedAlbumsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/albums/CheckUsersSavedAlbumsRequestTest.java similarity index 90% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedAlbumsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/albums/CheckUsersSavedAlbumsRequestTest.java index 07d3687d1..ebc87ffca 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedAlbumsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/albums/CheckUsersSavedAlbumsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.albums; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -12,11 +12,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +@SuppressWarnings("deprecation") public class CheckUsersSavedAlbumsRequestTest extends AbstractDataTest { private final CheckUsersSavedAlbumsRequest defaultRequest = ITest.SPOTIFY_API.checkUsersSavedAlbums(ITest.ID_ALBUM, ITest.ID_ALBUM) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/library/CheckUsersSavedAlbumsRequest.json")) + "requests/data/albums/CheckUsersSavedAlbumsRequest.json")) .build(); public CheckUsersSavedAlbumsRequestTest() throws Exception { diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumsTracksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumsTracksRequestTest.java index 7afc362c9..bee67fd51 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumsTracksRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetAlbumsTracksRequestTest.java @@ -16,7 +16,7 @@ public class GetAlbumsTracksRequestTest extends AbstractDataTest> { - private final GetAlbumsTracksRequest defaultRequest = SPOTIFY_API.getAlbumsTracks(ID_ALBUM) + private final GetAlbumTracksRequest defaultRequest = SPOTIFY_API.getAlbumTracks(ID_ALBUM) .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/albums/GetAlbumsTracksRequest.json")) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequestTest.java new file mode 100644 index 000000000..5ae23d484 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetNewReleasesRequestTest.java @@ -0,0 +1,60 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.AlbumSimplified; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SuppressWarnings("deprecation") +public class GetNewReleasesRequestTest extends AbstractDataTest> { + private final GetNewReleasesRequest defaultRequest = ITest.SPOTIFY_API + .getNewReleases() + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/albums/GetNewReleasesRequest.json")) + .limit(ITest.LIMIT) + .offset(ITest.OFFSET) + .build(); + + public GetNewReleasesRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/browse/new-releases?limit=10&offset=0", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Paging albumSimplifiedPaging) { + assertEquals( + "https://api.spotify.com/v1/browse/new-releases?country=SE&offset=0&limit=2", + albumSimplifiedPaging.getHref()); + assertEquals( + 1, + albumSimplifiedPaging.getItems().length); + assertEquals( + 1, + (int) albumSimplifiedPaging.getTotal()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequestTest.java new file mode 100644 index 000000000..e1cfcc8c9 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetSeveralAlbumsRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Album; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetSeveralAlbumsRequestTest extends AbstractDataTest { + private final GetSeveralAlbumsRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralAlbums(ITest.ID_ALBUM) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/albums/GetSeveralAlbumsRequest.json")) + .build(); + + public GetSeveralAlbumsRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/albums?ids=5zT1JLIj9E57p3e1rFm9Uq", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Album[] albums) { + assertNotNull(albums); + assertEquals(1, albums.length); + assertEquals("0sNOF9WDwhWunNAHPD3Baj", albums[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetCurrentUsersSavedAlbumsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetUsersSavedAlbumsRequestTest.java similarity index 83% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/GetCurrentUsersSavedAlbumsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/albums/GetUsersSavedAlbumsRequestTest.java index ddd4461ad..935c3ac66 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetCurrentUsersSavedAlbumsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/albums/GetUsersSavedAlbumsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.albums; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -15,17 +15,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -public class GetCurrentUsersSavedAlbumsRequestTest extends AbstractDataTest> { - private final GetCurrentUsersSavedAlbumsRequest defaultRequest = ITest.SPOTIFY_API.getCurrentUsersSavedAlbums() +public class GetUsersSavedAlbumsRequestTest extends AbstractDataTest> { + private final GetUsersSavedAlbumsRequest defaultRequest = ITest.SPOTIFY_API.getUsersSavedAlbums() .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/library/GetCurrentUsersSavedAlbumsRequest.json")) + "requests/data/albums/GetUsersSavedAlbumsRequest.json")) .limit(ITest.LIMIT) .market(ITest.MARKET) .offset(ITest.OFFSET) .build(); - public GetCurrentUsersSavedAlbumsRequestTest() throws Exception { + public GetUsersSavedAlbumsRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequestTest.java new file mode 100644 index 000000000..dc9e2fe0c --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/albums/RemoveAlbumsForCurrentUserRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SuppressWarnings("deprecation") +public class RemoveAlbumsForCurrentUserRequestTest extends AbstractDataTest { + private final RemoveAlbumsForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .removeAlbumsForCurrentUser(ITest.ID_ALBUM) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public RemoveAlbumsForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/albums?ids=5zT1JLIj9E57p3e1rFm9Uq", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequestTest.java new file mode 100644 index 000000000..98c6db6b9 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/albums/SaveAlbumsForCurrentUserRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.albums; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SuppressWarnings("deprecation") +public class SaveAlbumsForCurrentUserRequestTest extends AbstractDataTest { + private final SaveAlbumsForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .saveAlbumsForCurrentUser(ITest.ID_ALBUM) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public SaveAlbumsForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/albums?ids=5zT1JLIj9E57p3e1rFm9Uq", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistRequestTest.java index 189177a7b..81d05b2f8 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistRequestTest.java @@ -13,7 +13,6 @@ import java.util.concurrent.ExecutionException; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; public class GetArtistRequestTest extends AbstractDataTest { private final GetArtistRequest defaultRequest = ITest.SPOTIFY_API.getArtist(ITest.ID_ARTIST) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequestTest.java new file mode 100644 index 000000000..0ac3cfea7 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetArtistsTopTracksRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.artists; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Track; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetArtistsTopTracksRequestTest extends AbstractDataTest { + private final GetArtistsTopTracksRequest defaultRequest = ITest.SPOTIFY_API + .getArtistsTopTracks(ITest.ID_ARTIST) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/artists/GetArtistsTopTracksRequest.json")) + .build(); + + public GetArtistsTopTracksRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/artists/0LcJLqbBmaGUft1e9Mm8HV/top-tracks", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Track[] tracks) { + assertNotNull(tracks); + assertEquals(1, tracks.length); + assertEquals("6hDH3YWFdse1K7GPSGZPen", tracks[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequestTest.java new file mode 100644 index 000000000..c88095b6b --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/artists/GetSeveralArtistsRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.artists; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Artist; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetSeveralArtistsRequestTest extends AbstractDataTest { + private final GetSeveralArtistsRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralArtists(ITest.ID_ARTIST) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/artists/GetSeveralArtistsRequest.json")) + .build(); + + public GetSeveralArtistsRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/artists?ids=0LcJLqbBmaGUft1e9Mm8HV", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Artist[] artists) { + assertNotNull(artists); + assertEquals(1, artists.length); + assertEquals("0OdUWJ0sBjDrqHygGUXeCF", artists[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequestTest.java new file mode 100644 index 000000000..8c2119518 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/CheckUsersSavedAudiobooksRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SuppressWarnings("deprecation") +public class CheckUsersSavedAudiobooksRequestTest extends AbstractDataTest { + private final CheckUsersSavedAudiobooksRequest defaultRequest = ITest.SPOTIFY_API + .checkUsersSavedAudiobooks(ITest.ID_AUDIOBOOK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/audiobooks/CheckUsersSavedAudiobooksRequest.json")) + .build(); + + public CheckUsersSavedAudiobooksRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/audiobooks/contains?ids=7isl4tFkclqCygPqGxX8FV", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Boolean[] booleans) { + assertEquals(2, booleans.length); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequestTest.java new file mode 100644 index 000000000..c9a1cf85b --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookChaptersRequestTest.java @@ -0,0 +1,62 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.ChapterSimplified; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class GetAudiobookChaptersRequestTest extends AbstractDataTest> { + private final GetAudiobookChaptersRequest defaultRequest = ITest.SPOTIFY_API + .getAudiobookChapters(ITest.ID_AUDIOBOOK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/audiobooks/GetAudiobookChaptersRequest.json")) + .limit(ITest.LIMIT) + .offset(ITest.OFFSET) + .build(); + + public GetAudiobookChaptersRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/audiobooks/7isl4tFkclqCygPqGxX8FV/chapters?limit=10&offset=0", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Paging chapterPaging) { + assertNotNull(chapterPaging); + assertEquals( + "https://api.spotify.com/v1/audiobooks/7isl4tFkclqCygPqGxX8FV/chapters?offset=0&limit=20", + chapterPaging.getHref()); + assertEquals(1, chapterPaging.getItems().length); + assertEquals(20, (int) chapterPaging.getLimit()); + assertNull(chapterPaging.getNext()); + assertEquals(0, (int) chapterPaging.getOffset()); + assertNull(chapterPaging.getPrevious()); + assertEquals(135, (int) chapterPaging.getTotal()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequestTest.java new file mode 100644 index 000000000..e5e450466 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetAudiobookRequestTest.java @@ -0,0 +1,54 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Audiobook; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetAudiobookRequestTest extends AbstractDataTest { + private final GetAudiobookRequest defaultRequest = ITest.SPOTIFY_API + .getAudiobook(ITest.ID_AUDIOBOOK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/audiobooks/GetAudiobookRequest.json")) + .build(); + + public GetAudiobookRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/audiobooks/7isl4tFkclqCygPqGxX8FV", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Audiobook audiobook) { + assertNotNull(audiobook); + assertEquals("7isl4tFkclqCygPqGxX8FV", audiobook.getId()); + assertEquals("Moby-Dick", audiobook.getName()); + assertNotNull(audiobook.getAuthors()); + assertEquals(1, audiobook.getAuthors().length); + assertEquals("Herman Melville", audiobook.getAuthors()[0].getName()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequestTest.java new file mode 100644 index 000000000..05dfac0e2 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetSeveralAudiobooksRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.AudiobookSimplified; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetSeveralAudiobooksRequestTest extends AbstractDataTest { + private final GetSeveralAudiobooksRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralAudiobooks(ITest.ID_AUDIOBOOK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/audiobooks/GetSeveralAudiobooksRequest.json")) + .build(); + + public GetSeveralAudiobooksRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/audiobooks?ids=7isl4tFkclqCygPqGxX8FV", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final AudiobookSimplified[] audiobooks) { + assertNotNull(audiobooks); + assertEquals(1, audiobooks.length); + assertEquals("7isl4tFkclqCygPqGxX8FV", audiobooks[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequestTest.java new file mode 100644 index 000000000..ba26386c3 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/GetUsersSavedAudiobooksRequestTest.java @@ -0,0 +1,62 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.model_objects.specification.SavedAudiobook; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class GetUsersSavedAudiobooksRequestTest extends AbstractDataTest> { + private final GetUsersSavedAudiobooksRequest defaultRequest = ITest.SPOTIFY_API + .getUsersSavedAudiobooks() + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/audiobooks/GetUsersSavedAudiobooksRequest.json")) + .limit(ITest.LIMIT) + .offset(ITest.OFFSET) + .build(); + + public GetUsersSavedAudiobooksRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/audiobooks?limit=10&offset=0", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Paging savedAudiobookPaging) { + assertNotNull(savedAudiobookPaging); + assertEquals( + "https://api.spotify.com/v1/me/audiobooks?offset=0&limit=20", + savedAudiobookPaging.getHref()); + assertEquals(1, savedAudiobookPaging.getItems().length); + assertEquals(20, (int) savedAudiobookPaging.getLimit()); + assertNull(savedAudiobookPaging.getNext()); + assertEquals(0, (int) savedAudiobookPaging.getOffset()); + assertNull(savedAudiobookPaging.getPrevious()); + assertEquals(1, (int) savedAudiobookPaging.getTotal()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequestTest.java new file mode 100644 index 000000000..6d3502c0e --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/RemoveAudiobooksForCurrentUserRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +@SuppressWarnings("deprecation") +public class RemoveAudiobooksForCurrentUserRequestTest extends AbstractDataTest { + private final RemoveAudiobooksForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .removeAudiobooksForCurrentUser(ITest.ID_AUDIOBOOK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public RemoveAudiobooksForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/audiobooks?ids=7isl4tFkclqCygPqGxX8FV", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequestTest.java new file mode 100644 index 000000000..08a284dc4 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/audiobooks/SaveAudiobooksForCurrentUserRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.audiobooks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +@SuppressWarnings("deprecation") +public class SaveAudiobooksForCurrentUserRequestTest extends AbstractDataTest { + private final SaveAudiobooksForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .saveAudiobooksForCurrentUser(ITest.ID_AUDIOBOOK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public SaveAudiobooksForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/audiobooks?ids=7isl4tFkclqCygPqGxX8FV", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoriesRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoriesRequestTest.java new file mode 100644 index 000000000..f7446fd6f --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoriesRequestTest.java @@ -0,0 +1,66 @@ +package se.michaelthelin.spotify.requests.data.categories; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Category; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class GetCategoriesRequestTest extends AbstractDataTest> { + private final GetSeveralBrowseCategoriesRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralBrowseCategories() + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/categories/GetCategoriesRequest.json")) + .locale(ITest.LOCALE) + .limit(ITest.LIMIT) + .offset(ITest.OFFSET) + .build(); + + public GetCategoriesRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/browse/categories?locale=sv_SE&limit=10&offset=0", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Paging categoryPaging) { + assertEquals( + "https://api.spotify.com/v1/browse/categories?offset=0&limit=2", + categoryPaging.getHref()); + assertEquals( + 2, + categoryPaging.getItems().length); + assertEquals( + 2, + categoryPaging.getLimit()); + assertEquals( + 0, + (int) categoryPaging.getOffset()); + assertEquals( + 31, + (int) categoryPaging.getTotal()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoryRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoryRequestTest.java new file mode 100644 index 000000000..7fce49983 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/categories/GetCategoryRequestTest.java @@ -0,0 +1,60 @@ +package se.michaelthelin.spotify.requests.data.categories; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Category; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetCategoryRequestTest extends AbstractDataTest { + private final GetSingleBrowseCategoryRequest defaultRequest = ITest.SPOTIFY_API + .getSingleBrowseCategory(ITest.CATEGORY_ID) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/categories/GetCategoryRequest.json")) + .locale(ITest.LOCALE) + .build(); + + public GetCategoryRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/browse/categories/dinner?locale=sv_SE", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Category category) { + assertEquals( + "https://api.spotify.com/v1/browse/categories/toplists", + category.getHref()); + assertNotNull( + category.getIcons()); + assertEquals( + "toplists", + category.getId()); + assertEquals( + "Top Lists", + category.getName()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequestTest.java new file mode 100644 index 000000000..b3b1ad60d --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetChapterRequestTest.java @@ -0,0 +1,53 @@ +package se.michaelthelin.spotify.requests.data.chapters; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Chapter; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetChapterRequestTest extends AbstractDataTest { + private final GetChapterRequest defaultRequest = ITest.SPOTIFY_API + .getChapter(ITest.ID_CHAPTER) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/chapters/GetChapterRequest.json")) + .build(); + + public GetChapterRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/chapters/2kFJSKFOkDUEXFOh7WFJUv", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Chapter chapter) { + assertNotNull(chapter); + assertEquals("2kFJSKFOkDUEXFOh7WFJUv", chapter.getId()); + assertEquals("Chapter 1: Loomings.", chapter.getName()); + assertNotNull(chapter.getAudiobook()); + assertEquals("7isl4tFkclqCygPqGxX8FV", chapter.getAudiobook().getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequestTest.java new file mode 100644 index 000000000..c67ed7443 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/chapters/GetSeveralChaptersRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.chapters; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Chapter; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetSeveralChaptersRequestTest extends AbstractDataTest { + private final GetSeveralChaptersRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralChapters(ITest.ID_CHAPTER) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/chapters/GetSeveralChaptersRequest.json")) + .build(); + + public GetSeveralChaptersRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/chapters?ids=2kFJSKFOkDUEXFOh7WFJUv", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Chapter[] chapters) { + assertNotNull(chapters); + assertEquals(1, chapters.length); + assertEquals("2kFJSKFOkDUEXFOh7WFJUv", chapters[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedEpisodesRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/CheckUsersSavedEpisodesRequestTest.java similarity index 90% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedEpisodesRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/episodes/CheckUsersSavedEpisodesRequestTest.java index 0392eb6f6..8be1124ed 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedEpisodesRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/CheckUsersSavedEpisodesRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.episodes; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -12,12 +12,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +@SuppressWarnings("deprecation") public class CheckUsersSavedEpisodesRequestTest extends AbstractDataTest { private final CheckUsersSavedEpisodesRequest defaultRequest = ITest.SPOTIFY_API .checkUsersSavedEpisodes(ITest.ID_EPISODE, ITest.ID_EPISODE) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/library/CheckUsersSavedEpisodesRequest.json")) + "requests/data/episodes/CheckUsersSavedEpisodesRequest.json")) .build(); public CheckUsersSavedEpisodesRequestTest() throws Exception { diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetEpisodeRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetEpisodeRequestTest.java index 34f2614db..e36c5b144 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetEpisodeRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetEpisodeRequestTest.java @@ -71,7 +71,7 @@ public void shouldReturnDefault(final Episode episode) { assertFalse( episode.getExternallyHosted()); assertTrue( - episode.getPlayable()); + episode.getIsPlayable()); assertEquals( 1, episode.getLanguages().length); diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequestTest.java new file mode 100644 index 000000000..65d4c1de2 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetSeveralEpisodesRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.episodes; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Episode; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetSeveralEpisodesRequestTest extends AbstractDataTest { + private final GetSeveralEpisodesRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralEpisodes(ITest.ID_EPISODE) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/episodes/GetSeveralEpisodesRequest.json")) + .build(); + + public GetSeveralEpisodesRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/episodes?ids=4GI3dxEafwap1sFiTGPKd1", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Episode[] episodes) { + assertNotNull(episodes); + assertEquals(1, episodes.length); + assertEquals("4GI3dxEafwap1sFiTGPKd1", episodes[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedEpisodesRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetUsersSavedEpisodesRequestTest.java similarity index 95% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedEpisodesRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetUsersSavedEpisodesRequestTest.java index 4d02e1bdc..9f5bcb732 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedEpisodesRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/GetUsersSavedEpisodesRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.episodes; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -21,7 +21,7 @@ public class GetUsersSavedEpisodesRequestTest extends AbstractDataTest { + private final RemoveEpisodesForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .removeEpisodesForCurrentUser(ITest.ID_EPISODE) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public RemoveEpisodesForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/episodes?ids=4GI3dxEafwap1sFiTGPKd1", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequestTest.java new file mode 100644 index 000000000..667179f26 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/episodes/SaveEpisodesForCurrentUserRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.episodes; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SuppressWarnings("deprecation") +public class SaveEpisodesForCurrentUserRequestTest extends AbstractDataTest { + private final SaveEpisodesForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .saveEpisodesForCurrentUser(ITest.ID_EPISODE) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public SaveEpisodesForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/episodes?ids=4GI3dxEafwap1sFiTGPKd1", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequestTest.java deleted file mode 100644 index 5847d5f34..000000000 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/legacy/FollowPlaylistRequestTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package se.michaelthelin.spotify.requests.data.follow.legacy; - -import org.apache.hc.core5.http.ParseException; -import org.junit.jupiter.api.Test; -import se.michaelthelin.spotify.ITest; -import se.michaelthelin.spotify.TestUtil; -import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.requests.data.AbstractDataTest; - -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; -import static se.michaelthelin.spotify.Assertions.assertHasHeader; - -public class FollowPlaylistRequestTest extends AbstractDataTest { - private final FollowPlaylistRequest defaultRequest = ITest.SPOTIFY_API - .followPlaylist(ITest.ID_USER, ITest.ID_PLAYLIST, ITest.PUBLIC) - .setHttpManager( - TestUtil.MockedHttpManager.returningJson(null)) - .build(); - - public FollowPlaylistRequestTest() throws Exception { - } - - @Test - public void shouldComplyWithReference() { - assertHasAuthorizationHeader(defaultRequest); - assertHasHeader(defaultRequest, "Content-Type", "application/json"); - assertHasBodyParameter( - defaultRequest, - "public", - ITest.PUBLIC); - assertEquals( - "https://api.spotify.com:443/v1/users/abbaspotify/playlists/3AGOiaoRXMSjswCLtuNqv5/followers", - defaultRequest.getUri().toString()); - } - - @Test - public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { - shouldReturnDefault(defaultRequest.execute()); - } - - @Test - public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { - shouldReturnDefault(defaultRequest.executeAsync().get()); - } - - public void shouldReturnDefault(final String string) { - assertNull( - string); - } -} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/genres/GetRecommendationGenresRequestTest.java similarity index 74% rename from src/test/java/se/michaelthelin/spotify/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/genres/GetRecommendationGenresRequestTest.java index b153cf14c..a02474af3 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/genres/GetRecommendationGenresRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse.miscellaneous; +package se.michaelthelin.spotify.requests.data.genres; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -11,14 +11,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class GetAvailableGenreSeedsRequestTest extends AbstractDataTest { - private final GetAvailableGenreSeedsRequest defaultRequest = SPOTIFY_API.getAvailableGenreSeeds() +public class GetRecommendationGenresRequestTest extends AbstractDataTest { + private final GetRecommendationGenresRequest defaultRequest = SPOTIFY_API.getRecommendationGenres() .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/browse/miscellaneous/GetAvailableGenreSeedsRequest.json")) + "requests/data/genres/GetRecommendationGenresRequest.json")) .build(); - public GetAvailableGenreSeedsRequestTest() throws Exception { + public GetRecommendationGenresRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckLibraryContainsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckLibraryContainsRequestTest.java new file mode 100644 index 000000000..bccf9fbf3 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckLibraryContainsRequestTest.java @@ -0,0 +1,49 @@ +package se.michaelthelin.spotify.requests.data.library; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CheckLibraryContainsRequestTest extends AbstractDataTest { + private final CheckUsersSavedItemsRequest defaultRequest = ITest.SPOTIFY_API + .checkUsersSavedItems("spotify:track:01iyCAUm8EvOFqVWYJ3dVX,spotify:track:01iyCAUm8EvOFqVWYJ3dVX") + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/library/CheckLibraryContainsRequest.json")) + .build(); + + public CheckLibraryContainsRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/library/contains?uris=spotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX%2Cspotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Boolean[] booleans) { + assertEquals( + 2, + booleans.length); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/RemoveFromLibraryRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/library/RemoveLibraryItemsRequestTest.java similarity index 83% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/RemoveFromLibraryRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/library/RemoveLibraryItemsRequestTest.java index b5aa9e156..0f479cd20 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/RemoveFromLibraryRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/library/RemoveLibraryItemsRequestTest.java @@ -13,13 +13,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -public class RemoveFromLibraryRequestTest extends AbstractDataTest { - private final RemoveFromLibraryRequest defaultRequest = ITest.SPOTIFY_API.removeFromLibrary(ITest.URIS) +public class RemoveLibraryItemsRequestTest extends AbstractDataTest { + private final RemoveItemsFromLibraryRequest defaultRequest = ITest.SPOTIFY_API.removeItemsFromLibrary(ITest.URIS) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .build(); - public RemoveFromLibraryRequestTest() throws Exception { + public RemoveLibraryItemsRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/SaveToLibraryRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/library/SaveLibraryItemsRequestTest.java similarity index 84% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/SaveToLibraryRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/library/SaveLibraryItemsRequestTest.java index ae7413479..b102869d7 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/SaveToLibraryRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/library/SaveLibraryItemsRequestTest.java @@ -13,13 +13,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -public class SaveToLibraryRequestTest extends AbstractDataTest { - private final SaveToLibraryRequest defaultRequest = ITest.SPOTIFY_API.saveToLibrary(ITest.URIS) +public class SaveLibraryItemsRequestTest extends AbstractDataTest { + private final SaveItemsToLibraryRequest defaultRequest = ITest.SPOTIFY_API.saveItemsToLibrary(ITest.URIS) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .build(); - public SaveToLibraryRequestTest() throws Exception { + public SaveLibraryItemsRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequestTest.java new file mode 100644 index 000000000..24a2c27e2 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/markets/GetAvailableMarketsRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.markets; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class GetAvailableMarketsRequestTest extends AbstractDataTest { + private final GetAvailableMarketsRequest defaultRequest = ITest.SPOTIFY_API + .getAvailableMarkets() + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/markets/GetAvailableMarketsRequest.json")) + .build(); + + public GetAvailableMarketsRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/markets", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String[] markets) { + assertNotNull(markets); + assertTrue(markets.length > 0); + assertEquals("AD", markets[0]); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/AddItemToUsersPlaybackQueueRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/AddToQueueRequestTest.java similarity index 82% rename from src/test/java/se/michaelthelin/spotify/requests/data/player/AddItemToUsersPlaybackQueueRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/player/AddToQueueRequestTest.java index 1aa51fe3f..377becdc2 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/AddItemToUsersPlaybackQueueRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/AddToQueueRequestTest.java @@ -14,15 +14,15 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static se.michaelthelin.spotify.Assertions.assertHasHeader; -public class AddItemToUsersPlaybackQueueRequestTest extends AbstractDataTest { - private final AddItemToUsersPlaybackQueueRequest defaultRequest = ITest.SPOTIFY_API - .addItemToUsersPlaybackQueue("spotify:track:" + ITest.ID_TRACK) +public class AddToQueueRequestTest extends AbstractDataTest { + private final AddItemToPlaybackQueueRequest defaultRequest = ITest.SPOTIFY_API + .addItemToPlaybackQueue("spotify:track:" + ITest.ID_TRACK) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) .build(); - public AddItemToUsersPlaybackQueueRequestTest() throws Exception { + public AddToQueueRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetInformationAboutUsersCurrentPlaybackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetInformationAboutUsersCurrentPlaybackRequestTest.java index 05e7d4883..3fe150249 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetInformationAboutUsersCurrentPlaybackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetInformationAboutUsersCurrentPlaybackRequestTest.java @@ -18,8 +18,8 @@ import static org.junit.jupiter.api.Assertions.*; public class GetInformationAboutUsersCurrentPlaybackRequestTest extends AbstractDataTest { - private final GetInformationAboutUsersCurrentPlaybackRequest defaultRequest = ITest.SPOTIFY_API - .getInformationAboutUsersCurrentPlayback() + private final GetPlaybackStateRequest defaultRequest = ITest.SPOTIFY_API + .getPlaybackState() .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/player/GetInformationAboutUsersCurrentPlaybackRequest.json")) @@ -27,8 +27,8 @@ public class GetInformationAboutUsersCurrentPlaybackRequestTest extends Abstract .additionalTypes(ITest.ADDITIONAL_TYPES) .build(); - private final GetInformationAboutUsersCurrentPlaybackRequest defaultEpisodeRequest = ITest.SPOTIFY_API - .getInformationAboutUsersCurrentPlayback() + private final GetPlaybackStateRequest defaultEpisodeRequest = ITest.SPOTIFY_API + .getPlaybackState() .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/player/GetInformationAboutUsersCurrentPlaybackRequest_Episode.json")) @@ -36,8 +36,8 @@ public class GetInformationAboutUsersCurrentPlaybackRequestTest extends Abstract .additionalTypes(ITest.ADDITIONAL_TYPES) .build(); - private final GetInformationAboutUsersCurrentPlaybackRequest emptyRequest = ITest.SPOTIFY_API - .getInformationAboutUsersCurrentPlayback() + private final GetPlaybackStateRequest emptyRequest = ITest.SPOTIFY_API + .getPlaybackState() .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .market(ITest.MARKET) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetTheUsersQueueRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetQueueRequestTest.java similarity index 87% rename from src/test/java/se/michaelthelin/spotify/requests/data/player/GetTheUsersQueueRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/player/GetQueueRequestTest.java index 0d05f55ae..9f4a021b8 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetTheUsersQueueRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetQueueRequestTest.java @@ -14,15 +14,15 @@ import static org.junit.jupiter.api.Assertions.*; -public class GetTheUsersQueueRequestTest extends AbstractDataTest { +public class GetQueueRequestTest extends AbstractDataTest { - private final GetTheUsersQueueRequest defaultRequest = ITest.SPOTIFY_API - .getTheUsersQueue() + private final GetUsersQueueRequest defaultRequest = ITest.SPOTIFY_API + .getUsersQueue() .setHttpManager( - TestUtil.MockedHttpManager.returningJson("requests/data/player/GetTheUsersQueueRequest.json")) + TestUtil.MockedHttpManager.returningJson("requests/data/player/GetQueueRequest.json")) .build(); - public GetTheUsersQueueRequestTest() throws Exception { + public GetQueueRequestTest() throws Exception { assertEquals("https://api.spotify.com:443/v1/me/player/queue", defaultRequest.getUri().toString()); } diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetRecentlyPlayedRequestTest.java similarity index 84% rename from src/test/java/se/michaelthelin/spotify/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/player/GetRecentlyPlayedRequestTest.java index b67c8be6b..7b4cd5ce8 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetRecentlyPlayedRequestTest.java @@ -15,18 +15,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -public class GetCurrentUsersRecentlyPlayedTracksRequestTest extends AbstractDataTest> { - private final GetCurrentUsersRecentlyPlayedTracksRequest defaultRequest = ITest.SPOTIFY_API - .getCurrentUsersRecentlyPlayedTracks() +public class GetRecentlyPlayedRequestTest extends AbstractDataTest> { + private final GetRecentlyPlayedTracksRequest defaultRequest = ITest.SPOTIFY_API + .getRecentlyPlayedTracks() .after(ITest.AFTER) .before(ITest.BEFORE) .limit(ITest.LIMIT) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/player/GetCurrentUsersRecentlyPlayedTracksRequest.json")) + "requests/data/player/GetRecentlyPlayedRequest.json")) .build(); - public GetCurrentUsersRecentlyPlayedTracksRequestTest() throws Exception { + public GetRecentlyPlayedRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersAvailableDevicesTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersAvailableDevicesTest.java index 5ba77c30f..744573444 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersAvailableDevicesTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersAvailableDevicesTest.java @@ -14,15 +14,15 @@ import static org.junit.jupiter.api.Assertions.*; public class GetUsersAvailableDevicesTest extends AbstractDataTest { - private final GetUsersAvailableDevicesRequest defaultRequest = ITest.SPOTIFY_API - .getUsersAvailableDevices() + private final GetAvailableDevicesRequest defaultRequest = ITest.SPOTIFY_API + .getAvailableDevices() .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/player/GetUsersAvailableDevices.json")) .build(); - private final GetUsersAvailableDevicesRequest emptyRequest = ITest.SPOTIFY_API - .getUsersAvailableDevices() + private final GetAvailableDevicesRequest emptyRequest = ITest.SPOTIFY_API + .getAvailableDevices() .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/player/GetUsersAvailableDevices_None.json")) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersCurrentlyPlayingTrackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersCurrentlyPlayingTrackRequestTest.java index 571cfddca..85ba1dbe4 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersCurrentlyPlayingTrackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/GetUsersCurrentlyPlayingTrackRequestTest.java @@ -18,8 +18,8 @@ import static org.junit.jupiter.api.Assertions.*; public class GetUsersCurrentlyPlayingTrackRequestTest extends AbstractDataTest { - private final GetUsersCurrentlyPlayingTrackRequest defaultRequest = ITest.SPOTIFY_API - .getUsersCurrentlyPlayingTrack() + private final GetCurrentlyPlayingTrackRequest defaultRequest = ITest.SPOTIFY_API + .getCurrentlyPlayingTrack() .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/player/GetUsersCurrentlyPlayingTrackRequest.json")) @@ -27,8 +27,8 @@ public class GetUsersCurrentlyPlayingTrackRequestTest extends AbstractDataTest { - private final PauseUsersPlaybackRequest defaultRequest = ITest.SPOTIFY_API - .pauseUsersPlayback() + private final PausePlaybackRequest defaultRequest = ITest.SPOTIFY_API + .pausePlayback() .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionInCurrentlyPlayingTrackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionInCurrentlyPlayingTrackRequestTest.java index 925f91c44..e548802c6 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionInCurrentlyPlayingTrackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/SeekToPositionInCurrentlyPlayingTrackRequestTest.java @@ -15,8 +15,8 @@ import static se.michaelthelin.spotify.Assertions.assertHasHeader; public class SeekToPositionInCurrentlyPlayingTrackRequestTest extends AbstractDataTest { - private final SeekToPositionInCurrentlyPlayingTrackRequest defaultRequest = ITest.SPOTIFY_API - .seekToPositionInCurrentlyPlayingTrack(ITest.POSITION_MS) + private final SeekToPositionRequest defaultRequest = ITest.SPOTIFY_API + .seekToPosition(ITest.POSITION_MS) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeOnUsersPlaybackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeOnUsersPlaybackRequestTest.java index 9f9eef5a9..74bd3459e 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeOnUsersPlaybackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/SetRepeatModeOnUsersPlaybackRequestTest.java @@ -15,8 +15,8 @@ import static se.michaelthelin.spotify.Assertions.assertHasHeader; public class SetRepeatModeOnUsersPlaybackRequestTest extends AbstractDataTest { - private final SetRepeatModeOnUsersPlaybackRequest defaultRequest = ITest.SPOTIFY_API - .setRepeatModeOnUsersPlayback(ITest.STATE) + private final SetRepeatModeRequest defaultRequest = ITest.SPOTIFY_API + .setRepeatMode(ITest.STATE) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/SetVolumeForUsersPlaybackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/SetVolumeForUsersPlaybackRequestTest.java index d13a8cf24..c290a23d6 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/SetVolumeForUsersPlaybackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/SetVolumeForUsersPlaybackRequestTest.java @@ -15,8 +15,8 @@ import static se.michaelthelin.spotify.Assertions.assertHasHeader; public class SetVolumeForUsersPlaybackRequestTest extends AbstractDataTest { - private final SetVolumeForUsersPlaybackRequest defaultRequest = ITest.SPOTIFY_API - .setVolumeForUsersPlayback(ITest.VOLUME_PERCENT) + private final SetPlaybackVolumeRequest defaultRequest = ITest.SPOTIFY_API + .setPlaybackVolume(ITest.VOLUME_PERCENT) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToNextTrackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToNextTrackRequestTest.java index 0de937392..28d86c896 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToNextTrackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToNextTrackRequestTest.java @@ -15,8 +15,8 @@ import static se.michaelthelin.spotify.Assertions.assertHasHeader; public class SkipUsersPlaybackToNextTrackRequestTest extends AbstractDataTest { - private final SkipUsersPlaybackToNextTrackRequest defaultRequest = ITest.SPOTIFY_API - .skipUsersPlaybackToNextTrack() + private final SkipToNextRequest defaultRequest = ITest.SPOTIFY_API + .skipToNext() .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToPreviousTrackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToPreviousTrackRequestTest.java index d6a13296e..35a5cb71c 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToPreviousTrackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/SkipUsersPlaybackToPreviousTrackRequestTest.java @@ -15,8 +15,8 @@ import static se.michaelthelin.spotify.Assertions.assertHasHeader; public class SkipUsersPlaybackToPreviousTrackRequestTest extends AbstractDataTest { - private final SkipUsersPlaybackToPreviousTrackRequest defaultRequest = ITest.SPOTIFY_API - .skipUsersPlaybackToPreviousTrack() + private final SkipToPreviousRequest defaultRequest = ITest.SPOTIFY_API + .skipToPrevious() .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequestNumericTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/StartUsersPlaybackRequestNumericTest.java similarity index 87% rename from src/test/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequestNumericTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/player/StartUsersPlaybackRequestNumericTest.java index 371616db5..f8d7b4da0 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequestNumericTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/StartUsersPlaybackRequestNumericTest.java @@ -11,15 +11,15 @@ /** * Test for ensuring numeric and structured parameters are preserved with correct types in JSON request bodies */ -public class StartResumeUsersPlaybackRequestNumericTest { +public class StartUsersPlaybackRequestNumericTest { @Test public void shouldPreserveNumericParametersAsNumbers() { // Create a request with numeric position_ms parameter - StartResumeUsersPlaybackRequest request = new SpotifyApi.Builder() + StartResumePlaybackRequest request = new SpotifyApi.Builder() .setAccessToken("test-token") .build() - .startResumeUsersPlayback() + .startResumePlayback() .position_ms(10000) .build(); @@ -42,10 +42,10 @@ public void shouldPreserveBooleanParametersAsBooleans() { uris.add("spotify:track:test1"); uris.add("spotify:track:test2"); - StartResumeUsersPlaybackRequest request = new SpotifyApi.Builder() + StartResumePlaybackRequest request = new SpotifyApi.Builder() .setAccessToken("test-token") .build() - .startResumeUsersPlayback() + .startResumePlayback() .uris(uris) .build(); @@ -65,10 +65,10 @@ public void shouldPreserveJsonObjectParameters() { JsonObject offset = new JsonObject(); offset.addProperty("position", 5); - StartResumeUsersPlaybackRequest request = new SpotifyApi.Builder() + StartResumePlaybackRequest request = new SpotifyApi.Builder() .setAccessToken("test-token") .build() - .startResumeUsersPlayback() + .startResumePlayback() .offset(offset) .build(); diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/StartUsersPlaybackRequestTest.java similarity index 88% rename from src/test/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/player/StartUsersPlaybackRequestTest.java index 64f6b7965..8caf50332 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/StartResumeUsersPlaybackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/StartUsersPlaybackRequestTest.java @@ -15,9 +15,9 @@ import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; import static se.michaelthelin.spotify.Assertions.assertHasHeader; -public class StartResumeUsersPlaybackRequestTest extends AbstractDataTest { - private final StartResumeUsersPlaybackRequest defaultRequest = ITest.SPOTIFY_API - .startResumeUsersPlayback() +public class StartUsersPlaybackRequestTest extends AbstractDataTest { + private final StartResumePlaybackRequest defaultRequest = ITest.SPOTIFY_API + .startResumePlayback() .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .context_uri(ITest.CONTEXT_URI) @@ -27,7 +27,7 @@ public class StartResumeUsersPlaybackRequestTest extends AbstractDataTest { - private final ToggleShuffleForUsersPlaybackRequest defaultRequest = ITest.SPOTIFY_API - .toggleShuffleForUsersPlayback(ITest.STATE_BOOLEAN) + private final TogglePlaybackShuffleRequest defaultRequest = ITest.SPOTIFY_API + .togglePlaybackShuffle(ITest.STATE_BOOLEAN) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .device_id(ITest.DEVICE_ID) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/player/TransferUsersPlaybackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/player/TransferUsersPlaybackRequestTest.java index 7df526912..233d86771 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/player/TransferUsersPlaybackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/player/TransferUsersPlaybackRequestTest.java @@ -17,8 +17,8 @@ import static se.michaelthelin.spotify.Assertions.assertHasHeader; public class TransferUsersPlaybackRequestTest extends AbstractDataTest { - private final TransferUsersPlaybackRequest defaultRequest = ITest.SPOTIFY_API - .transferUsersPlayback(JsonParser.parseString("[\"" + ITest.DEVICE_ID + "\"]").getAsJsonArray()) + private final TransferPlaybackRequest defaultRequest = ITest.SPOTIFY_API + .transferPlayback(JsonParser.parseString("[\"" + ITest.DEVICE_ID + "\"]").getAsJsonArray()) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .play(ITest.PLAY) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/UploadCustomPlaylistCoverImageRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddCustomPlaylistCoverImageRequestTest.java similarity index 84% rename from src/test/java/se/michaelthelin/spotify/requests/data/playlists/UploadCustomPlaylistCoverImageRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddCustomPlaylistCoverImageRequestTest.java index 7d4c2724c..aabb2b4b6 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/UploadCustomPlaylistCoverImageRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddCustomPlaylistCoverImageRequestTest.java @@ -15,15 +15,15 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static se.michaelthelin.spotify.Assertions.assertHasHeader; -public class UploadCustomPlaylistCoverImageRequestTest extends AbstractDataTest { - private final UploadCustomPlaylistCoverImageRequest defaultRequest = ITest.SPOTIFY_API - .uploadCustomPlaylistCoverImage(ITest.ID_PLAYLIST) +public class AddCustomPlaylistCoverImageRequestTest extends AbstractDataTest { + private final AddCustomPlaylistCoverImageRequest defaultRequest = ITest.SPOTIFY_API + .addCustomPlaylistCoverImage(ITest.ID_PLAYLIST) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .image_data(ITest.IMAGE_DATA != null ? ITest.IMAGE_DATA : "") .build(); - public UploadCustomPlaylistCoverImageRequestTest() throws Exception { + public AddCustomPlaylistCoverImageRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ReplacePlaylistsItemsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistDeprecatedRequestTest.java similarity index 55% rename from src/test/java/se/michaelthelin/spotify/requests/data/playlists/ReplacePlaylistsItemsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistDeprecatedRequestTest.java index cd5ef16cf..b6d5132dd 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ReplacePlaylistsItemsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistDeprecatedRequestTest.java @@ -1,40 +1,49 @@ package se.michaelthelin.spotify.requests.data.playlists; +import com.google.gson.Gson; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; import se.michaelthelin.spotify.ITest; import se.michaelthelin.spotify.TestUtil; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.special.SnapshotResult; import se.michaelthelin.spotify.requests.data.AbstractDataTest; import java.io.IOException; import java.util.concurrent.ExecutionException; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; import static se.michaelthelin.spotify.Assertions.assertHasHeader; -public class ReplacePlaylistsItemsRequestTest extends AbstractDataTest { - private final ReplacePlaylistsItemsRequest defaultRequest = ITest.SPOTIFY_API - .replacePlaylistsItems(ITest.ID_PLAYLIST, new String[]{"spotify:track:" + ITest.ID_TRACK, "spotify:track:" + ITest.ID_TRACK}) +/** + * @deprecated Use {@link AddItemsToPlaylistRequestTest} instead. + */ +@Deprecated +public class AddItemsToPlaylistDeprecatedRequestTest extends AbstractDataTest { + private final AddItemsToPlaylistDeprecatedRequest defaultRequest = ITest.SPOTIFY_API + .addItemsToPlaylistDeprecated(ITest.ID_PLAYLIST, new Gson().fromJson(ITest.URIS, String[].class)) .setHttpManager( - TestUtil.MockedHttpManager.returningJson(null)) + TestUtil.MockedHttpManager.returningJson( + "requests/data/playlists/AddItemsToPlaylistRequest.json")) + .position(ITest.POSITION) .build(); - private final ReplacePlaylistsItemsRequest bodyRequest = ITest.SPOTIFY_API - .replacePlaylistsItems(ITest.ID_PLAYLIST, ITest.TRACKS) + private final AddItemsToPlaylistDeprecatedRequest bodyRequest = ITest.SPOTIFY_API + .addItemsToPlaylistDeprecated(ITest.ID_PLAYLIST, ITest.URIS) .setHttpManager( - TestUtil.MockedHttpManager.returningJson(null)) + TestUtil.MockedHttpManager.returningJson( + "requests/data/playlists/AddItemsToPlaylistRequest.json")) + .position(ITest.POSITION, true) .build(); - public ReplacePlaylistsItemsRequestTest() throws Exception { + public AddItemsToPlaylistDeprecatedRequestTest() throws Exception { } @Test public void shouldComplyWithReference() { assertHasAuthorizationHeader(defaultRequest); assertEquals( - "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks?uris=spotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX%2Cspotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX", + "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks?uris=spotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX%2Cspotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX&position=0", defaultRequest.getUri().toString()); assertHasAuthorizationHeader(bodyRequest); @@ -42,7 +51,11 @@ public void shouldComplyWithReference() { assertHasBodyParameter( bodyRequest, "uris", - ITest.TRACKS); + ITest.URIS); + assertHasBodyParameter( + bodyRequest, + "position", + ITest.POSITION); assertEquals( "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks", bodyRequest.getUri().toString()); @@ -58,8 +71,9 @@ public void shouldReturnDefault_async() throws ExecutionException, InterruptedEx shouldReturnDefault(defaultRequest.executeAsync().get()); } - public void shouldReturnDefault(final String string) { - assertNull( - string); + public void shouldReturnDefault(final SnapshotResult snapshotResult) { + assertEquals( + "JbtmHBDBAYu3/bt8BOXKjzKx3i0b6LCa/wVjyl6qQ2Yf6nFXkbmzuEa+ZI/U1yF+", + snapshotResult.getSnapshotId()); } } diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequestTest.java index cb49c439a..59f3eb0de 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/AddItemsToPlaylistRequestTest.java @@ -39,7 +39,7 @@ public AddItemsToPlaylistRequestTest() throws Exception { public void shouldComplyWithReference() { assertHasAuthorizationHeader(defaultRequest); assertEquals( - "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks?uris=spotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX%2Cspotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX&position=0", + "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/items?uris=spotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX%2Cspotify%3Atrack%3A01iyCAUm8EvOFqVWYJ3dVX&position=0", defaultRequest.getUri().toString()); assertHasAuthorizationHeader(bodyRequest); @@ -53,7 +53,7 @@ public void shouldComplyWithReference() { "position", ITest.POSITION); assertEquals( - "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks", + "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/items", bodyRequest.getUri().toString()); } diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistsDetailsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistDetailsRequestTest.java similarity index 88% rename from src/test/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistsDetailsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistDetailsRequestTest.java index 0a12058d9..e8c143e03 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistsDetailsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ChangePlaylistDetailsRequestTest.java @@ -15,9 +15,9 @@ import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; import static se.michaelthelin.spotify.Assertions.assertHasHeader; -public class ChangePlaylistsDetailsRequestTest extends AbstractDataTest { - private final ChangePlaylistsDetailsRequest defaultRequest = ITest.SPOTIFY_API - .changePlaylistsDetails(ITest.ID_PLAYLIST) +public class ChangePlaylistDetailsRequestTest extends AbstractDataTest { + private final ChangePlaylistDetailsRequest defaultRequest = ITest.SPOTIFY_API + .changePlaylistDetails(ITest.ID_PLAYLIST) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .collaborative(ITest.COLLABORATIVE) @@ -26,7 +26,7 @@ public class ChangePlaylistsDetailsRequestTest extends AbstractDataTest .public_(ITest.PUBLIC) .build(); - public ChangePlaylistsDetailsRequestTest() throws Exception { + public ChangePlaylistDetailsRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/RemoveItemsFromPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistForUserRequestTest.java similarity index 55% rename from src/test/java/se/michaelthelin/spotify/requests/data/playlists/RemoveItemsFromPlaylistRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistForUserRequestTest.java index e6308cd8f..b73ea38f6 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/RemoveItemsFromPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistForUserRequestTest.java @@ -5,36 +5,34 @@ import se.michaelthelin.spotify.ITest; import se.michaelthelin.spotify.TestUtil; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.model_objects.special.SnapshotResult; +import se.michaelthelin.spotify.model_objects.specification.Playlist; import se.michaelthelin.spotify.requests.data.AbstractDataTest; import java.io.IOException; import java.util.concurrent.ExecutionException; import static org.junit.jupiter.api.Assertions.assertEquals; -import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; +import static org.junit.jupiter.api.Assertions.assertNotNull; -public class RemoveItemsFromPlaylistRequestTest extends AbstractDataTest { - private final RemoveItemsFromPlaylistRequest defaultRequest = ITest.SPOTIFY_API - .removeItemsFromPlaylist(ITest.ID_PLAYLIST, ITest.TRACKS) +public class CreatePlaylistForUserRequestTest extends AbstractDataTest { + private final CreatePlaylistForUserRequest defaultRequest = ITest.SPOTIFY_API + .createPlaylistForUser(ITest.ID_USER, ITest.NAME) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/playlists/RemoveItemsFromPlaylistRequest.json")) - .snapshotId(ITest.SNAPSHOT_ID) + "requests/data/playlists/CreatePlaylistForUserRequest.json")) + .public_(ITest.PUBLIC) + .collaborative(ITest.COLLABORATIVE) + .description(ITest.DESCRIPTION) .build(); - public RemoveItemsFromPlaylistRequestTest() throws Exception { + public CreatePlaylistForUserRequestTest() throws Exception { } @Test public void shouldComplyWithReference() { assertHasAuthorizationHeader(defaultRequest); - assertHasBodyParameter( - defaultRequest, - "tracks", - ITest.TRACKS); assertEquals( - "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks", + "https://api.spotify.com:443/v1/users/abbaspotify/playlists", defaultRequest.getUri().toString()); } @@ -48,9 +46,13 @@ public void shouldReturnDefault_async() throws ExecutionException, InterruptedEx shouldReturnDefault(defaultRequest.executeAsync().get()); } - public void shouldReturnDefault(final SnapshotResult snapshotResult) { + public void shouldReturnDefault(final Playlist playlist) { + assertNotNull(playlist); assertEquals( - "JbtmHBDBAYu3/bt8BOXKjzKx3i0b6LCa/wVjyl6qQ2Yf6nFXkbmzuEa+ZI/U1yF+", - snapshotResult.getSnapshotId()); + "3cEYpjA9oz9GiPac4AsH4n", + playlist.getId()); + assertEquals( + "New Playlist", + playlist.getName()); } } diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistRequestTest.java index 838b1d8cb..866a14327 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/CreatePlaylistRequestTest.java @@ -86,7 +86,7 @@ public void shouldReturnDefault(final Playlist playlist) { assertNotNull( playlist.getOwner()); assertFalse( - playlist.getIsPublicAccess()); + playlist.getPublic()); assertEquals( "JbtmHBDBAkMzFjnFzSP0aeYCCMP1XSIY5VHZT_jUGrFTzNTa6tnPiSzeBMFIcH2", playlist.getSnapshotId()); diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/browse/GetCategorysPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetCategoryPlaylistsRequestTest.java similarity index 84% rename from src/test/java/se/michaelthelin/spotify/requests/data/browse/GetCategorysPlaylistRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetCategoryPlaylistsRequestTest.java index fdc6d44d4..f049d835a 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/browse/GetCategorysPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetCategoryPlaylistsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse; +package se.michaelthelin.spotify.requests.data.playlists; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -14,17 +14,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -public class GetCategorysPlaylistRequestTest extends AbstractDataTest> { - private final GetCategorysPlaylistsRequest defaultRequest = SPOTIFY_API.getCategorysPlaylists(CATEGORY_ID) +@SuppressWarnings("deprecation") +public class GetCategoryPlaylistsRequestTest extends AbstractDataTest> { + private final GetCategoryPlaylistsRequest defaultRequest = SPOTIFY_API.getCategoryPlaylists(CATEGORY_ID) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/browse/GetCategorysPlaylistsRequest.json")) + "requests/data/playlists/GetCategoryPlaylistsRequest.json")) .country(COUNTRY) .limit(LIMIT) .offset(OFFSET) .build(); - public GetCategorysPlaylistRequestTest() throws Exception { + public GetCategoryPlaylistsRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetListOfCurrentUsersPlaylistsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetCurrentUsersPlaylistsRequestTest.java similarity index 87% rename from src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetListOfCurrentUsersPlaylistsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetCurrentUsersPlaylistsRequestTest.java index 323842eb1..2f65ee981 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetListOfCurrentUsersPlaylistsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetCurrentUsersPlaylistsRequestTest.java @@ -15,9 +15,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -public class GetListOfCurrentUsersPlaylistsRequestTest extends AbstractDataTest> { - private final GetListOfCurrentUsersPlaylistsRequest defaultRequest = ITest.SPOTIFY_API - .getListOfCurrentUsersPlaylists() +public class GetCurrentUsersPlaylistsRequestTest extends AbstractDataTest> { + private final GetCurrentUsersPlaylistsRequest defaultRequest = ITest.SPOTIFY_API + .getCurrentUsersPlaylists() .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/playlists/GetListOfCurrentUsersPlaylistsRequest.json")) @@ -25,7 +25,7 @@ public class GetListOfCurrentUsersPlaylistsRequestTest extends AbstractDataTest< .offset(ITest.OFFSET) .build(); - public GetListOfCurrentUsersPlaylistsRequestTest() throws Exception { + public GetCurrentUsersPlaylistsRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/browse/GetListOfFeaturedPlaylistsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetFeaturedPlaylistsRequestTest.java similarity index 79% rename from src/test/java/se/michaelthelin/spotify/requests/data/browse/GetListOfFeaturedPlaylistsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetFeaturedPlaylistsRequestTest.java index c1f3e5c8b..0a12140b0 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/browse/GetListOfFeaturedPlaylistsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetFeaturedPlaylistsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse; +package se.michaelthelin.spotify.requests.data.playlists; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -13,11 +13,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -public class GetListOfFeaturedPlaylistsRequestTest extends AbstractDataTest { - private final GetListOfFeaturedPlaylistsRequest defaultRequest = SPOTIFY_API.getListOfFeaturedPlaylists() +@SuppressWarnings("deprecation") +public class GetFeaturedPlaylistsRequestTest extends AbstractDataTest { + private final GetFeaturedPlaylistsRequest defaultRequest = SPOTIFY_API.getFeaturedPlaylists() .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/browse/GetListOfFeaturedPlaylistsRequest.json")) + "requests/data/playlists/GetFeaturedPlaylistsRequest.json")) .country(COUNTRY) .limit(LIMIT) .locale(LOCALE) @@ -25,7 +26,7 @@ public class GetListOfFeaturedPlaylistsRequestTest extends AbstractDataTest .getPlaylistCoverImage(ITest.ID_PLAYLIST) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/playlists/GetPlaylistCoverImageRequest.json")) + "requests/data/playlists/GetPlaylistCoverRequest.json")) .build(); public GetPlaylistCoverImageRequestTest() throws Exception { diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java index 10b891a61..0e1175336 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java @@ -128,7 +128,7 @@ public void shouldReturnDefault(final Playlist playlist) { assertNotNull( playlist.getOwner()); assertNull( - playlist.getIsPublicAccess()); + playlist.getPublic()); assertEquals( "bNLWdmhh+HDsbHzhckXeDC0uyKyg4FjPI/KEsKjAE526usnz2LxwgyBoMShVL+z+", playlist.getSnapshotId()); diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistsItemsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistsItemsRequestTest.java deleted file mode 100644 index db6fc1244..000000000 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistsItemsRequestTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package se.michaelthelin.spotify.requests.data.playlists; - -import org.apache.hc.core5.http.ParseException; -import org.junit.jupiter.api.Test; -import se.michaelthelin.spotify.ITest; -import se.michaelthelin.spotify.TestUtil; -import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.model_objects.specification.Episode; -import se.michaelthelin.spotify.model_objects.specification.Paging; -import se.michaelthelin.spotify.model_objects.specification.PlaylistTrack; -import se.michaelthelin.spotify.model_objects.specification.Track; -import se.michaelthelin.spotify.requests.data.AbstractDataTest; - -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -import static org.junit.jupiter.api.Assertions.*; - -public class GetPlaylistsItemsRequestTest extends AbstractDataTest> { - private final GetPlaylistsItemsRequest defaultRequest = ITest.SPOTIFY_API - .getPlaylistsItems(ITest.ID_PLAYLIST) - .setHttpManager( - TestUtil.MockedHttpManager.returningJson( - "requests/data/playlists/GetPlaylistsItemsRequest.json")) - .fields(ITest.FIELDS) - .limit(ITest.LIMIT) - .market(ITest.MARKET) - .offset(ITest.OFFSET) - .additionalTypes(ITest.ADDITIONAL_TYPES) - .build(); - - private final GetPlaylistsItemsRequest defaultEpisodeRequest = ITest.SPOTIFY_API - .getPlaylistsItems(ITest.ID_PLAYLIST) - .setHttpManager( - TestUtil.MockedHttpManager.returningJson( - "requests/data/playlists/GetPlaylistsItemsRequest_Episode.json")) - .fields(ITest.FIELDS) - .limit(ITest.LIMIT) - .market(ITest.MARKET) - .offset(ITest.OFFSET) - .additionalTypes(ITest.ADDITIONAL_TYPES) - .build(); - - public GetPlaylistsItemsRequestTest() throws Exception { - } - - @Test - public void shouldComplyWithReference() { - assertHasAuthorizationHeader(defaultRequest); - assertEquals( - "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks?fields=description&limit=10&market=SE&offset=0&additional_types=track%2Cepisode", - defaultRequest.getUri().toString()); - } - - @Test - public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { - shouldReturnDefault(defaultRequest.execute()); - } - - @Test - public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { - shouldReturnDefault(defaultRequest.executeAsync().get()); - } - - public void shouldReturnDefault(final Paging playlistTrackPaging) { - assertEquals( - "https://api.spotify.com/v1/users/spotify_espa%C3%B1a/playlists/21THa8j9TaSGuXYNBU5tsC/tracks", - playlistTrackPaging.getHref()); - assertEquals( - 2, - playlistTrackPaging.getItems().length); - assertInstanceOf( - Track.class, - playlistTrackPaging.getItems()[0].getItem()); - assertEquals( - 100, - (int) playlistTrackPaging.getLimit()); - assertNull( - playlistTrackPaging.getNext()); - assertEquals( - 0, - (int) playlistTrackPaging.getOffset()); - assertNull( - playlistTrackPaging.getPrevious()); - assertEquals( - 58, - (int) playlistTrackPaging.getTotal()); - } - - @Test - public void shouldReturnDefaultEpisode_sync() throws IOException, SpotifyWebApiException, ParseException { - shouldReturnDefaultEpisode(defaultEpisodeRequest.execute()); - } - - @Test - public void shouldReturnDefaultEpisode_async() throws ExecutionException, InterruptedException { - shouldReturnDefaultEpisode(defaultEpisodeRequest.executeAsync().get()); - } - - public void shouldReturnDefaultEpisode(final Paging playlistTrackPaging) { - assertEquals( - "https://api.spotify.com/v1/playlists/21THa8j9TaSGuXYNBU5tsC/tracks?offset=0&limit=100&additional_types=episode", - playlistTrackPaging.getHref()); - assertEquals( - 1, - playlistTrackPaging.getItems().length); - assertInstanceOf( - Episode.class, - playlistTrackPaging.getItems()[0].getItem()); - assertEquals( - 100, - (int) playlistTrackPaging.getLimit()); - assertNull( - playlistTrackPaging.getNext()); - assertEquals( - 0, - (int) playlistTrackPaging.getOffset()); - assertNull( - playlistTrackPaging.getPrevious()); - assertEquals( - 58, - (int) playlistTrackPaging.getTotal()); - } -} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequestTest.java new file mode 100644 index 000000000..88db3a621 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetUsersPlaylistsRequestTest.java @@ -0,0 +1,59 @@ +package se.michaelthelin.spotify.requests.data.playlists; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Paging; +import se.michaelthelin.spotify.model_objects.specification.PlaylistSimplified; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class GetUsersPlaylistsRequestTest extends AbstractDataTest> { + private final GetUsersPlaylistsRequest defaultRequest = ITest.SPOTIFY_API + .getUsersPlaylists(ITest.ID_USER) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/playlists/GetListUsersPlaylistsRequest.json")) + .limit(ITest.LIMIT) + .offset(ITest.OFFSET) + .build(); + + public GetUsersPlaylistsRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/users/abbaspotify/playlists?limit=10&offset=0", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Paging playlistSimplifiedPaging) { + assertEquals( + "https://api.spotify.com/v1/users/%24wizzler%24/playlists", + playlistSimplifiedPaging.getHref()); + assertEquals( + 2, + playlistSimplifiedPaging.getItems().length); + assertEquals( + 9, + (int) playlistSimplifiedPaging.getTotal()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ReorderPlaylistsItemsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ReorderPlaylistsItemsRequestTest.java deleted file mode 100644 index ae137cd6f..000000000 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/ReorderPlaylistsItemsRequestTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package se.michaelthelin.spotify.requests.data.playlists; - -import org.apache.hc.core5.http.ParseException; -import org.junit.jupiter.api.Test; -import se.michaelthelin.spotify.ITest; -import se.michaelthelin.spotify.TestUtil; -import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; -import se.michaelthelin.spotify.model_objects.special.SnapshotResult; -import se.michaelthelin.spotify.requests.data.AbstractDataTest; - -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; -import static se.michaelthelin.spotify.Assertions.assertHasHeader; - -public class ReorderPlaylistsItemsRequestTest extends AbstractDataTest { - private final ReorderPlaylistsItemsRequest defaultRequest = ITest.SPOTIFY_API - .reorderPlaylistsItems(ITest.ID_PLAYLIST, ITest.RANGE_START, ITest.INSERT_BEFORE) - .setHttpManager( - TestUtil.MockedHttpManager.returningJson( - "requests/data/playlists/ReorderPlaylistsItemsRequest.json")) - .range_length(ITest.RANGE_LENGTH) - .snapshot_id(ITest.SNAPSHOT_ID) - .build(); - - public ReorderPlaylistsItemsRequestTest() throws Exception { - } - - @Test - public void shouldComplyWithReference() { - assertHasAuthorizationHeader(defaultRequest); - assertHasHeader(defaultRequest, "Content-Type", "application/json"); - assertHasBodyParameter( - defaultRequest, - "range_start", - ITest.RANGE_START); - assertHasBodyParameter( - defaultRequest, - "range_length", - ITest.RANGE_LENGTH); - assertHasBodyParameter( - defaultRequest, - "insert_before", - ITest.INSERT_BEFORE); - assertHasBodyParameter( - defaultRequest, - "snapshot_id", - ITest.SNAPSHOT_ID); - assertEquals( - "https://api.spotify.com:443/v1/playlists/3AGOiaoRXMSjswCLtuNqv5/tracks", - defaultRequest.getUri().toString()); - } - - @Test - public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { - shouldReturnDefault(defaultRequest.execute()); - } - - @Test - public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { - shouldReturnDefault(defaultRequest.executeAsync().get()); - } - - public void shouldReturnDefault(final SnapshotResult snapshotResult) { - assertEquals( - "KsWY41k+zLqbx7goYX9zr+2IUZQtqbBNfk4ZOgEpIurvab4VSHhEL2L4za8HW6D0", - snapshotResult.getSnapshotId()); - } -} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/search/SearchItemRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/search/SearchRequestTest.java similarity index 86% rename from src/test/java/se/michaelthelin/spotify/requests/data/search/SearchItemRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/search/SearchRequestTest.java index 645e79d9b..144de5573 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/search/SearchItemRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/search/SearchRequestTest.java @@ -16,19 +16,19 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -public class SearchItemRequestTest extends AbstractDataTest { - private final SearchItemRequest defaultRequest = ITest.SPOTIFY_API - .searchItem(ITest.Q, ModelObjectType.ARTIST.getType()) +public class SearchRequestTest extends AbstractDataTest { + private final SearchForItemRequest defaultRequest = ITest.SPOTIFY_API + .searchForItem(ITest.Q, ModelObjectType.ARTIST.getType()) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/search/SearchItemRequest.json")) + "requests/data/search/SearchRequest.json")) .limit(ITest.LIMIT) .market(ITest.MARKET) .offset(ITest.OFFSET) .includeExternal("audio") .build(); - public SearchItemRequestTest() throws Exception { + public SearchRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedShowsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/shows/CheckUsersSavedShowsRequestTest.java similarity index 90% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedShowsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/shows/CheckUsersSavedShowsRequestTest.java index 95032cebc..bce03cf56 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedShowsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/shows/CheckUsersSavedShowsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.shows; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -12,11 +12,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +@SuppressWarnings("deprecation") public class CheckUsersSavedShowsRequestTest extends AbstractDataTest { private final CheckUsersSavedShowsRequest defaultRequest = ITest.SPOTIFY_API.checkUsersSavedShows(ITest.ID_SHOW, ITest.ID_SHOW) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/library/CheckUsersSavedShowsRequest.json")) + "requests/data/shows/CheckUsersSavedShowsRequest.json")) .build(); public CheckUsersSavedShowsRequestTest() throws Exception { diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequestTest.java new file mode 100644 index 000000000..704b52cbb --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetSeveralShowsRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.shows; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.ShowSimplified; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetSeveralShowsRequestTest extends AbstractDataTest { + private final GetSeveralShowsRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralShows(ITest.ID_SHOW) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/shows/GetSeveralShowsRequest.json")) + .build(); + + public GetSeveralShowsRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/shows?ids=5AvwZVawapvyhJUIx71pdJ", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final ShowSimplified[] shows) { + assertNotNull(shows); + assertEquals(1, shows.length); + assertEquals("7iZEp9f2Gg8JvKNqK3t905", shows[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetShowsEpisodesRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetShowsEpisodesRequestTest.java index 7f9f3085d..fac781dce 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetShowsEpisodesRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetShowsEpisodesRequestTest.java @@ -15,7 +15,7 @@ public class GetShowsEpisodesRequestTest extends AbstractDataTest> { - private final GetShowsEpisodesRequest defaultRequest = SPOTIFY_API.getShowEpisodes(ID_SHOW) + private final GetShowEpisodesRequest defaultRequest = SPOTIFY_API.getShowEpisodes(ID_SHOW) .setHttpManager( TestUtil.MockedHttpManager.returningJson( "requests/data/shows/GetShowsEpisodesRequest.json")) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedShowsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetUsersSavedShowsRequestTest.java similarity index 94% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedShowsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/shows/GetUsersSavedShowsRequestTest.java index 51011b02a..f887488dd 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedShowsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/shows/GetUsersSavedShowsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.shows; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -19,7 +19,7 @@ public class GetUsersSavedShowsRequestTest extends AbstractDataTest { + private final RemoveShowsForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .removeShowsForCurrentUser(ITest.ID_SHOW) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public RemoveShowsForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/shows?ids=5AvwZVawapvyhJUIx71pdJ", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequestTest.java new file mode 100644 index 000000000..f3ebcf65d --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/shows/SaveShowsForCurrentUserRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.shows; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SuppressWarnings("deprecation") +public class SaveShowsForCurrentUserRequestTest extends AbstractDataTest { + private final SaveShowsForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .saveShowsForCurrentUser(ITest.ID_SHOW) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public SaveShowsForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/shows?ids=5AvwZVawapvyhJUIx71pdJ", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedTracksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/CheckUsersSavedTracksRequestTest.java similarity index 90% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedTracksRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/tracks/CheckUsersSavedTracksRequestTest.java index 7c3c1bc9c..88661f448 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/CheckUsersSavedTracksRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/CheckUsersSavedTracksRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.tracks; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -12,11 +12,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +@SuppressWarnings("deprecation") public class CheckUsersSavedTracksRequestTest extends AbstractDataTest { private final CheckUsersSavedTracksRequest defaultRequest = ITest.SPOTIFY_API.checkUsersSavedTracks(ITest.ID_TRACK, ITest.ID_TRACK) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/library/CheckUsersSavedTracksRequest.json")) + "requests/data/tracks/CheckUsersSavedTracksRequest.json")) .build(); public CheckUsersSavedTracksRequestTest() throws Exception { diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisForTrackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisRequestTest.java similarity index 84% rename from src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisForTrackRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisRequestTest.java index 50d5fc20f..8f54b84f1 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisForTrackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioAnalysisRequestTest.java @@ -15,15 +15,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -public class GetAudioAnalysisForTrackRequestTest extends AbstractDataTest { - private final GetAudioAnalysisForTrackRequest defaultRequest = ITest.SPOTIFY_API - .getAudioAnalysisForTrack(ITest.ID_TRACK) +@SuppressWarnings("deprecation") +public class GetAudioAnalysisRequestTest extends AbstractDataTest { + private final GetTracksAudioAnalysisRequest defaultRequest = ITest.SPOTIFY_API + .getTracksAudioAnalysis(ITest.ID_TRACK) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/tracks/GetAudioAnalysisForTrackRequest.json")) + "requests/data/tracks/GetAudioAnalysisRequest.json")) .build(); - public GetAudioAnalysisForTrackRequestTest() throws Exception { + public GetAudioAnalysisRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForTrackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesRequestTest.java similarity index 88% rename from src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForTrackRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesRequestTest.java index 4a239f125..7987c09a6 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForTrackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesRequestTest.java @@ -15,15 +15,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class GetAudioFeaturesForTrackRequestTest extends AbstractDataTest { - private final GetAudioFeaturesForTrackRequest defaultRequest = ITest.SPOTIFY_API - .getAudioFeaturesForTrack(ITest.ID_TRACK) +@SuppressWarnings("deprecation") +public class GetAudioFeaturesRequestTest extends AbstractDataTest { + private final GetTracksAudioFeaturesRequest defaultRequest = ITest.SPOTIFY_API + .getTracksAudioFeatures(ITest.ID_TRACK) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/tracks/GetAudioFeaturesForTrackRequest.json")) + "requests/data/tracks/GetAudioFeaturesRequest.json")) .build(); - public GetAudioFeaturesForTrackRequestTest() throws Exception { + public GetAudioFeaturesRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/browse/GetRecommendationsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetRecommendationsRequestTest.java similarity index 92% rename from src/test/java/se/michaelthelin/spotify/requests/data/browse/GetRecommendationsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetRecommendationsRequestTest.java index f359520d3..904221406 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/browse/GetRecommendationsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetRecommendationsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.browse; +package se.michaelthelin.spotify.requests.data.tracks; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -12,11 +12,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +@SuppressWarnings("deprecation") public class GetRecommendationsRequestTest extends AbstractDataTest { private final GetRecommendationsRequest defaultRequest = SPOTIFY_API.getRecommendations() .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/browse/GetRecommendationsRequest.json")) + "requests/data/tracks/GetRecommendationsRequest.json")) .limit(LIMIT) .market(MARKET) .max_popularity(MAX_POPULARITY) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralAudioFeaturesRequestTest.java similarity index 77% rename from src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralAudioFeaturesRequestTest.java index 7ed987fc4..90163e61f 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetAudioFeaturesForSeveralTracksRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralAudioFeaturesRequestTest.java @@ -13,15 +13,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class GetAudioFeaturesForSeveralTracksRequestTest extends AbstractDataTest { - private final GetAudioFeaturesForSeveralTracksRequest defaultRequest = ITest.SPOTIFY_API - .getAudioFeaturesForSeveralTracks(ITest.ID_TRACK, ITest.ID_TRACK) +@SuppressWarnings("deprecation") +public class GetSeveralAudioFeaturesRequestTest extends AbstractDataTest { + private final GetSeveralTracksAudioFeaturesRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralTracksAudioFeatures(ITest.ID_TRACK, ITest.ID_TRACK) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/tracks/GetAudioFeaturesForSeveralTracksRequest.json")) + "requests/data/tracks/GetSeveralAudioFeaturesRequest.json")) .build(); - public GetAudioFeaturesForSeveralTracksRequestTest() throws Exception { + public GetSeveralAudioFeaturesRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequestTest.java new file mode 100644 index 000000000..e02eff089 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetSeveralTracksRequestTest.java @@ -0,0 +1,51 @@ +package se.michaelthelin.spotify.requests.data.tracks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.Track; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetSeveralTracksRequestTest extends AbstractDataTest { + private final GetSeveralTracksRequest defaultRequest = ITest.SPOTIFY_API + .getSeveralTracks(ITest.ID_TRACK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/tracks/GetSeveralTracksRequest.json")) + .build(); + + public GetSeveralTracksRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/tracks?ids=01iyCAUm8EvOFqVWYJ3dVX", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final Track[] tracks) { + assertNotNull(tracks); + assertEquals(1, tracks.length); + assertEquals("0eGsygTp906u18L0Oimnem", tracks[0].getId()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetTrackRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetTrackRequestTest.java index 08c5afa71..787d895cf 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetTrackRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetTrackRequestTest.java @@ -58,7 +58,7 @@ public void shouldReturnDefault(final Track track) { 222200, (int) track.getDurationMs()); assertFalse( - track.getIsExplicit()); + track.getExplicit()); assertNotNull( track.getExternalUrls()); assertEquals( diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedTracksRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetUsersSavedTracksRequestTest.java similarity index 94% rename from src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedTracksRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetUsersSavedTracksRequestTest.java index 00c6fc032..439572745 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/library/GetUsersSavedTracksRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/GetUsersSavedTracksRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.library; +package se.michaelthelin.spotify.requests.data.tracks; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -19,7 +19,7 @@ public class GetUsersSavedTracksRequestTest extends AbstractDataTest { - private final UnfollowPlaylistRequest defaultRequest = ITest.SPOTIFY_API - .unfollowPlaylist(ITest.ID_USER, ITest.ID_PLAYLIST) +public class RemoveTracksForCurrentUserRequestTest extends AbstractDataTest { + private final RemoveUsersSavedTracksRequest defaultRequest = ITest.SPOTIFY_API + .removeUsersSavedTracks(ITest.ID_TRACK) .setHttpManager( TestUtil.MockedHttpManager.returningJson(null)) .build(); - public UnfollowPlaylistRequestTest() throws Exception { + public RemoveTracksForCurrentUserRequestTest() throws Exception { } @Test public void shouldComplyWithReference() { assertHasAuthorizationHeader(defaultRequest); assertEquals( - "https://api.spotify.com:443/v1/users/abbaspotify/playlists/3AGOiaoRXMSjswCLtuNqv5/followers", + "https://api.spotify.com:443/v1/me/tracks?ids=01iyCAUm8EvOFqVWYJ3dVX", defaultRequest.getUri().toString()); } @@ -42,7 +42,6 @@ public void shouldReturnDefault_async() throws ExecutionException, InterruptedEx } public void shouldReturnDefault(final String string) { - assertNull( - string); + assertNull(string); } } diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequestTest.java new file mode 100644 index 000000000..5d5d73a62 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/tracks/SaveTracksForCurrentUserRequestTest.java @@ -0,0 +1,48 @@ +package se.michaelthelin.spotify.requests.data.tracks; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SuppressWarnings("deprecation") +public class SaveTracksForCurrentUserRequestTest extends AbstractDataTest { + private final SaveTracksForCurrentUserRequest defaultRequest = ITest.SPOTIFY_API + .saveTracksForCurrentUser(ITest.ID_TRACK) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson(null)) + .build(); + + public SaveTracksForCurrentUserRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/me/tracks?ids=01iyCAUm8EvOFqVWYJ3dVX", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final String string) { + assertNull(string); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequestTest.java similarity index 90% rename from src/test/java/se/michaelthelin/spotify/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequestTest.java index c6f215607..2d0783705 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -12,12 +12,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +@SuppressWarnings("deprecation") public class CheckCurrentUserFollowsArtistsOrUsersRequestTest extends AbstractDataTest { private final CheckCurrentUserFollowsArtistsOrUsersRequest defaultRequest = SPOTIFY_API .checkCurrentUserFollowsArtistsOrUsers(ModelObjectType.ARTIST, new String[]{ID_ARTIST, ID_ARTIST}) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/follow/CheckCurrentUserFollowsArtistsOrUsersRequest.json")) + "requests/data/users/CheckCurrentUserFollowsArtistsOrUsersRequest.json")) .build(); public CheckCurrentUserFollowsArtistsOrUsersRequestTest() throws Exception { diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/CheckUsersFollowPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/CheckIfUserFollowsPlaylistRequestTest.java similarity index 73% rename from src/test/java/se/michaelthelin/spotify/requests/data/follow/CheckUsersFollowPlaylistRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/CheckIfUserFollowsPlaylistRequestTest.java index 5e111a4de..195b76f6b 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/CheckUsersFollowPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/CheckIfUserFollowsPlaylistRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -11,15 +11,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class CheckUsersFollowPlaylistRequestTest extends AbstractDataTest { - private final CheckUsersFollowPlaylistRequest defaultRequest = SPOTIFY_API - .checkUsersFollowPlaylist(ID_PLAYLIST, new String[]{ID_USER, ID_USER}) +public class CheckIfUserFollowsPlaylistRequestTest extends AbstractDataTest { + private final CheckIfUserFollowsPlaylistRequest defaultRequest = SPOTIFY_API + .checkIfUserFollowsPlaylist(ID_PLAYLIST, new String[]{ID_USER, ID_USER}) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/follow/CheckUsersFollowPlaylistRequest.json")) + "requests/data/users/CheckIfUserFollowsPlaylistRequest.json")) .build(); - public CheckUsersFollowPlaylistRequestTest() throws Exception { + public CheckIfUserFollowsPlaylistRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/FollowArtistsOrUsersRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/FollowArtistsOrUsersRequestTest.java similarity index 96% rename from src/test/java/se/michaelthelin/spotify/requests/data/follow/FollowArtistsOrUsersRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/FollowArtistsOrUsersRequestTest.java index 969855cd5..8f70fea7f 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/FollowArtistsOrUsersRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/FollowArtistsOrUsersRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -15,6 +15,7 @@ import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; import static se.michaelthelin.spotify.Assertions.assertHasHeader; +@SuppressWarnings("deprecation") public class FollowArtistsOrUsersRequestTest extends AbstractDataTest { private final FollowArtistsOrUsersRequest defaultRequest = SPOTIFY_API .followArtistsOrUsers(ModelObjectType.ARTIST, new String[]{ID_ARTIST, ID_ARTIST}) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/FollowPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/FollowPlaylistRequestTest.java similarity index 95% rename from src/test/java/se/michaelthelin/spotify/requests/data/follow/FollowPlaylistRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/FollowPlaylistRequestTest.java index aff4709a2..49be4d59a 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/FollowPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/FollowPlaylistRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -14,6 +14,7 @@ import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; import static se.michaelthelin.spotify.Assertions.assertHasHeader; +@SuppressWarnings("deprecation") public class FollowPlaylistRequestTest extends AbstractDataTest { private final FollowPlaylistRequest defaultRequest = SPOTIFY_API .followPlaylist(ID_PLAYLIST, PUBLIC) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/users_profile/GetCurrentUsersProfileRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/GetCurrentUsersProfileRequestTest.java similarity index 93% rename from src/test/java/se/michaelthelin/spotify/requests/data/users_profile/GetCurrentUsersProfileRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/GetCurrentUsersProfileRequestTest.java index 6efe4b424..86608cfac 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/users_profile/GetCurrentUsersProfileRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/GetCurrentUsersProfileRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.users_profile; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -20,7 +20,7 @@ public class GetCurrentUsersProfileRequestTest extends AbstractDataTest { .getCurrentUsersProfile() .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/users_profile/GetCurrentUsersProfileRequest.json")) + "requests/data/users/GetCurrentUsersProfileRequest.json")) .build(); public GetCurrentUsersProfileRequestTest() throws Exception { diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/GetUsersFollowedArtistsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/GetFollowedRequestTest.java similarity index 83% rename from src/test/java/se/michaelthelin/spotify/requests/data/follow/GetUsersFollowedArtistsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/GetFollowedRequestTest.java index dd743b155..d9bb1af8d 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/GetUsersFollowedArtistsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/GetFollowedRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -13,24 +13,24 @@ import static org.junit.jupiter.api.Assertions.*; -public class GetUsersFollowedArtistsRequestTest extends AbstractDataTest> { - private final GetUsersFollowedArtistsRequest defaultRequest = SPOTIFY_API.getUsersFollowedArtists(TYPE) +public class GetFollowedRequestTest extends AbstractDataTest> { + private final GetFollowedArtistsRequest defaultRequest = SPOTIFY_API.getFollowedArtists(TYPE) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/follow/GetUsersFollowedArtistsRequest.json")) + "requests/data/users/GetFollowedRequest.json")) .after(ID_ARTIST) .limit(LIMIT) .build(); - private final GetUsersFollowedArtistsRequest emptyRequest = SPOTIFY_API.getUsersFollowedArtists(TYPE) + private final GetFollowedArtistsRequest emptyRequest = SPOTIFY_API.getFollowedArtists(TYPE) .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/follow/GetUsersFollowedArtistsRequest_None.json")) + "requests/data/users/GetFollowedRequest_None.json")) .after(ID_ARTIST) .limit(LIMIT) .build(); - public GetUsersFollowedArtistsRequestTest() throws Exception { + public GetFollowedRequestTest() throws Exception { } @Test diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequestTest.java new file mode 100644 index 000000000..1b2f155a4 --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/GetUsersProfileRequestTest.java @@ -0,0 +1,66 @@ +package se.michaelthelin.spotify.requests.data.users; + +import org.apache.hc.core5.http.ParseException; +import org.junit.jupiter.api.Test; +import se.michaelthelin.spotify.ITest; +import se.michaelthelin.spotify.TestUtil; +import se.michaelthelin.spotify.enums.ModelObjectType; +import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; +import se.michaelthelin.spotify.model_objects.specification.User; +import se.michaelthelin.spotify.requests.data.AbstractDataTest; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GetUsersProfileRequestTest extends AbstractDataTest { + private final GetUsersProfileRequest defaultRequest = ITest.SPOTIFY_API + .getUsersProfile(ITest.ID_USER) + .setHttpManager( + TestUtil.MockedHttpManager.returningJson( + "requests/data/users/GetUsersProfileRequest.json")) + .build(); + + public GetUsersProfileRequestTest() throws Exception { + } + + @Test + public void shouldComplyWithReference() { + assertHasAuthorizationHeader(defaultRequest); + assertEquals( + "https://api.spotify.com:443/v1/users/abbaspotify", + defaultRequest.getUri().toString()); + } + + @Test + public void shouldReturnDefault_sync() throws IOException, SpotifyWebApiException, ParseException { + shouldReturnDefault(defaultRequest.execute()); + } + + @Test + public void shouldReturnDefault_async() throws ExecutionException, InterruptedException { + shouldReturnDefault(defaultRequest.executeAsync().get()); + } + + public void shouldReturnDefault(final User user) { + assertEquals( + "JM Wizzler", + user.getDisplayName()); + assertNotNull( + user.getExternalUrls()); + assertEquals( + "https://api.spotify.com/v1/users/wizzler", + user.getHref()); + assertEquals( + "wizzler", + user.getId()); + assertEquals( + ModelObjectType.USER, + user.getType()); + assertEquals( + "spotify:user:wizzler", + user.getUri()); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/UnfollowArtistsOrUsersRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/UnfollowArtistsOrUsersRequestTest.java similarity index 96% rename from src/test/java/se/michaelthelin/spotify/requests/data/follow/UnfollowArtistsOrUsersRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/UnfollowArtistsOrUsersRequestTest.java index af8c6f775..38a18d7e3 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/UnfollowArtistsOrUsersRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/UnfollowArtistsOrUsersRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -15,6 +15,7 @@ import static se.michaelthelin.spotify.Assertions.assertHasBodyParameter; import static se.michaelthelin.spotify.Assertions.assertHasHeader; +@SuppressWarnings("deprecation") public class UnfollowArtistsOrUsersRequestTest extends AbstractDataTest { private final UnfollowArtistsOrUsersRequest defaultRequest = SPOTIFY_API .unfollowArtistsOrUsers(ModelObjectType.ARTIST, new String[]{ID_ARTIST, ID_ARTIST}) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/follow/UnfollowPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/UnfollowPlaylistRequestTest.java similarity index 94% rename from src/test/java/se/michaelthelin/spotify/requests/data/follow/UnfollowPlaylistRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/UnfollowPlaylistRequestTest.java index 206877142..5d8816706 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/follow/UnfollowPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/UnfollowPlaylistRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.follow; +package se.michaelthelin.spotify.requests.data.users; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -13,6 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; +@SuppressWarnings("deprecation") public class UnfollowPlaylistRequestTest extends AbstractDataTest { private final UnfollowPlaylistRequest defaultRequest = ITest.SPOTIFY_API .unfollowPlaylist(ITest.ID_PLAYLIST) diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopArtistsRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopArtistsRequestTest.java similarity index 93% rename from src/test/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopArtistsRequestTest.java rename to src/test/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopArtistsRequestTest.java index ef7103865..17d87a549 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/personalization/simplified/GetUsersTopArtistsRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/users/simplified/GetUsersTopArtistsRequestTest.java @@ -1,4 +1,4 @@ -package se.michaelthelin.spotify.requests.data.personalization.simplified; +package se.michaelthelin.spotify.requests.data.users.simplified; import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; @@ -19,7 +19,7 @@ public class GetUsersTopArtistsRequestTest extends AbstractDataTest private final GetUsersTopTracksRequest defaultRequest = ITest.SPOTIFY_API.getUsersTopTracks() .setHttpManager( TestUtil.MockedHttpManager.returningJson( - "requests/data/personalization/simplified/GetUsersTopTracksRequest.json")) + "requests/data/users/simplified/GetUsersTopTracksRequest.json")) .limit(ITest.LIMIT) .offset(ITest.OFFSET) .time_range(ITest.TIME_RANGE)