Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Harry 2014-12-24 11:58:15 -04:00
commit 39a17b4349
33 changed files with 2551 additions and 77 deletions

View File

@ -1,4 +1,4 @@
# Api Progress ![Progress](http://progressed.io/bar/21)
# Api Progress ![Progress](http://progressed.io/bar/22)
These are all the Last.fm API methods currently available.
@ -6,7 +6,7 @@ These are all the Last.fm API methods currently available.
- Methods ~~marked with strikethrough~~ aren't currently implemented. Pull requests are welcome!
- Methods _marked with an asterisk *_ aren't listed on [the Last.fm documentation](http://www.last.fm/api), so they might not work!
This list is generated by the [ProgressReport](https://github.com/inflatablefriends/lastfm/tree/master/src/IF.Lastfm.ProgressReport) tool in the solution. Last updated on 08 December 2014 10:51
This list is generated by the [ProgressReport](https://github.com/inflatablefriends/lastfm/tree/master/src/IF.Lastfm.ProgressReport) tool in the solution. Last updated on 22 December 2014 23:37
## Album
- [album.getInfo](http://www.last.fm/api/show/album.getInfo)
@ -89,12 +89,12 @@ This list is generated by the [ProgressReport](https://github.com/inflatablefrie
## Library
- [library.getTracks](http://www.last.fm/api/show/library.getTracks)
- ~~[library.addAlbum](http://www.last.fm/api/show/library.addAlbum)~~
- ~~[library.addArtist](http://www.last.fm/api/show/library.addArtist)~~
- ~~[library.addTrack](http://www.last.fm/api/show/library.addTrack)~~
- ~~[library.getAlbums](http://www.last.fm/api/show/library.getAlbums)~~
- ~~[library.getArtists](http://www.last.fm/api/show/library.getArtists)~~
- ~~[library.getTracks](http://www.last.fm/api/show/library.getTracks)~~
- ~~[library.removeAlbum](http://www.last.fm/api/show/library.removeAlbum)~~
- ~~[library.removeArtist](http://www.last.fm/api/show/library.removeArtist)~~
- ~~[library.removeScrobble](http://www.last.fm/api/show/library.removeScrobble)~~

View File

@ -40,7 +40,7 @@
- release
# don't forget to update this!
version: 0.1.2.{build}
version: 0.1.3.{build}
assembly_info:
patch: true

View File

@ -1,5 +1,10 @@
using IF.Lastfm.Core.Api;
using IF.Lastfm.Core.Api.Commands;
using IF.Lastfm.Core.Api.Helpers;
using IF.Lastfm.Core.Objects;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json;
using System.Net;
using System.Net.Http;
using System.Text;
@ -25,5 +30,35 @@ protected HttpResponseMessage CreateResponseMessage(string message)
return response;
}
private static void JsonCompare(object expected, object actual)
{
var expectedJson = JsonConvert.SerializeObject(expected, Formatting.Indented);
var actualJson = JsonConvert.SerializeObject(actual, Formatting.Indented);
Assert.AreEqual(expectedJson, actualJson, expectedJson.DifferencesTo(actualJson));
}
protected async Task CompareResultsSingle(GetAsyncCommandBase<PageResponse<LastTrack>> command, object expected, byte[] resource)
{
var response = CreateResponseMessage(Encoding.UTF8.GetString(resource));
var parsed = await command.HandleResponse(response);
Assert.IsTrue(parsed.Success);
var actual = parsed.Content;
JsonCompare(expected, actual);
}
protected async Task CompareResultsMultiple(GetAsyncCommandBase<PageResponse<LastTrack>> command, object expected, byte[] resource, int itemIndex)
{
var response = CreateResponseMessage(Encoding.UTF8.GetString(resource));
var parsed = await command.HandleResponse(response);
Assert.IsTrue(parsed.Success);
var actual = parsed.Content[itemIndex];
JsonCompare(expected, actual);
}
}
}

View File

@ -0,0 +1,87 @@
using IF.Lastfm.Core.Api.Commands.LibraryApi;
using IF.Lastfm.Core.Api.Enums;
using IF.Lastfm.Core.Objects;
using IF.Lastfm.Core.Tests.Resources;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace IF.Lastfm.Core.Tests.Api.Commands.Library
{
[TestClass]
public class LibraryGetTracksCommandTests : CommandTestsBase
{
private readonly LibraryGetTracksCommand _command;
public LibraryGetTracksCommandTests()
{
_command = new LibraryGetTracksCommand(MAuth.Object, "rj", "", "", DateTime.MinValue)
{
Count = 1
};
}
[TestMethod]
public async Task HandleResponseMultiple()
{
//Testing the second track returned
var expectedTrack = new LastTrack
{
ArtistName = "Stevie Wonder",
Duration = new TimeSpan(0, 4, 8),
TotalPlayCount = 56,
Mbid = "0161855d-0b98-4f2d-b2ab-446dbd8d6759",
Name = "Superstition",
ArtistMbid = "1ee18fb3-18a6-4c7f-8ba0-bc41cdd0462e",
AlbumName = "Number Ones",
Url = new Uri("http://www.last.fm/music/Stevie+Wonder/_/Superstition", UriKind.Absolute),
Images = new LastImageSet(
"http://userserve-ak.last.fm/serve/34s/99695819.jpg",
"http://userserve-ak.last.fm/serve/64s/99695819.jpg",
"http://userserve-ak.last.fm/serve/126/99695819.jpg",
"http://userserve-ak.last.fm/serve/300x300/99695819.jpg")
};
await CompareResultsMultiple(_command, expectedTrack, LibraryApiResponses.LibraryGetTracksMultiple, 1);
}
[TestMethod]
public async Task HandleResponseSingle()
{
var expectedTrack = new LastTrack
{
ArtistName = "Dire Straits",
Duration = new TimeSpan(0, 5, 47),
TotalPlayCount = 81,
Mbid = "0317e524-7f70-4910-bc12-95dd468a29fc",
Name = "Sultans of Swing",
ArtistMbid = "614e3804-7d34-41ba-857f-811bad7c2b7a",
AlbumName = "Dire Straits (Remastered)",
Url = new Uri("http://www.last.fm/music/Dire+Straits/_/Sultans+of+Swing", UriKind.Absolute),
Images = new LastImageSet(
"http://userserve-ak.last.fm/serve/34s/56827829.jpg",
"http://userserve-ak.last.fm/serve/64s/56827829.jpg",
"http://userserve-ak.last.fm/serve/126/56827829.jpg",
"http://userserve-ak.last.fm/serve/300x300/56827829.jpg")
};
var expected = new List<LastTrack> { expectedTrack };
await CompareResultsSingle(_command, expected, LibraryApiResponses.LibraryGetTracksSingle);
}
[TestMethod]
public async Task HandleErrorResponse()
{
var response = CreateResponseMessage(Encoding.UTF8.GetString(AlbumApiResponses.AlbumGetInfoMissing));
var parsed = await _command.HandleResponse(response);
Assert.IsFalse(parsed.Success);
Assert.IsTrue(parsed.Error == LastFmApiError.MissingParameters);
}
}
}

View File

@ -0,0 +1,84 @@
using IF.Lastfm.Core.Api.Commands.UserApi;
using IF.Lastfm.Core.Api.Enums;
using IF.Lastfm.Core.Objects;
using IF.Lastfm.Core.Tests.Resources;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace IF.Lastfm.Core.Tests.Api.Commands.UserApi
{
[TestClass]
public class UserGetRecentTracksCommandTests : CommandTestsBase
{
private UserGetRecentTracksCommand _command;
public UserGetRecentTracksCommandTests()
{
_command = new UserGetRecentTracksCommand(MAuth.Object, "rj", DateTime.MinValue)
{
Count = 1
};
}
[TestMethod]
public async Task HandleResponseMultiple()
{
var expectedTrack = new LastTrack
{
ArtistName = "The Who",
TimePlayed = new DateTime(2014, 12, 19, 16, 13, 55,DateTimeKind.Utc),
Mbid = "79f3dc97-2297-47ee-8556-9a1bb4b48d53",
Name = "Pinball Wizard",
ArtistMbid = "9fdaa16b-a6c4-4831-b87c-bc9ca8ce7eaa",
AlbumName = "Tommy (Remastered)",
Url = new Uri("http://www.last.fm/music/The+Who/_/Pinball+Wizard", UriKind.Absolute),
Images = new LastImageSet(
"http://userserve-ak.last.fm/serve/34s/35234991.jpg",
"http://userserve-ak.last.fm/serve/64s/35234991.jpg",
"http://userserve-ak.last.fm/serve/126/35234991.jpg",
"http://userserve-ak.last.fm/serve/300x300/35234991.jpg")
};
await CompareResultsMultiple(_command, expectedTrack, UserApiResponses.UserGetRecentTracksMultiple, 2);
}
[TestMethod]
public async Task HandleResponseSingle()
{
var expectedTrack = new LastTrack
{
ArtistName = "Rick James",
Mbid = "",
Name = "Super Freak (Part 1) - 1981 Single Version",
ArtistMbid = "cba9cec2-be8d-41bd-91b4-a1cd7de39b0c",
TimePlayed = new DateTime(2014,12,20,10,16,52, DateTimeKind.Utc),
AlbumName = "The Definitive Collection",
Url = new Uri("http://www.last.fm/music/Rick+James/_/Super+Freak+(Part+1)+-+1981+Single+Version", UriKind.Absolute),
Images = new LastImageSet(
"http://userserve-ak.last.fm/serve/34s/90462319.jpg",
"http://userserve-ak.last.fm/serve/64s/90462319.jpg",
"http://userserve-ak.last.fm/serve/126/90462319.jpg",
"http://userserve-ak.last.fm/serve/300x300/90462319.jpg")
};
var expected = new List<LastTrack> { expectedTrack };
await CompareResultsSingle(_command, expected, UserApiResponses.UserGetRecentTracksSingle);
}
[TestMethod]
public async Task HandleErrorResponse()
{
var response = CreateResponseMessage(Encoding.UTF8.GetString(UserApiResponses.UserGetRecentTracksError));
var parsed = await _command.HandleResponse(response);
Assert.IsFalse(parsed.Success);
Assert.IsTrue(parsed.Error == LastFmApiError.MissingParameters);
}
}
}

View File

@ -79,7 +79,9 @@
<Compile Include="Api\Commands\AlbumApi\GetAlbumTopTagsCommandTest.cs" />
<Compile Include="Api\Commands\AlbumApi\SearchAlbumsCommandTests.cs" />
<Compile Include="Api\Commands\CommandTestsBase.cs" />
<Compile Include="Api\Commands\Library\LibraryGetTracksCommandTests.cs" />
<Compile Include="Api\Commands\TrackApi\GetTrackShoutsCommandTests.cs" />
<Compile Include="Api\Commands\UserApi\UserGetRecentTracksCommandTests.cs" />
<Compile Include="Api\Commands\UserApi\GetTrackShoutsCommandTests.cs" />
<Compile Include="Api\Helpers\ApiHelperTests.cs" />
<Compile Include="Api\MockAlbumApi.cs" />
@ -91,11 +93,21 @@
<DesignTime>True</DesignTime>
<DependentUpon>AlbumApiResponses.resx</DependentUpon>
</Compile>
<Compile Include="Resources\LibraryApiResponses.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>LibraryApiResponses.resx</DependentUpon>
</Compile>
<Compile Include="Resources\TrackApiResponses.Designer.cs">
<DependentUpon>TrackApiResponses.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
<Compile Include="Resources\UserApiResponses.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>UserApiResponses.resx</DependentUpon>
</Compile>
<Compile Include="TestHelper.cs" />
</ItemGroup>
<ItemGroup>
@ -116,10 +128,17 @@
<None Include="Resources\AlbumApi\AlbumSearchError.json" />
<None Include="Resources\AlbumApi\AlbumSearchSingle.json" />
<None Include="Resources\AlbumApi\AlbumGetTopTags.json" />
<None Include="Resources\LibraryApi\LibraryGetTracksMultiple.json" />
<None Include="Resources\LibraryApi\LibraryGetTracksSingle.json" />
<None Include="Resources\TrackApi\TrackGetShouts.json" />
<None Include="Resources\TrackApi\TrackGetShoutsEmpty.json" />
<None Include="Resources\TrackApi\TrackGetShoutsError.json" />
<None Include="Resources\TrackApi\TrackGetShoutsSingle.json" />
<None Include="Resources\UserApi\UserGetRecentTracksEmpty.json" />
<None Include="Resources\UserApi\UserGetRecentTracksError.json" />
<None Include="Resources\UserApi\UserGetRecentTracksMissing.json" />
<None Include="Resources\UserApi\UserGetRecentTracksMultiple.json" />
<None Include="Resources\UserApi\UserGetRecentTracksSingle.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IF.Lastfm.Core\IF.Lastfm.Core.csproj">
@ -133,10 +152,19 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>AlbumApiResponses.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Resources\LibraryApiResponses.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>LibraryApiResponses.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Resources\TrackApiResponses.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>TrackApiResponses.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Resources\UserApiResponses.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>UserApiResponses.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">

View File

@ -0,0 +1,46 @@
using System;
using IF.Lastfm.Core.Objects;
using Newtonsoft.Json.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using IF.Lastfm.Core.Tests.Resources;
using System.Threading.Tasks;
using System.Text;
using System.Collections.Generic;
namespace IF.Lastfm.Core.Tests.Objects
{
[TestClass]
public class LastTrackTests : ObjectsTestsBase
{
[TestMethod]
public async Task TestMethod1()
{
// var json = await response.Content.ReadAsStringAsync();
var response = CreateResponseMessage(Encoding.UTF8.GetString(LibraryApiResponses.LibraryGetTracksMultiple));
var json = await response.Content.ReadAsStringAsync();
JToken jtoken = JsonConvert.DeserializeObject<JToken>(json).SelectToken("tracks");
var tracksToken = jtoken.SelectToken("track");
var tracks = new List<LastTrack>();
foreach (var track in tracksToken.Children())
{
var t = LastTrack.ParseJToken(track);
tracks.Add(t);
}
Assert.AreEqual(tracks.Count, 20);
// var actual = parsed.Content;
//var token = JsonConvert.DeserializeObject<JToken>(json);//.SelectToken("shouts"); ;
//LastTrack.ParseJToken(jtoken);
}
}
}

View File

@ -0,0 +1,24 @@
using IF.Lastfm.Core.Api;
using Moq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace IF.Lastfm.Core.Tests.Objects
{
public abstract class ObjectsTestsBase
{
protected HttpResponseMessage CreateResponseMessage(string message)
{
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(message, Encoding.UTF8)
};
return response;
}
}
}

View File

@ -0,0 +1,793 @@
{
"tracks": {
"track": [
{
"name": "Sultans of Swing",
"duration": "347000",
"playcount": "81",
"tagcount": "0",
"mbid": "0317e524-7f70-4910-bc12-95dd468a29fc",
"url": "http://www.last.fm/music/Dire+Straits/_/Sultans+of+Swing",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dire Straits",
"mbid": "614e3804-7d34-41ba-857f-811bad7c2b7a",
"url": "http://www.last.fm/music/Dire+Straits"
},
"album": {
"name": "Dire Straits (Remastered)",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/56827829.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/56827829.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/56827829.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/56827829.jpg",
"size": "extralarge"
}
]
},
{
"name": "Superstition",
"duration": "248000",
"playcount": "56",
"tagcount": "0",
"mbid": "0161855d-0b98-4f2d-b2ab-446dbd8d6759",
"url": "http://www.last.fm/music/Stevie+Wonder/_/Superstition",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Stevie Wonder",
"mbid": "1ee18fb3-18a6-4c7f-8ba0-bc41cdd0462e",
"url": "http://www.last.fm/music/Stevie+Wonder"
},
"album": {
"name": "Number Ones",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/99695819.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/99695819.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/99695819.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/99695819.jpg",
"size": "extralarge"
}
]
},
{
"name": "Pull Me Under",
"duration": "494000",
"playcount": "56",
"tagcount": "0",
"mbid": "4b2c1184-8d48-4dfa-84c4-f26e9729a626",
"url": "http://www.last.fm/music/Dream+Theater/_/Pull+Me+Under",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dream Theater",
"mbid": "28503ab7-8bf2-4666-a7bd-2644bfc7cb1d",
"url": "http://www.last.fm/music/Dream+Theater"
},
"album": {
"name": "Images and Words",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/42406513.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/42406513.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/42406513.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/42406513.png",
"size": "extralarge"
}
]
},
{
"name": "The Pusher",
"duration": "349000",
"playcount": "55",
"tagcount": "1",
"mbid": "a1deb801-caea-4b66-9d35-537cb42c03b6",
"url": "http://www.last.fm/music/Steppenwolf/_/The+Pusher",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Steppenwolf",
"mbid": "12ff8858-bfcb-4812-a8dd-7e9debf0cbee",
"url": "http://www.last.fm/music/Steppenwolf"
},
"album": {
"name": "16 Greatest Hits",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/84527157.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/84527157.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/84527157.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/84527157.jpg",
"size": "extralarge"
}
]
},
{
"name": "Take the Time",
"duration": "501000",
"playcount": "54",
"tagcount": "0",
"mbid": "55f96185-3de8-40d2-98dd-0f54846e1951",
"url": "http://www.last.fm/music/Dream+Theater/_/Take+the+Time",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dream Theater",
"mbid": "28503ab7-8bf2-4666-a7bd-2644bfc7cb1d",
"url": "http://www.last.fm/music/Dream+Theater"
},
"album": {
"name": "Images and Words",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/42406513.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/42406513.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/42406513.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/42406513.png",
"size": "extralarge"
}
]
},
{
"name": "Another Day",
"duration": "263000",
"playcount": "54",
"tagcount": "0",
"mbid": "33f634b9-588c-49fd-83af-b1b1219b4db0",
"url": "http://www.last.fm/music/Dream+Theater/_/Another+Day",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dream Theater",
"mbid": "28503ab7-8bf2-4666-a7bd-2644bfc7cb1d",
"url": "http://www.last.fm/music/Dream+Theater"
},
"album": {
"name": "Images and Words",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/42406513.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/42406513.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/42406513.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/42406513.png",
"size": "extralarge"
}
]
},
{
"name": "Learning to Live",
"duration": "690000",
"playcount": "54",
"tagcount": "0",
"mbid": "7aa216d0-94dc-48d2-bb3c-7116843b8bf3",
"url": "http://www.last.fm/music/Dream+Theater/_/Learning+to+Live",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dream Theater",
"mbid": "28503ab7-8bf2-4666-a7bd-2644bfc7cb1d",
"url": "http://www.last.fm/music/Dream+Theater"
},
"album": {
"name": "Images and Words",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/42406513.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/42406513.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/42406513.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/42406513.png",
"size": "extralarge"
}
]
},
{
"name": "Three Minute Warning",
"duration": "1716000",
"playcount": "54",
"tagcount": "0",
"mbid": "b4ad3a39-5fd1-4021-b80d-e71eb8b2e20f",
"url": "http://www.last.fm/music/Liquid+Tension+Experiment/_/Three+Minute+Warning",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Liquid Tension Experiment",
"mbid": "bc641be9-ca36-4c61-9394-5230433f6646",
"url": "http://www.last.fm/music/Liquid+Tension+Experiment"
},
"album": {
"name": "Liquid Tension Experiment",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/88566859.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/88566859.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/88566859.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/88566859.jpg",
"size": "extralarge"
}
]
},
{
"name": "Cowboys",
"duration": "279000",
"playcount": "53",
"tagcount": "0",
"mbid": "eca7d591-1fd9-4cea-9cbe-0f31f474041d",
"url": "http://www.last.fm/music/Portishead/_/Cowboys",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Portishead",
"mbid": "17e0ef75-fae9-4fa3-b6f6-39a8c986d686",
"url": "http://www.last.fm/music/Portishead"
},
"album": {
"name": "Portishead",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/66825870.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/66825870.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/66825870.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/66825870.png",
"size": "extralarge"
}
]
},
{
"name": "Under a Glass Moon",
"duration": "423000",
"playcount": "47",
"tagcount": "0",
"mbid": "b0f7db49-8397-42c5-8e63-cb3b6f92b825",
"url": "http://www.last.fm/music/Dream+Theater/_/Under+a+Glass+Moon",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dream Theater",
"mbid": "28503ab7-8bf2-4666-a7bd-2644bfc7cb1d",
"url": "http://www.last.fm/music/Dream+Theater"
},
"album": {
"name": "Images and Words",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/42406513.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/42406513.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/42406513.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/42406513.png",
"size": "extralarge"
}
]
},
{
"name": "Money for Nothing",
"duration": "503000",
"playcount": "46",
"tagcount": "0",
"mbid": "06622908-5da7-4bb9-9b6b-53bc8dc039ee",
"url": "http://www.last.fm/music/Dire+Straits/_/Money+for+Nothing",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dire Straits",
"mbid": "614e3804-7d34-41ba-857f-811bad7c2b7a",
"url": "http://www.last.fm/music/Dire+Straits"
},
"album": {
"name": "Brothers In Arms - 20th Anniversary Edition",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/8801435.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/8801435.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/8801435.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/8801435.jpg",
"size": "extralarge"
}
]
},
{
"name": "Steamroller",
"duration": "177000",
"playcount": "44",
"tagcount": "0",
"mbid": "47cd0ce0-ff26-4bb0-adea-3b049f2321fd",
"url": "http://www.last.fm/music/James+Taylor/_/Steamroller",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "James Taylor",
"mbid": "0217fabf-0e84-4c36-b197-f1b6e1263506",
"url": "http://www.last.fm/music/James+Taylor"
},
"album": {
"name": "Greatest Hits",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/87576587.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/87576587.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/87576587.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/87576587.jpg",
"size": "extralarge"
}
]
},
{
"name": "Fire and Rain",
"duration": "272000",
"playcount": "43",
"tagcount": "0",
"mbid": "6d8b6dc1-0aff-4e72-a180-0839af79e8c1",
"url": "http://www.last.fm/music/James+Taylor/_/Fire+and+Rain",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "James Taylor",
"mbid": "0217fabf-0e84-4c36-b197-f1b6e1263506",
"url": "http://www.last.fm/music/James+Taylor"
},
"album": {
"name": "Sweet Baby James",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/69242572.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/69242572.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/69242572.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/69242572.png",
"size": "extralarge"
}
]
},
{
"name": "Gin And Juice",
"duration": "211000",
"playcount": "43",
"tagcount": "0",
"mbid": "1e9cc395-2fb9-45f2-8ac5-05cefa9668f1",
"url": "http://www.last.fm/music/Snoop+Dogg/_/Gin+And+Juice",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Snoop Dogg",
"mbid": "17d17695-f0e1-46fd-815f-bf577cc5f50d",
"url": "http://www.last.fm/music/Snoop+Dogg"
},
"album": {
"name": "Doggystyle",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/100162457.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/100162457.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/100162457.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/100162457.png",
"size": "extralarge"
}
]
},
{
"name": "Wait for Sleep",
"duration": "153000",
"playcount": "43",
"tagcount": "0",
"mbid": "8ec3f9d2-945f-43bb-9ef2-63b6cbbe2653",
"url": "http://www.last.fm/music/Dream+Theater/_/Wait+for+Sleep",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dream Theater",
"mbid": "28503ab7-8bf2-4666-a7bd-2644bfc7cb1d",
"url": "http://www.last.fm/music/Dream+Theater"
},
"album": {
"name": "Images and Words",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/42406513.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/42406513.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/42406513.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/42406513.png",
"size": "extralarge"
}
]
},
{
"name": "I Wish You Were Here",
"duration": "268000",
"playcount": "42",
"tagcount": "0",
"mbid": "890b1c78-6f6c-4917-a627-48e7f44c2568",
"url": "http://www.last.fm/music/Alpha+Blondy/_/I+Wish+You+Were+Here",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Alpha Blondy",
"mbid": "3906105b-189a-444e-b34a-e6dc5aa2c2e4",
"url": "http://www.last.fm/music/Alpha+Blondy"
},
"album": {
"name": "Jah Victory",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/93692707.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/93692707.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/93692707.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/93692707.jpg",
"size": "extralarge"
}
]
},
{
"name": "Walk of Life",
"duration": "249000",
"playcount": "40",
"tagcount": "0",
"mbid": "0ed233bf-41c0-4b0c-b330-32d7444eab2a",
"url": "http://www.last.fm/music/Dire+Straits/_/Walk+of+Life",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dire Straits",
"mbid": "614e3804-7d34-41ba-857f-811bad7c2b7a",
"url": "http://www.last.fm/music/Dire+Straits"
},
"album": {
"name": "Brothers In Arms - 20th Anniversary Edition",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/8801435.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/8801435.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/8801435.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/8801435.jpg",
"size": "extralarge"
}
]
},
{
"name": "You've Got a Friend",
"duration": "307000",
"playcount": "39",
"tagcount": "0",
"mbid": "2e3a3cb0-5e5a-415b-89cd-dc0ae74c91be",
"url": "http://www.last.fm/music/James+Taylor/_/You%27ve+Got+a+Friend",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "James Taylor",
"mbid": "0217fabf-0e84-4c36-b197-f1b6e1263506",
"url": "http://www.last.fm/music/James+Taylor"
},
"album": {
"name": "Mud Slide Slim and the Blue Horizon",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/83767473.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/83767473.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/83767473.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/83767473.png",
"size": "extralarge"
}
]
},
{
"name": "Telegraph Road",
"duration": "860000",
"playcount": "39",
"tagcount": "0",
"mbid": "f134485c-bf29-494c-888a-d4467d152609",
"url": "http://www.last.fm/music/Dire+Straits/_/Telegraph+Road",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dire Straits",
"mbid": "614e3804-7d34-41ba-857f-811bad7c2b7a",
"url": "http://www.last.fm/music/Dire+Straits"
},
"album": {
"name": "The Best of Dire Straits & Mark Knopfler - Private Investigations",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/98006973.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/98006973.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/98006973.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/98006973.jpg",
"size": "extralarge"
}
]
},
{
"name": "Midas Touch",
"duration": "234000",
"playcount": "39",
"tagcount": "0",
"mbid": "0128cb40-46b0-45c4-b451-a2d661f19732",
"url": "http://www.last.fm/music/Midnight+Star/_/Midas+Touch",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Midnight Star",
"mbid": "3d30a740-e36b-45b9-a395-a3b3696d1d7c",
"url": "http://www.last.fm/music/Midnight+Star"
},
"album": {
"name": "Soul Hits Of The 80's",
"position": ""
},
"image": [
{
"#text": "http://cdn.last.fm/flatness/catalogue/noimage/2/default_album_medium.png",
"size": "small"
},
{
"#text": "http://cdn.last.fm/flatness/catalogue/noimage/2/default_album_medium.png",
"size": "medium"
},
{
"#text": "http://cdn.last.fm/flatness/catalogue/noimage/2/default_album_medium.png",
"size": "large"
},
{
"#text": "http://cdn.last.fm/flatness/catalogue/noimage/2/default_album_medium.png",
"size": "extralarge"
}
]
}
],
"@attr": {
"user": "RJ",
"page": "0",
"perPage": "20",
"totalPages": "1949",
"total": "38966"
}
}
}

View File

@ -0,0 +1,50 @@
{
"tracks": {
"track": {
"name": "Sultans of Swing",
"duration": "347000",
"playcount": "81",
"tagcount": "0",
"mbid": "0317e524-7f70-4910-bc12-95dd468a29fc",
"url": "http://www.last.fm/music/Dire+Straits/_/Sultans+of+Swing",
"streamable": {
"#text": "0",
"fulltrack": "0"
},
"artist": {
"name": "Dire Straits",
"mbid": "614e3804-7d34-41ba-857f-811bad7c2b7a",
"url": "http://www.last.fm/music/Dire+Straits"
},
"album": {
"name": "Dire Straits (Remastered)",
"position": ""
},
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/56827829.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/56827829.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/56827829.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/56827829.jpg",
"size": "extralarge"
}
]
},
"@attr": {
"user": "RJ",
"page": "0",
"perPage": "1",
"totalPages": "38949",
"total": "38949"
}
}
}

View File

@ -0,0 +1,83 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace IF.Lastfm.Core.Tests.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class LibraryApiResponses {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal LibraryApiResponses() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("IF.Lastfm.Core.Tests.Resources.LibraryApiResponses", typeof(LibraryApiResponses).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] LibraryGetTracksMultiple {
get {
object obj = ResourceManager.GetObject("LibraryGetTracksMultiple", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] LibraryGetTracksSingle {
get {
object obj = ResourceManager.GetObject("LibraryGetTracksSingle", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="LibraryGetTracksMultiple" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>libraryapi\librarygettracksmultiple.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="LibraryGetTracksSingle" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>libraryapi\librarygettrackssingle.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@ -0,0 +1,10 @@
{
"recenttracks": {
"#text": "\n",
"user": "RT",
"page": "0",
"perPage": "20",
"totalPages": "0",
"total": "0"
}
}

View File

@ -0,0 +1,5 @@
{
"error": 6,
"message": "Invalid parameters - Your request is missing the [user] parameter",
"links": []
}

View File

@ -0,0 +1,5 @@
{
"error": 6,
"message": "No user with that name was found",
"links": []
}

View File

@ -0,0 +1,733 @@
{
"recenttracks": {
"track": [
{
"artist": {
"#text": "Santana",
"mbid": "1bc6816a-d056-4113-9b0a-6c52e5c31a3c"
},
"name": "No One to Depend On",
"streamable": "0",
"mbid": "3f8ed8da-dcc6-43dc-8266-3663007261a6",
"album": {
"#text": "Santana (III)",
"mbid": ""
},
"url": "http://www.last.fm/music/Santana/_/No+One+to+Depend+On",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/99461493.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/99461493.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/99461493.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/99461493.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 16:21",
"uts": "1419006075"
}
},
{
"artist": {
"#text": "The Rolling Stones",
"mbid": "b071f9fa-14b0-4217-8e97-eb41da73f598"
},
"name": "Love in Vain",
"streamable": "0",
"mbid": "3dde65c8-22c3-4637-b67e-b234177c847b",
"album": {
"#text": "Let It Bleed",
"mbid": "8bc2f5e2-122a-42db-b86c-fddedc77463a"
},
"url": "http://www.last.fm/music/The+Rolling+Stones/_/Love+in+Vain",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/101739037.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/101739037.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/101739037.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/101739037.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 16:16",
"uts": "1419005816"
}
},
{
"artist": {
"#text": "The Who",
"mbid": "9fdaa16b-a6c4-4831-b87c-bc9ca8ce7eaa"
},
"name": "Pinball Wizard",
"streamable": "0",
"mbid": "79f3dc97-2297-47ee-8556-9a1bb4b48d53",
"album": {
"#text": "Tommy (Remastered)",
"mbid": ""
},
"url": "http://www.last.fm/music/The+Who/_/Pinball+Wizard",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/35234991.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/35234991.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/35234991.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/35234991.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 16:13",
"uts": "1419005635"
}
},
{
"artist": {
"#text": "Cream",
"mbid": "04cd0cfd-bfd1-4c36-bc38-95c35e2c045f"
},
"name": "I'm So Glad",
"streamable": "0",
"mbid": "3dc91be5-c7ab-4af3-9557-19eb8e054d5a",
"album": {
"#text": "Fresh Cream (Remastered)",
"mbid": ""
},
"url": "http://www.last.fm/music/Cream/_/I%27m+So+Glad",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/89387215.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/89387215.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/89387215.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/89387215.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 16:09",
"uts": "1419005395"
}
},
{
"artist": {
"#text": "The Yardbirds",
"mbid": "191de76f-a224-445d-b041-54df16d65bf7"
},
"name": "Smokestack Lightning",
"streamable": "0",
"mbid": "580b35c9-b701-43d7-9ec3-6bd6f01534c2",
"album": {
"#text": "Five Live Yardbirds",
"mbid": "3fda56ac-efe1-4a26-9c86-116f5cc4b721"
},
"url": "http://www.last.fm/music/The+Yardbirds/_/Smokestack+Lightning",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/91925037.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/91925037.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/91925037.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/91925037.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 16:04",
"uts": "1419005063"
}
},
{
"artist": {
"#text": "Canned Heat",
"mbid": "815a0279-558c-4522-ac3b-6a1e259e95b5"
},
"name": "One Kind Favor",
"streamable": "0",
"mbid": "5bde419b-9e93-46c6-baf5-ef58a0b3bb73",
"album": {
"#text": "Living The Blues",
"mbid": "ec82ab15-8c01-4aa0-810c-d184d20f229b"
},
"url": "http://www.last.fm/music/Canned+Heat/_/One+Kind+Favor",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/100370719.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/100370719.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/100370719.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/100370719.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:59",
"uts": "1419004779"
}
},
{
"artist": {
"#text": "Cream",
"mbid": "04cd0cfd-bfd1-4c36-bc38-95c35e2c045f"
},
"name": "Politician",
"streamable": "0",
"mbid": "f2c2760c-ea5c-4ca0-8a8b-4199a41ffba0",
"album": {
"#text": "Wheels of Fire (Remastered)",
"mbid": ""
},
"url": "http://www.last.fm/music/Cream/_/Politician",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/75021714.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/75021714.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/75021714.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/75021714.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:55",
"uts": "1419004522"
}
},
{
"artist": {
"#text": "The Doors",
"mbid": "9efff43b-3b29-4082-824e-bc82f646f93d"
},
"name": "Light My Fire",
"streamable": "0",
"mbid": "05b7cd66-a700-4aa1-baf3-e1e41388f3cf",
"album": {
"#text": "The Doors",
"mbid": "8f3cf206-35f6-3c77-925e-766bdfbf6333"
},
"url": "http://www.last.fm/music/The+Doors/_/Light+My+Fire",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/88289473.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/88289473.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/88289473.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/88289473.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:48",
"uts": "1419004096"
}
},
{
"artist": {
"#text": "Full Metal Hammer",
"mbid": ""
},
"name": "Since Ive Been Loving You",
"streamable": "0",
"mbid": "",
"album": {
"#text": "It's A Full Metal Hammer Thing",
"mbid": ""
},
"url": "http://www.last.fm/music/Full+Metal+Hammer/_/Since+Ive+Been+Loving+You",
"image": [
{
"#text": "",
"size": "small"
},
{
"#text": "",
"size": "medium"
},
{
"#text": "",
"size": "large"
},
{
"#text": "",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:41",
"uts": "1419003662"
}
},
{
"artist": {
"#text": "The Jimi Hendrix Experience",
"mbid": "33b3c323-77c2-417c-a5b4-af7e6a111cc9"
},
"name": "Burning Of The Midnight Lamp",
"streamable": "0",
"mbid": "1a1c8a21-351d-4c43-8ed4-3fd3f5058e1b",
"album": {
"#text": "Electric Ladyland",
"mbid": "9fa7f446-b15c-3ad9-a4cc-3348e9140319"
},
"url": "http://www.last.fm/music/The+Jimi+Hendrix+Experience/_/Burning+Of+The+Midnight+Lamp",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/96516997.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/96516997.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/96516997.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/96516997.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:37",
"uts": "1419003443"
}
},
{
"artist": {
"#text": "Otis Rush",
"mbid": "40ee7c92-f44a-4d14-9aee-f87244465ee4"
},
"name": "Double Trouble",
"streamable": "0",
"mbid": "f23c009e-19c4-4196-8fe2-236c28546bfc",
"album": {
"#text": "Live At Montreux 1986",
"mbid": ""
},
"url": "http://www.last.fm/music/Otis+Rush/_/Double+Trouble",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/91112769.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/91112769.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/91112769.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/91112769.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:32",
"uts": "1419003132"
}
},
{
"artist": {
"#text": "The Yardbirds",
"mbid": "191de76f-a224-445d-b041-54df16d65bf7"
},
"name": "I Don't Care No More",
"streamable": "0",
"mbid": "30e22d26-15f7-4547-a0f4-b08feed1a7fc",
"album": {
"#text": "Rock Classics: Parable Of Arable Land",
"mbid": ""
},
"url": "http://www.last.fm/music/The+Yardbirds/_/I+Don%27t+Care+No+More",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/54760139.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/54760139.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/54760139.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/174s/54760139.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:28",
"uts": "1419002911"
}
},
{
"artist": {
"#text": "The Doors",
"mbid": "9efff43b-3b29-4082-824e-bc82f646f93d"
},
"name": "Crawling King Snake",
"streamable": "0",
"mbid": "a08905e0-dc59-47fe-ae93-be5bb0d22a84",
"album": {
"#text": "L.A. Woman",
"mbid": "492025d7-a5fd-40f0-94f9-8841e9078bb3"
},
"url": "http://www.last.fm/music/The+Doors/_/Crawling+King+Snake",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/88488175.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/88488175.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/88488175.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/88488175.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:23",
"uts": "1419002612"
}
},
{
"artist": {
"#text": "Jimmy Page",
"mbid": "519774a4-3b18-4042-b8c0-927845a616c9"
},
"name": "Prison Blues",
"streamable": "0",
"mbid": "f78a2ce9-3dba-439c-9e05-0783ccfa40c3",
"album": {
"#text": "Outrider",
"mbid": "a53095c1-a6ea-4bc9-a14c-6ecafeef738e"
},
"url": "http://www.last.fm/music/Jimmy+Page/_/Prison+Blues",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/90138723.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/90138723.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/90138723.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/90138723.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:16",
"uts": "1419002181"
}
},
{
"artist": {
"#text": "Cream",
"mbid": "04cd0cfd-bfd1-4c36-bc38-95c35e2c045f"
},
"name": "Spoonful",
"streamable": "0",
"mbid": "f6f5d7f0-b368-45c0-8505-4b33ac696035",
"album": {
"#text": "Fresh Cream (Remastered)",
"mbid": ""
},
"url": "http://www.last.fm/music/Cream/_/Spoonful",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/89387215.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/89387215.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/89387215.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/89387215.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:09",
"uts": "1419001787"
}
},
{
"artist": {
"#text": "The Doors",
"mbid": "9efff43b-3b29-4082-824e-bc82f646f93d"
},
"name": "Back Door Man",
"streamable": "0",
"mbid": "1976f693-f35f-4534-b341-31d51f46b208",
"album": {
"#text": "The Doors",
"mbid": "8f3cf206-35f6-3c77-925e-766bdfbf6333"
},
"url": "http://www.last.fm/music/The+Doors/_/Back+Door+Man",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/88289473.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/88289473.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/88289473.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/88289473.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:06",
"uts": "1419001574"
}
},
{
"artist": {
"#text": "The Yardbirds",
"mbid": "191de76f-a224-445d-b041-54df16d65bf7"
},
"name": "I Ain't Got You",
"streamable": "0",
"mbid": "19ee6ab9-1716-41e1-8aa7-cada544f5695",
"album": {
"#text": "Five Live",
"mbid": ""
},
"url": "http://www.last.fm/music/The+Yardbirds/_/I+Ain%27t+Got+You",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/87032633.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/87032633.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/87032633.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/87032633.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:04",
"uts": "1419001453"
}
},
{
"artist": {
"#text": "The Who",
"mbid": "9fdaa16b-a6c4-4831-b87c-bc9ca8ce7eaa"
},
"name": "Substitute (Remixed Live At Leeds Version)",
"streamable": "0",
"mbid": "",
"album": {
"#text": "Live At Leeds (25th Anniversary Edition)",
"mbid": ""
},
"url": "http://www.last.fm/music/The+Who/_/Substitute+(Remixed+Live+At+Leeds+Version)",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/82286267.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/82286267.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/82286267.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/82286267.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 15:01",
"uts": "1419001281"
}
},
{
"artist": {
"#text": "Cream",
"mbid": "04cd0cfd-bfd1-4c36-bc38-95c35e2c045f"
},
"name": "Tales of Brave Ulysses",
"streamable": "0",
"mbid": "f5e62507-07f1-45eb-83c6-6742d5260d06",
"album": {
"#text": "Disraeli Gears (Remastered)",
"mbid": ""
},
"url": "http://www.last.fm/music/Cream/_/Tales+of+Brave+Ulysses",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/57500153.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/57500153.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/57500153.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/57500153.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 14:58",
"uts": "1419001115"
}
},
{
"artist": {
"#text": "Jimi Hendrix",
"mbid": "06fb1c8b-566e-4cb2-985b-b467c90781d4"
},
"name": "Johnny B. Goode (Live Berkeley Community Center, Berkeley, CA May 30, 1970)",
"streamable": "0",
"mbid": "",
"album": {
"#text": "In The West",
"mbid": ""
},
"url": "http://www.last.fm/music/Jimi+Hendrix/_/Johnny+B.+Goode+(Live+Berkeley+Community+Center,+Berkeley,+CA+May+30,+1970)",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/78579114.png",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/78579114.png",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/78579114.png",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/78579114.png",
"size": "extralarge"
}
],
"date": {
"#text": "19 Dec 2014, 14:53",
"uts": "1419000831"
}
}
],
"@attr": {
"user": "RJ",
"page": "0",
"perPage": "20",
"totalPages": "3827",
"total": "76526"
}
}
}

View File

@ -0,0 +1,47 @@
{
"recenttracks": {
"track": {
"artist": {
"#text": "Rick James",
"mbid": "cba9cec2-be8d-41bd-91b4-a1cd7de39b0c"
},
"name": "Super Freak (Part 1) - 1981 Single Version",
"streamable": "0",
"mbid": "",
"album": {
"#text": "The Definitive Collection",
"mbid": "f22c19bf-1c88-4651-a0d3-8c50735f3c93"
},
"url": "http://www.last.fm/music/Rick+James/_/Super+Freak+(Part+1)+-+1981+Single+Version",
"image": [
{
"#text": "http://userserve-ak.last.fm/serve/34s/90462319.jpg",
"size": "small"
},
{
"#text": "http://userserve-ak.last.fm/serve/64s/90462319.jpg",
"size": "medium"
},
{
"#text": "http://userserve-ak.last.fm/serve/126/90462319.jpg",
"size": "large"
},
{
"#text": "http://userserve-ak.last.fm/serve/300x300/90462319.jpg",
"size": "extralarge"
}
],
"date": {
"#text": "20 Dec 2014, 10:16",
"uts": "1419070612"
}
},
"@attr": {
"user": "RJ",
"page": "0",
"perPage": "1",
"totalPages": "76536",
"total": "76536"
}
}
}

View File

@ -0,0 +1,113 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace IF.Lastfm.Core.Tests.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class UserApiResponses {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal UserApiResponses() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("IF.Lastfm.Core.Tests.Resources.UserApiResponses", typeof(UserApiResponses).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] UserGetRecentTracksEmpty {
get {
object obj = ResourceManager.GetObject("UserGetRecentTracksEmpty", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] UserGetRecentTracksError {
get {
object obj = ResourceManager.GetObject("UserGetRecentTracksError", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] UserGetRecentTracksMissing {
get {
object obj = ResourceManager.GetObject("UserGetRecentTracksMissing", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] UserGetRecentTracksMultiple {
get {
object obj = ResourceManager.GetObject("UserGetRecentTracksMultiple", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] UserGetRecentTracksSingle {
get {
object obj = ResourceManager.GetObject("UserGetRecentTracksSingle", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="UserGetRecentTracksEmpty" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>userapi\usergetrecenttracksempty.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="UserGetRecentTracksError" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>userapi\usergetrecenttrackserror.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="UserGetRecentTracksMissing" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>userapi\usergetrecenttracksmissing.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="UserGetRecentTracksMultiple" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>userapi\usergetrecenttracksmultiple.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="UserGetRecentTracksSingle" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>UserApi\UserGetRecentTracksSingle.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@ -14,7 +14,7 @@ protected GetAsyncCommandBase(ILastAuth auth)
Auth = auth;
}
public async override Task<T> ExecuteAsync()
public override async Task<T> ExecuteAsync()
{
SetParameters();
@ -30,14 +30,7 @@ public async override Task<T> ExecuteAsync()
}
catch (HttpRequestException)
{
if (LastFm.CatchRequestExceptions)
{
return LastResponse.CreateErrorResponse<T>(LastFmApiError.RequestFailed);
}
else
{
throw;
}
throw;
}
}

View File

@ -54,8 +54,6 @@ protected void DisableCaching()
public abstract Task<T> HandleResponse(HttpResponseMessage response);
/// <summary>
/// </summary>
protected HttpClient GetHttpClient()
{
var client = new HttpClient();

View File

@ -0,0 +1,62 @@
using IF.Lastfm.Core.Api.Enums;
using IF.Lastfm.Core.Api.Helpers;
using IF.Lastfm.Core.Objects;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace IF.Lastfm.Core.Api.Commands.LibraryApi
{
internal class LibraryGetTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public string Username { get; private set; }
public string Artist { get; private set; }
public string Album { get; private set; }
public DateTime From { get; private set; }
public LibraryGetTracksCommand(ILastAuth auth, string username, string artist, string album, DateTime from) : base(auth)
{
Method = "library.getTracks";
Username = username;
Artist = artist;
Album = album;
From = from;
}
public override void SetParameters()
{
Parameters.Add("user", Username);
Parameters.Add("artist", Artist);
Parameters.Add("album", Album);
Parameters.Add("from", From.ToUnixTimestamp().ToString());
AddPagingParameters();
DisableCaching();
}
public async override Task<PageResponse<LastTrack>> HandleResponse(HttpResponseMessage response)
{
var json = await response.Content.ReadAsStringAsync();
LastFmApiError error;
if (LastFm.IsResponseValid(json, out error) && response.IsSuccessStatusCode)
{
var jtoken = JsonConvert.DeserializeObject<JToken>(json).SelectToken("tracks");
var tracksToken = jtoken.SelectToken("track");
var pageInfoToken = jtoken.SelectToken("@attr");
return PageResponse<LastTrack>.CreateSuccessResponse(tracksToken, pageInfoToken, LastTrack.ParseJToken, false);
}
else
{
return LastResponse.CreateErrorResponse<PageResponse<LastTrack>>(error);
}
}
}
}

View File

@ -39,14 +39,7 @@ public override async Task<T> ExecuteAsync()
}
catch (HttpRequestException)
{
if (LastFm.CatchRequestExceptions)
{
return LastResponse.CreateErrorResponse<T>(LastFmApiError.RequestFailed);
}
else
{
throw;
}
return LastResponse.CreateErrorResponse<T>(LastFmApiError.RequestFailed);
}
}
}

View File

@ -7,16 +7,17 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using System.Linq;
namespace IF.Lastfm.Core.Api.Commands.UserApi
{
internal class GetRecentScrobblesCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
internal class UserGetRecentTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public string Username { get; private set; }
public DateTime From { get; private set; }
public GetRecentScrobblesCommand(ILastAuth auth, string username, DateTime from) : base(auth)
public UserGetRecentTracksCommand(ILastAuth auth, string username, DateTime from) : base(auth)
{
Method = "user.getRecentTracks";
@ -40,24 +41,11 @@ public async override Task<PageResponse<LastTrack>> HandleResponse(HttpResponseM
LastFmApiError error;
if (LastFm.IsResponseValid(json, out error) && response.IsSuccessStatusCode)
{
JToken jtoken = JsonConvert.DeserializeObject<JToken>(json).SelectToken("recenttracks");
var tracksToken = jtoken.SelectToken("track");
var tracks = new List<LastTrack>();
foreach (var track in tracksToken.Children())
{
var t = LastTrack.ParseJToken(track);
tracks.Add(t);
}
var pageresponse = PageResponse<LastTrack>.CreateSuccessResponse(tracks);
var jtoken = JsonConvert.DeserializeObject<JToken>(json).SelectToken("recenttracks");
var itemsToken = jtoken.SelectToken("track");
var attrToken = jtoken.SelectToken("@attr");
pageresponse.AddPageInfoFromJToken(attrToken);
return pageresponse;
return PageResponse<LastTrack>.CreateSuccessResponse(itemsToken, attrToken, LastTrack.ParseJToken, false);
}
else
{

View File

@ -0,0 +1,21 @@
using System;
using System.Threading.Tasks;
using IF.Lastfm.Core.Api.Enums;
using IF.Lastfm.Core.Api.Helpers;
using IF.Lastfm.Core.Objects;
namespace IF.Lastfm.Core.Api
{
public interface ILibraryApi
{
ILastAuth Auth { get; }
Task<PageResponse<LastTrack>> GetTracks(string username,
string artist,
string album,
DateTime since,
int startIndex = 0,
int endIndex = LastFm.DefaultPageLength);
}
}

View File

@ -0,0 +1,24 @@
using IF.Lastfm.Core.Api.Commands.LibraryApi;
using IF.Lastfm.Core.Api.Helpers;
using IF.Lastfm.Core.Objects;
using System;
using System.Threading.Tasks;
namespace IF.Lastfm.Core.Api
{
public class LibraryApi : ILibraryApi
{
public ILastAuth Auth { get; private set; }
public async Task<PageResponse<LastTrack>> GetTracks(string username, string artist, string album, DateTime since, int pagenumber = 0, int count = LastFm.DefaultPageLength)
{
var command = new LibraryGetTracksCommand(Auth, username, artist, album, since)
{
Page = pagenumber,
Count = count
};
return await command.ExecuteAsync();
}
}
}

View File

@ -1,9 +1,9 @@
using System;
using System.Threading.Tasks;
using IF.Lastfm.Core.Api.Commands.UserApi;
using IF.Lastfm.Core.Api.Commands.UserApi;
using IF.Lastfm.Core.Api.Enums;
using IF.Lastfm.Core.Api.Helpers;
using IF.Lastfm.Core.Objects;
using System;
using System.Threading.Tasks;
namespace IF.Lastfm.Core.Api
{
@ -16,14 +16,6 @@ public UserApi(ILastAuth auth)
Auth = auth;
}
/// <summary>
/// Gets the top albums for the given user.
/// </summary>
/// <param name="username"></param>
/// <param name="span"></param>
/// <param name="pagenumber"></param>
/// <param name="count"></param>
/// <returns></returns>
public async Task<PageResponse<LastAlbum>> GetTopAlbums(string username, LastStatsTimeSpan span, int pagenumber = 0, int count = LastFm.DefaultPageLength)
{
var command = new GetTopAlbumsCommand(Auth, username, span)
@ -35,17 +27,9 @@ public async Task<PageResponse<LastAlbum>> GetTopAlbums(string username, LastSta
return await command.ExecuteAsync();
}
/// <summary>
/// Gets scrobbles and stuff
/// </summary>
/// <param name="username"></param>
/// <param name="since"></param>
/// <param name="pagenumber"></param>
/// <param name="count"></param>
/// <returns></returns>
public async Task<PageResponse<LastTrack>> GetRecentScrobbles(string username, DateTime since, int pagenumber = 0, int count = LastFm.DefaultPageLength)
{
var command = new GetRecentScrobblesCommand(Auth, username, since)
var command = new UserGetRecentTracksCommand(Auth, username, since)
{
Page = pagenumber,
Count = count

View File

@ -41,7 +41,9 @@
<Compile Include="Api\AlbumApi.cs" />
<Compile Include="Api\ArtistApi.cs" />
<Compile Include="Api\Commands\AlbumApi\GetAlbumTopTagsCommand.cs" />
<Compile Include="Api\Commands\LibraryApi\LibraryGetTracksCommand.cs" />
<Compile Include="Api\Commands\UserApi\GetRecommendedArtistsCommand.cs" />
<Compile Include="Api\ILibraryApi.cs" />
<Compile Include="Api\LastAuth.cs" />
<Compile Include="Api\ChartApi.cs" />
<Compile Include="Api\Commands\AlbumApi\AddShoutCommand.cs" />
@ -70,7 +72,7 @@
<Compile Include="Api\Commands\TrackApi\SearchTracksCommand.cs" />
<Compile Include="Api\Commands\TrackApi\UnloveTrackCommand.cs" />
<Compile Include="Api\Commands\UserApi\AddShoutCommand.cs" />
<Compile Include="Api\Commands\UserApi\GetRecentScrobblesCommand.cs" />
<Compile Include="Api\Commands\UserApi\UserGetRecentTracksCommand.cs" />
<Compile Include="Api\Commands\UserApi\GetRecentStationsCommand.cs" />
<Compile Include="Api\Commands\UserApi\GetTopAlbumsCommand.cs" />
<Compile Include="Api\Commands\UserApi\GetUserInfoCommand.cs" />
@ -88,6 +90,7 @@
<Compile Include="Api\IChartApi.cs" />
<Compile Include="Api\ITrackApi.cs" />
<Compile Include="Api\IUserApi.cs" />
<Compile Include="Api\LibraryApi.cs" />
<Compile Include="Api\Scrobble.cs" />
<Compile Include="Api\TrackApi.cs" />
<Compile Include="Api\UserApi.cs" />

View File

@ -27,17 +27,6 @@ public class LastFm
#endregion
/// <summary>
/// Determines whether commands should throw HttpRequestExceptions or wrap them
/// in the response.
///
/// Using this can make client code neater, but it violates the principles of
/// separation of concerns and single responsibility a bit. This property won't
/// get removed but please only use it if you understand what it does!
/// </summary>
[Obsolete]
public static bool CatchRequestExceptions { get; set; }
#region Api helper methods
public static string FormatApiUrl(string method, string apikey, Dictionary<string, string> parameters = null, bool secure = false)

View File

@ -1,6 +1,6 @@
namespace IF.Lastfm.Core.Objects
{
public interface ILastfmObject
internal interface ILastfmObject
{
}

View File

@ -102,6 +102,11 @@ internal static string GetNameFromJToken(JToken albumToken)
name = albumToken.Value<string>("#text");
}
if (string.IsNullOrEmpty(name))
{
name = albumToken.Value<string>("name"); // Used in Library track lists
}
return name;
}
}

View File

@ -11,13 +11,17 @@ public LastImageSet()
{
}
public LastImageSet(string s, string m, string l, string xl, string xxl)
public LastImageSet(string s, string m, string l, string xl, string xxl = null)
{
Small = new Uri(s);
Medium = new Uri(m);
Large = new Uri(l);
ExtraLarge = new Uri(xl);
Mega = new Uri(xxl);
if (xxl != null)
{
Mega = new Uri(xxl);
}
}
public Uri Small { get; set; }

View File

@ -34,7 +34,7 @@ public class LastTrack : ILastfmObject
public int? Rank { get; set; }
#endregion
/// <summary>
/// Parses the given JToken into a track
/// </summary>
@ -48,6 +48,10 @@ internal static LastTrack ParseJToken(JToken token)
t.Id = token.Value<string>("id");
t.Name = token.Value<string>("name");
t.Mbid = token.Value<string>("mbid");
//0 to null
t.TotalPlayCount = token.Value<int?>("playcount");
t.Url = new Uri(token.Value<string>("url"), UriKind.Absolute);
var artistToken = token.SelectToken("artist");