From f182b5ea992e769ae5c29983285466f7b98799b4 Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 14:36:08 +0100 Subject: [PATCH 1/9] Added Async Methods for Search/Albums/Artists/Browse/Follow/Library --- SpotifyAPI/Web/SpotifyWebAPI.cs | 539 +++++++++++++++++++++++++++----- 1 file changed, 453 insertions(+), 86 deletions(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index 2960d665..900bff58 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -88,13 +88,21 @@ namespace SpotifyAPI.Web /// public Paging GetAlbumTracks(String id, int limit = 20, int offset = 0, String market = "") { - limit = Math.Min(limit, 50); - StringBuilder builder = new StringBuilder(APIBase + "/albums/" + id + "/tracks"); - builder.Append("?limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(market)) - builder.Append("&market=" + market); - return DownloadData>(builder.ToString()); + return DownloadData>(_builder.SearchItems(id, limit, offset, market)); + } + + /// + /// Get Spotify catalog information about an album’s tracks asynchronously. Optional parameters can be used to limit the number of + /// tracks returned. + /// + /// The Spotify ID for the album. + /// The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first track to return. Default: 0 (the first object). + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + public Task> GetAlbumTracksAsync(String id, int limit = 20, int offset = 0, String market = "") + { + return DownloadDataAsync>(_builder.SearchItems(id, limit, offset, market)); } /// @@ -106,8 +114,21 @@ namespace SpotifyAPI.Web public FullAlbum GetAlbum(String id, String market = "") { if (String.IsNullOrEmpty(market)) - return DownloadData(APIBase + "/albums/" + id); - return DownloadData(APIBase + "/albums/" + id + "?market=" + market); + return DownloadData(_builder.SearchItems(id)); + return DownloadData(_builder.SearchItems(id, market)); + } + + /// + /// Get Spotify catalog information for a single album asynchronously. + /// + /// The Spotify ID for the album. + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + public Task GetAlbumAsync(String id, String market = "") + { + if (String.IsNullOrEmpty(market)) + return DownloadDataAsync(_builder.SearchItems(id)); + return DownloadDataAsync(_builder.SearchItems(id, market)); } /// @@ -119,8 +140,21 @@ namespace SpotifyAPI.Web public SeveralAlbums GetSeveralAlbums(List ids, String market = "") { if (String.IsNullOrEmpty(market)) - return DownloadData(APIBase + "/albums?ids=" + string.Join(",", ids.Take(20))); - return DownloadData(APIBase + "/albums?market=" + market + "&ids=" + string.Join(",", ids.Take(20))); + return DownloadData(_builder.SearchItems(ids)); + return DownloadData(_builder.SearchItems(ids, market)); + } + + /// + /// Get Spotify catalog information for multiple albums identified by their Spotify IDs asynchrously. + /// + /// A list of the Spotify IDs for the albums. Maximum: 20 IDs. + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + public Task GetSeveralAlbumsAsync(List ids, String market = "") + { + if (String.IsNullOrEmpty(market)) + return DownloadDataAsync(_builder.SearchItems(ids)); + return DownloadDataAsync(_builder.SearchItems(ids, market)); } #endregion Albums @@ -134,7 +168,17 @@ namespace SpotifyAPI.Web /// public FullArtist GetArtist(String id) { - return DownloadData(APIBase + "/artists/" + id); + return DownloadData(_builder.SearchItems(id)); + } + + /// + /// Get Spotify catalog information for a single artist identified by their unique Spotify ID asynchronously. + /// + /// The Spotify ID for the artist. + /// + public Task GetArtistAsync(String id) + { + return DownloadDataAsync(_builder.SearchItems(id)); } /// @@ -145,7 +189,18 @@ namespace SpotifyAPI.Web /// public SeveralArtists GetRelatedArtists(String id) { - return DownloadData(APIBase + "/artists/" + id + "/related-artists"); + return DownloadData(_builder.SearchItems(id)); + } + + /// + /// Get Spotify catalog information about artists similar to a given artist asynchronously. Similarity is based on analysis of the + /// Spotify community’s listening history. + /// + /// The Spotify ID for the artist. + /// + public Task GetRelatedArtistsAsync(String id) + { + return DownloadDataAsync(_builder.SearchItems(id)); } /// @@ -156,7 +211,18 @@ namespace SpotifyAPI.Web /// public SeveralTracks GetArtistsTopTracks(String id, String country) { - return DownloadData(APIBase + "/artists/" + id + "/top-tracks?country=" + country); + return DownloadData(_builder.SearchItems(id, country)); + } + + /// + /// Get Spotify catalog information about an artist’s top tracks by country asynchronously. + /// + /// The Spotify ID for the artist. + /// The country: an ISO 3166-1 alpha-2 country code. + /// + public Task GetArtistsTopTracksAsync(String id, String country) + { + return DownloadDataAsync(_builder.SearchItems(id, country)); } /// @@ -177,14 +243,28 @@ namespace SpotifyAPI.Web /// public Paging GetArtistsAlbums(String id, AlbumType type = AlbumType.All, int limit = 20, int offset = 0, String market = "") { - limit = Math.Min(limit, 50); - StringBuilder builder = new StringBuilder(APIBase + "/artists/" + id + "/albums"); - builder.Append("?type=" + type.GetStringAttribute(",")); - builder.Append("&limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(market)) - builder.Append("&market=" + market); - return DownloadData>(builder.ToString()); + return DownloadData>(_builder.SearchItems(id, type, limit, offset, market)); + } + + /// + /// Get Spotify catalog information about an artist’s albums asynchronously. Optional parameters can be specified in the query string + /// to filter and sort the response. + /// + /// The Spotify ID for the artist. + /// + /// A list of keywords that will be used to filter the response. If not supplied, all album types will + /// be returned + /// + /// The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first album to return. Default: 0 + /// + /// An ISO 3166-1 alpha-2 country code. Supply this parameter to limit the response to one particular + /// geographical market + /// + /// + public Task> GetArtistsAlbumsAsync(String id, AlbumType type = AlbumType.All, int limit = 20, int offset = 0, String market = "") + { + return DownloadDataAsync>(_builder.SearchItems(id, type, limit, offset, market)); } /// @@ -194,7 +274,17 @@ namespace SpotifyAPI.Web /// public SeveralArtists GetSeveralArtists(List ids) { - return DownloadData(APIBase + "/artists?ids=" + string.Join(",", ids.Take(50))); + return DownloadData(_builder.SearchItems(ids)); + } + + /// + /// Get Spotify catalog information for several artists based on their Spotify IDs asynchronously. + /// + /// A list of the Spotify IDs for the artists. Maximum: 50 IDs. + /// + public Task GetSeveralArtistsAsync(List ids) + { + return DownloadDataAsync(_builder.SearchItems(ids)); } #endregion Artists @@ -217,17 +307,26 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetFeaturedPlaylists"); - limit = Math.Max(limit, 50); - StringBuilder builder = new StringBuilder(APIBase + "/browse/featured-playlists"); - builder.Append("?limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(locale)) - builder.Append("&locale=" + locale); - if (!String.IsNullOrEmpty(country)) - builder.Append("&country=" + country); - if (timestamp != default(DateTime)) - builder.Append("×tamp=" + timestamp.ToString("yyyy-MM-ddTHH:mm:ss")); - return DownloadData(builder.ToString()); + return DownloadData(_builder.SearchItems(locale, country, timestamp, limit, offset)); + } + + /// + /// Get a list of Spotify featured playlists asynchronously (shown, for example, on a Spotify player’s “Browse” tab). + /// + /// + /// The desired language, consisting of a lowercase ISO 639 language code and an uppercase ISO 3166-1 + /// alpha-2 country code, joined by an underscore. + /// + /// A country: an ISO 3166-1 alpha-2 country code. + /// A timestamp in ISO 8601 format + /// The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first item to return. Default: 0 + /// AUTH NEEDED + public Task GetFeaturedPlaylistsAsync(String locale = "", String country = "", DateTime timestamp = default(DateTime), int limit = 20, int offset = 0) + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetFeaturedPlaylists"); + return DownloadDataAsync(_builder.SearchItems(locale, country, timestamp, limit, offset)); } /// @@ -242,13 +341,22 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetNewAlbumReleases"); - limit = Math.Max(limit, 50); - StringBuilder builder = new StringBuilder(APIBase + "/browse/new-releases"); - builder.Append("?limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(country)) - builder.Append("&country=" + country); - return DownloadData(builder.ToString()); + return DownloadData(_builder.SearchItems(country, limit, offset)); + } + + /// + /// Get a list of new album releases featured in Spotify asynchronously (shown, for example, on a Spotify player’s “Browse” tab). + /// + /// A country: an ISO 3166-1 alpha-2 country code. + /// The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first item to return. Default: 0 + /// + /// AUTH NEEDED + public Task GetNewAlbumReleasesAsync(String country = "", int limit = 20, int offset = 0) + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetNewAlbumReleases"); + return DownloadDataAsync(_builder.SearchItems(country, limit, offset)); } /// @@ -270,15 +378,29 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetCategories"); - limit = Math.Min(50, limit); - StringBuilder builder = new StringBuilder(APIBase + "/browse/categories"); - builder.Append("?limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(country)) - builder.Append("&country=" + country); - if (!String.IsNullOrEmpty(locale)) - builder.Append("&locale=" + locale); - return DownloadData(builder.ToString()); + return DownloadData(_builder.SearchItems(country, locale, limit, offset)); + } + + /// + /// Get a list of categories used to tag items in Spotify asynchronously (on, for example, the Spotify player’s “Browse” tab). + /// + /// + /// 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 + /// + /// + /// The desired language, consisting of an ISO 639 language code and an ISO 3166-1 alpha-2 country + /// code, joined by an underscore + /// + /// The maximum number of categories to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first item to return. Default: 0 (the first object). + /// + /// AUTH NEEDED + public Task GetCategoriesAsync(String country = "", String locale = "", int limit = 20, int offset = 0) + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetCategories"); + return DownloadDataAsync(_builder.SearchItems(country, locale, limit, offset)); } /// @@ -297,12 +419,26 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public Category GetCategory(String categoryId, String country = "", String locale = "") { - StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId); - if (!String.IsNullOrEmpty(country)) - builder.Append("?country=" + country); - if (!String.IsNullOrEmpty(locale)) - builder.Append((country == "" ? "?locale=" : "&locale=") + locale); - return DownloadData(builder.ToString()); + return DownloadData(_builder.SearchItems(categoryId, country, locale)); + } + + /// + /// Get a single category used to tag items in Spotify asynchronously (on, for example, the Spotify player’s “Browse” tab). + /// + /// The Spotify category ID for the category. + /// + /// A country: an ISO 3166-1 alpha-2 country code. Provide this parameter to ensure that the category + /// exists for a particular country. + /// + /// + /// The desired language, consisting of an ISO 639 language code and an ISO 3166-1 alpha-2 country + /// code, joined by an underscore + /// + /// + /// AUTH NEEDED + public Task GetCategoryAsync(String categoryId, String country = "", String locale = "") + { + return DownloadDataAsync(_builder.SearchItems(categoryId, country, locale)); } /// @@ -316,13 +452,21 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public CategoryPlaylist GetCategoryPlaylists(String categoryId, String country = "", int limit = 20, int offset = 0) { - limit = Math.Min(50, limit); - StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId + "/playlists"); - builder.Append("?limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(country)) - builder.Append("&country=" + country); - return DownloadData(builder.ToString()); + return DownloadData(_builder.SearchItems(categoryId, country, limit, offset)); + } + + /// + /// Get a list of Spotify playlists tagged with a particular category asynchronously. + /// + /// The Spotify category ID for the category. + /// A country: an ISO 3166-1 alpha-2 country code. + /// The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first item to return. Default: 0 + /// + /// AUTH NEEDED + public Task GetCategoryPlaylistsAsync(String categoryId, String country = "", int limit = 20, int offset = 0) + { + return DownloadDataAsync(_builder.SearchItems(categoryId, country, limit, offset)); } #endregion Browse @@ -332,21 +476,31 @@ namespace SpotifyAPI.Web /// /// Get the current user’s followed artists. /// + /// The ID type: currently only artist is supported. /// The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. /// The last artist ID retrieved from the previous request. /// /// AUTH NEEDED - public FollowedArtists GetFollowedArtists(int limit = 20, String after = "") + public FollowedArtists GetFollowedArtists(FollowType followType, int limit = 20, String after = "") { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetFollowedArtists"); - limit = Math.Max(limit, 50); - const FollowType followType = FollowType.Artist; //currently only artist is supported. - StringBuilder builder = new StringBuilder(APIBase + "/me/following?type=" + followType.GetStringAttribute("")); - builder.Append("&limit=" + limit); - if (!String.IsNullOrEmpty(after)) - builder.Append("&after=" + after); - return DownloadData(builder.ToString()); + return DownloadData(_builder.SearchItems(followType, limit, after)); + } + + /// + /// Get the current user’s followed artists asynchronously. + /// + /// The ID type: currently only artist is supported. + /// The maximum number of items to return. Default: 20. Minimum: 1. Maximum: 50. + /// The last artist ID retrieved from the previous request. + /// + /// AUTH NEEDED + public Task GetFollowedArtistsAsync(FollowType followType, int limit = 20, String after = "") + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetFollowedArtists"); + return DownloadDataAsync(_builder.SearchItems(followType, limit, after)); } /// @@ -362,7 +516,25 @@ namespace SpotifyAPI.Web { {"ids", new JArray(ids)} }; - return UploadData(APIBase + "/me/following?type=" + followType.GetStringAttribute(""), ob.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + return UploadData(_builder.SearchItems(followType, ids), ob.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + } + + /// + /// Add the current user as a follower of one or more artists or other Spotify users asynchronously. + /// + /// The ID type: either artist or user. + /// A list of the artist or the user Spotify IDs + /// + /// AUTH NEEDED + public Task FollowAsync(FollowType followType, List ids) + { + JObject ob = new JObject + { + {"ids", new JArray(ids)} + }; + return + UploadDataAsync(_builder.SearchItems(followType, ids), + ob.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse()); } /// @@ -377,6 +549,18 @@ namespace SpotifyAPI.Web return Follow(followType, new List { id }); } + /// + /// Add the current user as a follower of one or more artists or other Spotify users asynchronously. + /// + /// The ID type: either artist or user. + /// Artists or the Users Spotify ID + /// + /// AUTH NEEDED + public Task FollowAsync(FollowType followType, String id) + { + return FollowAsync(followType, new List { id }); + } + /// /// Remove the current user as a follower of one or more artists or other Spotify users. /// @@ -390,7 +574,23 @@ namespace SpotifyAPI.Web { {"ids", new JArray(ids)} }; - return UploadData(APIBase + "/me/following?type=" + followType.GetStringAttribute(""), ob.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + return UploadData(_builder.SearchItems(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + } + + /// + /// Remove the current user as a follower of one or more artists or other Spotify users asynchronously. + /// + /// The ID type: either artist or user. + /// A list of the artist or the user Spotify IDs + /// + /// AUTH NEEDED + public Task UnfollowAsync(FollowType followType, List ids) + { + JObject ob = new JObject + { + {"ids", new JArray(ids)} + }; + return UploadDataAsync(_builder.SearchItems(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); } /// @@ -405,6 +605,18 @@ namespace SpotifyAPI.Web return Unfollow(followType, new List { id }); } + /// + /// Remove the current user as a follower of one or more artists or other Spotify users asynchronously. + /// + /// The ID type: either artist or user. + /// Artists or the Users Spotify ID + /// + /// AUTH NEEDED + public Task UnfollowAsync(FollowType followType, String id) + { + return UnfollowAsync(followType, new List { id }); + } + /// /// Check to see if the current user is following one or more artists or other Spotify users. /// @@ -416,12 +628,29 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowing"); - JToken res = DownloadData(APIBase + "/me/following/contains?type=" + followType.GetStringAttribute("") + "&ids=" + string.Join(",", ids)); + JToken res = DownloadData(_builder.SearchItems(followType, ids)); if (res is JArray) return new ListResponse { List = res.ToObject>(), Error = null }; return new ListResponse { List = null, Error = res["error"].ToObject() }; } + /// + /// Check to see if the current user is following one or more artists or other Spotify users asynchronously. + /// + /// The ID type: either artist or user. + /// A list of the artist or the user Spotify IDs to check + /// + /// AUTH NEEDED + public Task> IsFollowingAsync(FollowType followType, List ids) + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for IsFollowing"); + JToken res = DownloadDataAsync(_builder.SearchItems(followType, ids)); + if (res is JArray) //todo expression is always false + return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); + return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); + } + /// /// Check to see if the current user is following one artist or another Spotify user. /// @@ -434,6 +663,18 @@ namespace SpotifyAPI.Web return IsFollowing(followType, new List { id }); } + /// + /// Check to see if the current user is following one artist or another Spotify user asynchronously. + /// + /// The ID type: either artist or user. + /// Artists or the Users Spotify ID + /// + /// AUTH NEEDED + public Task> IsFollowingAsync(FollowType followType, String id) + { + return IsFollowingAsync(followType, new List { id }); + } + /// /// Add the current user as a follower of a playlist. /// @@ -454,7 +695,30 @@ namespace SpotifyAPI.Web { {"public", showPublic} }; - return UploadData(APIBase + "/users/" + ownerId + "/playlists/" + playlistId + "/followers", body.ToString(Formatting.None), "PUT"); + return UploadData(_builder.SearchItems(ownerId, playlistId, showPublic), body.ToString(Formatting.None), "PUT"); + } + + /// + /// Add the current user as a follower of a playlist asynchronously. + /// + /// The Spotify user ID of the person who owns the playlist. + /// + /// 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. + /// + /// + /// If true the playlist will be included in user's public playlists, if false it will remain + /// private. + /// + /// + /// AUTH NEEDED + public Task FollowPlaylistAsync(String ownerId, String playlistId, bool showPublic = true) + { + JObject body = new JObject + { + {"public", showPublic} + }; + return UploadDataAsync(_builder.SearchItems(ownerId, playlistId, showPublic), body.ToString(Formatting.None), "PUT"); } /// @@ -466,7 +730,19 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ErrorResponse UnfollowPlaylist(String ownerId, String playlistId) { - return UploadData(APIBase + "/users/" + ownerId + "/playlists/" + playlistId + "/followers", "", "DELETE"); + return UploadData(_builder.SearchItems(ownerId, playlistId), "", "DELETE"); + } + + /// + /// Remove the current user as a follower of a playlist asynchronously. + /// + /// The Spotify user ID of the person who owns the playlist. + /// The Spotify ID of the playlist that is to be no longer followed. + /// + /// AUTH NEEDED + public Task UnfollowPlaylistAsync(String ownerId, String playlistId) + { + return UploadDataAsync(_builder.SearchItems(ownerId, playlistId), "", "DELETE"); } /// @@ -481,12 +757,30 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowingPlaylist"); - JToken res = DownloadData(APIBase + "/users/" + ownerId + "/playlists/" + playlistId + "/followers/contains?ids=" + string.Join(",", ids)); + JToken res = DownloadData(_builder.SearchItems(ownerId, playlistId, ids)); if (res is JArray) return new ListResponse { List = res.ToObject>(), Error = null }; return new ListResponse { List = null, Error = res["error"].ToObject() }; } + /// + /// Check to see if one or more Spotify users are following a specified playlist asynchronously. + /// + /// The Spotify user ID of the person who owns the playlist. + /// The Spotify ID of the playlist. + /// A list of Spotify User IDs + /// + /// AUTH NEEDED + public Task> IsFollowingPlaylistAsync(String ownerId, String playlistId, List ids) + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for IsFollowingPlaylist"); + JToken res = DownloadDataAsync(_builder.SearchItems(ownerId, playlistId, ids)); + if (res is JArray) //todo expression is always false + return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); + return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); + } + /// /// Check to see if one or more Spotify users are following a specified playlist. /// @@ -500,6 +794,19 @@ namespace SpotifyAPI.Web return IsFollowingPlaylist(ownerId, playlistId, new List { id }); } + /// + /// Check to see if one or more Spotify users are following a specified playlist asynchronously. + /// + /// The Spotify user ID of the person who owns the playlist. + /// The Spotify ID of the playlist. + /// A Spotify User ID + /// + /// AUTH NEEDED + public Task> IsFollowingPlaylistAsync(String ownerId, String playlistId, String id) + { + return IsFollowingPlaylistAsync(ownerId, playlistId, new List { id }); + } + #endregion Follow #region Library @@ -513,7 +820,19 @@ namespace SpotifyAPI.Web public ErrorResponse SaveTracks(List ids) { JArray array = new JArray(ids); - return UploadData(APIBase + "/me/tracks/", array.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + return UploadData(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + } + + /// + /// Save one or more tracks to the current user’s “Your Music” library asynchronously. + /// + /// A list of the Spotify IDs + /// + /// AUTH NEEDED + public Task SaveTracksAsync(List ids) + { + JArray array = new JArray(ids); + return UploadDataAsync(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse()); } /// @@ -527,6 +846,17 @@ namespace SpotifyAPI.Web return SaveTracks(new List { id }); } + /// + /// Save one track to the current user’s “Your Music” library asynchronously. + /// + /// A Spotify ID + /// + /// AUTH NEEDED + public Task SaveTrackAsync(String id) + { + return SaveTracksAsync(new List { id }); + } + /// /// Get a list of the songs saved in the current Spotify user’s “Your Music” library. /// @@ -539,13 +869,22 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetSavedTracks"); - limit = Math.Min(limit, 50); - StringBuilder builder = new StringBuilder(APIBase + "/me/tracks"); - builder.Append("?limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(market)) - builder.Append("&market=" + market); - return DownloadData>(builder.ToString()); + return DownloadData>(_builder.SearchItems(limit, offset, market)); + } + + /// + /// Get a list of the songs saved in the current Spotify user’s “Your Music” library asynchronously. + /// + /// The maximum number of objects to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first object to return. Default: 0 (i.e., the first object) + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + /// AUTH NEEDED + public Task> GetSavedTracksAsync(int limit = 20, int offset = 0, String market = "") + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetSavedTracks"); + return DownloadDataAsync>(_builder.SearchItems(limit, offset, market)); } /// @@ -557,7 +896,19 @@ namespace SpotifyAPI.Web public ErrorResponse RemoveSavedTracks(List ids) { JArray array = new JArray(ids); - return UploadData(APIBase + "/me/tracks/", array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + return UploadData(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + } + + /// + /// Remove one or more tracks from the current user’s “Your Music” library asynchronously. + /// + /// A list of the Spotify IDs. + /// + /// AUTH NEEDED + public Task RemoveSavedTracksAsync(List ids) + { + JArray array = new JArray(ids); + return UploadDataAsync(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); } /// @@ -576,6 +927,22 @@ namespace SpotifyAPI.Web return new ListResponse { List = null, Error = res["error"].ToObject() }; } + /// + /// Check if one or more tracks is already saved in the current Spotify user’s “Your Music” library asynchronously. + /// + /// A list of the Spotify IDs. + /// + /// AUTH NEEDED + public Task> CheckSavedTracksAsync(List ids) + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for CheckSavedTracks"); + JToken res = DownloadDataAsync(SpotifyWebBuilder.APIBase + "/me/tracks/contains?ids=" + string.Join(",", ids)); + if (res is JArray) //todo expression is always false + return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); + return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); + } + #endregion Library #region Playlists From 92e66ed4c3bfebe5ae2fa9a7a63b2a8dae5abe9f Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 14:57:20 +0100 Subject: [PATCH 2/9] Removed parameter checks --- SpotifyAPI/Web/SpotifyWebAPI.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index 900bff58..e4771f38 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -113,8 +113,6 @@ namespace SpotifyAPI.Web /// public FullAlbum GetAlbum(String id, String market = "") { - if (String.IsNullOrEmpty(market)) - return DownloadData(_builder.SearchItems(id)); return DownloadData(_builder.SearchItems(id, market)); } @@ -126,8 +124,6 @@ namespace SpotifyAPI.Web /// public Task GetAlbumAsync(String id, String market = "") { - if (String.IsNullOrEmpty(market)) - return DownloadDataAsync(_builder.SearchItems(id)); return DownloadDataAsync(_builder.SearchItems(id, market)); } @@ -139,8 +135,6 @@ namespace SpotifyAPI.Web /// public SeveralAlbums GetSeveralAlbums(List ids, String market = "") { - if (String.IsNullOrEmpty(market)) - return DownloadData(_builder.SearchItems(ids)); return DownloadData(_builder.SearchItems(ids, market)); } @@ -152,8 +146,6 @@ namespace SpotifyAPI.Web /// public Task GetSeveralAlbumsAsync(List ids, String market = "") { - if (String.IsNullOrEmpty(market)) - return DownloadDataAsync(_builder.SearchItems(ids)); return DownloadDataAsync(_builder.SearchItems(ids, market)); } From ab05201bd223b627709af92dd5ff969b261c4812 Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 15:15:14 +0100 Subject: [PATCH 3/9] Changed UploadData query to _builder --- SpotifyAPI/Web/SpotifyWebAPI.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index e4771f38..b7252870 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -812,7 +812,7 @@ namespace SpotifyAPI.Web public ErrorResponse SaveTracks(List ids) { JArray array = new JArray(ids); - return UploadData(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + return UploadData(_builder.SearchItems(array.ToString(Formatting.None), "PUT") ?? new ErrorResponse()); } /// @@ -824,7 +824,7 @@ namespace SpotifyAPI.Web public Task SaveTracksAsync(List ids) { JArray array = new JArray(ids); - return UploadDataAsync(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse()); + return UploadDataAsync(_builder.SearchItems(array.ToString(Formatting.None)), "PUT") ?? Task.FromResult(new ErrorResponse()); } /// @@ -888,7 +888,7 @@ namespace SpotifyAPI.Web public ErrorResponse RemoveSavedTracks(List ids) { JArray array = new JArray(ids); - return UploadData(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + return UploadData(_builder.SearchItems(array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); } /// @@ -900,7 +900,7 @@ namespace SpotifyAPI.Web public Task RemoveSavedTracksAsync(List ids) { JArray array = new JArray(ids); - return UploadDataAsync(SpotifyWebBuilder.APIBase + "/me/tracks/", array.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); + return UploadDataAsync(_builder.SearchItems(array.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); } /// From 9bb25a81607dbf863de37c2d9560c4bf31ca9df4 Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 15:21:04 +0100 Subject: [PATCH 4/9] Corrected syntax mistake in SaveTracksAsync method --- SpotifyAPI/Web/SpotifyWebAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index b7252870..e1ad5dd1 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -824,7 +824,7 @@ namespace SpotifyAPI.Web public Task SaveTracksAsync(List ids) { JArray array = new JArray(ids); - return UploadDataAsync(_builder.SearchItems(array.ToString(Formatting.None)), "PUT") ?? Task.FromResult(new ErrorResponse()); + return UploadDataAsync(_builder.SearchItems(array.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse())); } /// From dca8d5e3deb3adf7fb8cc74b911099fe483d8519 Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 18:08:24 +0100 Subject: [PATCH 5/9] Corrected all _builder method names until Playlists --- SpotifyAPI/Web/SpotifyWebAPI.cs | 96 ++++++++++++++++----------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index e1ad5dd1..a327ce2a 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -88,7 +88,7 @@ namespace SpotifyAPI.Web /// public Paging GetAlbumTracks(String id, int limit = 20, int offset = 0, String market = "") { - return DownloadData>(_builder.SearchItems(id, limit, offset, market)); + return DownloadData>(_builder.GetAlbumTracks(id, limit, offset, market)); } /// @@ -102,7 +102,7 @@ namespace SpotifyAPI.Web /// public Task> GetAlbumTracksAsync(String id, int limit = 20, int offset = 0, String market = "") { - return DownloadDataAsync>(_builder.SearchItems(id, limit, offset, market)); + return DownloadDataAsync>(_builder.GetAlbumTracks(id, limit, offset, market)); } /// @@ -113,7 +113,7 @@ namespace SpotifyAPI.Web /// public FullAlbum GetAlbum(String id, String market = "") { - return DownloadData(_builder.SearchItems(id, market)); + return DownloadData(_builder.GetAlbum(id, market)); } /// @@ -124,7 +124,7 @@ namespace SpotifyAPI.Web /// public Task GetAlbumAsync(String id, String market = "") { - return DownloadDataAsync(_builder.SearchItems(id, market)); + return DownloadDataAsync(_builder.GetAlbum(id, market)); } /// @@ -135,7 +135,7 @@ namespace SpotifyAPI.Web /// public SeveralAlbums GetSeveralAlbums(List ids, String market = "") { - return DownloadData(_builder.SearchItems(ids, market)); + return DownloadData(_builder.GetSeveralAlbums(ids, market)); } /// @@ -146,7 +146,7 @@ namespace SpotifyAPI.Web /// public Task GetSeveralAlbumsAsync(List ids, String market = "") { - return DownloadDataAsync(_builder.SearchItems(ids, market)); + return DownloadDataAsync(_builder.GetSeveralAlbums(ids, market)); } #endregion Albums @@ -160,7 +160,7 @@ namespace SpotifyAPI.Web /// public FullArtist GetArtist(String id) { - return DownloadData(_builder.SearchItems(id)); + return DownloadData(_builder.GetArtist(id)); } /// @@ -170,7 +170,7 @@ namespace SpotifyAPI.Web /// public Task GetArtistAsync(String id) { - return DownloadDataAsync(_builder.SearchItems(id)); + return DownloadDataAsync(_builder.GetArtist(id)); } /// @@ -181,7 +181,7 @@ namespace SpotifyAPI.Web /// public SeveralArtists GetRelatedArtists(String id) { - return DownloadData(_builder.SearchItems(id)); + return DownloadData(_builder.GetRelatedArtists(id)); } /// @@ -192,7 +192,7 @@ namespace SpotifyAPI.Web /// public Task GetRelatedArtistsAsync(String id) { - return DownloadDataAsync(_builder.SearchItems(id)); + return DownloadDataAsync(_builder.GetRelatedArtists(id)); } /// @@ -203,7 +203,7 @@ namespace SpotifyAPI.Web /// public SeveralTracks GetArtistsTopTracks(String id, String country) { - return DownloadData(_builder.SearchItems(id, country)); + return DownloadData(_builder.GetArtistsTopTracks(id, country)); } /// @@ -214,7 +214,7 @@ namespace SpotifyAPI.Web /// public Task GetArtistsTopTracksAsync(String id, String country) { - return DownloadDataAsync(_builder.SearchItems(id, country)); + return DownloadDataAsync(_builder.GetArtistsTopTracks(id, country)); } /// @@ -235,7 +235,7 @@ namespace SpotifyAPI.Web /// public Paging GetArtistsAlbums(String id, AlbumType type = AlbumType.All, int limit = 20, int offset = 0, String market = "") { - return DownloadData>(_builder.SearchItems(id, type, limit, offset, market)); + return DownloadData>(_builder.GetArtistsAlbums(id, type, limit, offset, market)); } /// @@ -256,7 +256,7 @@ namespace SpotifyAPI.Web /// public Task> GetArtistsAlbumsAsync(String id, AlbumType type = AlbumType.All, int limit = 20, int offset = 0, String market = "") { - return DownloadDataAsync>(_builder.SearchItems(id, type, limit, offset, market)); + return DownloadDataAsync>(_builder.GetArtistsAlbums(id, type, limit, offset, market)); } /// @@ -266,7 +266,7 @@ namespace SpotifyAPI.Web /// public SeveralArtists GetSeveralArtists(List ids) { - return DownloadData(_builder.SearchItems(ids)); + return DownloadData(_builder.GetSeveralArtists(ids)); } /// @@ -276,7 +276,7 @@ namespace SpotifyAPI.Web /// public Task GetSeveralArtistsAsync(List ids) { - return DownloadDataAsync(_builder.SearchItems(ids)); + return DownloadDataAsync(_builder.GetSeveralArtists(ids)); } #endregion Artists @@ -299,7 +299,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetFeaturedPlaylists"); - return DownloadData(_builder.SearchItems(locale, country, timestamp, limit, offset)); + return DownloadData(_builder.GetFeaturedPlaylists(locale, country, timestamp, limit, offset)); } /// @@ -318,7 +318,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetFeaturedPlaylists"); - return DownloadDataAsync(_builder.SearchItems(locale, country, timestamp, limit, offset)); + return DownloadDataAsync(_builder.GetFeaturedPlaylists(locale, country, timestamp, limit, offset)); } /// @@ -333,7 +333,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetNewAlbumReleases"); - return DownloadData(_builder.SearchItems(country, limit, offset)); + return DownloadData(_builder.GetNewAlbumReleases(country, limit, offset)); } /// @@ -348,7 +348,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetNewAlbumReleases"); - return DownloadDataAsync(_builder.SearchItems(country, limit, offset)); + return DownloadDataAsync(_builder.GetNewAlbumReleases(country, limit, offset)); } /// @@ -370,7 +370,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetCategories"); - return DownloadData(_builder.SearchItems(country, locale, limit, offset)); + return DownloadData(_builder.GetCategories(country, locale, limit, offset)); } /// @@ -392,7 +392,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetCategories"); - return DownloadDataAsync(_builder.SearchItems(country, locale, limit, offset)); + return DownloadDataAsync(_builder.GetCategories(country, locale, limit, offset)); } /// @@ -411,7 +411,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public Category GetCategory(String categoryId, String country = "", String locale = "") { - return DownloadData(_builder.SearchItems(categoryId, country, locale)); + return DownloadData(_builder.GetCategory(categoryId, country, locale)); } /// @@ -430,7 +430,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public Task GetCategoryAsync(String categoryId, String country = "", String locale = "") { - return DownloadDataAsync(_builder.SearchItems(categoryId, country, locale)); + return DownloadDataAsync(_builder.GetCategory(categoryId, country, locale)); } /// @@ -444,7 +444,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public CategoryPlaylist GetCategoryPlaylists(String categoryId, String country = "", int limit = 20, int offset = 0) { - return DownloadData(_builder.SearchItems(categoryId, country, limit, offset)); + return DownloadData(_builder.GetCategoryPlaylists(categoryId, country, limit, offset)); } /// @@ -458,7 +458,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public Task GetCategoryPlaylistsAsync(String categoryId, String country = "", int limit = 20, int offset = 0) { - return DownloadDataAsync(_builder.SearchItems(categoryId, country, limit, offset)); + return DownloadDataAsync(_builder.GetCategoryPlaylists(categoryId, country, limit, offset)); } #endregion Browse @@ -477,7 +477,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetFollowedArtists"); - return DownloadData(_builder.SearchItems(followType, limit, after)); + return DownloadData(_builder.GetFollowedArtists(followType, limit, after)); } /// @@ -492,7 +492,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetFollowedArtists"); - return DownloadDataAsync(_builder.SearchItems(followType, limit, after)); + return DownloadDataAsync(_builder.GetFollowedArtists(followType, limit, after)); } /// @@ -508,7 +508,7 @@ namespace SpotifyAPI.Web { {"ids", new JArray(ids)} }; - return UploadData(_builder.SearchItems(followType, ids), ob.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + return UploadData(_builder.Follow(followType, ids), ob.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); } /// @@ -525,7 +525,7 @@ namespace SpotifyAPI.Web {"ids", new JArray(ids)} }; return - UploadDataAsync(_builder.SearchItems(followType, ids), + UploadDataAsync(_builder.Follow(followType, ids), ob.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse()); } @@ -566,7 +566,7 @@ namespace SpotifyAPI.Web { {"ids", new JArray(ids)} }; - return UploadData(_builder.SearchItems(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + return UploadData(_builder.Unfollow(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); } /// @@ -582,7 +582,7 @@ namespace SpotifyAPI.Web { {"ids", new JArray(ids)} }; - return UploadDataAsync(_builder.SearchItems(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); + return UploadDataAsync(_builder.Unfollow(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); } /// @@ -620,7 +620,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowing"); - JToken res = DownloadData(_builder.SearchItems(followType, ids)); + JToken res = DownloadData(_builder.IsFollowing(followType, ids)); if (res is JArray) return new ListResponse { List = res.ToObject>(), Error = null }; return new ListResponse { List = null, Error = res["error"].ToObject() }; @@ -637,7 +637,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowing"); - JToken res = DownloadDataAsync(_builder.SearchItems(followType, ids)); + JToken res = DownloadDataAsync(_builder.IsFollowing(followType, ids)); if (res is JArray) //todo expression is always false return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); @@ -687,7 +687,7 @@ namespace SpotifyAPI.Web { {"public", showPublic} }; - return UploadData(_builder.SearchItems(ownerId, playlistId, showPublic), body.ToString(Formatting.None), "PUT"); + return UploadData(_builder.FollowPlaylist(ownerId, playlistId, showPublic), body.ToString(Formatting.None), "PUT"); } /// @@ -710,7 +710,7 @@ namespace SpotifyAPI.Web { {"public", showPublic} }; - return UploadDataAsync(_builder.SearchItems(ownerId, playlistId, showPublic), body.ToString(Formatting.None), "PUT"); + return UploadDataAsync(_builder.FollowPlaylist(ownerId, playlistId, showPublic), body.ToString(Formatting.None), "PUT"); } /// @@ -722,7 +722,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ErrorResponse UnfollowPlaylist(String ownerId, String playlistId) { - return UploadData(_builder.SearchItems(ownerId, playlistId), "", "DELETE"); + return UploadData(_builder.UnfollowPlaylist(ownerId, playlistId), "", "DELETE"); } /// @@ -734,7 +734,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public Task UnfollowPlaylistAsync(String ownerId, String playlistId) { - return UploadDataAsync(_builder.SearchItems(ownerId, playlistId), "", "DELETE"); + return UploadDataAsync(_builder.UnfollowPlaylist(ownerId, playlistId), "", "DELETE"); } /// @@ -749,7 +749,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowingPlaylist"); - JToken res = DownloadData(_builder.SearchItems(ownerId, playlistId, ids)); + JToken res = DownloadData(_builder.IsFollowingPlaylist(ownerId, playlistId, ids)); if (res is JArray) return new ListResponse { List = res.ToObject>(), Error = null }; return new ListResponse { List = null, Error = res["error"].ToObject() }; @@ -767,7 +767,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowingPlaylist"); - JToken res = DownloadDataAsync(_builder.SearchItems(ownerId, playlistId, ids)); + JToken res = DownloadDataAsync(_builder.IsFollowingPlaylist(ownerId, playlistId, ids)); if (res is JArray) //todo expression is always false return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); @@ -812,7 +812,7 @@ namespace SpotifyAPI.Web public ErrorResponse SaveTracks(List ids) { JArray array = new JArray(ids); - return UploadData(_builder.SearchItems(array.ToString(Formatting.None), "PUT") ?? new ErrorResponse()); + return UploadData(_builder.SaveTracks(array.ToString(Formatting.None), "PUT") ?? new ErrorResponse()); } /// @@ -824,7 +824,7 @@ namespace SpotifyAPI.Web public Task SaveTracksAsync(List ids) { JArray array = new JArray(ids); - return UploadDataAsync(_builder.SearchItems(array.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse())); + return UploadDataAsync(_builder.SaveTracks(array.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse())); } /// @@ -861,7 +861,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetSavedTracks"); - return DownloadData>(_builder.SearchItems(limit, offset, market)); + return DownloadData>(_builder.GetSavedTracks(limit, offset, market)); } /// @@ -876,7 +876,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetSavedTracks"); - return DownloadDataAsync>(_builder.SearchItems(limit, offset, market)); + return DownloadDataAsync>(_builder.GetSavedTracks(limit, offset, market)); } /// @@ -888,7 +888,7 @@ namespace SpotifyAPI.Web public ErrorResponse RemoveSavedTracks(List ids) { JArray array = new JArray(ids); - return UploadData(_builder.SearchItems(array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + return UploadData(_builder.RemoveSavedTracks(array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); } /// @@ -900,7 +900,7 @@ namespace SpotifyAPI.Web public Task RemoveSavedTracksAsync(List ids) { JArray array = new JArray(ids); - return UploadDataAsync(_builder.SearchItems(array.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); + return UploadDataAsync(_builder.RemoveSavedTracks(array.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); } /// @@ -913,7 +913,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for CheckSavedTracks"); - JToken res = DownloadData(APIBase + "/me/tracks/contains?ids=" + string.Join(",", ids)); + JToken res = DownloadData(_builder.CheckSavedTracks(ids)); if (res is JArray) return new ListResponse { List = res.ToObject>(), Error = null }; return new ListResponse { List = null, Error = res["error"].ToObject() }; @@ -929,7 +929,7 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for CheckSavedTracks"); - JToken res = DownloadDataAsync(SpotifyWebBuilder.APIBase + "/me/tracks/contains?ids=" + string.Join(",", ids)); + JToken res = DownloadDataAsync(_builder.CheckSavedTracks(ids)); if (res is JArray) //todo expression is always false return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); From a6c3d33abc34390bd4463efe08f3c01d0dc90354 Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 19:21:30 +0100 Subject: [PATCH 6/9] Added Async Methods for Playlists/Profiles/Tracks --- SpotifyAPI/Web/SpotifyWebAPI.cs | 296 ++++++++++++++++++++++++++++---- 1 file changed, 262 insertions(+), 34 deletions(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index a327ce2a..c39b1771 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -951,11 +951,22 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetUserPlaylists"); - limit = Math.Min(limit, 50); - StringBuilder builder = new StringBuilder(APIBase + "/users/" + userId + "/playlists"); - builder.Append("?limit=" + limit); - builder.Append("&offset=" + offset); - return DownloadData>(builder.ToString()); + return DownloadData>(_builder.GetUserPlaylists(userId, limit, offset)); + } + + /// + /// Get a list of the playlists owned or followed by a Spotify user asynchronously. + /// + /// The user's Spotify user ID. + /// The maximum number of playlists to return. Default: 20. Minimum: 1. Maximum: 50. + /// The index of the first playlist to return. Default: 0 (the first object) + /// + /// AUTH NEEDED + public Task> GetUserPlaylistsAsync(String userId, int limit = 20, int offset = 0) + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetUserPlaylists"); + return DownloadDataAsync>(_builder.GetUserPlaylists(userId, limit, offset)); } /// @@ -974,11 +985,26 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetPlaylist"); - StringBuilder builder = new StringBuilder(APIBase + "/users/" + userId + "/playlists/" + playlistId); - builder.Append("?fields=" + fields); - if (!String.IsNullOrEmpty(market)) - builder.Append("&market=" + market); - return DownloadData(builder.ToString()); + return DownloadData(_builder.GetPlaylist(userId, playlistId, fields, market)); + } + + /// + /// Get a playlist owned by a Spotify user asynchronously. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// + /// Filters for the query: a comma-separated list of the fields to return. If omitted, all fields are + /// returned. + /// + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + /// AUTH NEEDED + public Task GetPlaylistAsync(String userId, String playlistId, String fields = "", String market = "") + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetPlaylist"); + return DownloadDataAsync(_builder.GetPlaylist(userId, playlistId, fields, market)); } /// @@ -999,14 +1025,28 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetPlaylistTracks"); - limit = Math.Max(limit, 100); - StringBuilder builder = new StringBuilder(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks"); - builder.Append("?fields=" + fields); - builder.Append("&limit=" + limit); - builder.Append("&offset=" + offset); - if (!String.IsNullOrEmpty(market)) - builder.Append("&market=" + market); - return DownloadData>(builder.ToString()); + return DownloadData>(_builder.GetPlaylistTracks(userId, playlistId, fields, limit, offset, market)); + } + + /// + /// Get full details of the tracks of a playlist owned by a Spotify user asyncronously. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// + /// Filters for the query: a comma-separated list of the fields to return. If omitted, all fields are + /// returned. + /// + /// The maximum number of tracks to return. Default: 100. Minimum: 1. Maximum: 100. + /// The index of the first object to return. Default: 0 (i.e., the first object) + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + /// AUTH NEEDED + public Task> GetPlaylistTracksAsync(String userId, String playlistId, String fields = "", int limit = 100, int offset = 0, String market = "") + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetPlaylistTracks"); + return DownloadDataAsync>(_builder.GetPlaylistTracks(userId, playlistId, fields, limit, offset, market)); } /// @@ -1030,7 +1070,31 @@ namespace SpotifyAPI.Web {"name", playlistName}, {"public", isPublic} }; - return UploadData(APIBase + "/users/" + userId + "/playlists", body.ToString(Formatting.None)); + return UploadData(_builder.CreatePlaylist(userId, playlistName, isPublic), body.ToString(Formatting.None)); + } + + /// + /// Create a playlist for a Spotify user asynchronously. (The playlist will be empty until you add tracks.) + /// + /// The user's Spotify user ID. + /// + /// The name for the new playlist, for example "Your Coolest Playlist". This name does not need + /// to be unique. + /// + /// + /// default true. If true the playlist will be public, if false it will be private. To be able to + /// create private playlists, the user must have granted the playlist-modify-private scope. + /// + /// + /// AUTH NEEDED + public Task CreatePlaylistAsync(String userId, String playlistName, Boolean isPublic = true) + { + JObject body = new JObject + { + {"name", playlistName}, + {"public", isPublic} + }; + return UploadDataAsync(_builder.CreatePlaylist(userId, playlistName, isPublic), body.ToString(Formatting.None)); } /// @@ -1049,7 +1113,26 @@ namespace SpotifyAPI.Web body.Add("name", newName); if (newPublic != null) body.Add("public", newPublic); - return UploadData(APIBase + "/users/" + userId + "/playlists/" + playlistId, body.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + return UploadData(_builder.UpdatePlaylist(userId, playlistId, newName, newPublic), body.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + } + + /// + /// Change a playlist’s name and public/private state asynchronously. (The user must, of course, own the playlist.) + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// The new name for the playlist, for example "My New Playlist Title". + /// If true the playlist will be public, if false it will be private. + /// + /// AUTH NEEDED + public Task UpdatePlaylistAsync(String userId, String playlistId, String newName = null, Boolean? newPublic = null) + { + JObject body = new JObject(); + if (newName != null) + body.Add("name", newName); + if (newPublic != null) + body.Add("public", newPublic); + return UploadDataAsync(_builder.UpdatePlaylist(userId, playlistId, newName, newPublic), body.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); } /// @@ -1067,7 +1150,25 @@ namespace SpotifyAPI.Web { {"uris", new JArray(uris.Take(100))} }; - return UploadData(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks", body.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + return UploadData(_builder.ReplacePlaylistTracks(userId, playlistId, uris), body.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); + } + + /// + /// Replace all the tracks in a playlist asynchronously, overwriting its existing tracks. This powerful request can be useful for + /// replacing tracks, re-ordering existing tracks, or clearing the playlist. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// A list of Spotify track URIs to set. A maximum of 100 tracks can be set in one request. + /// + /// AUTH NEEDED + public Task ReplacePlaylistTracksAsync(String userId, String playlistId, List uris) + { + JObject body = new JObject + { + {"uris", new JArray(uris.Take(100))} + }; + return UploadDataAsync(_builder.ReplacePlaylistTracks(userId, playlistId, uris), body.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); } /// @@ -1087,7 +1188,27 @@ namespace SpotifyAPI.Web { {"tracks", JArray.FromObject(uris.Take(100))} }; - return UploadData(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks", body.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + return UploadData(_builder.RemovePlaylistTracks(userId, playlistId, uris), body.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + } + + /// + /// Remove one or more tracks from a user’s playlist asynchronously. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// + /// array of objects containing Spotify URI strings (and their position in the playlist). A maximum of + /// 100 objects can be sent at once. + /// + /// + /// AUTH NEEDED + public Task RemovePlaylistTracksAsync(String userId, String playlistId, List uris) + { + JObject body = new JObject + { + {"tracks", JArray.FromObject(uris.Take(100))} + }; + return UploadDataAsync(_builder.RemovePlaylistTracks(userId, playlistId, uris), body.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); } /// @@ -1103,6 +1224,19 @@ namespace SpotifyAPI.Web return RemovePlaylistTracks(userId, playlistId, new List { uri }); } + /// + /// Remove one or more tracks from a user’s playlist asynchronously. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// Spotify URI + /// + /// AUTH NEEDED + public Task RemovePlaylistTrackAsync(String userId, String playlistId, DeleteTrackUri uri) + { + return RemovePlaylistTracksAsync(userId, playlistId, new List { uri }); + } + /// /// Add one or more tracks to a user’s playlist. /// @@ -1118,9 +1252,27 @@ namespace SpotifyAPI.Web { {"uris", JArray.FromObject(uris.Take(100))} }; - if (position == null) - return UploadData(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks", body.ToString(Formatting.None)) ?? new ErrorResponse(); - return UploadData(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks?position=" + position, body.ToString(Formatting.None)) ?? new ErrorResponse(); + return UploadData(_builder.AddPlaylistTracks(userId, playlistId, uris, position), body.ToString(Formatting.None)) ?? new ErrorResponse(); + + } + + /// + /// Add one or more tracks to a user’s playlist asynchronously. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// A list of Spotify track URIs to add + /// The position to insert the tracks, a zero-based index + /// + /// AUTH NEEDED + public Task AddPlaylistTracksAsync(String userId, String playlistId, List uris, int? position = null) + { + JObject body = new JObject + { + {"uris", JArray.FromObject(uris.Take(100))} + }; + return UploadDataAsync(_builder.AddPlaylistTracks(userId, playlistId, uris, position), body.ToString(Formatting.None)) ?? new ErrorResponse(); + } /// @@ -1137,6 +1289,20 @@ namespace SpotifyAPI.Web return AddPlaylistTracks(userId, playlistId, new List { uri }, position); } + /// + /// Add one or more tracks to a user’s playlist asynchronously. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// A Spotify Track URI + /// The position to insert the tracks, a zero-based index + /// + /// AUTH NEEDED + public Task AddPlaylistTrackAsync(String userId, String playlistId, String uri, int? position = null) + { + return AddPlaylistTracksAsync(userId, playlistId, new List { uri }, position); + } + /// /// Reorder a track or a group of tracks in a playlist. /// @@ -1158,7 +1324,29 @@ namespace SpotifyAPI.Web }; if (!String.IsNullOrEmpty(snapshotId)) body.Add("snapshot_id", snapshotId); - return UploadData(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks", body.ToString(Formatting.None), "PUT"); + return UploadData(_builder.ReorderPlaylist(userId, playlistId, rangeStart, insertBefore, rangeLength, snapshotId), body.ToString(Formatting.None), "PUT"); + } + + /// + /// Reorder a track or a group of tracks in a playlist asynchronously. + /// + /// The user's Spotify user ID. + /// The Spotify ID for the playlist. + /// The position of the first track to be reordered. + /// The position where the tracks should be inserted. + /// The amount of tracks to be reordered. Defaults to 1 if not set. + /// The playlist's snapshot ID against which you want to make the changes. + /// + /// AUTH NEEDED + public Task ReorderPlaylistAsync(String userId, String playlistId, int rangeStart, int insertBefore, int rangeLength = 1, String snapshotId = "") + { + JObject body = new JObject + { + {"range_start", rangeStart}, + {"range_length", rangeLength}, + {"insert_before", insertBefore} + }; + return UploadDataAsync(_builder.ReorderPlaylist(userId, playlistId, rangeStart, insertBefore, rangeLength, snapshotId), body.ToString(Formatting.None), "PUT"); } #endregion Playlists @@ -1174,7 +1362,19 @@ namespace SpotifyAPI.Web { if (!UseAuth) throw new InvalidOperationException("Auth is required for GetPrivateProfile"); - return DownloadData(APIBase + "/me"); + return DownloadData(_builder.GetPrivateProfile()); + } + + /// + /// Get detailed profile information about the current user asynchronously (including the current user’s username). + /// + /// + /// AUTH NEEDED + public Task GetPrivateProfileAsync() + { + if (!UseAuth) + throw new InvalidOperationException("Auth is required for GetPrivateProfile"); + return DownloadDataAsync(_builder.GetPrivateProfile()); } /// @@ -1184,7 +1384,17 @@ namespace SpotifyAPI.Web /// public PublicProfile GetPublicProfile(String userId) { - return DownloadData(APIBase + "/users/" + userId); + return DownloadData(_builder.GetPublicProfile(userId)); + } + + /// + /// Get public profile information about a Spotify user asynchronously. + /// + /// The user's Spotify user ID. + /// + public Task GetPublicProfileAsync(String userId) + { + return DownloadDataAsync(_builder.GetPublicProfile(userId)); } #endregion Profiles @@ -1199,9 +1409,18 @@ namespace SpotifyAPI.Web /// public SeveralTracks GetSeveralTracks(List ids, String market = "") { - if (String.IsNullOrEmpty(market)) - return DownloadData(APIBase + "/tracks?ids=" + string.Join(",", ids.Take(50))); - return DownloadData(APIBase + "/tracks?market=" + market + "&ids=" + string.Join(",", ids.Take(50))); + return DownloadData(_builder.GetSeveralTracks(ids, market)); + } + + /// + /// Get Spotify catalog information for multiple tracks based on their Spotify IDs asynchronously. + /// + /// A list of the Spotify IDs for the tracks. Maximum: 50 IDs. + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + public Task GetSeveralTracksAsync(List ids, String market = "") + { + return DownloadDataAsync(_builder.GetSeveralTracks(ids, market)); } /// @@ -1212,9 +1431,18 @@ namespace SpotifyAPI.Web /// public FullTrack GetTrack(String id, String market = "") { - if (String.IsNullOrEmpty(market)) - return DownloadData(APIBase + "/tracks/" + id); - return DownloadData(APIBase + "/tracks/" + id + "?market=" + market); + return DownloadData(_builder.GetTrack(id, market)); + } + + /// + /// Get Spotify catalog information for a single track identified by its unique Spotify ID asynchronously. + /// + /// The Spotify ID for the track. + /// An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking. + /// + public Task GetTrackAsync(String id, String market = "") + { + return DownloadDataAsync(_builder.GetTrack(id, market)); } #endregion Tracks From d3b6913690fdc9ea04803ee9e2840e2aaa75f2fa Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 19:31:20 +0100 Subject: [PATCH 7/9] Removed Task.FromResult where not needed --- SpotifyAPI/Web/SpotifyWebAPI.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index c39b1771..f82c167c 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -526,7 +526,7 @@ namespace SpotifyAPI.Web }; return UploadDataAsync(_builder.Follow(followType, ids), - ob.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse()); + ob.ToString(Formatting.None), "PUT") ?? new ErrorResponse(); } /// @@ -582,7 +582,7 @@ namespace SpotifyAPI.Web { {"ids", new JArray(ids)} }; - return UploadDataAsync(_builder.Unfollow(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); + return UploadDataAsync(_builder.Unfollow(followType, ids), ob.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); } /// @@ -824,7 +824,7 @@ namespace SpotifyAPI.Web public Task SaveTracksAsync(List ids) { JArray array = new JArray(ids); - return UploadDataAsync(_builder.SaveTracks(array.ToString(Formatting.None), "PUT") ?? Task.FromResult(new ErrorResponse())); + return UploadDataAsync(_builder.SaveTracks(array.ToString(Formatting.None), "PUT") ?? new ErrorResponse()); } /// @@ -888,7 +888,7 @@ namespace SpotifyAPI.Web public ErrorResponse RemoveSavedTracks(List ids) { JArray array = new JArray(ids); - return UploadData(_builder.RemoveSavedTracks(array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse(); + return UploadData(_builder.RemoveSavedTracks(array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse()); } /// @@ -900,7 +900,7 @@ namespace SpotifyAPI.Web public Task RemoveSavedTracksAsync(List ids) { JArray array = new JArray(ids); - return UploadDataAsync(_builder.RemoveSavedTracks(array.ToString(Formatting.None), "DELETE") ?? Task.FromResult(new ErrorResponse()); + return UploadDataAsync(_builder.RemoveSavedTracks(array.ToString(Formatting.None), "DELETE") ?? new ErrorResponse()); } /// From a913f1d459dd9c5c82237e5fd8919c8ce09d55f1 Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 19:44:52 +0100 Subject: [PATCH 8/9] Added 3 compilebreakers on Todo Items --- SpotifyAPI/Web/SpotifyWebAPI.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index f82c167c..30f55096 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -638,6 +638,7 @@ namespace SpotifyAPI.Web if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowing"); JToken res = DownloadDataAsync(_builder.IsFollowing(followType, ids)); +# Compilebreaker if (res is JArray) //todo expression is always false return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); @@ -768,6 +769,7 @@ namespace SpotifyAPI.Web if (!UseAuth) throw new InvalidOperationException("Auth is required for IsFollowingPlaylist"); JToken res = DownloadDataAsync(_builder.IsFollowingPlaylist(ownerId, playlistId, ids)); +# Compilebreaker if (res is JArray) //todo expression is always false return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); @@ -930,6 +932,7 @@ namespace SpotifyAPI.Web if (!UseAuth) throw new InvalidOperationException("Auth is required for CheckSavedTracks"); JToken res = DownloadDataAsync(_builder.CheckSavedTracks(ids)); +# Compilebreaker if (res is JArray) //todo expression is always false return Task.FromResult(new ListResponse { List = res.ToObject>(), Error = null }); return Task.FromResult(new ListResponse { List = null, Error = res["error"].ToObject() }); From c51a2679246ae32abdfc76083b34c68a22cfbdc7 Mon Sep 17 00:00:00 2001 From: Jimmy Appelt Date: Fri, 6 Nov 2015 19:56:50 +0100 Subject: [PATCH 9/9] CM Clean --- SpotifyAPI/Web/SpotifyWebAPI.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index 30f55096..79763111 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -5,7 +5,6 @@ using SpotifyAPI.Web.Models; using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; namespace SpotifyAPI.Web @@ -1256,7 +1255,6 @@ namespace SpotifyAPI.Web {"uris", JArray.FromObject(uris.Take(100))} }; return UploadData(_builder.AddPlaylistTracks(userId, playlistId, uris, position), body.ToString(Formatting.None)) ?? new ErrorResponse(); - } /// @@ -1275,7 +1273,6 @@ namespace SpotifyAPI.Web {"uris", JArray.FromObject(uris.Take(100))} }; return UploadDataAsync(_builder.AddPlaylistTracks(userId, playlistId, uris, position), body.ToString(Formatting.None)) ?? new ErrorResponse(); - } ///