Skip to content

Commit

Permalink
Minor refactorings after public release
Browse files Browse the repository at this point in the history
  • Loading branch information
GiancarloLelli committed Feb 19, 2017
1 parent 76f0b67 commit 92756c7
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 112 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
86 changes: 33 additions & 53 deletions src/GL.Sdk.Groove.Client/GrooveMusicClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ public GrooveMusicClient(string clientId, string clientSecret, RegionInfo locale
/// <returns>The list of items found in the catalog</returns>
public async Task<GrooveResponse> 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<GrooveResponse>(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<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -71,9 +70,8 @@ public async Task<GrooveResponse> SearchAsync(string keyword)
public async Task<GrooveResponse> 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<GrooveResponse>(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<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -87,9 +85,8 @@ public async Task<GrooveResponse> 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<GrooveResponse>(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<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -105,9 +102,8 @@ public async Task<GrooveResponse> 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<GrooveResponse>(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<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -117,9 +113,8 @@ public async Task<GrooveResponse> SearchAsync(string keyword, int maxResults, IE
/// <returns>The list of items found in the catalog</returns>
public async Task<GrooveResponse> ContinueSearchAsync(string continuationToken)
{
var url = $"search?continuationToken={continuationToken}";
var response = await m_client.Value.QueryMusicServiceAsync<GrooveResponse>(url);
return response;
var url = $"1/content/music/search?continuationToken={continuationToken}";
return await m_client.Value.QueryMusicServiceAsync<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -130,9 +125,8 @@ public async Task<GrooveResponse> ContinueSearchAsync(string continuationToken)
public async Task<GrooveResponse> LookupAsync(IEnumerable<string> 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<GrooveResponse>(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<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -145,9 +139,8 @@ public async Task<GrooveResponse> LookupAsync(IEnumerable<string> 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<GrooveResponse>(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<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -162,9 +155,8 @@ public async Task<GrooveResponse> LookupAsync(IEnumerable<string> 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<GrooveResponse>(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<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -176,9 +168,8 @@ public async Task<GrooveResponse> LookupAsync(IEnumerable<string> ids, IEnumerab
public async Task<GrooveResponse> ContinueLookupAsync(string continuationToken, IEnumerable<string> ids)
{
var formattedParams = ParametersFormatter.Format(ids);
var url = $"{formattedParams}/lookup?continuationToken={continuationToken}";
var response = await m_client.Value.QueryCatalogServiceAsync<GrooveResponse>(url);
return response;
var url = $"1/content/{formattedParams}/lookup?continuationToken={continuationToken}";
return await m_client.Value.QueryMusicServiceAsync<GrooveResponse>(url);
}

/// <summary>
Expand All @@ -187,9 +178,8 @@ public async Task<GrooveResponse> ContinueLookupAsync(string continuationToken,
/// <returns>The list of available genres</returns>
public async Task<GenresResponse> GetGenresAsync()
{
string url = $"catalog/genres?country={m_culture.Name}&language={m_culture.Name}";
var response = await m_client.Value.QueryMusicServiceAsync<GenresResponse>(url);
return response;
string url = $"1/content/music/catalog/genres?country={m_culture.Name}&language={m_culture.Name}";
return await m_client.Value.QueryMusicServiceAsync<GenresResponse>(url);
}

/// <summary>
Expand All @@ -198,30 +188,24 @@ public async Task<GenresResponse> GetGenresAsync()
/// <returns>The list of featured albums</returns>
public async Task<FeaturedResponse> GetSpotlightAsync()
{
string url = $"spotlight?country={m_culture.Name}&language={m_culture.Name}";
var response = await m_client.Value.QueryMusicServiceAsync<FeaturedResponse>(url);
return response;
string url = $"1/content/music/spotlight?country={m_culture.Name}&language={m_culture.Name}";
return await m_client.Value.QueryMusicServiceAsync<FeaturedResponse>(url);
}

/// <summary>
/// Fetches the user's profile
/// </summary>
/// <returns>The user profile</returns>
public async Task<UserProfileResponse> GetUserProfileAsync()
{
var response = await m_client.Value.QueryMusicServiceAsync<UserProfileResponse>("/1/user/music/profile");
return response;
}
public async Task<UserProfileResponse> GetUserProfileAsync() => await m_client.Value.QueryMusicServiceAsync<UserProfileResponse>("1/user/music/profile");

/// <summary>
/// Fetches the new releases for the current locale
/// </summary>
/// <returns>The list of new releases</returns>
public async Task<FeaturedResponse> GetNewReleasesAsync()
{
var url = $"newreleases?country={m_culture.Name}&language={m_culture.Name}";
var response = await m_client.Value.QueryMusicServiceAsync<FeaturedResponse>(url);
return response;
var url = $"1/content/music/newreleases?country={m_culture.Name}&language={m_culture.Name}";
return await m_client.Value.QueryMusicServiceAsync<FeaturedResponse>(url);
}

/// <summary>
Expand All @@ -231,9 +215,8 @@ public async Task<FeaturedResponse> GetNewReleasesAsync()
/// <returns>The list of new releases</returns>
public async Task<FeaturedResponse> GetNewReleasesAsync(GenreModel genre)
{
var url = $"newreleases?genre={genre.Name}&country={m_culture.Name}&language={m_culture.Name}";
var response = await m_client.Value.QueryMusicServiceAsync<FeaturedResponse>(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<FeaturedResponse>(url);
}

/// <summary>
Expand All @@ -242,9 +225,8 @@ public async Task<FeaturedResponse> GetNewReleasesAsync(GenreModel genre)
/// <returns>The list of available moods</returns>
public async Task<MoodsResponse> GetAvailableMoodsAsync()
{
var url = $"catalog/moods?&country={m_culture.Name}&language={m_culture.Name}";
var response = await m_client.Value.QueryMusicServiceAsync<MoodsResponse>(url);
return response;
var url = $"1/content/music/catalog/moods?&country={m_culture.Name}&language={m_culture.Name}";
return await m_client.Value.QueryMusicServiceAsync<MoodsResponse>(url);
}

/// <summary>
Expand All @@ -253,9 +235,8 @@ public async Task<MoodsResponse> GetAvailableMoodsAsync()
/// <returns></returns>
public async Task<ActivitiesResponse> GetAvailableActivitiesAsync()
{
var url = $"catalog/activities?&country={m_culture.Name}&language={m_culture.Name}";
var response = await m_client.Value.QueryMusicServiceAsync<ActivitiesResponse>(url);
return response;
var url = $"1/content/music/catalog/activities?&country={m_culture.Name}&language={m_culture.Name}";
return await m_client.Value.QueryMusicServiceAsync<ActivitiesResponse>(url);
}

/// <summary>
Expand All @@ -266,9 +247,8 @@ public async Task<ActivitiesResponse> GetAvailableActivitiesAsync()
/// <returns></returns>
public async Task<TrackPlaybackResponse> 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<TrackPlaybackResponse>(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<TrackPlaybackResponse>(url);
}

/// <summary>
Expand Down
34 changes: 9 additions & 25 deletions src/GL.Sdk.Groove.Client/Http/GrooveHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string> m_requestData;
private static HttpClient _grooveHttpClient;
private readonly Dictionary<string, string> _requestData;

public AuthTokenModel AccessToken { get; private set; }

Expand All @@ -22,48 +21,37 @@ 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<string, string>()
_requestData = new Dictionary<string, string>()
{
{ "client_id", clientId },
{ "client_secret", clientSecret },
{ "scope", "app.music.xboxlive.com" },
{ "grant_type", "client_credentials" }
};

Task.Run(async () => await AuthenticateAsync()).Wait();
AuthenticateAsync().GetAwaiter().GetResult();
}

public async Task<T> QueryMusicServiceAsync<T>(string request)
{
await ValidateTokenAsync();
var response = await m_musicHttp.GetAsync(request);
string json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}

public async Task<T> QueryCatalogServiceAsync<T>(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<T>(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<AuthTokenModel>(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}");
}
}

Expand All @@ -73,10 +61,6 @@ private async Task ValidateTokenAsync()
await AuthenticateAsync();
}

public void Dispose()
{
m_musicHttp?.Dispose();
m_catalogHttp?.Dispose();
}
public void Dispose() => _grooveHttpClient?.Dispose();
}
}
6 changes: 1 addition & 5 deletions src/GL.Sdk.Groove.Models/Responses/ActivitiesResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@

namespace GL.Sdk.Groove.Models.Responses
{
public class ActivitiesResponse
public class ActivitiesResponse : ResponseBase
{
public string Culture { get; set; }

public IEnumerable<CatalogItem> CatalogActivities { get; set; }

public ErrorModel Error { get; set; }
}
}
4 changes: 1 addition & 3 deletions src/GL.Sdk.Groove.Models/Responses/FeaturedResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
}
6 changes: 1 addition & 5 deletions src/GL.Sdk.Groove.Models/Responses/GenresResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@

namespace GL.Sdk.Groove.Models.Responses
{
public class GenresResponse
public class GenresResponse : ResponseBase
{
public IEnumerable<string> Genres { get; set; }

public string Culture { get; set; }

public ErrorModel Error { get; set; }
}
}
6 changes: 1 addition & 5 deletions src/GL.Sdk.Groove.Models/Responses/GrooveResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace GL.Sdk.Groove.Models.Responses
{
public class GrooveResponse
public class GrooveResponse : ResponseBase
{
public TrackLookupResponse Tracks { get; set; }

Expand All @@ -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; }
}
}
6 changes: 1 addition & 5 deletions src/GL.Sdk.Groove.Models/Responses/MoodsResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@

namespace GL.Sdk.Groove.Models.Responses
{
public class MoodsResponse
public class MoodsResponse : ResponseBase
{
public string Culture { get; set; }

public IEnumerable<CatalogItem> CatalogMoods { get; set; }

public ErrorModel Error { get; set; }
}
}
13 changes: 13 additions & 0 deletions src/GL.Sdk.Groove.Models/Responses/ResponseBase.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
4 changes: 1 addition & 3 deletions src/GL.Sdk.Groove.Models/Responses/TrackPlaybackResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
}
Loading

0 comments on commit 92756c7

Please sign in to comment.