From 249a535e0772d767518348622ae723cd890ad794 Mon Sep 17 00:00:00 2001 From: Jonas Dellinger Date: Thu, 7 May 2020 18:03:20 +0200 Subject: [PATCH] Added Player Client #451 --- .editorconfig | 2 + .../Clients/Interfaces/IPlayerClient.cs | 42 +++++ .../Clients/Interfaces/IPlaylistsClient.cs | 4 +- .../Clients/Interfaces/ISpotifyClient.cs | 2 + SpotifyAPI.Web/Clients/PlayerClient.cs | 154 ++++++++++++++++++ SpotifyAPI.Web/Clients/PlaylistsClient.cs | 8 +- SpotifyAPI.Web/Clients/SpotifyClient.cs | 3 + SpotifyAPI.Web/Http/APIConnector.cs | 8 + .../Http/Interfaces/IAPIConnector.cs | 2 + .../Converters/PlaylistElementConverter.cs | 2 +- .../Models/Request/PlayerAddToQueueRequest.cs | 18 ++ .../Request/PlayerCurrentPlaybackRequest.cs | 34 ++++ .../Request/PlayerCurrentlyPlayingRequest.cs | 36 ++++ .../Request/PlayerPausePlaybackRequest.cs | 8 + .../Request/PlayerRecentlyPlayedRequest.cs | 14 ++ .../Request/PlayerResumePlaybackRequest.cs | 33 ++++ .../Models/Request/PlayerSeekToRequest.cs | 16 ++ .../Models/Request/PlayerSetRepeatRequest.cs | 30 ++++ .../Models/Request/PlayerShuffleRequest.cs | 16 ++ .../Models/Request/PlayerSkipNextRequest.cs | 8 + .../Request/PlayerSkipPreviousRequest.cs | 8 + .../Request/PlayerTransferPlaybackRequest.cs | 20 +++ .../Models/Request/PlayerVolumeRequest.cs | 16 ++ .../Models/Request/PlaylistGetItemsRequest.cs | 2 +- .../Models/Request/PlaylistGetRequest.cs | 2 +- SpotifyAPI.Web/Models/Response/Actions.cs | 9 + SpotifyAPI.Web/Models/Response/Context.cs | 12 ++ .../Models/Response/CurrentlyPlaying.cs | 17 ++ .../Response/CurrentlyPlayingContext.cs | 21 +++ SpotifyAPI.Web/Models/Response/Device.cs | 13 ++ .../Models/Response/DeviceResponse.cs | 9 + SpotifyAPI.Web/Models/Response/FullEpisode.cs | 2 +- .../Models/Response/FullPlaylist.cs | 2 +- SpotifyAPI.Web/Models/Response/FullTrack.cs | 2 +- .../Response/Interfaces/IPlaylistElement.cs | 2 +- .../Models/Response/PlayHistoryItem.cs | 10 ++ .../Models/Response/PlaylistTrack.cs | 2 +- .../Models/Response/SimplePlaylist.cs | 2 +- SpotifyAPI.Web/SpotifyUrls.cs | 26 +++ 39 files changed, 602 insertions(+), 15 deletions(-) create mode 100644 SpotifyAPI.Web/Clients/Interfaces/IPlayerClient.cs create mode 100644 SpotifyAPI.Web/Clients/PlayerClient.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerAddToQueueRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerCurrentPlaybackRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerCurrentlyPlayingRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerPausePlaybackRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerRecentlyPlayedRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerResumePlaybackRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerSeekToRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerSetRepeatRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerShuffleRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerSkipNextRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerSkipPreviousRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerTransferPlaybackRequest.cs create mode 100644 SpotifyAPI.Web/Models/Request/PlayerVolumeRequest.cs create mode 100644 SpotifyAPI.Web/Models/Response/Actions.cs create mode 100644 SpotifyAPI.Web/Models/Response/Context.cs create mode 100644 SpotifyAPI.Web/Models/Response/CurrentlyPlaying.cs create mode 100644 SpotifyAPI.Web/Models/Response/CurrentlyPlayingContext.cs create mode 100644 SpotifyAPI.Web/Models/Response/Device.cs create mode 100644 SpotifyAPI.Web/Models/Response/DeviceResponse.cs create mode 100644 SpotifyAPI.Web/Models/Response/PlayHistoryItem.cs diff --git a/.editorconfig b/.editorconfig index 0866092c..c6c0c0dc 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,8 @@ indent_size = 2 # Does not seem to work... dotnet_diagnostic.CA1303.severity = none dotnet_diagnostic.CA1056.severity = none +dotnet_diagnostic.CA1034.severity = none +dotnet_diagnostic.CA1054.severity = none # Sort using and Import directives with System.* appearing first dotnet_sort_system_directives_first = true dotnet_style_require_accessibility_modifiers = always:warning diff --git a/SpotifyAPI.Web/Clients/Interfaces/IPlayerClient.cs b/SpotifyAPI.Web/Clients/Interfaces/IPlayerClient.cs new file mode 100644 index 00000000..70a5eb27 --- /dev/null +++ b/SpotifyAPI.Web/Clients/Interfaces/IPlayerClient.cs @@ -0,0 +1,42 @@ +using System.Net; +using System.Threading.Tasks; + +namespace SpotifyAPI.Web +{ + public interface IPlayerClient + { + Task SkipNext(); + Task SkipNext(PlayerSkipNextRequest request); + + Task SetRepeat(PlayerSetRepeatRequest request); + + Task TransferPlayback(PlayerTransferPlaybackRequest request); + + Task GetCurrentlyPlaying(PlayerCurrentlyPlayingRequest request); + + Task GetCurrentPlayback(); + Task GetCurrentPlayback(PlayerCurrentPlaybackRequest request); + + Task SeekTo(PlayerSeekToRequest request); + + Task SkipPrevious(); + Task SkipPrevious(PlayerSkipPreviousRequest request); + + Task ResumePlayback(); + Task ResumePlayback(PlayerResumePlaybackRequest request); + + Task PausePlayback(); + Task PausePlayback(PlayerPausePlaybackRequest request); + + Task SetVolume(PlayerVolumeRequest request); + + Task> GetRecentlyPlayed(); + Task> GetRecentlyPlayed(PlayerRecentlyPlayedRequest request); + + Task GetAvailableDevices(); + + Task SetShuffle(PlayerShuffleRequest request); + + Task AddToQueue(PlayerAddToQueueRequest request); + } +} diff --git a/SpotifyAPI.Web/Clients/Interfaces/IPlaylistsClient.cs b/SpotifyAPI.Web/Clients/Interfaces/IPlaylistsClient.cs index e121d881..1651c441 100644 --- a/SpotifyAPI.Web/Clients/Interfaces/IPlaylistsClient.cs +++ b/SpotifyAPI.Web/Clients/Interfaces/IPlaylistsClient.cs @@ -9,8 +9,8 @@ namespace SpotifyAPI.Web Task AddItems(string playlistId, PlaylistAddItemsRequest request); - Task>> GetItems(string playlistId); - Task>> GetItems(string playlistId, PlaylistGetItemsRequest request); + Task>> GetItems(string playlistId); + Task>> GetItems(string playlistId, PlaylistGetItemsRequest request); Task Create(string userId, PlaylistCreateRequest request); diff --git a/SpotifyAPI.Web/Clients/Interfaces/ISpotifyClient.cs b/SpotifyAPI.Web/Clients/Interfaces/ISpotifyClient.cs index 3cb40f35..f999b3cc 100644 --- a/SpotifyAPI.Web/Clients/Interfaces/ISpotifyClient.cs +++ b/SpotifyAPI.Web/Clients/Interfaces/ISpotifyClient.cs @@ -22,6 +22,8 @@ namespace SpotifyAPI.Web ITracksClient Tracks { get; } + IPlayerClient Player { get; } + Task> Paginate(Paging firstPage); Task> Paginate(Paging firstPage, Func> mapper); Task> Paginate(Func>> getFirstPage); diff --git a/SpotifyAPI.Web/Clients/PlayerClient.cs b/SpotifyAPI.Web/Clients/PlayerClient.cs new file mode 100644 index 00000000..87b3318e --- /dev/null +++ b/SpotifyAPI.Web/Clients/PlayerClient.cs @@ -0,0 +1,154 @@ +using System.Net; +using System.Threading.Tasks; +using SpotifyAPI.Web.Http; +using URLs = SpotifyAPI.Web.SpotifyUrls; + +namespace SpotifyAPI.Web +{ + public class PlayerClient : APIClient, IPlayerClient + { + public PlayerClient(IAPIConnector apiConnector) : base(apiConnector) { } + + public async Task AddToQueue(PlayerAddToQueueRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Post(URLs.PlayerQueue(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public Task GetAvailableDevices() + { + return API.Get(URLs.PlayerDevices()); + } + + public Task GetCurrentlyPlaying(PlayerCurrentlyPlayingRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return API.Get(URLs.PlayerCurrentlyPlaying(), request.BuildQueryParams()); + } + + public Task GetCurrentPlayback() + { + return API.Get(URLs.Player()); + } + + public Task GetCurrentPlayback(PlayerCurrentPlaybackRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return API.Get(URLs.Player(), request.BuildQueryParams()); + } + + public Task> GetRecentlyPlayed() + { + return API.Get>(URLs.PlayerRecentlyPlayed()); + } + + public Task> GetRecentlyPlayed(PlayerRecentlyPlayedRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return API.Get>(URLs.PlayerRecentlyPlayed(), request.BuildQueryParams()); + } + + public async Task PausePlayback() + { + var statusCode = await API.Put(URLs.PlayerPause(), null, null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task PausePlayback(PlayerPausePlaybackRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Put(URLs.PlayerPause(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task ResumePlayback() + { + var statusCode = await API.Put(URLs.PlayerResume(), null, null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task ResumePlayback(PlayerResumePlaybackRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API + .Put(URLs.PlayerResume(), request.BuildQueryParams(), request.BuildBodyParams()) + .ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SeekTo(PlayerSeekToRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Put(URLs.PlayerSeek(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SetRepeat(PlayerSetRepeatRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Put(URLs.PlayerRepeat(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SetShuffle(PlayerShuffleRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Put(URLs.PlayerShuffle(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SetVolume(PlayerVolumeRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Put(URLs.PlayerVolume(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SkipNext() + { + var statusCode = await API.Post(URLs.PlayerNext(), null, null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SkipNext(PlayerSkipNextRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Post(URLs.PlayerNext(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SkipPrevious() + { + var statusCode = await API.Post(URLs.PlayerPrevious(), null, null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task SkipPrevious(PlayerSkipPreviousRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Post(URLs.PlayerPrevious(), request.BuildQueryParams(), null).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + + public async Task TransferPlayback(PlayerTransferPlaybackRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var statusCode = await API.Put(URLs.Player(), null, request.BuildBodyParams()).ConfigureAwait(false); + return statusCode == HttpStatusCode.NoContent; + } + } +} diff --git a/SpotifyAPI.Web/Clients/PlaylistsClient.cs b/SpotifyAPI.Web/Clients/PlaylistsClient.cs index 6b74e146..c134d7d1 100644 --- a/SpotifyAPI.Web/Clients/PlaylistsClient.cs +++ b/SpotifyAPI.Web/Clients/PlaylistsClient.cs @@ -26,20 +26,20 @@ namespace SpotifyAPI.Web return API.Post(URLs.PlaylistTracks(playlistId), null, request.BuildBodyParams()); } - public Task>> GetItems(string playlistId) + public Task>> GetItems(string playlistId) { Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); var request = new PlaylistGetItemsRequest(); - return API.Get>>(URLs.PlaylistTracks(playlistId), request.BuildQueryParams()); + return API.Get>>(URLs.PlaylistTracks(playlistId), request.BuildQueryParams()); } - public Task>> GetItems(string playlistId, PlaylistGetItemsRequest request) + public Task>> GetItems(string playlistId, PlaylistGetItemsRequest request) { Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); Ensure.ArgumentNotNull(request, nameof(request)); - return API.Get>>(URLs.PlaylistTracks(playlistId), request.BuildQueryParams()); + return API.Get>>(URLs.PlaylistTracks(playlistId), request.BuildQueryParams()); } public Task Create(string userId, PlaylistCreateRequest request) diff --git a/SpotifyAPI.Web/Clients/SpotifyClient.cs b/SpotifyAPI.Web/Clients/SpotifyClient.cs index 1d8d039e..43c1d6c9 100644 --- a/SpotifyAPI.Web/Clients/SpotifyClient.cs +++ b/SpotifyAPI.Web/Clients/SpotifyClient.cs @@ -26,6 +26,7 @@ namespace SpotifyAPI.Web Search = new SearchClient(_apiConnector); Follow = new FollowClient(_apiConnector); Tracks = new TracksClient(_apiConnector); + Player = new PlayerClient(_apiConnector); } public IPaginator DefaultPaginator { get; } @@ -44,6 +45,8 @@ namespace SpotifyAPI.Web public ITracksClient Tracks { get; } + public IPlayerClient Player { get; } + public Task> Paginate(Paging firstPage) { return DefaultPaginator.Paginate(firstPage, _apiConnector); diff --git a/SpotifyAPI.Web/Http/APIConnector.cs b/SpotifyAPI.Web/Http/APIConnector.cs index b563a247..e48e2760 100644 --- a/SpotifyAPI.Web/Http/APIConnector.cs +++ b/SpotifyAPI.Web/Http/APIConnector.cs @@ -77,6 +77,14 @@ namespace SpotifyAPI.Web.Http return SendAPIRequest(uri, HttpMethod.Get, parameters); } + public async Task Get(Uri uri, IDictionary parameters, object body) + { + Ensure.ArgumentNotNull(uri, nameof(uri)); + + var response = await SendAPIRequestDetailed(uri, HttpMethod.Get, parameters, body).ConfigureAwait(false); + return response.StatusCode; + } + public Task Post(Uri uri) { Ensure.ArgumentNotNull(uri, nameof(uri)); diff --git a/SpotifyAPI.Web/Http/Interfaces/IAPIConnector.cs b/SpotifyAPI.Web/Http/Interfaces/IAPIConnector.cs index 81f2a615..d7c402e7 100644 --- a/SpotifyAPI.Web/Http/Interfaces/IAPIConnector.cs +++ b/SpotifyAPI.Web/Http/Interfaces/IAPIConnector.cs @@ -18,6 +18,8 @@ namespace SpotifyAPI.Web.Http Task Get(Uri uri); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")] Task Get(Uri uri, IDictionary parameters); + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")] + Task Get(Uri uri, IDictionary parameters, object body); Task Post(Uri uri); Task Post(Uri uri, IDictionary parameters); diff --git a/SpotifyAPI.Web/Models/Converters/PlaylistElementConverter.cs b/SpotifyAPI.Web/Models/Converters/PlaylistElementConverter.cs index d17b39cf..1505bb05 100644 --- a/SpotifyAPI.Web/Models/Converters/PlaylistElementConverter.cs +++ b/SpotifyAPI.Web/Models/Converters/PlaylistElementConverter.cs @@ -4,7 +4,7 @@ using Newtonsoft.Json.Linq; namespace SpotifyAPI.Web { - public class PlaylistElementConverter : JsonConverter + public class PlayableItemConverter : JsonConverter { public override bool CanConvert(Type objectType) => true; diff --git a/SpotifyAPI.Web/Models/Request/PlayerAddToQueueRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerAddToQueueRequest.cs new file mode 100644 index 00000000..01ebcce8 --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerAddToQueueRequest.cs @@ -0,0 +1,18 @@ +namespace SpotifyAPI.Web +{ + public class PlayerAddToQueueRequest : RequestParams + { + public PlayerAddToQueueRequest(string uri) + { + Ensure.ArgumentNotNullOrEmptyString(uri, nameof(uri)); + + Uri = uri; + } + + [QueryParam("uri")] + public string Uri { get; } + + [QueryParam("device_id")] + public string DeviceId { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerCurrentPlaybackRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerCurrentPlaybackRequest.cs new file mode 100644 index 00000000..a8a4c2fc --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerCurrentPlaybackRequest.cs @@ -0,0 +1,34 @@ +using System; + +namespace SpotifyAPI.Web +{ + public class PlayerCurrentPlaybackRequest : RequestParams + { + public PlayerCurrentPlaybackRequest(AdditionalTypes types = AdditionalTypes.All) + { + Ensure.ArgumentNotNull(types, nameof(types)); + + AdditionalTypesParam = types; + } + + [QueryParam("market")] + public string Market { get; set; } + + /// + /// This is set to `"track", "episode"` by default. + /// + /// + [QueryParam("additional_types")] + public AdditionalTypes AdditionalTypesParam { get; } + + [Flags] + public enum AdditionalTypes + { + [String("track")] + Track = 1, + [String("episode")] + Episode = 2, + All = Track | Episode + } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerCurrentlyPlayingRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerCurrentlyPlayingRequest.cs new file mode 100644 index 00000000..3817be50 --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerCurrentlyPlayingRequest.cs @@ -0,0 +1,36 @@ +using System; + +namespace SpotifyAPI.Web +{ + public class PlayerCurrentlyPlayingRequest : RequestParams + { + public PlayerCurrentlyPlayingRequest(string market, AdditionalTypes types = AdditionalTypes.All) + { + Ensure.ArgumentNotNullOrEmptyString(market, nameof(market)); + Ensure.ArgumentNotNull(types, nameof(types)); + + Market = market; + AdditionalTypesParam = types; + } + + [QueryParam("market")] + public string Market { get; } + + /// + /// This is set to `"track", "episode"` by default. + /// + /// + [QueryParam("additional_types")] + public AdditionalTypes AdditionalTypesParam { get; } + + [Flags] + public enum AdditionalTypes + { + [String("track")] + Track = 1, + [String("episode")] + Episode = 2, + All = Track | Episode + } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerPausePlaybackRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerPausePlaybackRequest.cs new file mode 100644 index 00000000..2b058a3c --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerPausePlaybackRequest.cs @@ -0,0 +1,8 @@ +namespace SpotifyAPI.Web +{ + public class PlayerPausePlaybackRequest : RequestParams + { + [QueryParam("device_id")] + public string DeviceId { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerRecentlyPlayedRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerRecentlyPlayedRequest.cs new file mode 100644 index 00000000..5df75fca --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerRecentlyPlayedRequest.cs @@ -0,0 +1,14 @@ +namespace SpotifyAPI.Web +{ + public class PlayerRecentlyPlayedRequest : RequestParams + { + [QueryParam("limit")] + public int? Limit { get; set; } + + [QueryParam("after")] + public long? After { get; set; } + + [QueryParam("before")] + public long? Before { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerResumePlaybackRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerResumePlaybackRequest.cs new file mode 100644 index 00000000..6041ed00 --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerResumePlaybackRequest.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace SpotifyAPI.Web +{ + public class PlayerResumePlaybackRequest : RequestParams + { + [QueryParam("device_id")] + public string DeviceId { get; set; } + + [BodyParam("context_uri")] + public string ContextUri { get; set; } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227")] + [BodyParam("uris")] + public IList Uris { get; set; } + + [BodyParam("offset")] + public Offset OffsetParam { get; set; } + + [BodyParam("position_ms")] + public int? PositionMs { get; set; } + + public class Offset + { + [JsonProperty("uri", NullValueHandling = NullValueHandling.Ignore)] + public string Uri { get; set; } + + [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] + public int? Position { get; set; } + } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerSeekToRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerSeekToRequest.cs new file mode 100644 index 00000000..439de03a --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerSeekToRequest.cs @@ -0,0 +1,16 @@ +namespace SpotifyAPI.Web +{ + public class PlayerSeekToRequest : RequestParams + { + public PlayerSeekToRequest(long positionMs) + { + PositonMs = positionMs; + } + + [QueryParam("position_ms")] + public long PositonMs { get; } + + [QueryParam("device_id")] + public string DeviceId { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerSetRepeatRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerSetRepeatRequest.cs new file mode 100644 index 00000000..9d780f3b --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerSetRepeatRequest.cs @@ -0,0 +1,30 @@ +namespace SpotifyAPI.Web +{ + public class PlayerSetRepeatRequest : RequestParams + { + public PlayerSetRepeatRequest(State state) + { + Ensure.ArgumentNotNull(state, nameof(state)); + + StateParam = state; + } + + [QueryParam("device_id")] + public string DeviceId { get; set; } + + [QueryParam("state")] + public State StateParam { get; } + + public enum State + { + [String("track")] + Track, + + [String("context")] + Context, + + [String("off")] + Off + } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerShuffleRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerShuffleRequest.cs new file mode 100644 index 00000000..3573cde1 --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerShuffleRequest.cs @@ -0,0 +1,16 @@ +namespace SpotifyAPI.Web +{ + public class PlayerShuffleRequest : RequestParams + { + public PlayerShuffleRequest(bool state) + { + State = state; + } + + [QueryParam("state")] + public bool State { get; } + + [QueryParam("device_id")] + public string DeviceId { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerSkipNextRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerSkipNextRequest.cs new file mode 100644 index 00000000..45d94920 --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerSkipNextRequest.cs @@ -0,0 +1,8 @@ +namespace SpotifyAPI.Web +{ + public class PlayerSkipNextRequest : RequestParams + { + [QueryParam("device_id")] + public string DeviceId { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerSkipPreviousRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerSkipPreviousRequest.cs new file mode 100644 index 00000000..d7c6139f --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerSkipPreviousRequest.cs @@ -0,0 +1,8 @@ +namespace SpotifyAPI.Web +{ + public class PlayerSkipPreviousRequest : RequestParams + { + [QueryParam("device_id")] + public string DeviceId { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerTransferPlaybackRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerTransferPlaybackRequest.cs new file mode 100644 index 00000000..8a946f34 --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerTransferPlaybackRequest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace SpotifyAPI.Web +{ + public class PlayerTransferPlaybackRequest : RequestParams + { + public PlayerTransferPlaybackRequest(IList deviceIds) + { + Ensure.ArgumentNotNullOrEmptyList(deviceIds, nameof(deviceIds)); + + DeviceIds = deviceIds; + } + + [BodyParam("device_ids")] + public IList DeviceIds { get; } + + [BodyParam("play")] + public bool? Play { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlayerVolumeRequest.cs b/SpotifyAPI.Web/Models/Request/PlayerVolumeRequest.cs new file mode 100644 index 00000000..b6e8b44c --- /dev/null +++ b/SpotifyAPI.Web/Models/Request/PlayerVolumeRequest.cs @@ -0,0 +1,16 @@ +namespace SpotifyAPI.Web +{ + public class PlayerVolumeRequest : RequestParams + { + public PlayerVolumeRequest(int volumePercent) + { + VolumePercent = volumePercent; + } + + [QueryParam("volume_percent")] + public int VolumePercent { get; } + + [QueryParam("device_id")] + public string DeviceId { get; set; } + } +} diff --git a/SpotifyAPI.Web/Models/Request/PlaylistGetItemsRequest.cs b/SpotifyAPI.Web/Models/Request/PlaylistGetItemsRequest.cs index bf5ab5c1..0791d570 100644 --- a/SpotifyAPI.Web/Models/Request/PlaylistGetItemsRequest.cs +++ b/SpotifyAPI.Web/Models/Request/PlaylistGetItemsRequest.cs @@ -30,7 +30,7 @@ namespace SpotifyAPI.Web /// /// [QueryParam("additional_types")] - public AdditionalTypes AdditionalTypesParam { get; set; } + public AdditionalTypes AdditionalTypesParam { get; } [Flags] public enum AdditionalTypes diff --git a/SpotifyAPI.Web/Models/Request/PlaylistGetRequest.cs b/SpotifyAPI.Web/Models/Request/PlaylistGetRequest.cs index 45c4d789..8b57df6d 100644 --- a/SpotifyAPI.Web/Models/Request/PlaylistGetRequest.cs +++ b/SpotifyAPI.Web/Models/Request/PlaylistGetRequest.cs @@ -17,7 +17,7 @@ namespace SpotifyAPI.Web /// /// [QueryParam("additional_types")] - public AdditionalTypes AdditionalTypesParam { get; set; } + public AdditionalTypes AdditionalTypesParam { get; } [Flags] public enum AdditionalTypes diff --git a/SpotifyAPI.Web/Models/Response/Actions.cs b/SpotifyAPI.Web/Models/Response/Actions.cs new file mode 100644 index 00000000..a20b3793 --- /dev/null +++ b/SpotifyAPI.Web/Models/Response/Actions.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace SpotifyAPI.Web +{ + public class Actions + { + public Dictionary Disallows { get; private set; } + } +} diff --git a/SpotifyAPI.Web/Models/Response/Context.cs b/SpotifyAPI.Web/Models/Response/Context.cs new file mode 100644 index 00000000..ec2833cc --- /dev/null +++ b/SpotifyAPI.Web/Models/Response/Context.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace SpotifyAPI.Web +{ + public class Context + { + public Dictionary ExternalUrls { get; private set; } + public string Href { get; private set; } + public string Type { get; private set; } + public string Uri { get; private set; } + } +} diff --git a/SpotifyAPI.Web/Models/Response/CurrentlyPlaying.cs b/SpotifyAPI.Web/Models/Response/CurrentlyPlaying.cs new file mode 100644 index 00000000..39198262 --- /dev/null +++ b/SpotifyAPI.Web/Models/Response/CurrentlyPlaying.cs @@ -0,0 +1,17 @@ +using System; +using Newtonsoft.Json; + +namespace SpotifyAPI.Web +{ + public class CurrentlyPlaying + { + public Context Context { get; private set; } + public string CurrentlyPlayingType { get; private set; } + public bool IsPlaying { get; private set; } + + [JsonConverter(typeof(PlayableItemConverter))] + public IPlayableItem Item { get; private set; } + public int? ProgressMs { get; private set; } + public long Timestamp { get; private set; } + } +} diff --git a/SpotifyAPI.Web/Models/Response/CurrentlyPlayingContext.cs b/SpotifyAPI.Web/Models/Response/CurrentlyPlayingContext.cs new file mode 100644 index 00000000..d88adc71 --- /dev/null +++ b/SpotifyAPI.Web/Models/Response/CurrentlyPlayingContext.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace SpotifyAPI.Web +{ + public class CurrentlyPlayingContext + { + public Device Device { get; private set; } + public string RepeatState { get; private set; } + public bool ShuffleState { get; private set; } + public Context Context { get; private set; } + public long Timestamp { get; private set; } + public int ProgressMs { get; private set; } + public bool IsPlaying { get; private set; } + + [JsonConverter(typeof(PlayableItemConverter))] + public IPlayableItem Item { get; private set; } + + public string CurrentlyPlayingType { get; private set; } + public Actions Actions { get; private set; } + } +} diff --git a/SpotifyAPI.Web/Models/Response/Device.cs b/SpotifyAPI.Web/Models/Response/Device.cs new file mode 100644 index 00000000..75fce65d --- /dev/null +++ b/SpotifyAPI.Web/Models/Response/Device.cs @@ -0,0 +1,13 @@ +namespace SpotifyAPI.Web +{ + public class Device + { + public string Id { get; private set; } + public bool IsActive { get; private set; } + public bool IsPrivateSession { get; private set; } + public bool IsRestricted { get; private set; } + public string Name { get; private set; } + public string Type { get; private set; } + public int? VolumePercent { get; private set; } + } +} diff --git a/SpotifyAPI.Web/Models/Response/DeviceResponse.cs b/SpotifyAPI.Web/Models/Response/DeviceResponse.cs new file mode 100644 index 00000000..dd560136 --- /dev/null +++ b/SpotifyAPI.Web/Models/Response/DeviceResponse.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace SpotifyAPI.Web +{ + public class DeviceResponse + { + public List Devices { get; private set; } + } +} diff --git a/SpotifyAPI.Web/Models/Response/FullEpisode.cs b/SpotifyAPI.Web/Models/Response/FullEpisode.cs index 13aabae9..60ec67ae 100644 --- a/SpotifyAPI.Web/Models/Response/FullEpisode.cs +++ b/SpotifyAPI.Web/Models/Response/FullEpisode.cs @@ -4,7 +4,7 @@ using Newtonsoft.Json.Converters; namespace SpotifyAPI.Web { - public class FullEpisode : IPlaylistItem + public class FullEpisode : IPlayableItem { public string AudioPreviewUrl { get; private set; } public string Description { get; private set; } diff --git a/SpotifyAPI.Web/Models/Response/FullPlaylist.cs b/SpotifyAPI.Web/Models/Response/FullPlaylist.cs index c35b9955..8dc284d6 100644 --- a/SpotifyAPI.Web/Models/Response/FullPlaylist.cs +++ b/SpotifyAPI.Web/Models/Response/FullPlaylist.cs @@ -12,7 +12,7 @@ namespace SpotifyAPI.Web public PublicUser Owner { get; private set; } public bool Public { get; private set; } public string SnapshotId { get; private set; } - public Paging> Tracks { get; private set; } + public Paging> Tracks { get; private set; } public string Type { get; private set; } public string Uri { get; private set; } } diff --git a/SpotifyAPI.Web/Models/Response/FullTrack.cs b/SpotifyAPI.Web/Models/Response/FullTrack.cs index 9f91948e..024fa80c 100644 --- a/SpotifyAPI.Web/Models/Response/FullTrack.cs +++ b/SpotifyAPI.Web/Models/Response/FullTrack.cs @@ -4,7 +4,7 @@ using Newtonsoft.Json.Converters; namespace SpotifyAPI.Web { - public class FullTrack : IPlaylistItem + public class FullTrack : IPlayableItem { public SimpleAlbum Album { get; private set; } public List Artists { get; private set; } diff --git a/SpotifyAPI.Web/Models/Response/Interfaces/IPlaylistElement.cs b/SpotifyAPI.Web/Models/Response/Interfaces/IPlaylistElement.cs index 30b38e01..2aaa2a6c 100644 --- a/SpotifyAPI.Web/Models/Response/Interfaces/IPlaylistElement.cs +++ b/SpotifyAPI.Web/Models/Response/Interfaces/IPlaylistElement.cs @@ -9,7 +9,7 @@ namespace SpotifyAPI.Web Episode } - public interface IPlaylistItem + public interface IPlayableItem { [JsonConverter(typeof(StringEnumConverter))] public ItemType Type { get; } diff --git a/SpotifyAPI.Web/Models/Response/PlayHistoryItem.cs b/SpotifyAPI.Web/Models/Response/PlayHistoryItem.cs new file mode 100644 index 00000000..f7f84ead --- /dev/null +++ b/SpotifyAPI.Web/Models/Response/PlayHistoryItem.cs @@ -0,0 +1,10 @@ +using System; +namespace SpotifyAPI.Web +{ + public class PlayHistoryItem + { + public SimpleTrack Track { get; private set; } + public DateTime PlayedAt { get; private set; } + public Context Context { get; private set; } + } +} diff --git a/SpotifyAPI.Web/Models/Response/PlaylistTrack.cs b/SpotifyAPI.Web/Models/Response/PlaylistTrack.cs index 07b57b60..6ff7ce4d 100644 --- a/SpotifyAPI.Web/Models/Response/PlaylistTrack.cs +++ b/SpotifyAPI.Web/Models/Response/PlaylistTrack.cs @@ -9,7 +9,7 @@ namespace SpotifyAPI.Web public PublicUser AddedBy { get; private set; } public bool IsLocal { get; private set; } - [JsonConverter(typeof(PlaylistElementConverter))] + [JsonConverter(typeof(PlayableItemConverter))] public T Track { get; private set; } } } diff --git a/SpotifyAPI.Web/Models/Response/SimplePlaylist.cs b/SpotifyAPI.Web/Models/Response/SimplePlaylist.cs index 2a1a94c8..e0b72d47 100644 --- a/SpotifyAPI.Web/Models/Response/SimplePlaylist.cs +++ b/SpotifyAPI.Web/Models/Response/SimplePlaylist.cs @@ -16,7 +16,7 @@ namespace SpotifyAPI.Web public PublicUser Owner { get; private set; } public bool? Public { get; private set; } public string SnapshotId { get; private set; } - public Paging> Tracks { get; private set; } + public Paging> Tracks { get; private set; } public string Type { get; private set; } public string Uri { get; private set; } } diff --git a/SpotifyAPI.Web/SpotifyUrls.cs b/SpotifyAPI.Web/SpotifyUrls.cs index 2e8fd218..3258afcc 100644 --- a/SpotifyAPI.Web/SpotifyUrls.cs +++ b/SpotifyAPI.Web/SpotifyUrls.cs @@ -61,6 +61,32 @@ namespace SpotifyAPI.Web public static Uri AudioFeatures() => EUri($"audio-features"); + public static Uri Player() => EUri($"me/player"); + + public static Uri PlayerQueue() => EUri($"me/player/queue"); + + public static Uri PlayerDevices() => EUri($"me/player/devices"); + + public static Uri PlayerCurrentlyPlaying() => EUri($"me/player/currently-playing"); + + public static Uri PlayerRecentlyPlayed() => EUri($"me/player/recently-played"); + + public static Uri PlayerPause() => EUri($"me/player/pause"); + + public static Uri PlayerResume() => EUri($"me/player/play"); + + public static Uri PlayerSeek() => EUri($"me/player/seek"); + + public static Uri PlayerRepeat() => EUri($"me/player/repeat"); + + public static Uri PlayerShuffle() => EUri($"me/player/shuffle"); + + public static Uri PlayerVolume() => EUri($"me/player/volume"); + + public static Uri PlayerNext() => EUri($"me/player/next"); + + public static Uri PlayerPrevious() => EUri($"me/player/previous"); + private static Uri EUri(FormattableString path) => new Uri(path.ToString(_provider), UriKind.Relative); } }