diff --git a/IF.Lastfm.Core/Api/Auth.cs b/IF.Lastfm.Core/Api/Auth.cs index 77ac9bf..0ea39de 100644 --- a/IF.Lastfm.Core/Api/Auth.cs +++ b/IF.Lastfm.Core/Api/Auth.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using System.Linq; using System.Net.Http; +using System.Text; using System.Threading.Tasks; using IF.Lastfm.Core.Api.Enums; using IF.Lastfm.Core.Api.Helpers; @@ -12,15 +14,15 @@ namespace IF.Lastfm.Core.Api { public class Auth : IAuth { - private const string ApiSignatureSeedFormat = "api_key{0}method{1}password{2}username{3}{4}"; private const string ApiAuthMethod = "auth.getMobileSession"; private readonly string _apiSecret; + private string _password; + private string _username; public bool HasAuthenticated { get { return User != null; } } public string ApiKey { get; private set; } public UserSession User { get; private set; } - public string ApiSignature { get; private set; } public Auth(string apikey, string secret) { @@ -32,10 +34,12 @@ public async Task GetSessionTokenAsync(string username, string pas { const string apiMethod = "auth.getMobileSession"; - var apisigseed = string.Format(ApiSignatureSeedFormat, ApiKey, ApiAuthMethod, password, username, _apiSecret); - ApiSignature = MD5.GetHashString(apisigseed); + _password = password; + _username = username; - var postContent = LastFm.CreatePostBody(apiMethod, ApiKey, ApiSignature, new Dictionary + var apisig = GenerateMethodSignature(apiMethod); + + var postContent = LastFm.CreatePostBody(apiMethod, ApiKey, apisig, new Dictionary { {"password", password}, {"username", username} @@ -59,5 +63,30 @@ public async Task GetSessionTokenAsync(string username, string pas return LastResponse.CreateErrorResponse(error); } } + + public string GenerateMethodSignature(string method, Dictionary parameters = null) + { + if (parameters == null) + { + parameters = new Dictionary(); + } + + parameters.Add("api_key", ApiKey); + parameters.Add("method", method); + parameters.Add("password", _password); + parameters.Add("username", _username); + + var builder = new StringBuilder(); + + foreach (var kv in parameters.OrderBy(kv => kv.Key)) + { + builder.Append(kv.Key); + builder.Append(kv.Value); + } + + builder.Append(_apiSecret); + + return MD5.GetHashString(builder.ToString()); + } } } \ No newline at end of file diff --git a/IF.Lastfm.Core/Api/Helpers/ApiExtensions.cs b/IF.Lastfm.Core/Api/Helpers/ApiExtensions.cs index 0038a58..3e9fe23 100644 --- a/IF.Lastfm.Core/Api/Helpers/ApiExtensions.cs +++ b/IF.Lastfm.Core/Api/Helpers/ApiExtensions.cs @@ -28,9 +28,11 @@ public static int ToInt(this bool b) return b ? 1 : 0; } - public static double ToUnixTimestamp(this DateTime dt) + public static int ToUnixTimestamp(this DateTime dt) { - return (dt - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; + var d = (dt - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; + + return Convert.ToInt32(d); } } } \ No newline at end of file diff --git a/IF.Lastfm.Core/Api/IAuth.cs b/IF.Lastfm.Core/Api/IAuth.cs index 80fb63c..b31b548 100644 --- a/IF.Lastfm.Core/Api/IAuth.cs +++ b/IF.Lastfm.Core/Api/IAuth.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using IF.Lastfm.Core.Api.Helpers; using IF.Lastfm.Core.Objects; @@ -9,7 +10,6 @@ public interface IAuth bool HasAuthenticated { get; } string ApiKey { get; } UserSession User { get; } - string ApiSignature { get; } /// /// Gets the session token which is used as authentication for any service calls. @@ -20,5 +20,7 @@ public interface IAuth /// Session token used to authenticate calls to last.fm /// API: Auth.getMobileSession Task GetSessionTokenAsync(string username, string password); + + string GenerateMethodSignature(string method, Dictionary parameters = null); } } \ No newline at end of file diff --git a/IF.Lastfm.Core/Api/TrackApi.cs b/IF.Lastfm.Core/Api/TrackApi.cs index 3f9f7b7..41d229e 100644 --- a/IF.Lastfm.Core/Api/TrackApi.cs +++ b/IF.Lastfm.Core/Api/TrackApi.cs @@ -22,18 +22,23 @@ public async Task ScrobbleAsync(Scrobble scrobble) { const string apiMethod = "track.scrobble"; + var methodParameters = new Dictionary + { + {"artist", scrobble.Artist}, + {"album", scrobble.Album}, + {"track", scrobble.Track}, + {"albumArtist", scrobble.AlbumArtist}, + {"chosenByUser", scrobble.ChosenByUser.ToInt().ToString()}, + {"timestamp", scrobble.TimePlayed.ToUnixTimestamp().ToString()}, + {"sk", Auth.User.Token} + }; + + var apisig = Auth.GenerateMethodSignature(apiMethod, methodParameters); + var postContent = LastFm.CreatePostBody(apiMethod, Auth.ApiKey, - Auth.ApiSignature, - new Dictionary - { - {"artist", scrobble.Artist}, - {"album", scrobble.Album}, - {"track", scrobble.Track}, - {"albumArtist", scrobble.AlbumArtist}, - {"chosenByUser", scrobble.ChosenByUser.ToInt().ToString()}, - {"timestamp", scrobble.TimePlayed.ToUnixTimestamp().ToString()} - }); + apisig, + methodParameters); var httpClient = new HttpClient(); HttpResponseMessage response = await httpClient.PostAsync(LastFm.ApiRoot, postContent); diff --git a/IF.Lastfm.Demo.Apollo/ApiTest.xaml b/IF.Lastfm.Demo.Apollo/ApiTest.xaml new file mode 100644 index 0000000..149dae7 --- /dev/null +++ b/IF.Lastfm.Demo.Apollo/ApiTest.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + +