tag.getSimilar, tidying some tests

This commit is contained in:
Rikki Tooley 2015-06-21 19:58:04 +01:00
parent 3e991abc8a
commit 80c3308fd0
21 changed files with 482 additions and 83 deletions

View File

@ -1,4 +1,4 @@
# Api Progress ![Progress](http://progressed.io/bar/27) # Api Progress ![Progress](http://progressed.io/bar/28)
These are all the Last.fm API methods currently available. 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 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! - 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](src/IF.Lastfm.ProgressReport) tool in the solution. Last updated on Saturday, 20 June 2015 10:32 This list is generated by the [ProgressReport](src/IF.Lastfm.ProgressReport) tool in the solution. Last updated on Sunday, 21 June 2015 17:53
## Album ## Album
- [album.getInfo](http://www.last.fm/api/show/album.getInfo) - [album.getInfo](http://www.last.fm/api/show/album.getInfo)
@ -113,8 +113,8 @@ This list is generated by the [ProgressReport](src/IF.Lastfm.ProgressReport) too
## Tag ## Tag
- [tag.getSimilar](http://www.last.fm/api/show/tag.getSimilar)
- ~~[tag.getInfo](http://www.last.fm/api/show/tag.getInfo)~~ - ~~[tag.getInfo](http://www.last.fm/api/show/tag.getInfo)~~
- ~~[tag.getSimilar](http://www.last.fm/api/show/tag.getSimilar)~~
- ~~[tag.getTopAlbums](http://www.last.fm/api/show/tag.getTopAlbums)~~ - ~~[tag.getTopAlbums](http://www.last.fm/api/show/tag.getTopAlbums)~~
- ~~[tag.getTopArtists](http://www.last.fm/api/show/tag.getTopArtists)~~ - ~~[tag.getTopArtists](http://www.last.fm/api/show/tag.getTopArtists)~~
- ~~[tag.getTopTags](http://www.last.fm/api/show/tag.getTopTags)~~ - ~~[tag.getTopTags](http://www.last.fm/api/show/tag.getTopTags)~~

View File

@ -1,11 +1,5 @@
using System.Threading.Tasks; using IF.Lastfm.Core.Api;
using IF.Lastfm.Core.Api;
using IF.Lastfm.Core.Api.Commands;
using IF.Lastfm.Core.Api.Helpers;
using IF.Lastfm.Core.Objects;
using NUnit.Framework;
using Moq; using Moq;
using Newtonsoft.Json;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
@ -30,35 +24,5 @@ protected HttpResponseMessage CreateResponseMessage(string message)
return response; 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

@ -4,6 +4,7 @@
using NUnit.Framework; using NUnit.Framework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using IF.Lastfm.Core.Api.Commands.Library; using IF.Lastfm.Core.Api.Commands.Library;
@ -12,20 +13,14 @@ namespace IF.Lastfm.Core.Tests.Api.Commands.Library
{ {
public class LibraryGetTracksCommandTests : CommandTestsBase public class LibraryGetTracksCommandTests : CommandTestsBase
{ {
private readonly GetTracksCommand _command;
public LibraryGetTracksCommandTests()
{
_command = new GetTracksCommand(MAuth.Object, "rj", "", "", DateTimeOffset.MinValue)
{
Count = 1
};
}
[Test] [Test]
public async Task HandleResponseMultiple() public async Task HandleResponseMultiple()
{ {
//Testing the second track returned var command = new GetTracksCommand(MAuth.Object, "rj", "", "", DateTimeOffset.MinValue)
{
Count = 1
};
var expectedTrack = new LastTrack var expectedTrack = new LastTrack
{ {
ArtistName = "Stevie Wonder", ArtistName = "Stevie Wonder",
@ -44,12 +39,21 @@ public async Task HandleResponseMultiple()
}; };
await CompareResultsMultiple(_command, expectedTrack, LibraryApiResponses.LibraryGetTracksMultiple, 1); var response = CreateResponseMessage(Encoding.UTF8.GetString(LibraryApiResponses.LibraryGetTracksMultiple));
var actual = await command.HandleResponse(response);
Assert.IsTrue(actual.Success);
TestHelper.AssertSerialiseEqual(expectedTrack, actual.Content[1]); // Testing the second track returned
} }
[Test] [Test]
public async Task HandleResponseSingle() public async Task HandleResponseSingle()
{ {
var command = new GetTracksCommand(MAuth.Object, "rj", "", "", DateTimeOffset.MinValue)
{
Count = 1
};
var expectedTrack = new LastTrack var expectedTrack = new LastTrack
{ {
ArtistName = "Dire Straits", ArtistName = "Dire Straits",
@ -66,18 +70,25 @@ public async Task HandleResponseSingle()
"http://userserve-ak.last.fm/serve/126/56827829.jpg", "http://userserve-ak.last.fm/serve/126/56827829.jpg",
"http://userserve-ak.last.fm/serve/300x300/56827829.jpg") "http://userserve-ak.last.fm/serve/300x300/56827829.jpg")
}; };
var response = CreateResponseMessage(Encoding.UTF8.GetString(LibraryApiResponses.LibraryGetTracksSingle));
var actual = await command.HandleResponse(response);
var expected = new List<LastTrack> { expectedTrack }; Assert.IsTrue(actual.Success);
TestHelper.AssertSerialiseEqual(expectedTrack, actual.Single());
await CompareResultsSingle(_command, expected, LibraryApiResponses.LibraryGetTracksSingle);
} }
[Test] [Test]
public async Task HandleErrorResponse() public async Task HandleErrorResponse()
{ {
var command = new GetTracksCommand(MAuth.Object, "rj", "", "", DateTimeOffset.MinValue)
{
Count = 1
};
var response = CreateResponseMessage(Encoding.UTF8.GetString(AlbumApiResponses.AlbumGetInfoMissing)); var response = CreateResponseMessage(Encoding.UTF8.GetString(AlbumApiResponses.AlbumGetInfoMissing));
var parsed = await _command.HandleResponse(response); var parsed = await command.HandleResponse(response);
Assert.IsFalse(parsed.Success); Assert.IsFalse(parsed.Success);
Assert.IsTrue(parsed.Status == LastResponseStatus.MissingParameters); Assert.IsTrue(parsed.Status == LastResponseStatus.MissingParameters);

View File

@ -0,0 +1,67 @@
using System;
using System.Linq;
using IF.Lastfm.Core.Api.Enums;
using IF.Lastfm.Core.Tests.Resources;
using NUnit.Framework;
using System.Text;
using System.Threading.Tasks;
using IF.Lastfm.Core.Api.Commands.Tag;
using IF.Lastfm.Core.Objects;
namespace IF.Lastfm.Core.Tests.Api.Commands.Tag
{
public class GetSimilarCommandTests : CommandTestsBase
{
[Test]
public async Task HandleSuccessResponse()
{
const string tagName = "daria";
var command = new GetSimilarCommand(MAuth.Object, tagName);
var expectedTagNames = new[]
{
"road trip",
"longing",
"old school rap",
"pj harvey",
"girl band",
"alt rock",
"female rock",
"90s",
"post-grunge",
"acid jazz"
};
var expectedTags = expectedTagNames.Select(tag => new LastTag
{
Name = tag,
Url = new Uri(String.Format("http://www.last.fm/tag/{0}", Uri.EscapeUriString(tag))),
RelatedTo = tagName,
Streamable = true
}).ToList();
expectedTags[0].Streamable = false;
expectedTags[1].Streamable = null;
var response = CreateResponseMessage(Encoding.UTF8.GetString(TagApiResponses.GetSimilarSuccess));
var actual = await command.HandleResponse(response);
Assert.IsTrue(actual.Skip(2).All(t => t.Streamable.GetValueOrDefault()));
Assert.IsTrue(actual.All(t => t.RelatedTo == tagName));
Assert.IsTrue(actual.Success);
TestHelper.AssertSerialiseEqual(expectedTags, actual.ToList());
}
[Test]
public async Task HandleErrorResponse()
{
var command = new GetSimilarCommand(MAuth.Object, "arroooo");
var response = CreateResponseMessage(Encoding.UTF8.GetString(TagApiResponses.GetSimilarError));
var parsed = await command.HandleResponse(response);
Assert.IsFalse(parsed.Success);
Assert.IsTrue(parsed.Status == LastResponseStatus.MissingParameters);
}
}
}

View File

@ -4,6 +4,7 @@
using NUnit.Framework; using NUnit.Framework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using IF.Lastfm.Core.Api.Commands.User; using IF.Lastfm.Core.Api.Commands.User;
@ -11,23 +12,16 @@
namespace IF.Lastfm.Core.Tests.Api.Commands namespace IF.Lastfm.Core.Tests.Api.Commands
{ {
public class UserGetRecentTracksCommandTests : CommandTestsBase public class UserGetRecentTracksCommandTests : CommandTestsBase
{ {
private GetRecentTracksCommand _command;
[SetUp]
public void Initialise()
{
_command = new GetRecentTracksCommand(MAuth.Object, "rj")
{
Count = 1
};
}
[Test] [Test]
public async Task HandleResponseMultiple() public async Task HandleResponseMultiple()
{ {
var command = new GetRecentTracksCommand(MAuth.Object, "rj")
{
Count = 1
};
var expectedTrack = new LastTrack var expectedTrack = new LastTrack
{ {
ArtistName = "The Who", ArtistName = "The Who",
@ -44,12 +38,21 @@ public async Task HandleResponseMultiple()
"http://userserve-ak.last.fm/serve/300x300/35234991.jpg") "http://userserve-ak.last.fm/serve/300x300/35234991.jpg")
}; };
await CompareResultsMultiple(_command, expectedTrack, UserApiResponses.UserGetRecentTracksMultiple, 2); var response = CreateResponseMessage(Encoding.UTF8.GetString(UserApiResponses.UserGetRecentTracksMultiple));
var actual = await command.HandleResponse(response);
Assert.IsTrue(actual.Success);
TestHelper.AssertSerialiseEqual(expectedTrack, actual.Content[2]);
} }
[Test] [Test]
public async Task HandleResponseSingle() public async Task HandleResponseSingle()
{ {
var command = new GetRecentTracksCommand(MAuth.Object, "rj")
{
Count = 1
};
var expectedTrack = new LastTrack var expectedTrack = new LastTrack
{ {
ArtistName = "Rick James", ArtistName = "Rick James",
@ -66,18 +69,25 @@ public async Task HandleResponseSingle()
"http://userserve-ak.last.fm/serve/126/90462319.jpg", "http://userserve-ak.last.fm/serve/126/90462319.jpg",
"http://userserve-ak.last.fm/serve/300x300/90462319.jpg") "http://userserve-ak.last.fm/serve/300x300/90462319.jpg")
}; };
var response = CreateResponseMessage(Encoding.UTF8.GetString(UserApiResponses.UserGetRecentTracksSingle));
var actual = await command.HandleResponse(response);
var expected = new List<LastTrack> { expectedTrack }; Assert.IsTrue(actual.Success);
TestHelper.AssertSerialiseEqual(expectedTrack, actual.Single());
await CompareResultsSingle(_command, expected, UserApiResponses.UserGetRecentTracksSingle);
} }
[Test] [Test]
public async Task HandleErrorResponse() public async Task HandleErrorResponse()
{ {
var command = new GetRecentTracksCommand(MAuth.Object, "rj")
{
Count = 1
};
var response = CreateResponseMessage(Encoding.UTF8.GetString(UserApiResponses.UserGetRecentTracksError)); var response = CreateResponseMessage(Encoding.UTF8.GetString(UserApiResponses.UserGetRecentTracksError));
var parsed = await _command.HandleResponse(response); var parsed = await command.HandleResponse(response);
Assert.IsFalse(parsed.Success); Assert.IsFalse(parsed.Success);
Assert.IsTrue(parsed.Status == LastResponseStatus.MissingParameters); Assert.IsTrue(parsed.Status == LastResponseStatus.MissingParameters);

View File

@ -92,6 +92,7 @@
<Compile Include="Api\Commands\Library\LibraryGetTracksCommandTests.cs" /> <Compile Include="Api\Commands\Library\LibraryGetTracksCommandTests.cs" />
<Compile Include="Api\Commands\Library\RemoveScrobbleCommandTests.cs" /> <Compile Include="Api\Commands\Library\RemoveScrobbleCommandTests.cs" />
<Compile Include="Api\Commands\Library\RemoveTrackCommandTests.cs" /> <Compile Include="Api\Commands\Library\RemoveTrackCommandTests.cs" />
<Compile Include="Api\Commands\Tag\GetSimilarCommandTests.cs" />
<Compile Include="Api\Commands\TrackApi\GetTrackShoutsCommandTests.cs" /> <Compile Include="Api\Commands\TrackApi\GetTrackShoutsCommandTests.cs" />
<Compile Include="Api\Commands\ArtistGetInfoCommandTests.cs" /> <Compile Include="Api\Commands\ArtistGetInfoCommandTests.cs" />
<Compile Include="Api\Commands\TrackScrobbleCommandTests.cs" /> <Compile Include="Api\Commands\TrackScrobbleCommandTests.cs" />
@ -121,6 +122,11 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>LibraryApiResponses.resx</DependentUpon> <DependentUpon>LibraryApiResponses.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Resources\TagApiResponses.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>TagApiResponses.resx</DependentUpon>
</Compile>
<Compile Include="Resources\TrackApiResponses.Designer.cs"> <Compile Include="Resources\TrackApiResponses.Designer.cs">
<DependentUpon>TrackApiResponses.resx</DependentUpon> <DependentUpon>TrackApiResponses.resx</DependentUpon>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
@ -167,6 +173,8 @@
<None Include="Resources\ArtistApi\ArtistGetTopTagsSingle.json" /> <None Include="Resources\ArtistApi\ArtistGetTopTagsSingle.json" />
<None Include="Resources\LibraryApi\LibraryGetTracksMultiple.json" /> <None Include="Resources\LibraryApi\LibraryGetTracksMultiple.json" />
<None Include="Resources\LibraryApi\LibraryGetTracksSingle.json" /> <None Include="Resources\LibraryApi\LibraryGetTracksSingle.json" />
<None Include="Resources\Tag\GetSimilarError.json" />
<None Include="Resources\Tag\GetSimilarSuccess.json" />
<None Include="Resources\TrackApi\TrackGetShouts.json" /> <None Include="Resources\TrackApi\TrackGetShouts.json" />
<None Include="Resources\TrackApi\TrackGetShoutsEmpty.json" /> <None Include="Resources\TrackApi\TrackGetShoutsEmpty.json" />
<None Include="Resources\TrackApi\TrackGetShoutsError.json" /> <None Include="Resources\TrackApi\TrackGetShoutsError.json" />
@ -209,6 +217,10 @@
<LastGenOutput>LibraryApiResponses.Designer.cs</LastGenOutput> <LastGenOutput>LibraryApiResponses.Designer.cs</LastGenOutput>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Resources\TagApiResponses.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>TagApiResponses.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Resources\TrackApiResponses.resx"> <EmbeddedResource Include="Resources\TrackApiResponses.resx">
<Generator>PublicResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>TrackApiResponses.Designer.cs</LastGenOutput> <LastGenOutput>TrackApiResponses.Designer.cs</LastGenOutput>

View File

@ -8,7 +8,6 @@
namespace IF.Lastfm.Core.Tests namespace IF.Lastfm.Core.Tests
{ {
public class LastFmTests public class LastFmTests
{ {
[Test] [Test]

View File

@ -0,0 +1,5 @@
{
"error": 6,
"message": "Invalid tag",
"links": []
}

View File

@ -0,0 +1,58 @@
{
"similartags": {
"tag": [
{
"name": "road trip",
"url": "http://www.last.fm/tag/road%20trip",
"streamable": "0"
},
{
"name": "longing",
"url": "http://www.last.fm/tag/longing"
},
{
"name": "old school rap",
"url": "http://www.last.fm/tag/old%20school%20rap",
"streamable": "1"
},
{
"name": "pj harvey",
"url": "http://www.last.fm/tag/pj%20harvey",
"streamable": "1"
},
{
"name": "girl band",
"url": "http://www.last.fm/tag/girl%20band",
"streamable": "1"
},
{
"name": "alt rock",
"url": "http://www.last.fm/tag/alt%20rock",
"streamable": "1"
},
{
"name": "female rock",
"url": "http://www.last.fm/tag/female%20rock",
"streamable": "1"
},
{
"name": "90s",
"url": "http://www.last.fm/tag/90s",
"streamable": "1"
},
{
"name": "post-grunge",
"url": "http://www.last.fm/tag/post-grunge",
"streamable": "1"
},
{
"name": "acid jazz",
"url": "http://www.last.fm/tag/acid%20jazz",
"streamable": "1"
}
],
"@attr": {
"tag": "daria"
}
}
}

View File

@ -0,0 +1,83 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.0
//
// 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 TagApiResponses {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal TagApiResponses() {
}
/// <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.TagApiResponses", typeof(TagApiResponses).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[] GetSimilarError {
get {
object obj = ResourceManager.GetObject("GetSimilarError", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] GetSimilarSuccess {
get {
object obj = ResourceManager.GetObject("GetSimilarSuccess", 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="GetSimilarError" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>tag\getsimilarerror.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="GetSimilarSuccess" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>tag\getsimilarsuccess.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@ -50,7 +50,7 @@ public async override Task<PageResponse<LastTag>> HandleResponse(HttpResponseMes
var resultsToken = jtoken.SelectToken("tags"); var resultsToken = jtoken.SelectToken("tags");
var itemsToken = resultsToken.SelectToken("tag"); var itemsToken = resultsToken.SelectToken("tag");
return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, LastTag.ParseJToken); return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, token => LastTag.ParseJToken(token));
} }
else else
{ {

View File

@ -58,7 +58,7 @@ public async override Task<PageResponse<LastTag>> HandleResponse(HttpResponseMes
var resultsToken = jtoken.SelectToken("toptags"); var resultsToken = jtoken.SelectToken("toptags");
var itemsToken = resultsToken.SelectToken("tag"); var itemsToken = resultsToken.SelectToken("tag");
return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, resultsToken, LastTag.ParseJToken, LastPageResultsType.Attr); return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, resultsToken, token => LastTag.ParseJToken(token), LastPageResultsType.Attr);
} }
else else
{ {

View File

@ -46,7 +46,7 @@ public async override Task<PageResponse<LastTag>> HandleResponse(HttpResponseMes
var resultsToken = jtoken.SelectToken("tags"); var resultsToken = jtoken.SelectToken("tags");
var itemsToken = resultsToken.SelectToken("tag"); var itemsToken = resultsToken.SelectToken("tag");
return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, LastTag.ParseJToken); return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, token => LastTag.ParseJToken(token));
} }
else else
{ {

View File

@ -38,7 +38,7 @@ public async override Task<PageResponse<LastTag>> HandleResponse(HttpResponseMes
var resultsToken = jtoken.SelectToken("toptags"); var resultsToken = jtoken.SelectToken("toptags");
var itemsToken = resultsToken.SelectToken("tag"); var itemsToken = resultsToken.SelectToken("tag");
return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, LastTag.ParseJToken); return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, token => LastTag.ParseJToken(token));
} }
else else
{ {

View File

@ -0,0 +1,47 @@
using System.Net.Http;
using System.Threading.Tasks;
using IF.Lastfm.Core.Api.Enums;
using IF.Lastfm.Core.Api.Helpers;
using IF.Lastfm.Core.Objects;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace IF.Lastfm.Core.Api.Commands.Tag
{
[ApiMethodName("tag.getSimilar")]
internal class GetSimilarCommand : GetAsyncCommandBase<PageResponse<LastTag>>
{
public string TagName { get; set; }
public GetSimilarCommand(ILastAuth auth, string tagname)
: base(auth)
{
TagName = tagname;
}
public override void SetParameters()
{
Parameters.Add("tag", TagName);
DisableCaching();
}
public async override Task<PageResponse<LastTag>> HandleResponse(HttpResponseMessage response)
{
var json = await response.Content.ReadAsStringAsync();
LastResponseStatus status;
if (LastFm.IsResponseValid(json, out status) && response.IsSuccessStatusCode)
{
var jtoken = JsonConvert.DeserializeObject<JToken>(json).SelectToken("similartags");
var itemsToken = jtoken.SelectToken("tag");
var attrToken = jtoken.SelectToken("@attr");
var relatedTag = attrToken.SelectToken("tag").Value<string>();
return PageResponse<LastTag>.CreateSuccessResponse(itemsToken, jt => LastTag.ParseJToken(jt, relatedTag));
}
return LastResponse.CreateErrorResponse<PageResponse<LastTag>>(status);
}
}
}

View File

@ -63,6 +63,7 @@
<Compile Include="Api\Commands\Library\GetTracksCommand.cs" /> <Compile Include="Api\Commands\Library\GetTracksCommand.cs" />
<Compile Include="Api\Commands\Library\RemoveScrobbleCommand.cs" /> <Compile Include="Api\Commands\Library\RemoveScrobbleCommand.cs" />
<Compile Include="Api\Commands\Library\RemoveTrackCommand.cs" /> <Compile Include="Api\Commands\Library\RemoveTrackCommand.cs" />
<Compile Include="Api\Commands\Tag\GetSimilarCommand.cs" />
<Compile Include="Api\Commands\Track\ScrobbleCommand.cs" /> <Compile Include="Api\Commands\Track\ScrobbleCommand.cs" />
<Compile Include="Api\Commands\Track\UpdateNowPlayingCommand.cs" /> <Compile Include="Api\Commands\Track\UpdateNowPlayingCommand.cs" />
<Compile Include="Api\Commands\UnauthenticatedPostAsyncCommandBase.cs" /> <Compile Include="Api\Commands\UnauthenticatedPostAsyncCommandBase.cs" />

View File

@ -67,7 +67,7 @@ internal static LastAlbum ParseJToken(JToken token)
{ {
a.TopTags = a.TopTags =
tagToken.Type == JTokenType.Array tagToken.Type == JTokenType.Array
? tagToken.Children().Select(LastTag.ParseJToken) ? tagToken.Children().Select(token1 => LastTag.ParseJToken(token1))
: new List<LastTag> { LastTag.ParseJToken(tagToken) }; : new List<LastTag> { LastTag.ParseJToken(tagToken) };
} }
} }

View File

@ -104,7 +104,7 @@ internal static LastArtist ParseJToken(JToken token)
{ {
a.Tags = a.Tags =
tagToken.Type == JTokenType.Array tagToken.Type == JTokenType.Array
? tagToken.Children().Select(LastTag.ParseJToken) ? tagToken.Children().Select(token1 => LastTag.ParseJToken(token1))
: new List<LastTag> { LastTag.ParseJToken(tagToken) }; : new List<LastTag> { LastTag.ParseJToken(tagToken) };
} }
} }

View File

@ -13,6 +13,10 @@ public class LastTag : ILastfmObject
public int? Count { get; set; } public int? Count { get; set; }
public string RelatedTo { get; set; }
public bool? Streamable { get; set; }
#endregion #endregion
public LastTag() public LastTag()
@ -26,7 +30,7 @@ public LastTag(string name, string uri, int? count = null)
Count = count; Count = count;
} }
internal static LastTag ParseJToken(JToken token) internal static LastTag ParseJToken(JToken token, string relatedTag = null)
{ {
var name = token.Value<string>("name"); var name = token.Value<string>("name");
var url = token.Value<string>("url"); var url = token.Value<string>("url");
@ -38,7 +42,18 @@ internal static LastTag ParseJToken(JToken token)
count = countToken.ToObject<int?>(); count = countToken.ToObject<int?>();
} }
return new LastTag(name, url, count); bool? streamable = null;
var streamableToken = token.SelectToken("streamable");
if (streamableToken != null)
{
streamable = Convert.ToBoolean(streamableToken.Value<int>());
}
return new LastTag(name, url, count)
{
Streamable = streamable,
RelatedTo = relatedTag
};
} }
} }
} }

View File

@ -94,7 +94,7 @@ internal static LastTrack ParseJToken(JToken token)
{ {
t.TopTags = t.TopTags =
tagToken.Type == JTokenType.Array tagToken.Type == JTokenType.Array
? tagToken.Children().Select(LastTag.ParseJToken) ? tagToken.Children().Select(token1 => LastTag.ParseJToken(token1))
: new List<LastTag> { LastTag.ParseJToken(tagToken) }; : new List<LastTag> { LastTag.ParseJToken(tagToken) };
} }
} }