diff --git a/src/IF.Lastfm.Core.Tests/Api/Commands/AlbumGetTagsByUserCommandTests.cs b/src/IF.Lastfm.Core.Tests/Api/Commands/AlbumGetTagsByUserCommandTests.cs new file mode 100644 index 0000000..adcdf24 --- /dev/null +++ b/src/IF.Lastfm.Core.Tests/Api/Commands/AlbumGetTagsByUserCommandTests.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using IF.Lastfm.Core.Api.Commands.AlbumApi; +using IF.Lastfm.Core.Api.Enums; +using IF.Lastfm.Core.Objects; +using IF.Lastfm.Core.Tests.Resources; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IF.Lastfm.Core.Tests.Api.Commands +{ + [TestClass] + public class AlbumGetTagsByUserCommandTests : CommandTestsBase + { + private AlbumGetTagsByUserCommand _command; + + [TestInitialize] + public void Initialise() + { + _command = new AlbumGetTagsByUserCommand(MAuth.Object, "", "", ""); + } + + [TestMethod] + public async Task HandleResponseSingle() + { + var expectedTags = new List + { + new LastTag("Test Tag", "http://www.last.fm/tag/test%20tag") + }; + + var response = CreateResponseMessage(Encoding.UTF8.GetString(AlbumApiResponses.AlbumGetTagsSingle)); + var parsed = await _command.HandleResponse(response); + + var expectedJson = expectedTags.TestSerialise(); + var actualJson = parsed.Content.TestSerialise(); + + parsed.AssertValues(true, 1, 1, 1, 1); + Assert.AreEqual(expectedJson, actualJson, expectedJson.DifferencesTo(actualJson)); + } + + [TestMethod] + public async Task HandleResponseMultiple() + { + var expectedTags = new List + { + new LastTag("test tag 2: electric boogaloo", "http://www.last.fm/tag/test%20tag%202%3A%20electric%20boogaloo"), + new LastTag("Test Tag", "http://www.last.fm/tag/test%20tag") + }; + + var response = CreateResponseMessage(Encoding.UTF8.GetString(AlbumApiResponses.AlbumGetTagsMultiple)); + var parsed = await _command.HandleResponse(response); + + var expectedJson = expectedTags.TestSerialise(); + var actualJson = parsed.Content.TestSerialise(); + + parsed.AssertValues(true, 2, 2, 1, 1); + Assert.AreEqual(expectedJson, actualJson, expectedJson.DifferencesTo(actualJson)); + } + + [TestMethod] + public async Task HandleResponseEmpty() + { + var response = CreateResponseMessage(Encoding.UTF8.GetString(AlbumApiResponses.AlbumGetTagsEmpty)); + var parsed = await _command.HandleResponse(response); + + parsed.AssertValues(true, 0, 0, 1, 1); + Assert.IsTrue(!parsed.Content.Any()); + } + + [TestMethod] + public async Task HandleResponseError() + { + var response = CreateResponseMessage(Encoding.UTF8.GetString(AlbumApiResponses.AlbumGetTagsError)); + var parsed = await _command.HandleResponse(response); + + parsed.AssertValues(false, 0, 0, 1, 1); + Assert.IsFalse(parsed.Success); + Assert.IsTrue(parsed.Error == LastFmApiError.MissingParameters); + Assert.IsTrue(!parsed.Content.Any()); + } + } +} \ No newline at end of file diff --git a/src/IF.Lastfm.Core.Tests/Api/Commands/CommandTestsBase.cs b/src/IF.Lastfm.Core.Tests/Api/Commands/CommandTestsBase.cs index 51b5f7e..23418c6 100644 --- a/src/IF.Lastfm.Core.Tests/Api/Commands/CommandTestsBase.cs +++ b/src/IF.Lastfm.Core.Tests/Api/Commands/CommandTestsBase.cs @@ -1,4 +1,5 @@ -using IF.Lastfm.Core.Api; +using System.Threading.Tasks; +using IF.Lastfm.Core.Api; using IF.Lastfm.Core.Api.Commands; using IF.Lastfm.Core.Api.Helpers; using IF.Lastfm.Core.Objects; @@ -8,7 +9,6 @@ using System.Net; using System.Net.Http; using System.Text; -using System.Threading.Tasks; namespace IF.Lastfm.Core.Tests.Api.Commands { diff --git a/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj b/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj index 25e9ba1..0a9ca9b 100644 --- a/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj +++ b/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj @@ -42,6 +42,7 @@ false + False @@ -78,6 +79,7 @@ + diff --git a/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsEmpty.json b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsEmpty.json new file mode 100644 index 0000000..46c4306 --- /dev/null +++ b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsEmpty.json @@ -0,0 +1,7 @@ +{ + "tags": { + "#text": "\n", + "artist": "Hot Chip", + "album": "Made in the Dark" + } +} \ No newline at end of file diff --git a/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsError.json b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsError.json new file mode 100644 index 0000000..51805a6 --- /dev/null +++ b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsError.json @@ -0,0 +1,5 @@ +{ + "error": 6, + "message": "Invalid user supplied", + "links": [] +} \ No newline at end of file diff --git a/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsMultiple.json b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsMultiple.json new file mode 100644 index 0000000..142e074 --- /dev/null +++ b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsMultiple.json @@ -0,0 +1,18 @@ +{ + "tags": { + "tag": [ + { + "name": "test tag 2: electric boogaloo", + "url": "http://www.last.fm/tag/test%20tag%202%3A%20electric%20boogaloo" + }, + { + "name": "Test Tag", + "url": "http://www.last.fm/tag/test%20tag" + } + ], + "@attr": { + "artist": "Hot Chip", + "album": "Coming on Strong" + } + } +} \ No newline at end of file diff --git a/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsSingle.json b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsSingle.json new file mode 100644 index 0000000..7a88d45 --- /dev/null +++ b/src/IF.Lastfm.Core.Tests/Resources/AlbumApi/AlbumGetTagsSingle.json @@ -0,0 +1,12 @@ +{ + "tags": { + "tag": { + "name": "Test Tag", + "url": "http://www.last.fm/tag/test%20tag" + }, + "@attr": { + "artist": "Hot Chip", + "album": "The Warning" + } + } +} \ No newline at end of file diff --git a/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.Designer.cs b/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.Designer.cs index 41229c8..58fbe35 100644 --- a/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.Designer.cs +++ b/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.Designer.cs @@ -120,6 +120,46 @@ internal static byte[] AlbumGetShoutsSingle { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] AlbumGetTagsEmpty { + get { + object obj = ResourceManager.GetObject("AlbumGetTagsEmpty", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] AlbumGetTagsError { + get { + object obj = ResourceManager.GetObject("AlbumGetTagsError", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] AlbumGetTagsMultiple { + get { + object obj = ResourceManager.GetObject("AlbumGetTagsMultiple", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] AlbumGetTagsSingle { + get { + object obj = ResourceManager.GetObject("AlbumGetTagsSingle", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.resx b/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.resx index f5b34bf..88dc098 100644 --- a/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.resx +++ b/src/IF.Lastfm.Core.Tests/Resources/AlbumApiResponses.resx @@ -136,6 +136,18 @@ albumapi\albumgetshoutssingle.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + AlbumApi\AlbumGetTagsEmpty.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + AlbumApi\AlbumGetTagsError.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + AlbumApi\AlbumGetTagsMultiple.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + AlbumApi\AlbumGetTagsSingle.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + AlbumApi\AlbumGetTopTags.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/src/IF.Lastfm.Core.Tests/TestHelper.cs b/src/IF.Lastfm.Core.Tests/TestHelper.cs index ac49183..1fbcede 100644 --- a/src/IF.Lastfm.Core.Tests/TestHelper.cs +++ b/src/IF.Lastfm.Core.Tests/TestHelper.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Text; +using IF.Lastfm.Core.Api.Helpers; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; namespace IF.Lastfm.Core.Tests @@ -83,5 +85,22 @@ public static DateTime RoundToNearestSecond(this DateTime dt) ? dt.AddMilliseconds(-ms) : dt.AddMilliseconds(1000 - ms); } + + public static void AssertValues(this PageResponse pageResponse, bool success, int totalItems, int pageSize, int page, int totalPages) + where T : new() + { + const string messageFormat = "Page response:\n{0}\n\nExpected {1} to equal {2}"; + var json = pageResponse.TestSerialise(); + Func testMessage = (property, count) => string.Format(messageFormat, json, property, count); + + Assert.IsTrue(pageResponse.Success == success, testMessage("success", success)); + Assert.IsTrue(pageResponse.TotalItems == totalItems, testMessage("totalitems", totalItems)); + Assert.IsTrue(pageResponse.PageSize == pageSize, testMessage("pagesize", pageSize)); + Assert.IsTrue(pageResponse.Page == page, testMessage("page", page)); + Assert.IsTrue(pageResponse.TotalPages == totalPages, testMessage("totalpages", totalPages)); + + Assert.IsNotNull(pageResponse.Content, "page content is null"); + Assert.IsTrue(pageResponse.Content.Count == totalItems, testMessage("content length", totalItems)); + } } } diff --git a/src/IF.Lastfm.Core/Api/AlbumApi.cs b/src/IF.Lastfm.Core/Api/AlbumApi.cs index 7c2fc5c..e402495 100644 --- a/src/IF.Lastfm.Core/Api/AlbumApi.cs +++ b/src/IF.Lastfm.Core/Api/AlbumApi.cs @@ -36,14 +36,19 @@ public async Task> GetAlbumInfoByMbidAsync(string albumM return await command.ExecuteAsync(); } - public Task> GetBuyLinksForAlbumAsync(string artist, string album, CountryCode country, bool autocorrect = false) - { - throw new NotImplementedException(); - } + //public Task> GetBuyLinksForAlbumAsync(string artist, string album, CountryCode country, bool autocorrect = false) + //{ + // throw new NotImplementedException(); + //} - public Task> GetUserTagsForAlbumAsync(string artist, string album, string username, bool autocorrect = false) + public Task> GetTagsByUserAsync(string artist, string album, string username, bool autocorrect = false) { - throw new NotImplementedException(); + var command = new AlbumGetTagsByUserCommand(Auth, artist, album, username) + { + Autocorrect = autocorrect + }; + + return command.ExecuteAsync(); } public async Task> GetTopTagsForAlbumAsync(string artist, string album, bool autocorrect = false) diff --git a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetUserTagsForAlbumCommand.cs b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/AlbumGetTagsByUserCommand.cs similarity index 64% rename from src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetUserTagsForAlbumCommand.cs rename to src/IF.Lastfm.Core/Api/Commands/AlbumApi/AlbumGetTagsByUserCommand.cs index e959223..2b3648b 100644 --- a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetUserTagsForAlbumCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/AlbumGetTagsByUserCommand.cs @@ -12,40 +12,31 @@ namespace IF.Lastfm.Core.Api.Commands.AlbumApi { - internal class GetUserTagsForAlbumCommand: GetAsyncCommandBase> + internal class AlbumGetTagsByUserCommand : GetAsyncCommandBase> { - public string AlbumMbid { get; set; } - public string ArtistName { get; set; } public string AlbumName { get; set; } - public string UserName { get; set; } + public string Username { get; set; } + public bool Autocorrect { get; set; } - public GetUserTagsForAlbumCommand(ILastAuth auth, string album, string artist, string username) + public AlbumGetTagsByUserCommand(ILastAuth auth, string artist, string album, string username) : base(auth) { Method = "album.getTags"; - AlbumName = album; ArtistName = artist; - UserName = username; + AlbumName = album; + Username = username; } - public override void SetParameters() { - if (AlbumMbid != null) - { - Parameters.Add("mbid", AlbumMbid); - } - else - { - Parameters.Add("artist", ArtistName); - Parameters.Add("album", AlbumName); - Parameters.Add("user", UserName); - } + Parameters.Add("artist", ArtistName); + Parameters.Add("album", AlbumName); + Parameters.Add("user", Username); Parameters.Add("autocorrect", Convert.ToInt32(Autocorrect).ToString()); AddPagingParameters(); @@ -60,14 +51,14 @@ public async override Task> HandleResponse(HttpResponseMes if (LastFm.IsResponseValid(json, out error) && response.IsSuccessStatusCode) { var jtoken = JsonConvert.DeserializeObject(json); - var resultsToken = jtoken.SelectToken("toptags"); + var resultsToken = jtoken.SelectToken("tags"); var itemsToken = resultsToken.SelectToken("tag"); - return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastTag.ParseJToken, false); + return PageResponse.CreateSuccessResponse(itemsToken, LastTag.ParseJToken); } else { - return LastResponse.CreateErrorResponse>(error); + return PageResponse.CreateErrorResponse(error); } } } diff --git a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumShoutsCommand.cs index a1fbd77..a5636ec 100644 --- a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumShoutsCommand.cs @@ -47,7 +47,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = jtoken.SelectToken("shout"); var pageInfoToken = jtoken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumTopTagsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumTopTagsCommand.cs index 3e18bb9..1a88400 100644 --- a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumTopTagsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/GetAlbumTopTagsCommand.cs @@ -64,7 +64,7 @@ public async override Task> HandleResponse(HttpResponseMes var resultsToken = jtoken.SelectToken("toptags"); var itemsToken = resultsToken.SelectToken("tag"); - return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastTag.ParseJToken, false); + return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastTag.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/SearchAlbumsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/SearchAlbumsCommand.cs index 857c12b..41fc6fc 100644 --- a/src/IF.Lastfm.Core/Api/Commands/AlbumApi/SearchAlbumsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/AlbumApi/SearchAlbumsCommand.cs @@ -39,7 +39,7 @@ public async override Task> HandleResponse(HttpResponseM var resultsToken = jtoken.SelectToken("results"); var itemsToken = resultsToken.SelectToken("albummatches").SelectToken("album"); - return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastAlbum.ParseJToken, true); + return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastAlbum.ParseJToken, LastPageResultsType.OpenQuery); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetArtistShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetArtistShoutsCommand.cs index 1e7741e..d0d1701 100644 --- a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetArtistShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetArtistShoutsCommand.cs @@ -42,7 +42,7 @@ public override async Task> HandleResponse(HttpResponseM var itemsToken = shoutsToken.SelectToken("shout"); var pageInfoToken = shoutsToken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetSimilarArtistsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetSimilarArtistsCommand.cs index 4296089..f05af25 100644 --- a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetSimilarArtistsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetSimilarArtistsCommand.cs @@ -50,7 +50,7 @@ public async override Task> HandleResponse(HttpResponse var jtoken = JsonConvert.DeserializeObject(json); var itemsToken = jtoken.SelectToken("similarartists").SelectToken("artist"); - return PageResponse.CreateSuccessResponse(itemsToken, null, LastArtist.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, LastArtist.ParseJToken); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopAlbumsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopAlbumsCommand.cs index e88a526..d798a44 100644 --- a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopAlbumsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopAlbumsCommand.cs @@ -39,7 +39,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = albumsToken.SelectToken("album"); var pageInfoToken = albumsToken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastAlbum.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastAlbum.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopTracksCommand.cs index 9faf473..165c45d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/GetTopTracksCommand.cs @@ -39,7 +39,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = tracksToken.SelectToken("track"); var pageInfoToken = tracksToken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastTrack.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastTrack.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/SearchArtistsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/SearchArtistsCommand.cs index 9bb2e84..707983d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/ArtistApi/SearchArtistsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/ArtistApi/SearchArtistsCommand.cs @@ -38,7 +38,7 @@ public async override Task> HandleResponse(HttpResponse var resultsToken = jtoken.SelectToken("results"); var itemsToken = resultsToken.SelectToken("artistmatches").SelectToken("artist"); - return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastArtist.ParseJToken, true); + return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastArtist.ParseJToken, LastPageResultsType.OpenQuery); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopArtistsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopArtistsCommand.cs index 2575191..636cbf9 100644 --- a/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopArtistsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopArtistsCommand.cs @@ -33,7 +33,7 @@ public async override Task> HandleResponse(HttpResponse var itemsToken = jtoken.SelectToken("artist"); var pageInfoToken = jtoken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastArtist.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastArtist.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopTracksCommand.cs index cb71967..e6afa43 100644 --- a/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/ChartApi/GetTopTracksCommand.cs @@ -34,7 +34,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = tracksToken.SelectToken("track"); var pageInfoToken = tracksToken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastTrack.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastTrack.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/LibraryApi/LibraryGetTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/LibraryApi/LibraryGetTracksCommand.cs index d152699..8974440 100644 --- a/src/IF.Lastfm.Core/Api/Commands/LibraryApi/LibraryGetTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/LibraryApi/LibraryGetTracksCommand.cs @@ -51,7 +51,7 @@ public async override Task> HandleResponse(HttpResponseM var tracksToken = jtoken.SelectToken("track"); var pageInfoToken = jtoken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(tracksToken, pageInfoToken, LastTrack.ParseJToken, false); + return PageResponse.CreateSuccessResponse(tracksToken, pageInfoToken, LastTrack.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetSimilarTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetSimilarTracksCommand.cs index 9a83cc7..1f3854c 100644 --- a/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetSimilarTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetSimilarTracksCommand.cs @@ -55,7 +55,7 @@ public async override Task> HandleResponse(HttpResponseM var jtoken = JsonConvert.DeserializeObject(json); var itemsToken = jtoken.SelectToken("similartracks").SelectToken("track"); - return PageResponse.CreateSuccessResponse(itemsToken, null, LastTrack.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, LastTrack.ParseJToken); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetTrackShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetTrackShoutsCommand.cs index 497dec8..256673d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetTrackShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/TrackApi/GetTrackShoutsCommand.cs @@ -47,7 +47,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = jtoken.SelectToken("shout"); var pageInfoToken = jtoken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/TrackApi/SearchTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/TrackApi/SearchTracksCommand.cs index 3018941..ae1fb20 100644 --- a/src/IF.Lastfm.Core/Api/Commands/TrackApi/SearchTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/TrackApi/SearchTracksCommand.cs @@ -38,7 +38,7 @@ public async override Task> HandleResponse(HttpResponseM var resultsToken = jtoken.SelectToken("results"); var itemsToken = resultsToken.SelectToken("trackmatches").SelectToken("track"); - return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastTrack.ParseJToken, true); + return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastTrack.ParseJToken, LastPageResultsType.OpenQuery); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/UserApi/GetRecommendedArtistsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/UserApi/GetRecommendedArtistsCommand.cs index e0ea94e..31c01e2 100644 --- a/src/IF.Lastfm.Core/Api/Commands/UserApi/GetRecommendedArtistsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/UserApi/GetRecommendedArtistsCommand.cs @@ -31,7 +31,7 @@ public async override Task> HandleResponse(HttpResponse var resultsToken = jtoken.SelectToken("recommendations"); var itemsToken = resultsToken.SelectToken("artist"); - return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastArtist.ParseJToken, false); + return PageResponse.CreateSuccessResponse(itemsToken, resultsToken, LastArtist.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/UserApi/GetTopAlbumsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/UserApi/GetTopAlbumsCommand.cs index 55d3e05..54eef7e 100644 --- a/src/IF.Lastfm.Core/Api/Commands/UserApi/GetTopAlbumsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/UserApi/GetTopAlbumsCommand.cs @@ -40,7 +40,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = jtoken.SelectToken("topalbums").SelectToken("album"); var pageInfoToken = jtoken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastAlbum.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastAlbum.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/UserApi/GetUserShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/UserApi/GetUserShoutsCommand.cs index ea05bea..e7154dd 100644 --- a/src/IF.Lastfm.Core/Api/Commands/UserApi/GetUserShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/UserApi/GetUserShoutsCommand.cs @@ -38,7 +38,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = shoutsToken.SelectToken("shout"); var pageInfoToken = jtoken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken); + return PageResponse.CreateSuccessResponse(itemsToken, pageInfoToken, LastShout.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Commands/UserApi/UserGetRecentTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/UserApi/UserGetRecentTracksCommand.cs index 0075334..04f9119 100644 --- a/src/IF.Lastfm.Core/Api/Commands/UserApi/UserGetRecentTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/UserApi/UserGetRecentTracksCommand.cs @@ -48,7 +48,7 @@ public async override Task> HandleResponse(HttpResponseM var itemsToken = jtoken.SelectToken("track"); var attrToken = jtoken.SelectToken("@attr"); - return PageResponse.CreateSuccessResponse(itemsToken, attrToken, LastTrack.ParseJToken, false); + return PageResponse.CreateSuccessResponse(itemsToken, attrToken, LastTrack.ParseJToken, LastPageResultsType.Attr); } else { diff --git a/src/IF.Lastfm.Core/Api/Enums/LastStatsTimeSpan.cs b/src/IF.Lastfm.Core/Api/Enums/LastStatsTimeSpan.cs index d373209..6ae51ff 100644 --- a/src/IF.Lastfm.Core/Api/Enums/LastStatsTimeSpan.cs +++ b/src/IF.Lastfm.Core/Api/Enums/LastStatsTimeSpan.cs @@ -29,4 +29,11 @@ public enum Gender Male, Female } + + public enum LastPageResultsType + { + None = 0, + Attr, + OpenQuery + } } \ No newline at end of file diff --git a/src/IF.Lastfm.Core/Api/Helpers/LastResponse.cs b/src/IF.Lastfm.Core/Api/Helpers/LastResponse.cs index 1ecf6f3..0a2eaf0 100644 --- a/src/IF.Lastfm.Core/Api/Helpers/LastResponse.cs +++ b/src/IF.Lastfm.Core/Api/Helpers/LastResponse.cs @@ -4,7 +4,14 @@ namespace IF.Lastfm.Core.Api.Helpers { - public class LastResponse + public interface ILastResponse + { + bool Success { get; set; } + + LastFmApiError Error { get; set; } + } + + public class LastResponse : ILastResponse { #region Properties diff --git a/src/IF.Lastfm.Core/Api/Helpers/PageResponse.cs b/src/IF.Lastfm.Core/Api/Helpers/PageResponse.cs index 5cda4f7..48f25ca 100644 --- a/src/IF.Lastfm.Core/Api/Helpers/PageResponse.cs +++ b/src/IF.Lastfm.Core/Api/Helpers/PageResponse.cs @@ -1,28 +1,48 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using IF.Lastfm.Core.Api.Enums; -using IF.Lastfm.Core.Objects; +using IF.Lastfm.Core.Json; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace IF.Lastfm.Core.Api.Helpers { - public class PageResponse : LastResponse, IEnumerable where T : new() + public interface IPageResponse : ILastResponse, IEnumerable where T : new() + { + IReadOnlyList Content { get; } + + int Page { get; } + + int PageSize { get; } + + int TotalPages { get; } + + int TotalItems { get; } + } + + [JsonConverter(typeof(PageResponseJsonConverter))] + public class PageResponse : LastResponse, IPageResponse where T : new() { private int? _totalItems; private int? _pageSize; - public PageResponse() + public PageResponse() : this(Enumerable.Empty()) + { + } + + public PageResponse(IEnumerable content) { Page = 1; TotalPages = 1; - Content = new List(); + Content = new ReadOnlyCollection(content.ToList()); } #region Properties - public List Content { get; internal set; } + public IReadOnlyList Content { get; internal set; } public int Page { get; internal set; } @@ -46,14 +66,9 @@ public int PageSize public IEnumerator GetEnumerator() { - if (Content != null) - { - return Content.GetEnumerator(); - } - else - { - return null; - } + return Content != null + ? Content.GetEnumerator() + : null; } IEnumerator IEnumerable.GetEnumerator() @@ -72,6 +87,20 @@ IEnumerator IEnumerable.GetEnumerator() #region Factory methods + public static PageResponse CreateErrorResponse(LastFmApiError error) + { + var r = new PageResponse + { + Success = false, + Error = error + }; + + r.AddDefaultPageInfo(); + + return r; + } + + public new static PageResponse CreateSuccessResponse() { var r = new PageResponse @@ -80,71 +109,86 @@ IEnumerator IEnumerable.GetEnumerator() Error = LastFmApiError.None }; + r.AddDefaultPageInfo(); + return r; } [Obsolete] public static PageResponse CreateSuccessResponse(IEnumerable content) { - var r = new PageResponse + var r = new PageResponse(content) { Success = true, Error = LastFmApiError.None }; - - r.Content.AddRange(content); - + return r; } - - public static PageResponse CreateSuccessResponse(JToken itemsToken, JToken pageInfoToken, Func parseToken, bool isOpenQueryToken = false) - { - var pageresponse = CreateSuccessResponse(); + public static PageResponse CreateSuccessResponse(JToken itemsToken, Func parseToken) + { + return CreateSuccessResponse(itemsToken, null, parseToken, LastPageResultsType.None); + } + + public static PageResponse CreateSuccessResponse(JToken itemsToken, JToken pageInfoToken, Func parseToken, LastPageResultsType pageResultsType) + { + IEnumerable items; if (itemsToken != null && itemsToken.Children().Any()) { // array notation isn't used on the api when only one object is available if (itemsToken.Type != JTokenType.Array) { var item = parseToken(itemsToken); - pageresponse.Content.Add(item); - } - else - { - var items = itemsToken.Children().Select(parseToken); - pageresponse.Content.AddRange(items); - } - } + items = new[] {item}; - if (pageInfoToken != null) - { - if (isOpenQueryToken) - { - pageresponse.AddPageInfoFromOpenQueryJToken(pageInfoToken); } else { - pageresponse.AddPageInfoFromJToken(pageInfoToken); + items = itemsToken.Children().Select(parseToken); } } else { - pageresponse.AddDefaultPageInfo(pageresponse.Content.Count); + items = Enumerable.Empty(); } + var pageresponse = new PageResponse(items); + + switch (pageResultsType) + { + case LastPageResultsType.Attr: + pageresponse.AddPageInfoFromJToken(pageInfoToken); + break; + case LastPageResultsType.OpenQuery: + pageresponse.AddPageInfoFromOpenQueryJToken(pageInfoToken); + break; + case LastPageResultsType.None: + default: + pageresponse.AddDefaultPageInfo(pageresponse.Content); + break; + } + + pageresponse.Success = true; + return pageresponse; } - private void AddDefaultPageInfo(int count) + #endregion + + private void AddDefaultPageInfo() + { + AddDefaultPageInfo(Enumerable.Empty().ToList()); + } + + private void AddDefaultPageInfo(IReadOnlyCollection items) { Page = 1; TotalPages = 1; - TotalItems = count; - PageSize = count; + TotalItems = items.Count; + PageSize = items.Count; } - #endregion - internal void AddPageInfoFromJToken(JToken attrToken) { if (attrToken == null) diff --git a/src/IF.Lastfm.Core/Api/IAlbumApi.cs b/src/IF.Lastfm.Core/Api/IAlbumApi.cs index 3fb173c..4e9cb43 100644 --- a/src/IF.Lastfm.Core/Api/IAlbumApi.cs +++ b/src/IF.Lastfm.Core/Api/IAlbumApi.cs @@ -12,12 +12,12 @@ public interface IAlbumApi Task> GetAlbumInfoByMbidAsync(string albumMbid, bool autocorrect = false); - Task> GetBuyLinksForAlbumAsync(string artist, - string album, - CountryCode country, - bool autocorrect = false); + //Task> GetBuyLinksForAlbumAsync(string artist, + // string album, + // CountryCode country, + // bool autocorrect = false); - Task> GetUserTagsForAlbumAsync(string artist, + Task> GetTagsByUserAsync(string artist, string album, string username, bool autocorrect = false); diff --git a/src/IF.Lastfm.Core/IF.Lastfm.Core.csproj b/src/IF.Lastfm.Core/IF.Lastfm.Core.csproj index 44e505d..5ecc184 100644 --- a/src/IF.Lastfm.Core/IF.Lastfm.Core.csproj +++ b/src/IF.Lastfm.Core/IF.Lastfm.Core.csproj @@ -41,7 +41,7 @@ - + @@ -99,6 +99,7 @@ + diff --git a/src/IF.Lastfm.Core/Json/LastFmBooleanConverter.cs b/src/IF.Lastfm.Core/Json/LastFmBooleanConverter.cs index ec2640a..01880f4 100644 --- a/src/IF.Lastfm.Core/Json/LastFmBooleanConverter.cs +++ b/src/IF.Lastfm.Core/Json/LastFmBooleanConverter.cs @@ -1,5 +1,6 @@ using System; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace IF.Lastfm.Core.Json { diff --git a/src/IF.Lastfm.Core/Json/PageResponseJsonConverter.cs b/src/IF.Lastfm.Core/Json/PageResponseJsonConverter.cs new file mode 100644 index 0000000..396c401 --- /dev/null +++ b/src/IF.Lastfm.Core/Json/PageResponseJsonConverter.cs @@ -0,0 +1,39 @@ +using System; +using IF.Lastfm.Core.Api.Helpers; +using Newtonsoft.Json; + +namespace IF.Lastfm.Core.Json +{ + public class PageResponseJsonConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var pageResponse = (IPageResponse) value; + + dynamic container = new + { + success = pageResponse.Success, + items = pageResponse.Content, + page = new + { + totalItems = pageResponse.TotalItems, + pageSize = pageResponse.PageSize, + page = pageResponse.Page, + totalPages = pageResponse.TotalPages + } + }; + + serializer.Serialize(writer, container); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return serializer.Deserialize(reader, objectType); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof (PageResponse<>); + } + } +} \ No newline at end of file