Merge pull request #72 from yaurthek/methodsNamesAsAttributes

Statically expose each LastCommand's method name using an attribute on the class
This commit is contained in:
Rikki Tooley 2015-06-21 17:49:33 +01:00
commit edc6e1d144
47 changed files with 107 additions and 105 deletions

View File

@ -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](src/IF.Lastfm.ProgressReport) tool in the solution. Last updated on 05 April 2015 00:02
This list is generated by the [ProgressReport](src/IF.Lastfm.ProgressReport) tool in the solution. Last updated on Saturday, 20 June 2015 10:32
## Album
- [album.getInfo](http://www.last.fm/api/show/album.getInfo)

View File

@ -33,7 +33,7 @@ The API is structured according to [the command pattern](http://en.wikipedia.org
Once you have chosen an API method to work on, you need to do five things before submitting it for inclusion in the API:
1. Create the command in the right folder
2. Implement the command, deriving from `GetAsyncCommandBase<T>` or `PostAsyncCommandBase<T>` (depending on what [the documentation](http://www.last.fm/api) says)
2. Implement the command, deriving from `GetAsyncCommandBase<T>` or `PostAsyncCommandBase<T>` (depending on what [the documentation](http://www.last.fm/api) says), and add an `ApiMethodNameAttribute` on the class, corresponding to the API method you are implementing. (for example, `[ApiMethodName("album.shout")]`)
3. Create a method on the relevant *Api class
4. Collect sample responses from the API for this method
5. Create a unit test class for the command using the sample responses

View File

@ -0,0 +1,27 @@
using IF.Lastfm.Core.Api;
using IF.Lastfm.Core.Api.Commands;
using IF.Lastfm.Core.Api.Helpers;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace IF.Lastfm.Core.Tests.Api
{
public class LastMethodsNamesTests
{
[Test]
public void EnsureEachCommandHasAnApiMethodNameAttribute()
{
var commandBaseType = typeof(LastAsyncCommandBase);
var allCommands = commandBaseType.Assembly.DefinedTypes
.Where(t => t != commandBaseType && commandBaseType.IsAssignableFrom(t))
.Where(t => t.IsClass && !t.IsAbstract);
var commandsWithoutAttribute = allCommands.Where(x => !x.GetCustomAttributes<ApiMethodNameAttribute>().Any());
Assert.IsFalse(commandsWithoutAttribute.Any(), "Warning, all commands should have anApiMethodNameAttribute.");
}
}
}

View File

@ -99,6 +99,7 @@
<Compile Include="Api\Commands\UserGetRecommendedArtistsCommandTests.cs" />
<Compile Include="Api\Commands\UserGetTopAlbumsCommandTests.cs" />
<Compile Include="Api\Helpers\ApiHelperTests.cs" />
<Compile Include="Api\LastMethodsNamesTests.cs" />
<Compile Include="Api\LastAuthTests.cs" />
<Compile Include="Api\MockAlbumApi.cs" />
<Compile Include="MockLastFm.cs" />

View File

@ -1,9 +1,11 @@
using System.Net.Http;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IF.Lastfm.Core.Api.Helpers;
namespace IF.Lastfm.Core.Api.Commands.Album
{
[ApiMethodName("album.shout")]
internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
{
public string Album { get; set; }
@ -15,8 +17,6 @@ internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
public AddShoutCommand(ILastAuth auth, string album, string artist, string message)
: base(auth)
{
Method = "album.shout";
Album = album;
Artist = artist;
Message = message;

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Album
{
[ApiMethodName("album.getInfo")]
internal class GetInfoCommand : GetAsyncCommandBase<LastResponse<LastAlbum>>
{
public string AlbumMbid { get; set; }
@ -19,11 +20,7 @@ internal class GetInfoCommand : GetAsyncCommandBase<LastResponse<LastAlbum>>
public bool Autocorrect { get; set; }
public GetInfoCommand(ILastAuth auth)
: base(auth)
{
Method = "album.getInfo";
}
public GetInfoCommand(ILastAuth auth) : base(auth) { }
public GetInfoCommand(ILastAuth auth, string album, string artist)
: this(auth)

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Album
{
[ApiMethodName("album.getShouts")]
internal class GetShoutsCommand : GetAsyncCommandBase<PageResponse<LastShout>>
{
public string AlbumName { get; set; }
@ -20,8 +21,6 @@ internal class GetShoutsCommand : GetAsyncCommandBase<PageResponse<LastShout>>
public GetShoutsCommand(ILastAuth auth, string albumname, string artistname)
: base(auth)
{
Method = "album.getShouts";
AlbumName = albumname;
ArtistName = artistname;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Album
{
[ApiMethodName("album.getTags")]
internal class GetTagsByUserCommand : GetAsyncCommandBase<PageResponse<LastTag>>
{
public string ArtistName { get; set; }
@ -22,8 +23,6 @@ internal class GetTagsByUserCommand : GetAsyncCommandBase<PageResponse<LastTag>>
public GetTagsByUserCommand(ILastAuth auth, string artist, string album, string username)
: base(auth)
{
Method = "album.getTags";
ArtistName = artist;
AlbumName = album;
Username = username;

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Album
{
[ApiMethodName("album.getTopTags")]
internal class GetTopTagsCommand : GetAsyncCommandBase<PageResponse<LastTag>>
{
public string AlbumMbid { get; set; }
@ -19,11 +20,7 @@ internal class GetTopTagsCommand : GetAsyncCommandBase<PageResponse<LastTag>>
public bool Autocorrect { get; set; }
public GetTopTagsCommand(ILastAuth auth)
: base(auth)
{
Method = "album.getTopTags";
}
public GetTopTagsCommand(ILastAuth auth) : base(auth) { }
public GetTopTagsCommand(ILastAuth auth, string album, string artist)
: this(auth)

View File

@ -8,6 +8,7 @@
namespace IF.Lastfm.Core.Api.Commands.Album
{
[ApiMethodName("album.search")]
internal class SearchCommand : GetAsyncCommandBase<PageResponse<LastAlbum>>
{
public string AlbumName { get; set; }
@ -15,8 +16,6 @@ internal class SearchCommand : GetAsyncCommandBase<PageResponse<LastAlbum>>
public SearchCommand(ILastAuth auth, string albumName)
: base(auth)
{
Method = "album.search";
AlbumName = albumName;
}

View File

@ -4,6 +4,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.shout")]
internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
{
public string Artist { get; set; }
@ -12,8 +13,6 @@ internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
public AddShoutCommand(ILastAuth auth, string artist, string message) : base(auth)
{
Method = "artist.shout";
Artist = artist;
Message = message;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.getInfo")]
internal class GetInfoCommand : GetAsyncCommandBase<LastResponse<LastArtist>>
{
public string ArtistMbid { get; set; }
@ -19,11 +20,7 @@ internal class GetInfoCommand : GetAsyncCommandBase<LastResponse<LastArtist>>
public bool Autocorrect { get; set; }
public GetInfoCommand(ILastAuth auth)
: base(auth)
{
Method = "artist.getInfo";
}
public GetInfoCommand(ILastAuth auth) : base(auth) { }
/// <summary>
/// TODO Bio language

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.getShouts")]
internal class GetShoutsCommand : GetAsyncCommandBase<PageResponse<LastShout>>
{
public string ArtistName { get; set; }
@ -17,7 +18,6 @@ internal class GetShoutsCommand : GetAsyncCommandBase<PageResponse<LastShout>>
public GetShoutsCommand(ILastAuth auth, string artistname)
: base(auth)
{
Method = "artist.getShouts";
ArtistName = artistname;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.getSimilar")]
internal class GetSimilarCommand : GetAsyncCommandBase<PageResponse<LastArtist>>
{
public bool Autocorrect { get; set; }
@ -20,8 +21,6 @@ internal class GetSimilarCommand : GetAsyncCommandBase<PageResponse<LastArtist>>
public GetSimilarCommand(ILastAuth auth, string artistName)
: base(auth)
{
Method = "artist.getSimilar";
ArtistName = artistName;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.getTags")]
internal class GetTagsByUserCommand : GetAsyncCommandBase<PageResponse<LastTag>>
{
public string ArtistName { get; set; }
@ -20,8 +21,6 @@ internal class GetTagsByUserCommand : GetAsyncCommandBase<PageResponse<LastTag>>
public GetTagsByUserCommand(ILastAuth auth, string artist, string username)
: base(auth)
{
Method = "artist.getTags";
ArtistName = artist;
Username = username;
}

View File

@ -8,6 +8,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.getTopAlbums")]
internal class GetTopAlbumsCommand : GetAsyncCommandBase<PageResponse<LastAlbum>>
{
public string ArtistName { get; set; }
@ -15,7 +16,6 @@ internal class GetTopAlbumsCommand : GetAsyncCommandBase<PageResponse<LastAlbum>
public GetTopAlbumsCommand(ILastAuth auth, string artistname)
: base(auth)
{
Method = "artist.getTopAlbums";
ArtistName = artistname;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.getTopTags")]
internal class GetTopTagsCommand : GetAsyncCommandBase<PageResponse<LastTag>>
{
public string ArtistName { get; set; }
@ -17,8 +18,6 @@ internal class GetTopTagsCommand : GetAsyncCommandBase<PageResponse<LastTag>>
public GetTopTagsCommand(ILastAuth auth, string artistName) : base(auth)
{
Method = "artist.getTopTags";
ArtistName = artistName;
}

View File

@ -8,6 +8,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.getTopTracks")]
internal class GetTopTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public string ArtistName { get; set; }
@ -15,7 +16,6 @@ internal class GetTopTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>
public GetTopTracksCommand(ILastAuth auth, string artistname)
: base(auth)
{
Method = "artist.getTopTracks";
ArtistName = artistname;
}

View File

@ -8,6 +8,7 @@
namespace IF.Lastfm.Core.Api.Commands.Artist
{
[ApiMethodName("artist.search")]
internal class SearchCommand : GetAsyncCommandBase<PageResponse<LastArtist>>
{
public string ArtistName { get; set; }
@ -15,7 +16,6 @@ internal class SearchCommand : GetAsyncCommandBase<PageResponse<LastArtist>>
public SearchCommand(ILastAuth auth, string artistName)
: base(auth)
{
Method = "artist.search";
ArtistName = artistName;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Auth
{
[ApiMethodName("auth.getMobileSession")]
internal class GetMobileSessionCommand : UnauthenticatedPostAsyncCommandBase<LastResponse<LastUserSession>>
{
public string Username { get; set; }
@ -17,7 +18,6 @@ internal class GetMobileSessionCommand : UnauthenticatedPostAsyncCommandBase<Las
public GetMobileSessionCommand(ILastAuth auth, string username, string password) : base(auth)
{
Method = "auth.getMobileSession";
Username = username;
Password = password;
}

View File

@ -8,13 +8,10 @@
namespace IF.Lastfm.Core.Api.Commands.Chart
{
[ApiMethodName("chart.getTopArtists")]
internal class GetTopArtistsCommand : GetAsyncCommandBase<PageResponse<LastArtist>>
{
public GetTopArtistsCommand(ILastAuth auth)
: base(auth)
{
Method = "chart.getTopArtists";
}
public GetTopArtistsCommand(ILastAuth auth) : base(auth) { }
public override void SetParameters()
{
@ -40,7 +37,7 @@ public async override Task<PageResponse<LastArtist>> HandleResponse(HttpResponse
return LastResponse.CreateErrorResponse<PageResponse<LastArtist>>(status);
}
}
}
}

View File

@ -8,13 +8,10 @@
namespace IF.Lastfm.Core.Api.Commands.Chart
{
[ApiMethodName("chart.getTopTracks")]
internal class GetTopTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public GetTopTracksCommand(ILastAuth auth)
: base(auth)
{
Method = "chart.getTopTracks";
}
public GetTopTracksCommand(ILastAuth auth) : base(auth) { }
public override void SetParameters()
{

View File

@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using System.Reflection;
namespace IF.Lastfm.Core.Api.Commands
{
@ -11,7 +12,19 @@ namespace IF.Lastfm.Core.Api.Commands
/// </summary>
public abstract class LastAsyncCommandBase
{
public string Method { get; protected set; }
public string Method
{
get
{
var methodNameAttribute = this.GetType().GetTypeInfo().GetCustomAttribute<ApiMethodNameAttribute>();
if (methodNameAttribute == null)
{
throw new NotImplementedException(@"Could not find an ApiMethodNameAttribute on the current Command implementation.
This custom attribute must be present on all Commands. For more information, see the ApiMethodNameAttribute documentation.");
}
return methodNameAttribute.Text;
}
}
public Dictionary<string, string> Parameters { get; set; }

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Library
{
[ApiMethodName("library.getTracks")]
internal class GetTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public string Username { get; private set; }
@ -22,8 +23,6 @@ internal class GetTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
public GetTracksCommand(ILastAuth auth, string username, string artist, string album, DateTimeOffset from)
: base(auth)
{
Method = "library.getTracks";
Username = username;
Artist = artist;
Album = album;

View File

@ -8,6 +8,7 @@
using Newtonsoft.Json;
namespace IF.Lastfm.Core.Api.Commands.Library {
[ApiMethodName("library.removeScrobble")]
internal class RemoveScrobbleCommand : PostAsyncCommandBase<LastResponse> {
public string Artist { get; set; }
@ -15,8 +16,6 @@ internal class RemoveScrobbleCommand : PostAsyncCommandBase<LastResponse> {
public DateTimeOffset Timestamp { get; set; }
public RemoveScrobbleCommand( ILastAuth auth, string artist, string track, DateTimeOffset timestamp ) : base( auth ) {
Method = "library.removeScrobble";
Artist = artist;
Track = track;
Timestamp = timestamp;

View File

@ -3,14 +3,13 @@
using IF.Lastfm.Core.Api.Helpers;
namespace IF.Lastfm.Core.Api.Commands.Library {
[ApiMethodName("library.removeTrack")]
internal class RemoveTrackCommand : PostAsyncCommandBase<LastResponse> {
public string Artist { get; set; }
public string Track { get; set; }
public RemoveTrackCommand( ILastAuth auth, string artist, string track) : base( auth ) {
Method = "library.removeTrack";
Artist = artist;
Track = track;
}

View File

@ -4,6 +4,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.shout")]
internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
{
public string Track { get; set; }
@ -15,8 +16,6 @@ internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
public AddShoutCommand(ILastAuth auth, string track, string artist, string message) : base(auth)
{
Method = "track.shout";
Track = track;
Artist = artist;
Message = message;

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.getInfo")]
internal class GetInfoCommand : GetAsyncCommandBase<LastResponse<LastTrack>>
{
public string TrackMbid { get; set; }
@ -21,11 +22,7 @@ internal class GetInfoCommand : GetAsyncCommandBase<LastResponse<LastTrack>>
public bool Autocorrect { get; set; }
public GetInfoCommand(ILastAuth auth)
: base(auth)
{
Method = "track.getInfo";
}
public GetInfoCommand(ILastAuth auth) : base(auth) { }
public override void SetParameters()
{

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.getShouts")]
internal class GetShoutsCommand : GetAsyncCommandBase<PageResponse<LastShout>>
{
public string TrackName { get; set; }
@ -20,8 +21,6 @@ internal class GetShoutsCommand : GetAsyncCommandBase<PageResponse<LastShout>>
public GetShoutsCommand(ILastAuth auth, string trackname, string artistname)
: base(auth)
{
Method = "track.getShouts";
TrackName = trackname;
ArtistName = artistname;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.getSimilar")]
internal class GetSimilarCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public string ArtistName { get; set; }
@ -22,8 +23,6 @@ internal class GetSimilarCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
public GetSimilarCommand(ILastAuth auth, string trackName, string artistName)
: base(auth)
{
Method = "track.getSimilar";
ArtistName = artistName;
TrackName = trackName;
}

View File

@ -4,6 +4,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.love")]
internal class LoveCommand : PostAsyncCommandBase<LastResponse>
{
public string TrackName { get; set; }
@ -13,8 +14,6 @@ internal class LoveCommand : PostAsyncCommandBase<LastResponse>
public LoveCommand(ILastAuth auth, string trackname, string artistname)
: base(auth)
{
Method = "track.love";
TrackName = trackname;
ArtistName = artistname;
}

View File

@ -10,6 +10,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.scrobble")]
internal class ScrobbleCommand : PostAsyncCommandBase<ScrobbleResponse>
{
public IList<Scrobble> Scrobbles { get; private set; }
@ -22,7 +23,6 @@ public ScrobbleCommand(ILastAuth auth, IList<Scrobble> scrobbles)
throw new ArgumentOutOfRangeException("scrobbles", "Only 50 scrobbles can be sent at a time");
}
Method = "track.scrobble";
Scrobbles = scrobbles;
}

View File

@ -8,6 +8,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.search")]
internal class SearchCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public string TrackName { get; set; }
@ -15,7 +16,6 @@ internal class SearchCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
public SearchCommand(ILastAuth auth, string trackName)
: base(auth)
{
Method = "track.search";
TrackName = trackName;
}

View File

@ -4,6 +4,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.unlove")]
internal class UnloveCommand : PostAsyncCommandBase<LastResponse>
{
public string TrackName { get; set; }
@ -13,8 +14,6 @@ internal class UnloveCommand : PostAsyncCommandBase<LastResponse>
public UnloveCommand(ILastAuth auth, string trackname, string artistname)
: base(auth)
{
Method = "track.unlove";
TrackName = trackname;
ArtistName = artistname;
}

View File

@ -7,6 +7,7 @@
namespace IF.Lastfm.Core.Api.Commands.Track
{
[ApiMethodName("track.updateNowPlaying")]
internal class UpdateNowPlayingCommand : PostAsyncCommandBase<LastResponse>
{
public string Artist { get; set; }
@ -24,8 +25,6 @@ internal class UpdateNowPlayingCommand : PostAsyncCommandBase<LastResponse>
public UpdateNowPlayingCommand(ILastAuth auth, string artist, string album, string track)
: base(auth)
{
Method = "track.updateNowPlaying";
Artist = artist;
Album = album;
Track = track;

View File

@ -4,6 +4,7 @@
namespace IF.Lastfm.Core.Api.Commands.User
{
[ApiMethodName("user.shout")]
internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
{
public string Recipient { get; set; }
@ -13,8 +14,6 @@ internal class AddShoutCommand : PostAsyncCommandBase<LastResponse>
public AddShoutCommand(ILastAuth auth, string recipient, string message)
: base(auth)
{
Method = "user.shout";
Recipient = recipient;
Message = message;
}

View File

@ -8,13 +8,13 @@
namespace IF.Lastfm.Core.Api.Commands.User
{
[ApiMethodName("user.getInfo")]
internal class GetInfoCommand : GetAsyncCommandBase<LastResponse<LastUser>>
{
public string Username { get; set; }
public GetInfoCommand(ILastAuth auth, string username) : base(auth)
{
Method = "user.getInfo";
Username = username;
}

View File

@ -9,13 +9,13 @@
namespace IF.Lastfm.Core.Api.Commands.User
{
[ApiMethodName("user.getRecentStations")]
internal class GetRecentStationsCommand : PostAsyncCommandBase<PageResponse<LastStation>>
{
public string Username { get; private set; }
public GetRecentStationsCommand(ILastAuth auth, string username) : base(auth)
{
Method = "user.getRecentStations";
Username = username;
}

View File

@ -9,6 +9,7 @@
namespace IF.Lastfm.Core.Api.Commands.User
{
[ApiMethodName("user.getRecentTracks")]
internal class GetRecentTracksCommand : GetAsyncCommandBase<PageResponse<LastTrack>>
{
public string Username { get; private set; }
@ -17,8 +18,6 @@ internal class GetRecentTracksCommand : GetAsyncCommandBase<PageResponse<LastTra
public GetRecentTracksCommand(ILastAuth auth, string username) : base(auth)
{
Method = "user.getRecentTracks";
Username = username;
}

View File

@ -8,12 +8,10 @@
namespace IF.Lastfm.Core.Api.Commands.User
{
[ApiMethodName("user.getRecommendedArtists")]
internal class GetRecommendedArtistsCommand : PostAsyncCommandBase<PageResponse<LastArtist>>
{
public GetRecommendedArtistsCommand(ILastAuth auth) : base(auth)
{
Method = "user.getRecommendedArtists";
}
public GetRecommendedArtistsCommand(ILastAuth auth) : base(auth) { }
public override void SetParameters()
{

View File

@ -8,13 +8,13 @@
namespace IF.Lastfm.Core.Api.Commands.User
{
[ApiMethodName("user.getShouts")]
internal class GetShoutsCommand : GetAsyncCommandBase<PageResponse<LastShout>>
{
public string Username { get; set; }
public GetShoutsCommand(ILastAuth auth, string username) : base(auth)
{
Method = "user.getShouts";
Username = username;
}

View File

@ -7,6 +7,7 @@
namespace IF.Lastfm.Core.Api.Commands.User
{
[ApiMethodName("user.getTopAlbums")]
internal class GetTopAlbumsCommand : GetAsyncCommandBase<PageResponse<LastAlbum>>
{
public string Username { get; set; }
@ -14,7 +15,6 @@ internal class GetTopAlbumsCommand : GetAsyncCommandBase<PageResponse<LastAlbum>
public GetTopAlbumsCommand(ILastAuth auth, string username, LastStatsTimeSpan span) : base(auth)
{
Method = "user.getTopAlbums";
Username = username;
TimeSpan = span;
}

View File

@ -1,4 +1,5 @@
using System;
using IF.Lastfm.Core.Api.Commands;
using System;
namespace IF.Lastfm.Core.Api.Helpers
{
@ -11,4 +12,14 @@ public ApiNameAttribute(string name)
Text = name;
}
}
/// <summary>
/// This attribute defines the api method name (i.e: "album.getInfo") for a Command.
/// When applied on a <see cref="LastAsyncCommandBase"/> implementation, the <see cref="LastAsyncCommandBase.Method"/> property is set to the attribute value.
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class ApiMethodNameAttribute : ApiNameAttribute
{
public ApiMethodNameAttribute(string name) : base(name) { }
}
}

View File

@ -4,6 +4,7 @@
using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System;
namespace IF.Lastfm.Syro.Helpers
{

View File

@ -5,6 +5,7 @@
using System.Net.Http;
using System.Text;
using HtmlAgilityPack;
using System.Globalization;
namespace IF.Lastfm.Syro.Tools
{
@ -91,7 +92,7 @@ internal static void WriteReport(Dictionary<string, IEnumerable<string>> apiGrou
{
var markdownBuilder = new StringBuilder();
var percent = GetPercentage(apiGroup, allImplemented);
markdownBuilder.AppendFormat(_progressReportIntro, (int)Math.Floor(percent), DateTime.UtcNow.ToString("f"));
markdownBuilder.AppendFormat(_progressReportIntro, (int)Math.Floor(percent), DateTime.UtcNow.ToString("f", CultureInfo.InvariantCulture));
foreach (var group in apiGroup.OrderBy(kv => kv.Key))
{

View File

@ -31,19 +31,5 @@ internal static IEnumerable<Type> GetImplementedCommands()
return types;
}
public static LastAsyncCommandBase CreateCommand(Type type)
{
var typeInfo = type.GetTypeInfo();
// assuming there is only one constructor
var constructor = typeInfo.DeclaredConstructors.First();
var parameters = constructor.GetParameters();
var arguments = new object[parameters.Count()]; // to keep reflection happy
var instance = (LastAsyncCommandBase)Activator.CreateInstance(type, arguments);
return instance;
}
}
}

View File

@ -350,7 +350,7 @@ await Task.Run(() =>
}
// reflect on Last.fm assembly to find all implemented commands
var allImplemented = Reflektor.GetImplementedCommands().Select(Reflektor.CreateCommand).Select(c => c.Method).ToList();
var allImplemented = Reflektor.GetImplementedCommands().Select(x => x.GetCustomAttribute<ApiNameAttribute>().Text).ToList();
// generate the markdown
_reportPath = Path.GetFullPath(SolutionDir + ReportFilename);