diff --git a/PROGRESS.md b/PROGRESS.md index 154daa2..d582406 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -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) diff --git a/doc/contributing.md b/doc/contributing.md index 580e74c..9696c80 100644 --- a/doc/contributing.md +++ b/doc/contributing.md @@ -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` or `PostAsyncCommandBase` (depending on what [the documentation](http://www.last.fm/api) says) +2. Implement the command, deriving from `GetAsyncCommandBase` or `PostAsyncCommandBase` (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 diff --git a/src/IF.Lastfm.Core.Tests/Api/LastMethodsNamesTests.cs b/src/IF.Lastfm.Core.Tests/Api/LastMethodsNamesTests.cs new file mode 100644 index 0000000..98b3786 --- /dev/null +++ b/src/IF.Lastfm.Core.Tests/Api/LastMethodsNamesTests.cs @@ -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().Any()); + + Assert.IsFalse(commandsWithoutAttribute.Any(), "Warning, all commands should have anApiMethodNameAttribute."); + } + } +} \ No newline at end of file diff --git a/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj b/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj index c487bb1..f9ef721 100644 --- a/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj +++ b/src/IF.Lastfm.Core.Tests/IF.Lastfm.Core.Tests.csproj @@ -99,6 +99,7 @@ + diff --git a/src/IF.Lastfm.Core/Api/Commands/Album/AddShoutCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Album/AddShoutCommand.cs index c8fc451..445447a 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Album/AddShoutCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Album/AddShoutCommand.cs @@ -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 { public string Album { get; set; } @@ -15,8 +17,6 @@ internal class AddShoutCommand : PostAsyncCommandBase public AddShoutCommand(ILastAuth auth, string album, string artist, string message) : base(auth) { - Method = "album.shout"; - Album = album; Artist = artist; Message = message; diff --git a/src/IF.Lastfm.Core/Api/Commands/Album/GetInfoCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Album/GetInfoCommand.cs index 3a2c5f0..7a79d0b 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Album/GetInfoCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Album/GetInfoCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Album { + [ApiMethodName("album.getInfo")] internal class GetInfoCommand : GetAsyncCommandBase> { public string AlbumMbid { get; set; } @@ -19,11 +20,7 @@ internal class GetInfoCommand : GetAsyncCommandBase> 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) diff --git a/src/IF.Lastfm.Core/Api/Commands/Album/GetShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Album/GetShoutsCommand.cs index 550b4e2..7c5e892 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Album/GetShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Album/GetShoutsCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Album { + [ApiMethodName("album.getShouts")] internal class GetShoutsCommand : GetAsyncCommandBase> { public string AlbumName { get; set; } @@ -20,8 +21,6 @@ internal class GetShoutsCommand : GetAsyncCommandBase> public GetShoutsCommand(ILastAuth auth, string albumname, string artistname) : base(auth) { - Method = "album.getShouts"; - AlbumName = albumname; ArtistName = artistname; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Album/GetTagsByUserCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Album/GetTagsByUserCommand.cs index 9910570..e71ac8d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Album/GetTagsByUserCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Album/GetTagsByUserCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Album { + [ApiMethodName("album.getTags")] internal class GetTagsByUserCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -22,8 +23,6 @@ internal class GetTagsByUserCommand : GetAsyncCommandBase> public GetTagsByUserCommand(ILastAuth auth, string artist, string album, string username) : base(auth) { - Method = "album.getTags"; - ArtistName = artist; AlbumName = album; Username = username; diff --git a/src/IF.Lastfm.Core/Api/Commands/Album/GetTopTagsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Album/GetTopTagsCommand.cs index a9144ba..26028d5 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Album/GetTopTagsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Album/GetTopTagsCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Album { + [ApiMethodName("album.getTopTags")] internal class GetTopTagsCommand : GetAsyncCommandBase> { public string AlbumMbid { get; set; } @@ -19,11 +20,7 @@ internal class GetTopTagsCommand : GetAsyncCommandBase> 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) diff --git a/src/IF.Lastfm.Core/Api/Commands/Album/SearchCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Album/SearchCommand.cs index 6185f72..bff1423 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Album/SearchCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Album/SearchCommand.cs @@ -8,6 +8,7 @@ namespace IF.Lastfm.Core.Api.Commands.Album { + [ApiMethodName("album.search")] internal class SearchCommand : GetAsyncCommandBase> { public string AlbumName { get; set; } @@ -15,8 +16,6 @@ internal class SearchCommand : GetAsyncCommandBase> public SearchCommand(ILastAuth auth, string albumName) : base(auth) { - Method = "album.search"; - AlbumName = albumName; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/AddShoutCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/AddShoutCommand.cs index a8c723f..5e60a45 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/AddShoutCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/AddShoutCommand.cs @@ -4,6 +4,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.shout")] internal class AddShoutCommand : PostAsyncCommandBase { public string Artist { get; set; } @@ -12,8 +13,6 @@ internal class AddShoutCommand : PostAsyncCommandBase public AddShoutCommand(ILastAuth auth, string artist, string message) : base(auth) { - Method = "artist.shout"; - Artist = artist; Message = message; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/GetInfoCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/GetInfoCommand.cs index 06269c3..a42deed 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/GetInfoCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/GetInfoCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.getInfo")] internal class GetInfoCommand : GetAsyncCommandBase> { public string ArtistMbid { get; set; } @@ -19,11 +20,7 @@ internal class GetInfoCommand : GetAsyncCommandBase> public bool Autocorrect { get; set; } - public GetInfoCommand(ILastAuth auth) - : base(auth) - { - Method = "artist.getInfo"; - } + public GetInfoCommand(ILastAuth auth) : base(auth) { } /// /// TODO Bio language diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/GetShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/GetShoutsCommand.cs index d5a88bd..709220d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/GetShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/GetShoutsCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.getShouts")] internal class GetShoutsCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -17,7 +18,6 @@ internal class GetShoutsCommand : GetAsyncCommandBase> public GetShoutsCommand(ILastAuth auth, string artistname) : base(auth) { - Method = "artist.getShouts"; ArtistName = artistname; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/GetSimilarCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/GetSimilarCommand.cs index bed77f8..2366b94 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/GetSimilarCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/GetSimilarCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.getSimilar")] internal class GetSimilarCommand : GetAsyncCommandBase> { public bool Autocorrect { get; set; } @@ -20,8 +21,6 @@ internal class GetSimilarCommand : GetAsyncCommandBase> public GetSimilarCommand(ILastAuth auth, string artistName) : base(auth) { - Method = "artist.getSimilar"; - ArtistName = artistName; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTagsByUserCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTagsByUserCommand.cs index 1854fe8..ce3f31a 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTagsByUserCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTagsByUserCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.getTags")] internal class GetTagsByUserCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -20,8 +21,6 @@ internal class GetTagsByUserCommand : GetAsyncCommandBase> public GetTagsByUserCommand(ILastAuth auth, string artist, string username) : base(auth) { - Method = "artist.getTags"; - ArtistName = artist; Username = username; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopAlbumsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopAlbumsCommand.cs index cc9a1a0..a1adcd2 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopAlbumsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopAlbumsCommand.cs @@ -8,6 +8,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.getTopAlbums")] internal class GetTopAlbumsCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -15,7 +16,6 @@ internal class GetTopAlbumsCommand : GetAsyncCommandBase public GetTopAlbumsCommand(ILastAuth auth, string artistname) : base(auth) { - Method = "artist.getTopAlbums"; ArtistName = artistname; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTagsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTagsCommand.cs index ec27893..7d41a6b 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTagsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTagsCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.getTopTags")] internal class GetTopTagsCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -17,8 +18,6 @@ internal class GetTopTagsCommand : GetAsyncCommandBase> public GetTopTagsCommand(ILastAuth auth, string artistName) : base(auth) { - Method = "artist.getTopTags"; - ArtistName = artistName; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTracksCommand.cs index 4344208..2558522 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/GetTopTracksCommand.cs @@ -8,6 +8,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.getTopTracks")] internal class GetTopTracksCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -15,7 +16,6 @@ internal class GetTopTracksCommand : GetAsyncCommandBase public GetTopTracksCommand(ILastAuth auth, string artistname) : base(auth) { - Method = "artist.getTopTracks"; ArtistName = artistname; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Artist/SearchCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Artist/SearchCommand.cs index 1556570..41f9c22 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Artist/SearchCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Artist/SearchCommand.cs @@ -8,6 +8,7 @@ namespace IF.Lastfm.Core.Api.Commands.Artist { + [ApiMethodName("artist.search")] internal class SearchCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -15,7 +16,6 @@ internal class SearchCommand : GetAsyncCommandBase> public SearchCommand(ILastAuth auth, string artistName) : base(auth) { - Method = "artist.search"; ArtistName = artistName; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Auth/GetMobileSessionCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Auth/GetMobileSessionCommand.cs index 9716ad8..73bf2f2 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Auth/GetMobileSessionCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Auth/GetMobileSessionCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Auth { + [ApiMethodName("auth.getMobileSession")] internal class GetMobileSessionCommand : UnauthenticatedPostAsyncCommandBase> { public string Username { get; set; } @@ -17,7 +18,6 @@ internal class GetMobileSessionCommand : UnauthenticatedPostAsyncCommandBase> { - 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> HandleResponse(HttpResponse return LastResponse.CreateErrorResponse>(status); } - + } } } diff --git a/src/IF.Lastfm.Core/Api/Commands/Chart/GetTopTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Chart/GetTopTracksCommand.cs index cd5a4e8..6233d50 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Chart/GetTopTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Chart/GetTopTracksCommand.cs @@ -8,13 +8,10 @@ namespace IF.Lastfm.Core.Api.Commands.Chart { + [ApiMethodName("chart.getTopTracks")] internal class GetTopTracksCommand : GetAsyncCommandBase> { - public GetTopTracksCommand(ILastAuth auth) - : base(auth) - { - Method = "chart.getTopTracks"; - } + public GetTopTracksCommand(ILastAuth auth) : base(auth) { } public override void SetParameters() { diff --git a/src/IF.Lastfm.Core/Api/Commands/LastAsyncCommandBase.cs b/src/IF.Lastfm.Core/Api/Commands/LastAsyncCommandBase.cs index ee72dbe..f77b9dc 100644 --- a/src/IF.Lastfm.Core/Api/Commands/LastAsyncCommandBase.cs +++ b/src/IF.Lastfm.Core/Api/Commands/LastAsyncCommandBase.cs @@ -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 /// public abstract class LastAsyncCommandBase { - public string Method { get; protected set; } + public string Method + { + get + { + var methodNameAttribute = this.GetType().GetTypeInfo().GetCustomAttribute(); + 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 Parameters { get; set; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Library/GetTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Library/GetTracksCommand.cs index b3a6e34..4e449c7 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Library/GetTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Library/GetTracksCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Library { + [ApiMethodName("library.getTracks")] internal class GetTracksCommand : GetAsyncCommandBase> { public string Username { get; private set; } @@ -22,8 +23,6 @@ internal class GetTracksCommand : GetAsyncCommandBase> public GetTracksCommand(ILastAuth auth, string username, string artist, string album, DateTimeOffset from) : base(auth) { - Method = "library.getTracks"; - Username = username; Artist = artist; Album = album; diff --git a/src/IF.Lastfm.Core/Api/Commands/Library/RemoveScrobbleCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Library/RemoveScrobbleCommand.cs index b2459ca..34bfa5d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Library/RemoveScrobbleCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Library/RemoveScrobbleCommand.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json; namespace IF.Lastfm.Core.Api.Commands.Library { + [ApiMethodName("library.removeScrobble")] internal class RemoveScrobbleCommand : PostAsyncCommandBase { public string Artist { get; set; } @@ -15,8 +16,6 @@ internal class RemoveScrobbleCommand : PostAsyncCommandBase { 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; diff --git a/src/IF.Lastfm.Core/Api/Commands/Library/RemoveTrackCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Library/RemoveTrackCommand.cs index dc51d5c..e0aac39 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Library/RemoveTrackCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Library/RemoveTrackCommand.cs @@ -3,14 +3,13 @@ using IF.Lastfm.Core.Api.Helpers; namespace IF.Lastfm.Core.Api.Commands.Library { + [ApiMethodName("library.removeTrack")] internal class RemoveTrackCommand : PostAsyncCommandBase { 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; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/AddShoutCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/AddShoutCommand.cs index 0e1b2ff..b1656ef 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/AddShoutCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/AddShoutCommand.cs @@ -4,6 +4,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.shout")] internal class AddShoutCommand : PostAsyncCommandBase { public string Track { get; set; } @@ -15,8 +16,6 @@ internal class AddShoutCommand : PostAsyncCommandBase public AddShoutCommand(ILastAuth auth, string track, string artist, string message) : base(auth) { - Method = "track.shout"; - Track = track; Artist = artist; Message = message; diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/GetInfoCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/GetInfoCommand.cs index 3f8ee60..d22ac12 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/GetInfoCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/GetInfoCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.getInfo")] internal class GetInfoCommand : GetAsyncCommandBase> { public string TrackMbid { get; set; } @@ -21,11 +22,7 @@ internal class GetInfoCommand : GetAsyncCommandBase> public bool Autocorrect { get; set; } - public GetInfoCommand(ILastAuth auth) - : base(auth) - { - Method = "track.getInfo"; - } + public GetInfoCommand(ILastAuth auth) : base(auth) { } public override void SetParameters() { diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/GetShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/GetShoutsCommand.cs index e41b235..7f12bf7 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/GetShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/GetShoutsCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.getShouts")] internal class GetShoutsCommand : GetAsyncCommandBase> { public string TrackName { get; set; } @@ -20,8 +21,6 @@ internal class GetShoutsCommand : GetAsyncCommandBase> public GetShoutsCommand(ILastAuth auth, string trackname, string artistname) : base(auth) { - Method = "track.getShouts"; - TrackName = trackname; ArtistName = artistname; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/GetSimilarCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/GetSimilarCommand.cs index 742d521..76fa0ad 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/GetSimilarCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/GetSimilarCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.getSimilar")] internal class GetSimilarCommand : GetAsyncCommandBase> { public string ArtistName { get; set; } @@ -22,8 +23,6 @@ internal class GetSimilarCommand : GetAsyncCommandBase> public GetSimilarCommand(ILastAuth auth, string trackName, string artistName) : base(auth) { - Method = "track.getSimilar"; - ArtistName = artistName; TrackName = trackName; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/LoveCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/LoveCommand.cs index a4923c4..edc956c 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/LoveCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/LoveCommand.cs @@ -4,6 +4,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.love")] internal class LoveCommand : PostAsyncCommandBase { public string TrackName { get; set; } @@ -13,8 +14,6 @@ internal class LoveCommand : PostAsyncCommandBase public LoveCommand(ILastAuth auth, string trackname, string artistname) : base(auth) { - Method = "track.love"; - TrackName = trackname; ArtistName = artistname; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/ScrobbleCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/ScrobbleCommand.cs index d0bc64f..99e493d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/ScrobbleCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/ScrobbleCommand.cs @@ -10,6 +10,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.scrobble")] internal class ScrobbleCommand : PostAsyncCommandBase { public IList Scrobbles { get; private set; } @@ -22,7 +23,6 @@ public ScrobbleCommand(ILastAuth auth, IList scrobbles) throw new ArgumentOutOfRangeException("scrobbles", "Only 50 scrobbles can be sent at a time"); } - Method = "track.scrobble"; Scrobbles = scrobbles; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/SearchCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/SearchCommand.cs index e0cacc8..e5b87cc 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/SearchCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/SearchCommand.cs @@ -8,6 +8,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.search")] internal class SearchCommand : GetAsyncCommandBase> { public string TrackName { get; set; } @@ -15,7 +16,6 @@ internal class SearchCommand : GetAsyncCommandBase> public SearchCommand(ILastAuth auth, string trackName) : base(auth) { - Method = "track.search"; TrackName = trackName; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/UnloveCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/UnloveCommand.cs index 84811d7..29ece5d 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/UnloveCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/UnloveCommand.cs @@ -4,6 +4,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.unlove")] internal class UnloveCommand : PostAsyncCommandBase { public string TrackName { get; set; } @@ -13,8 +14,6 @@ internal class UnloveCommand : PostAsyncCommandBase public UnloveCommand(ILastAuth auth, string trackname, string artistname) : base(auth) { - Method = "track.unlove"; - TrackName = trackname; ArtistName = artistname; } diff --git a/src/IF.Lastfm.Core/Api/Commands/Track/UpdateNowPlayingCommand.cs b/src/IF.Lastfm.Core/Api/Commands/Track/UpdateNowPlayingCommand.cs index 51a1b40..c9c6eb8 100644 --- a/src/IF.Lastfm.Core/Api/Commands/Track/UpdateNowPlayingCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/Track/UpdateNowPlayingCommand.cs @@ -7,6 +7,7 @@ namespace IF.Lastfm.Core.Api.Commands.Track { + [ApiMethodName("track.updateNowPlaying")] internal class UpdateNowPlayingCommand : PostAsyncCommandBase { public string Artist { get; set; } @@ -24,8 +25,6 @@ internal class UpdateNowPlayingCommand : PostAsyncCommandBase public UpdateNowPlayingCommand(ILastAuth auth, string artist, string album, string track) : base(auth) { - Method = "track.updateNowPlaying"; - Artist = artist; Album = album; Track = track; diff --git a/src/IF.Lastfm.Core/Api/Commands/User/AddShoutCommand.cs b/src/IF.Lastfm.Core/Api/Commands/User/AddShoutCommand.cs index 5e27e53..2950aa9 100644 --- a/src/IF.Lastfm.Core/Api/Commands/User/AddShoutCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/User/AddShoutCommand.cs @@ -4,6 +4,7 @@ namespace IF.Lastfm.Core.Api.Commands.User { + [ApiMethodName("user.shout")] internal class AddShoutCommand : PostAsyncCommandBase { public string Recipient { get; set; } @@ -13,8 +14,6 @@ internal class AddShoutCommand : PostAsyncCommandBase public AddShoutCommand(ILastAuth auth, string recipient, string message) : base(auth) { - Method = "user.shout"; - Recipient = recipient; Message = message; } diff --git a/src/IF.Lastfm.Core/Api/Commands/User/GetInfoCommand.cs b/src/IF.Lastfm.Core/Api/Commands/User/GetInfoCommand.cs index af8923f..d31e780 100644 --- a/src/IF.Lastfm.Core/Api/Commands/User/GetInfoCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/User/GetInfoCommand.cs @@ -8,13 +8,13 @@ namespace IF.Lastfm.Core.Api.Commands.User { + [ApiMethodName("user.getInfo")] internal class GetInfoCommand : GetAsyncCommandBase> { public string Username { get; set; } public GetInfoCommand(ILastAuth auth, string username) : base(auth) { - Method = "user.getInfo"; Username = username; } diff --git a/src/IF.Lastfm.Core/Api/Commands/User/GetRecentStationsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/User/GetRecentStationsCommand.cs index 90abdea..254d3b9 100644 --- a/src/IF.Lastfm.Core/Api/Commands/User/GetRecentStationsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/User/GetRecentStationsCommand.cs @@ -9,13 +9,13 @@ namespace IF.Lastfm.Core.Api.Commands.User { + [ApiMethodName("user.getRecentStations")] internal class GetRecentStationsCommand : PostAsyncCommandBase> { public string Username { get; private set; } public GetRecentStationsCommand(ILastAuth auth, string username) : base(auth) { - Method = "user.getRecentStations"; Username = username; } diff --git a/src/IF.Lastfm.Core/Api/Commands/User/GetRecentTracksCommand.cs b/src/IF.Lastfm.Core/Api/Commands/User/GetRecentTracksCommand.cs index fbdc76b..a45d352 100644 --- a/src/IF.Lastfm.Core/Api/Commands/User/GetRecentTracksCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/User/GetRecentTracksCommand.cs @@ -9,6 +9,7 @@ namespace IF.Lastfm.Core.Api.Commands.User { + [ApiMethodName("user.getRecentTracks")] internal class GetRecentTracksCommand : GetAsyncCommandBase> { public string Username { get; private set; } @@ -17,8 +18,6 @@ internal class GetRecentTracksCommand : GetAsyncCommandBase> { - public GetRecommendedArtistsCommand(ILastAuth auth) : base(auth) - { - Method = "user.getRecommendedArtists"; - } + public GetRecommendedArtistsCommand(ILastAuth auth) : base(auth) { } public override void SetParameters() { diff --git a/src/IF.Lastfm.Core/Api/Commands/User/GetShoutsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/User/GetShoutsCommand.cs index 6223f66..d820ac7 100644 --- a/src/IF.Lastfm.Core/Api/Commands/User/GetShoutsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/User/GetShoutsCommand.cs @@ -8,13 +8,13 @@ namespace IF.Lastfm.Core.Api.Commands.User { + [ApiMethodName("user.getShouts")] internal class GetShoutsCommand : GetAsyncCommandBase> { public string Username { get; set; } public GetShoutsCommand(ILastAuth auth, string username) : base(auth) { - Method = "user.getShouts"; Username = username; } diff --git a/src/IF.Lastfm.Core/Api/Commands/User/GetTopAlbumsCommand.cs b/src/IF.Lastfm.Core/Api/Commands/User/GetTopAlbumsCommand.cs index 6e29044..1beca30 100644 --- a/src/IF.Lastfm.Core/Api/Commands/User/GetTopAlbumsCommand.cs +++ b/src/IF.Lastfm.Core/Api/Commands/User/GetTopAlbumsCommand.cs @@ -7,6 +7,7 @@ namespace IF.Lastfm.Core.Api.Commands.User { + [ApiMethodName("user.getTopAlbums")] internal class GetTopAlbumsCommand : GetAsyncCommandBase> { public string Username { get; set; } @@ -14,7 +15,6 @@ internal class GetTopAlbumsCommand : GetAsyncCommandBase public GetTopAlbumsCommand(ILastAuth auth, string username, LastStatsTimeSpan span) : base(auth) { - Method = "user.getTopAlbums"; Username = username; TimeSpan = span; } diff --git a/src/IF.Lastfm.Core/Api/Helpers/ApiNameAttribute.cs b/src/IF.Lastfm.Core/Api/Helpers/ApiNameAttribute.cs index b52e890..d391fe8 100644 --- a/src/IF.Lastfm.Core/Api/Helpers/ApiNameAttribute.cs +++ b/src/IF.Lastfm.Core/Api/Helpers/ApiNameAttribute.cs @@ -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; } } + + /// + /// This attribute defines the api method name (i.e: "album.getInfo") for a Command. + /// When applied on a implementation, the property is set to the attribute value. + /// + [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] + public class ApiMethodNameAttribute : ApiNameAttribute + { + public ApiMethodNameAttribute(string name) : base(name) { } + } } \ No newline at end of file diff --git a/src/IF.Lastfm.Syro/Helpers/DummyGetAsyncCommand.cs b/src/IF.Lastfm.Syro/Helpers/DummyGetAsyncCommand.cs index 5d188bb..cd4986d 100644 --- a/src/IF.Lastfm.Syro/Helpers/DummyGetAsyncCommand.cs +++ b/src/IF.Lastfm.Syro/Helpers/DummyGetAsyncCommand.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json.Linq; using System.Net.Http; using System.Threading.Tasks; +using System; namespace IF.Lastfm.Syro.Helpers { diff --git a/src/IF.Lastfm.Syro/Tools/ProgressReport.cs b/src/IF.Lastfm.Syro/Tools/ProgressReport.cs index 116731c..f917a7e 100644 --- a/src/IF.Lastfm.Syro/Tools/ProgressReport.cs +++ b/src/IF.Lastfm.Syro/Tools/ProgressReport.cs @@ -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> 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)) { diff --git a/src/IF.Lastfm.Syro/Tools/Reflektor.cs b/src/IF.Lastfm.Syro/Tools/Reflektor.cs index a80ddf5..a785e71 100644 --- a/src/IF.Lastfm.Syro/Tools/Reflektor.cs +++ b/src/IF.Lastfm.Syro/Tools/Reflektor.cs @@ -31,19 +31,5 @@ internal static IEnumerable 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; - } } } \ No newline at end of file diff --git a/src/IF.Lastfm.Syro/ViewModels/MainViewModel.cs b/src/IF.Lastfm.Syro/ViewModels/MainViewModel.cs index 8beaa8b..8397689 100644 --- a/src/IF.Lastfm.Syro/ViewModels/MainViewModel.cs +++ b/src/IF.Lastfm.Syro/ViewModels/MainViewModel.cs @@ -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().Text).ToList(); // generate the markdown _reportPath = Path.GetFullPath(SolutionDir + ReportFilename);