From 92756c71b7e3535a7c7f4bbb9f1e30ce575048c0 Mon Sep 17 00:00:00 2001 From: Giancarlo Lelli Date: Sun, 19 Feb 2017 09:36:12 +0100 Subject: [PATCH] Minor refactorings after public release --- README.md | 2 +- src/GL.Sdk.Groove.Client/GrooveMusicClient.cs | 86 +++++++------------ .../Http/GrooveHttpClient.cs | 34 ++------ .../Responses/ActivitiesResponse.cs | 6 +- .../Responses/FeaturedResponse.cs | 4 +- .../Responses/GenresResponse.cs | 6 +- .../Responses/GrooveResponse.cs | 6 +- .../Responses/MoodsResponse.cs | 6 +- .../Responses/ResponseBase.cs | 13 +++ .../Responses/TrackPlaybackResponse.cs | 4 +- .../Responses/UserProfileResponse.cs | 6 +- .../GL.Sdk.Groove.Test.csproj | 3 +- test/GL.Sdk.Groove.Test/Program.cs | 2 +- 13 files changed, 66 insertions(+), 112 deletions(-) create mode 100644 src/GL.Sdk.Groove.Models/Responses/ResponseBase.cs diff --git a/README.md b/README.md index 0294b1a..9e42dfc 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ For those who are too lazy to browse to that file, here's a snippet of that file ```csharp class Program { - static void Main(string[] args) => Task.Run(async () => await MainAsync(args)).Wait(); + static void Main(string[] args) => MainAsync(args).GetAwaiter().GetResult(); static async Task MainAsync(string[] args) { diff --git a/src/GL.Sdk.Groove.Client/GrooveMusicClient.cs b/src/GL.Sdk.Groove.Client/GrooveMusicClient.cs index 50c3d8f..642f939 100644 --- a/src/GL.Sdk.Groove.Client/GrooveMusicClient.cs +++ b/src/GL.Sdk.Groove.Client/GrooveMusicClient.cs @@ -57,9 +57,8 @@ public GrooveMusicClient(string clientId, string clientSecret, RegionInfo locale /// The list of items found in the catalog public async Task SearchAsync(string keyword) { - var url = $"search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -71,9 +70,8 @@ public async Task SearchAsync(string keyword) public async Task SearchAsync(string keyword, int maxResults) { if (maxResults > 25 || maxResults <= 0) throw new ArgumentException("maxResults must be greater than 0 and less than 25", "maxResults"); - var url = $"search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}&maxitems={maxResults}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}&maxitems={maxResults}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -87,9 +85,8 @@ public async Task SearchAsync(string keyword, int maxResults, IE { if (maxResults > 25) throw new ArgumentException("maxResults must be greater than 0 and less than 25", "maxResults"); var aggregatedFilters = ParametersFormatter.Format(filters.Select(x => x.ToString())); - var url = $"search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}&maxitems={maxResults}&filters={aggregatedFilters}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}&maxitems={maxResults}&filters={aggregatedFilters}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -105,9 +102,8 @@ public async Task SearchAsync(string keyword, int maxResults, IE if (maxResults > 25) throw new ArgumentException("maxResults must be greater than 0 and less than 25", "maxResults"); var aggregatedFilters = ParametersFormatter.Format(filters.Select(x => x.ToString())); var formattedSource = ParametersFormatter.Format(source.Select(x => x.ToString())); - var url = $"search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}&maxitems={maxResults}&filters={aggregatedFilters}&source={formattedSource}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/search?q={Uri.EscapeDataString(keyword)}&country={m_culture.Name}&language={m_culture.Name}&maxitems={maxResults}&filters={aggregatedFilters}&source={formattedSource}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -117,9 +113,8 @@ public async Task SearchAsync(string keyword, int maxResults, IE /// The list of items found in the catalog public async Task ContinueSearchAsync(string continuationToken) { - var url = $"search?continuationToken={continuationToken}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/search?continuationToken={continuationToken}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -130,9 +125,8 @@ public async Task ContinueSearchAsync(string continuationToken) public async Task LookupAsync(IEnumerable ids) { var formattedParams = ParametersFormatter.Format(ids); - var url = $"{formattedParams}/lookup?locale={m_culture.Name}&country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryCatalogServiceAsync(url); - return response; + var url = $"1/content/{formattedParams}/lookup?locale={m_culture.Name}&country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -145,9 +139,8 @@ public async Task LookupAsync(IEnumerable ids, IEnumerab { var formattedParams = ParametersFormatter.Format(ids); var formattedSource = ParametersFormatter.Format(source.Select(x => x.ToString())); - var url = $"{formattedParams}/lookup?locale={m_culture.Name}&country={m_culture.Name}&language={m_culture.Name}&source={formattedSource}"; - var response = await m_client.Value.QueryCatalogServiceAsync(url); - return response; + var url = $"1/content/{formattedParams}/lookup?locale={m_culture.Name}&country={m_culture.Name}&language={m_culture.Name}&source={formattedSource}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -162,9 +155,8 @@ public async Task LookupAsync(IEnumerable ids, IEnumerab var formattedParams = ParametersFormatter.Format(ids); var formattedSource = ParametersFormatter.Format(source.Select(x => x.ToString())); var formattedExtras = ParametersFormatter.Format(extraFields.Select(x => x.ToString())); - var url = $"{formattedParams}/lookup?locale={m_culture.Name}&country={m_culture.Name}&language={m_culture.Name}&source={formattedSource}&extras={formattedExtras}"; - var response = await m_client.Value.QueryCatalogServiceAsync(url); - return response; + var url = $"1/content/{formattedParams}/lookup?locale={m_culture.Name}&country={m_culture.Name}&language={m_culture.Name}&source={formattedSource}&extras={formattedExtras}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -176,9 +168,8 @@ public async Task LookupAsync(IEnumerable ids, IEnumerab public async Task ContinueLookupAsync(string continuationToken, IEnumerable ids) { var formattedParams = ParametersFormatter.Format(ids); - var url = $"{formattedParams}/lookup?continuationToken={continuationToken}"; - var response = await m_client.Value.QueryCatalogServiceAsync(url); - return response; + var url = $"1/content/{formattedParams}/lookup?continuationToken={continuationToken}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -187,9 +178,8 @@ public async Task ContinueLookupAsync(string continuationToken, /// The list of available genres public async Task GetGenresAsync() { - string url = $"catalog/genres?country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + string url = $"1/content/music/catalog/genres?country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -198,20 +188,15 @@ public async Task GetGenresAsync() /// The list of featured albums public async Task GetSpotlightAsync() { - string url = $"spotlight?country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + string url = $"1/content/music/spotlight?country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// /// Fetches the user's profile /// /// The user profile - public async Task GetUserProfileAsync() - { - var response = await m_client.Value.QueryMusicServiceAsync("/1/user/music/profile"); - return response; - } + public async Task GetUserProfileAsync() => await m_client.Value.QueryMusicServiceAsync("1/user/music/profile"); /// /// Fetches the new releases for the current locale @@ -219,9 +204,8 @@ public async Task GetUserProfileAsync() /// The list of new releases public async Task GetNewReleasesAsync() { - var url = $"newreleases?country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/newreleases?country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -231,9 +215,8 @@ public async Task GetNewReleasesAsync() /// The list of new releases public async Task GetNewReleasesAsync(GenreModel genre) { - var url = $"newreleases?genre={genre.Name}&country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/newreleases?genre={genre.Name}&country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -242,9 +225,8 @@ public async Task GetNewReleasesAsync(GenreModel genre) /// The list of available moods public async Task GetAvailableMoodsAsync() { - var url = $"catalog/moods?&country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/catalog/moods?&country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -253,9 +235,8 @@ public async Task GetAvailableMoodsAsync() /// public async Task GetAvailableActivitiesAsync() { - var url = $"catalog/activities?&country={m_culture.Name}&language={m_culture.Name}"; - var response = await m_client.Value.QueryMusicServiceAsync(url); - return response; + var url = $"1/content/music/catalog/activities?&country={m_culture.Name}&language={m_culture.Name}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// @@ -266,9 +247,8 @@ public async Task GetAvailableActivitiesAsync() /// public async Task GetPreviewStreamAsync(string track, PlaybackType streamType) { - var url = $"{track}/{streamType}?country={m_culture.Name}&language={m_culture.Name}&clientInstanceId={m_client.Value.ClienteInstanceId}"; - var response = await m_client.Value.QueryCatalogServiceAsync(url); - return response; + var url = $"1/content/{track}/{streamType}?country={m_culture.Name}&language={m_culture.Name}&clientInstanceId={m_client.Value.ClienteInstanceId}"; + return await m_client.Value.QueryMusicServiceAsync(url); } /// diff --git a/src/GL.Sdk.Groove.Client/Http/GrooveHttpClient.cs b/src/GL.Sdk.Groove.Client/Http/GrooveHttpClient.cs index cbc200c..1474555 100644 --- a/src/GL.Sdk.Groove.Client/Http/GrooveHttpClient.cs +++ b/src/GL.Sdk.Groove.Client/Http/GrooveHttpClient.cs @@ -11,9 +11,8 @@ namespace GL.Sdk.Groove.Client.Http { internal class GrooveHttpClient : IDisposable { - private readonly HttpClient m_musicHttp; - private readonly HttpClient m_catalogHttp; - private readonly Dictionary m_requestData; + private static HttpClient _grooveHttpClient; + private readonly Dictionary _requestData; public AuthTokenModel AccessToken { get; private set; } @@ -22,11 +21,9 @@ internal class GrooveHttpClient : IDisposable public GrooveHttpClient(string clientId, string clientSecret) { ClienteInstanceId = Guid.NewGuid(); + _grooveHttpClient = new HttpClient() { BaseAddress = new Uri("https://music.xboxlive.com/") }; - m_musicHttp = new HttpClient() { BaseAddress = new Uri("https://music.xboxlive.com/1/content/music/") }; - m_catalogHttp = new HttpClient() { BaseAddress = new Uri("https://music.xboxlive.com/1/content/") }; - - m_requestData = new Dictionary() + _requestData = new Dictionary() { { "client_id", clientId }, { "client_secret", clientSecret }, @@ -34,36 +31,27 @@ public GrooveHttpClient(string clientId, string clientSecret) { "grant_type", "client_credentials" } }; - Task.Run(async () => await AuthenticateAsync()).Wait(); + AuthenticateAsync().GetAwaiter().GetResult(); } public async Task QueryMusicServiceAsync(string request) { await ValidateTokenAsync(); - var response = await m_musicHttp.GetAsync(request); - string json = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(json); - } - - public async Task QueryCatalogServiceAsync(string request) - { - await ValidateTokenAsync(); - var response = await m_catalogHttp.GetAsync(request); + var response = await _grooveHttpClient.GetAsync(request); string json = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(json); } private async Task AuthenticateAsync() { - var response = await m_musicHttp.PostAsync(new Uri("https://login.live.com/accesstoken.srf"), new FormUrlEncodedContent(m_requestData)); + var response = await _grooveHttpClient.PostAsync(new Uri("https://login.live.com/accesstoken.srf"), new FormUrlEncodedContent(_requestData)); if (response.IsSuccessStatusCode) { String responseString = await response.Content.ReadAsStringAsync(); AuthTokenModel tokenResponse = JsonConvert.DeserializeObject(responseString); AccessToken = tokenResponse; AccessToken.TokenExpiryDate = Convert.ToDouble(tokenResponse.ExpiresIn).UnixTimeStampToDateTime(); - m_musicHttp.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {AccessToken.AccessToken}"); - m_catalogHttp.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {AccessToken.AccessToken}"); + _grooveHttpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {AccessToken.AccessToken}"); } } @@ -73,10 +61,6 @@ private async Task ValidateTokenAsync() await AuthenticateAsync(); } - public void Dispose() - { - m_musicHttp?.Dispose(); - m_catalogHttp?.Dispose(); - } + public void Dispose() => _grooveHttpClient?.Dispose(); } } diff --git a/src/GL.Sdk.Groove.Models/Responses/ActivitiesResponse.cs b/src/GL.Sdk.Groove.Models/Responses/ActivitiesResponse.cs index d138640..cab144b 100644 --- a/src/GL.Sdk.Groove.Models/Responses/ActivitiesResponse.cs +++ b/src/GL.Sdk.Groove.Models/Responses/ActivitiesResponse.cs @@ -4,12 +4,8 @@ namespace GL.Sdk.Groove.Models.Responses { - public class ActivitiesResponse + public class ActivitiesResponse : ResponseBase { - public string Culture { get; set; } - public IEnumerable CatalogActivities { get; set; } - - public ErrorModel Error { get; set; } } } diff --git a/src/GL.Sdk.Groove.Models/Responses/FeaturedResponse.cs b/src/GL.Sdk.Groove.Models/Responses/FeaturedResponse.cs index ad2f9e1..a492ab1 100644 --- a/src/GL.Sdk.Groove.Models/Responses/FeaturedResponse.cs +++ b/src/GL.Sdk.Groove.Models/Responses/FeaturedResponse.cs @@ -4,10 +4,8 @@ namespace GL.Sdk.Groove.Models.Responses { - public class FeaturedResponse + public class FeaturedResponse : ResponseBase { public FeaturedItemCollectionModel Results { get; set; } - - public ErrorModel Error { get; set; } } } diff --git a/src/GL.Sdk.Groove.Models/Responses/GenresResponse.cs b/src/GL.Sdk.Groove.Models/Responses/GenresResponse.cs index 49b1e48..ebc1596 100644 --- a/src/GL.Sdk.Groove.Models/Responses/GenresResponse.cs +++ b/src/GL.Sdk.Groove.Models/Responses/GenresResponse.cs @@ -4,12 +4,8 @@ namespace GL.Sdk.Groove.Models.Responses { - public class GenresResponse + public class GenresResponse : ResponseBase { public IEnumerable Genres { get; set; } - - public string Culture { get; set; } - - public ErrorModel Error { get; set; } } } diff --git a/src/GL.Sdk.Groove.Models/Responses/GrooveResponse.cs b/src/GL.Sdk.Groove.Models/Responses/GrooveResponse.cs index 6f3077a..3e96c65 100644 --- a/src/GL.Sdk.Groove.Models/Responses/GrooveResponse.cs +++ b/src/GL.Sdk.Groove.Models/Responses/GrooveResponse.cs @@ -4,7 +4,7 @@ namespace GL.Sdk.Groove.Models.Responses { - public class GrooveResponse + public class GrooveResponse : ResponseBase { public TrackLookupResponse Tracks { get; set; } @@ -13,9 +13,5 @@ public class GrooveResponse public ArtistLookupResponse Artists { get; set; } public PlaylistLookupResponse Playlists { get; set; } - - public ErrorModel Error { get; set; } - - public string Culture { get; set; } } } diff --git a/src/GL.Sdk.Groove.Models/Responses/MoodsResponse.cs b/src/GL.Sdk.Groove.Models/Responses/MoodsResponse.cs index 5999769..72ec44e 100644 --- a/src/GL.Sdk.Groove.Models/Responses/MoodsResponse.cs +++ b/src/GL.Sdk.Groove.Models/Responses/MoodsResponse.cs @@ -4,12 +4,8 @@ namespace GL.Sdk.Groove.Models.Responses { - public class MoodsResponse + public class MoodsResponse : ResponseBase { - public string Culture { get; set; } - public IEnumerable CatalogMoods { get; set; } - - public ErrorModel Error { get; set; } } } diff --git a/src/GL.Sdk.Groove.Models/Responses/ResponseBase.cs b/src/GL.Sdk.Groove.Models/Responses/ResponseBase.cs new file mode 100644 index 0000000..477de46 --- /dev/null +++ b/src/GL.Sdk.Groove.Models/Responses/ResponseBase.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace GL.Sdk.Groove.Models.Responses +{ + public class ResponseBase + { + public string Culture { get; set; } + + public ErrorModel Error { get; set; } + } +} diff --git a/src/GL.Sdk.Groove.Models/Responses/TrackPlaybackResponse.cs b/src/GL.Sdk.Groove.Models/Responses/TrackPlaybackResponse.cs index 292fee8..d889ef3 100644 --- a/src/GL.Sdk.Groove.Models/Responses/TrackPlaybackResponse.cs +++ b/src/GL.Sdk.Groove.Models/Responses/TrackPlaybackResponse.cs @@ -4,14 +4,12 @@ namespace GL.Sdk.Groove.Models.Responses { - public class TrackPlaybackResponse + public class TrackPlaybackResponse : ResponseBase { public string ContentType { get; set; } public DateTime ExpiresOn { get; set; } public Uri Url { get; set; } - - public ErrorModel Error { get; set; } } } diff --git a/src/GL.Sdk.Groove.Models/Responses/UserProfileResponse.cs b/src/GL.Sdk.Groove.Models/Responses/UserProfileResponse.cs index b8df47b..4fe241a 100644 --- a/src/GL.Sdk.Groove.Models/Responses/UserProfileResponse.cs +++ b/src/GL.Sdk.Groove.Models/Responses/UserProfileResponse.cs @@ -4,18 +4,14 @@ namespace GL.Sdk.Groove.Models.Responses { - public class UserProfileResponse + public class UserProfileResponse : ResponseBase { public bool IsSubscriptionAvailableForPurchase { get; set; } public bool HasSuscription { get; set; } - public string Culture { get; set; } - public CollectionModel Collection { get; set; } public SubscriptionModel Subscription { get; set; } - - public ErrorModel Error { get; set; } } } diff --git a/test/GL.Sdk.Groove.Test/GL.Sdk.Groove.Test.csproj b/test/GL.Sdk.Groove.Test/GL.Sdk.Groove.Test.csproj index 8123342..fdaba58 100644 --- a/test/GL.Sdk.Groove.Test/GL.Sdk.Groove.Test.csproj +++ b/test/GL.Sdk.Groove.Test/GL.Sdk.Groove.Test.csproj @@ -4,6 +4,7 @@ netcoreapp1.1 - + + \ No newline at end of file diff --git a/test/GL.Sdk.Groove.Test/Program.cs b/test/GL.Sdk.Groove.Test/Program.cs index d54627b..9e31220 100644 --- a/test/GL.Sdk.Groove.Test/Program.cs +++ b/test/GL.Sdk.Groove.Test/Program.cs @@ -6,7 +6,7 @@ class Program { - static void Main(string[] args) => Task.Run(async () => await MainAsync(args)).Wait(); + static void Main(string[] args) => MainAsync(args).GetAwaiter().GetResult(); static async Task MainAsync(string[] args) {