/// <summary> /// Builds an API URI /// </summary> /// <param name="command">The command to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="queryParams">The querystring parameters</param> /// <returns> /// A Uri to call /// </returns> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when an unknown method is used</exception> /// <exception cref="CountryCodeRequiredException">Thrown when a CountryCode is required but not supplied</exception> /// <exception cref="ApiCredentialsRequiredException">Thrown when an API Key has not been supplied</exception> /// <exception cref="System.ArgumentNullException"></exception> public Uri BuildUri(MusicClientCommand command, IMusicClientSettings settings, List<KeyValuePair<string, string>> queryParams) { if (command == null) { throw new ArgumentNullException("command"); } if (settings == null) { throw new ArgumentNullException("settings"); } // Build API url var url = new StringBuilder(); url.Append(command.BaseApiUri); url.Append(command.BaseApiVersion); this.AddCountryCode(url, command, settings.CountryCode); command.AppendUriPath(url); if (!command.RequiresEmptyQuerystring) { this.AppendQueryString(url, command, settings, queryParams); } return new Uri(url.ToString()); }
/// <summary> /// Creates a Genre from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A Genre object /// </returns> internal static Language FromJToken(JToken item, IMusicClientSettings settings) { return new Language() { Id = item.Value<string>("id"), Name = item.Value<string>("name"), }; }
/// <summary> /// Adds authorisation parameters to the querystring /// </summary> /// <param name="url">The url being built.</param> /// <param name="settings">The music client settings.</param> protected virtual void AddAuthorisationParams(StringBuilder url, IMusicClientSettings settings) { if (string.IsNullOrEmpty(settings.ClientId)) { throw new ApiCredentialsRequiredException(); } url.AppendFormat(@"?client_id={0}", settings.ClientId); }
public ArtistImageUriWriter(IMusicClientSettings settings) { if (settings == null) { throw new ArgumentNullException("MusicClientSettings are required - this is usually only null in test scenarios circumventing MusicClient creation"); } this._settings = settings; }
/// <summary> /// Adds authorisation parameters to the querystring /// </summary> /// <param name="url">The url being built.</param> /// <param name="settings">The music client settings.</param> protected virtual void AddAuthorisationParams(StringBuilder url, IMusicClientSettings settings) { if (string.IsNullOrEmpty(settings.AppId) || string.IsNullOrEmpty(settings.AppCode)) { throw new ApiCredentialsRequiredException(); } url.AppendFormat(@"?app_id={0}&app_code={1}", settings.AppId, settings.AppCode); }
/// <summary> /// Creates a Genre from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A Genre object /// </returns> internal static Genre FromJToken(JToken item, IMusicClientSettings settings) { var languages = item.Value <JArray>("lang"); return(new Genre() { Id = item.Value <string>("id"), Name = item.Value <string>("name"), Languages = languages == null ? new List <string>() : languages.Select(x => x.Value <string>()).ToList() }); }
/// <summary> /// Extracts the tracks from the json. /// </summary> /// <param name="tracksToken">The tracks token.</param> /// <param name="settings">The settings.</param> /// <returns> /// A list of tracks /// </returns> private static List <Product> ExtractTracks(JToken tracksToken, IMusicClientSettings settings) { List <Product> tracks = null; if (tracksToken != null) { tracks = new ArrayJsonProcessor().ParseList(tracksToken, MusicClientCommand.ArrayNameItems, FromJToken, settings); } return(tracks); }
/// <summary> /// Makes the API request /// </summary> /// <typeparam name="T">The type of response</typeparam> /// <param name="command">The command to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="cancellationToken">The cancellation token to cancel operation.</param> /// <returns>A response for the API request.</returns> public async Task <Response <T> > SendRequestAsync <T>( MusicClientCommand <T> command, IMusicClientSettings settings, CancellationToken?cancellationToken) { return(await this.SendRequestAsync( command, settings, command.BuildQueryStringParams(), command.HandleRawData, await command.BuildRequestHeadersAsync(), cancellationToken)); }
/// <summary> /// Builds an API URI /// </summary> /// <param name="command">The command to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="querystringParams">The querystring parameters.</param> /// <returns> /// A Uri to call /// </returns> public Uri BuildUri(MusicClientCommand command, IMusicClientSettings settings, List<KeyValuePair<string, string>> querystringParams) { DirectoryInfo jsonDir = new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, @"..\..\json")); if (jsonDir.Exists) { FileInfo[] json = jsonDir.GetFiles(this._filename); if (json.Length > 0) { return new Uri("file://" + json[0].FullName.Replace(@"\", @"/")); } } throw new FileNotFoundException("Could not find required test file in " + jsonDir.FullName); }
/// <summary> /// Builds an API URI /// </summary> /// <param name="command">The command to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="querystringParams">The querystring parameters.</param> /// <returns> /// A Uri to call /// </returns> public Uri BuildUri(MusicClientCommand command, IMusicClientSettings settings, List <KeyValuePair <string, string> > querystringParams) { DirectoryInfo jsonDir = new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, @"..\..\json")); if (jsonDir.Exists) { FileInfo[] json = jsonDir.GetFiles(this._filename); if (json.Length > 0) { return(new Uri("file://" + json[0].FullName.Replace(@"\", @"/"))); } } throw new FileNotFoundException("Could not find required test file in " + jsonDir.FullName); }
/// <summary> /// Creates a UserEvent from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A UserEvent object /// </returns> internal static UserEvent FromJToken(JToken item, IMusicClientSettings settings) { return(new UserEvent { Action = ParseHelper.ParseEnumOrDefault <UserEventAction>(item.Value <string>("action")), Client = item.Value <string>("client"), ClientVersion = item.Value <string>("clientversion"), DateTime = item.Value <DateTime>("datetime"), Location = Location.FromJToken(item["location"]), Mix = Mix.FromJToken(item["mix"], settings), Offset = item.Value <int>("offset"), Product = Product.FromJToken(item["product"], settings), Target = ParseHelper.ParseEnumOrDefault <UserEventTarget>(item.Value <string>("target")), ClientType = ParseHelper.ParseEnumOrDefault <UserEventClientType>(item.Value <string>("clienttype")) }); }
private static Genre[] GetGenres(JToken item, IMusicClientSettings settings) { // Extract genres... Genre[] genres = null; JArray jsonGenres = item.Value <JArray>("genres"); if (jsonGenres != null) { var list = new List <Genre>(); foreach (JToken jsonGenre in jsonGenres) { list.Add(Genre.FromJToken(jsonGenre, settings)); } genres = list.ToArray(); } return(genres); }
/// <summary> /// Builds an API URI /// </summary> /// <param name="method">The method to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="pathParams">The path parameters.</param> /// <param name="querystringParams">The querystring parameters.</param> /// <returns> /// A Uri to call /// </returns> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when an unknown method is used</exception> /// <exception cref="CountryCodeRequiredException">Thrown when a CountryCode is required but not supplied</exception> /// <exception cref="ApiCredentialsRequiredException">Thrown when an API Key has not been supplied</exception> /// <exception cref="System.ArgumentNullException"></exception> public Uri BuildUri(ApiMethod method, IMusicClientSettings settings, Dictionary<string, string> pathParams, Dictionary<string, string> querystringParams) { if (method == null) { throw new ArgumentNullException("method"); } if (settings == null) { throw new ArgumentNullException("settings"); } // Build API url StringBuilder url = new StringBuilder(); url.Append(method.BaseApiUri); AddCountryCode(url, method, settings.CountryCode); method.AppendUriPath(url, pathParams); this.AppendQueryString(url, settings, querystringParams); return new Uri(url.ToString()); }
/// <summary> /// Creates an Artist from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// An Artist object /// </returns> internal static Artist FromJToken(JToken item, IMusicClientSettings settings) { // Extract thumbnails... Uri square50 = null; Uri square100 = null; Uri square200 = null; Uri square320 = null; MusicItem.ExtractThumbs(item["thumbnails"], out square50, out square100, out square200, out square320); // Derive 640 thumb Uri square640 = null; if (square320 != null) { square640 = new Uri(square320.ToString().Replace("320x320", "640x640")); } var count = item["count"]; var playCount = (count != null && count.Type != JTokenType.Null) ? count.Value <int>() : 0; return(new Artist() { Id = item.Value <string>("id"), Name = item.Value <string>("name"), Country = GetCountry(item), Genres = GetGenres(item, settings), MusicBrainzId = item.Value <string>("mbid"), Origin = GetOrigin(item), Thumb50Uri = square50, Thumb100Uri = square100, Thumb200Uri = square200, Thumb320Uri = square320, Thumb640Uri = square640, PlayCount = playCount }); }
/// <summary> /// Makes the API request /// </summary> /// <typeparam name="T">The type of response</typeparam> /// <param name="command">The command to call.</param> /// <param name="settings">The app id.</param> /// <param name="querystring">The querystring params.</param> /// <param name="callback">The callback to hit when done.</param> /// <param name="requestHeaders">HTTP headers to add to the request</param> public void SendRequestAsync <T>( MusicClientCommand command, IMusicClientSettings settings, List <KeyValuePair <string, string> > querystring, IResponseCallback <T> callback, Dictionary <string, string> requestHeaders = null) { this._lastSettings = settings; this._queryString = querystring; // Ensure URI building is exercised... Uri uri = this.UriBuilder.BuildUri(command, settings, querystring); // Ensure we call this method to make // sure the code gets a run through... string body = command.BuildRequestBody(); if (this._responseInfo != null) { command.SetAdditionalResponseInfo(this._responseInfo); } this.NextFakeResponse.DoCallback <T>(callback); }
/// <summary> /// Appends the appropriate query string parameters to the url /// </summary> /// <param name="url">The url being built.</param> /// <param name="settings">The music client settings.</param> /// <param name="querystringParams">The querystring parameters.</param> private void AppendQueryString(StringBuilder url, IMusicClientSettings settings, Dictionary<string, string> querystringParams) { // Add required parameters this.AddAuthorisationParams(url, settings); url.AppendFormat(@"&domain=music"); // Add other parameters... if (querystringParams != null) { foreach (string key in querystringParams.Keys) { if (!string.IsNullOrEmpty(querystringParams[key])) { url.AppendFormat(@"&{0}={1}", key, querystringParams[key]); } } } }
/// <summary> /// Appends the appropriate query string parameters to the url /// </summary> /// <param name="url">The url being built.</param> /// <param name="command">The command for the url being built</param> /// <param name="settings">The music client settings.</param> /// <param name="queryParams">The query string.</param> private void AppendQueryString(StringBuilder url, MusicClientCommand command, IMusicClientSettings settings, List<KeyValuePair<string, string>> queryParams) { // Add required parameters this.AddAuthorisationParams(url, settings); url.AppendFormat("&domain=music"); // Add other parameters... if (queryParams != null) { foreach (KeyValuePair<string, string> pair in queryParams) { url.AppendFormat("&{0}={1}", pair.Key, pair.Value); } } }
/// <summary> /// Parses a json array /// </summary> /// <typeparam name="T">The type being parsed</typeparam> /// <param name="rawJson">The raw json</param> /// <param name="listName">The name of the list</param> /// <param name="converter">A delegate that can parse each object of type T</param> /// <param name="settings">The settings.</param> /// <returns> /// A list of type T of each of the items in the array /// </returns> public List <T> ParseList <T>(JToken rawJson, string listName, MusicClientCommand.JTokenConversionDelegate <T> converter, IMusicClientSettings settings) { var results = new List <T>(); foreach (JToken item in rawJson.Children()) { T result = converter(item, settings); if (result != null) { results.Add(result); } } return(results); }
/// <summary> /// Parses a named json list. /// </summary> /// <typeparam name="T">The type being parsed</typeparam> /// <param name="rawJson">The raw json</param> /// <param name="listName">The name of the list if appropriate eg. items</param> /// <param name="converter">A delegate that can parse each object of type T</param> /// <param name="settings">The settings.</param> /// <returns> /// A list of type T /// </returns> public List <T> ParseList <T>(JToken rawJson, string listName, MusicClientCommand.JTokenConversionDelegate <T> converter, IMusicClientSettings settings) { List <T> results = new List <T>(); JArray items = rawJson.Value <JArray>(listName); if (items != null) { foreach (JToken item in rawJson.Value <JArray>(listName)) { T result = converter(item, settings); if (result != null) { results.Add(result); } } } return(results); }
/// <summary> /// Appends the appropriate query string parameters to the url /// </summary> /// <param name="url">The url being built.</param> /// <param name="command">The command for the url being built</param> /// <param name="settings">The music client settings.</param> /// <param name="queryParams">The query string.</param> private void AppendQueryString(StringBuilder url, MusicClientCommand command, IMusicClientSettings settings, List<KeyValuePair<string, string>> queryParams) { // Add required parameters this.AddAuthorisationParams(url, settings); if (!string.IsNullOrEmpty(command.ServiceDomain)) { url.AppendFormat("&domain={0}", command.ServiceDomain); } if (!string.IsNullOrWhiteSpace(settings.Language)) { url.AppendFormat("&lang={0}", settings.Language); } // Add other parameters... if (queryParams != null) { foreach (KeyValuePair<string, string> pair in queryParams) { url.AppendFormat("&{0}={1}", pair.Key, pair.Value == null ? string.Empty : Uri.EscapeDataString(pair.Value)); } } }
/// <summary> /// Creates a Product from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A Product object /// </returns> internal static Product FromJToken(JToken item, IMusicClientSettings settings) { if (item == null) { return null; } // Extract category... Category category = Category.Unknown; JToken jsonCategory = item["category"]; if (jsonCategory != null) { category = ParseHelper.ParseEnumOrDefault<Category>(jsonCategory.Value<string>("id")); } // Extract genres... Genre[] genres = null; JArray jsonGenres = item.Value<JArray>("genres"); if (jsonGenres != null) { List<Genre> list = new List<Genre>(); foreach (JToken jsonGenre in jsonGenres) { list.Add((Genre)Genre.FromJToken(jsonGenre, settings)); } genres = list.ToArray(); } // Extract takenfrom... Product takenFrom = null; JToken jsonTakenFrom = item["takenfrom"]; if (jsonTakenFrom != null) { takenFrom = (Product)FromJToken(jsonTakenFrom, settings); } // Extract price... Price price = null; JToken jsonPrices = item["prices"]; if (jsonPrices != null) { JToken jsonPermDownload = jsonPrices["permanentdownload"]; if (jsonPermDownload != null) { price = Price.FromJToken(jsonPermDownload); } } // Extract Artists... Artist[] performers = null; if (item["creators"] != null) { JArray jsonArtists = item["creators"].Value<JArray>("performers") ?? item["creators"].Value<JArray>("composers"); if (jsonArtists != null) { List<Artist> list = new List<Artist>(); foreach (JToken jsonArtist in jsonArtists) { list.Add((Artist)Artist.FromJToken(jsonArtist, settings)); } performers = list.ToArray(); } } // Extract trackcount... int? trackCount = null; JToken jsonTrackCount = item["trackcount"]; if (jsonTrackCount != null) { trackCount = item.Value<int>("trackcount"); } // Extract thumbnails... Uri square50 = null; Uri square100 = null; Uri square200 = null; Uri square320 = null; MusicItem.ExtractThumbs(item["thumbnails"], out square50, out square100, out square200, out square320); // Extract Bollywood information var actorNames = new List<string>(); if (item["actornames"] != null) { ParseArray(item, actorNames, "actornames"); } var lyricistNames = new List<string>(); if (item["lyricistnames"] != null) { ParseArray(item, lyricistNames, "lyricistnames"); } var singerNames = new List<string>(); if (item["singernames"] != null) { ParseArray(item, singerNames, "singernames"); } var movieDirectorNames = new List<string>(); if (item["moviedirectornames"] != null) { ParseArray(item, movieDirectorNames, "moviedirectornames"); } var movieProducerNames = new List<string>(); if (item["movieproducernames"] != null) { ParseArray(item, movieProducerNames, "movieproducernames"); } var musicDirectorNames = new List<string>(); if (item["musicdirectornames"] != null) { ParseArray(item, musicDirectorNames, "musicdirectornames"); } var parentalAdvisory = item.Value<bool>("parentaladvisory"); // Extract bpm... int bpm = 0; if (item["bpm"] != null) { bpm = item.Value<int>("bpm"); } // Derive 640 thumb Uri square640 = null; if (square320 != null) { square640 = new Uri(square320.ToString().Replace("w=320", "w=640")); } // Create the resulting Product object... var product = new Product() { Id = item.Value<string>("id"), Name = item.Value<string>("name"), Thumb50Uri = square50, Thumb100Uri = square100, Thumb200Uri = square200, Thumb320Uri = square320, Thumb640Uri = square640, Category = category, Genres = genres, TakenFrom = takenFrom, Price = price, TrackCount = trackCount, Tracks = ExtractTracks(item["tracks"], settings), Performers = performers, Duration = item.Value<int?>("duration"), VariousArtists = item.Value<bool>("variousartists"), StreetReleaseDate = item.Value<DateTime>("streetreleasedate"), SellerStatement = item.Value<string>("sellerstatement"), Label = item.Value<string>("label"), ActorNames = actorNames, LyricistsNames = lyricistNames, SingerNames = singerNames, MovieDirectorNames = movieDirectorNames, MovieProducerNames = movieProducerNames, MusicDirectorNames = musicDirectorNames, ParentalAdvisory = parentalAdvisory, Bpm = bpm }; var sequence = item.Value<int>("sequence"); if (sequence >= 1) { product.Sequence = sequence; } return product; }
private static Genre[] GetGenres(JToken item, IMusicClientSettings settings) { // Extract genres... Genre[] genres = null; JArray jsonGenres = item.Value<JArray>("genres"); if (jsonGenres != null) { var list = new List<Genre>(); foreach (JToken jsonGenre in jsonGenres) { list.Add(Genre.FromJToken(jsonGenre, settings)); } genres = list.ToArray(); } return genres; }
/// <summary> /// Creates a Product from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A Product object /// </returns> internal static Product FromJToken(JToken item, IMusicClientSettings settings) { if (item == null) { return(null); } // Extract category... Category category = Category.Unknown; JToken jsonCategory = item["category"]; if (jsonCategory != null) { category = ParseHelper.ParseEnumOrDefault <Category>(jsonCategory.Value <string>("id")); } // Extract genres... Genre[] genres = null; JArray jsonGenres = item.Value <JArray>("genres"); if (jsonGenres != null) { List <Genre> list = new List <Genre>(); foreach (JToken jsonGenre in jsonGenres) { list.Add((Genre)Genre.FromJToken(jsonGenre, settings)); } genres = list.ToArray(); } // Extract takenfrom... Product takenFrom = null; JToken jsonTakenFrom = item["takenfrom"]; if (jsonTakenFrom != null) { takenFrom = (Product)FromJToken(jsonTakenFrom, settings); } // Extract price... Price price = null; JToken jsonPrices = item["prices"]; if (jsonPrices != null) { JToken jsonPermDownload = jsonPrices["permanentdownload"]; if (jsonPermDownload != null) { price = Price.FromJToken(jsonPermDownload); } } // Extract Artists... Artist[] performers = null; if (item["creators"] != null) { JArray jsonArtists = item["creators"].Value <JArray>("performers") ?? item["creators"].Value <JArray>("composers"); if (jsonArtists != null) { List <Artist> list = new List <Artist>(); foreach (JToken jsonArtist in jsonArtists) { list.Add((Artist)Artist.FromJToken(jsonArtist, settings)); } performers = list.ToArray(); } } // Extract trackcount... int? trackCount = null; JToken jsonTrackCount = item["trackcount"]; if (jsonTrackCount != null) { trackCount = item.Value <int>("trackcount"); } // Extract thumbnails... Uri square50 = null; Uri square100 = null; Uri square200 = null; Uri square320 = null; MusicItem.ExtractThumbs(item["thumbnails"], out square50, out square100, out square200, out square320); // Extract Bollywood information var actorNames = new List <string>(); if (item["actornames"] != null) { ParseArray(item, actorNames, "actornames"); } var lyricistNames = new List <string>(); if (item["lyricistnames"] != null) { ParseArray(item, lyricistNames, "lyricistnames"); } var singerNames = new List <string>(); if (item["singernames"] != null) { ParseArray(item, singerNames, "singernames"); } var movieDirectorNames = new List <string>(); if (item["moviedirectornames"] != null) { ParseArray(item, movieDirectorNames, "moviedirectornames"); } var movieProducerNames = new List <string>(); if (item["movieproducernames"] != null) { ParseArray(item, movieProducerNames, "movieproducernames"); } var musicDirectorNames = new List <string>(); if (item["musicdirectornames"] != null) { ParseArray(item, musicDirectorNames, "musicdirectornames"); } var parentalAdvisory = item.Value <bool>("parentaladvisory"); // Extract bpm... int bpm = 0; if (item["bpm"] != null) { bpm = item.Value <int>("bpm"); } // Derive 640 thumb Uri square640 = null; if (square320 != null) { square640 = new Uri(square320.ToString().Replace("w=320", "w=640")); } // Create the resulting Product object... var product = new Product() { Id = item.Value <string>("id"), Name = item.Value <string>("name"), Thumb50Uri = square50, Thumb100Uri = square100, Thumb200Uri = square200, Thumb320Uri = square320, Thumb640Uri = square640, Category = category, Genres = genres, TakenFrom = takenFrom, Price = price, TrackCount = trackCount, Tracks = ExtractTracks(item["tracks"], settings), Performers = performers, Duration = item.Value <int?>("duration"), VariousArtists = item.Value <bool>("variousartists"), StreetReleaseDate = item.Value <DateTime>("streetreleasedate"), SellerStatement = item.Value <string>("sellerstatement"), Label = item.Value <string>("label"), ActorNames = actorNames, LyricistsNames = lyricistNames, SingerNames = singerNames, MovieDirectorNames = movieDirectorNames, MovieProducerNames = movieProducerNames, MusicDirectorNames = musicDirectorNames, ParentalAdvisory = parentalAdvisory, Bpm = bpm }; var sequence = item.Value <int>("sequence"); if (sequence >= 1) { product.Sequence = sequence; } return(product); }
/// <summary> /// Deserializes from JSON /// </summary> /// <param name="item">The json</param> /// <param name="settings">The settings.</param> /// <returns> /// An AccessToken instance /// </returns> internal static TokenResponse FromJToken(JToken item, IMusicClientSettings settings) { return JsonConvert.DeserializeObject<TokenResponse>(item.ToString()); }
/// <summary> /// Builds an API URI /// </summary> /// <param name="command">The method to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="querystringParams">The querystring parameters.</param> /// <returns> /// A Uri to call /// </returns> public Uri BuildUri(MusicClientCommand command, IMusicClientSettings settings, List<KeyValuePair<string, string>> querystringParams) { return this._uri; }
/// <summary> /// Creates a Mix from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A Mix object /// </returns> internal static Mix FromJToken(JToken item, IMusicClientSettings settings) { const string PlayMeThumbUri = "http://dev.mixrad.io/assets/playme/{0}x{0}.png"; if (item == null) { return null; } bool parentalAdvisory = false; JToken parentaladvisoryToken = item["parentaladvisory"]; if (parentaladvisoryToken != null) { parentalAdvisory = item.Value<bool>("parentaladvisory"); } JToken featuredArtists = item["featuredartists"]; var featuredArtistsList = new List<Artist>(); if (featuredArtists != null) { foreach (JToken token in featuredArtists) { Artist artist = Artist.FromJToken(token, settings); featuredArtistsList.Add(artist); } } Uri square50 = null; Uri square100 = null; Uri square200 = null; Uri square320 = null; Uri square640 = null; var thumbnailsToken = item["thumbnails"]; MusicItem.ExtractThumbs(thumbnailsToken, out square50, out square100, out square200, out square320); if (thumbnailsToken != null) { square640 = Mix.ExtractThumb(thumbnailsToken, "640x640"); } var seeds = item["seeds"]; SeedCollection seedCollection = null; if (seeds != null) { seedCollection = SeedCollection.FromJson(item.ToString()); } else { var mixId = item.Value<string>("id"); if (!string.IsNullOrEmpty(mixId)) { seedCollection = new SeedCollection(Seed.FromMixId(mixId)); } } var name = item.Value<string>("name"); var description = item.Value<string>("description"); if (seedCollection != null && seedCollection.Count > 0) { if (seedCollection.Count(s => s.Type == SeedType.UserId) > 0) { if (square50 == null) { square50 = new Uri(string.Format(PlayMeThumbUri, 50)); } if (square100 == null) { square100 = new Uri(string.Format(PlayMeThumbUri, 100)); } if (square200 == null) { square200 = new Uri(string.Format(PlayMeThumbUri, 200)); } if (square320 == null) { square320 = new Uri(string.Format(PlayMeThumbUri, 320)); } if (square640 == null) { square640 = new Uri(string.Format(PlayMeThumbUri, 640)); } if (string.IsNullOrEmpty(name)) { name = "Play Me"; } } else if (seedCollection.Count(s => s.Type == SeedType.ArtistId) > 0) { var artistSeeds = seedCollection.Where(s => (s.Type == SeedType.ArtistId)).ToArray(); if (string.IsNullOrEmpty(name)) { // Derive a name var names = artistSeeds.Select(s => s.Name).Where(s => !string.IsNullOrEmpty(s)).ToArray(); name = names.Length > 0 ? string.Join(", ", names) : "Artist Mix"; } // Derive a thumbnail image var idSeed = artistSeeds.FirstOrDefault(s => !string.IsNullOrEmpty(s.Id)); if (idSeed != null && settings != null) { var builder = new ArtistImageUriWriter(settings); if (square50 == null) { square50 = builder.BuildForId(idSeed.Id, 50); } if (square100 == null) { square100 = builder.BuildForId(idSeed.Id, 100); } if (square200 == null) { square200 = builder.BuildForId(idSeed.Id, 200); } if (square320 == null) { square320 = builder.BuildForId(idSeed.Id, 320); } if (square640 == null) { square640 = builder.BuildForId(idSeed.Id, 640); } } } } return new Mix() { Name = name, TrackCount = item.Value<int>("numbertracks"), ParentalAdvisory = parentalAdvisory, Seeds = seedCollection, Thumb50Uri = square50, Thumb100Uri = square100, Thumb200Uri = square200, Thumb320Uri = square320, Thumb640Uri = square640, Description = description, FeaturedArtists = featuredArtistsList }; }
/// <summary> /// Extracts a /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// Returns the string value /// </returns> private static string ExtractStringFromJToken(JToken item, IMusicClientSettings settings) { return(item.Value <string>()); }
/// <summary> /// Creates a Mix from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A Mix object /// </returns> internal static Mix FromJToken(JToken item, IMusicClientSettings settings) { const string PlayMeThumbUri = "http://dev.mixrad.io/assets/playme/{0}x{0}.png"; if (item == null) { return(null); } bool parentalAdvisory = false; JToken parentaladvisoryToken = item["parentaladvisory"]; if (parentaladvisoryToken != null) { parentalAdvisory = item.Value <bool>("parentaladvisory"); } JToken featuredArtists = item["featuredartists"]; var featuredArtistsList = new List <Artist>(); if (featuredArtists != null) { foreach (JToken token in featuredArtists) { Artist artist = Artist.FromJToken(token, settings); featuredArtistsList.Add(artist); } } Uri square50 = null; Uri square100 = null; Uri square200 = null; Uri square320 = null; Uri square640 = null; var thumbnailsToken = item["thumbnails"]; MusicItem.ExtractThumbs(thumbnailsToken, out square50, out square100, out square200, out square320); if (thumbnailsToken != null) { square640 = Mix.ExtractThumb(thumbnailsToken, "640x640"); } var seeds = item["seeds"]; SeedCollection seedCollection = null; if (seeds != null) { seedCollection = SeedCollection.FromJson(item.ToString()); } else { var mixId = item.Value <string>("id"); if (!string.IsNullOrEmpty(mixId)) { seedCollection = new SeedCollection(Seed.FromMixId(mixId)); } } var name = item.Value <string>("name"); var description = item.Value <string>("description"); if (seedCollection != null && seedCollection.Count > 0) { if (seedCollection.Count(s => s.Type == SeedType.UserId) > 0) { if (square50 == null) { square50 = new Uri(string.Format(PlayMeThumbUri, 50)); } if (square100 == null) { square100 = new Uri(string.Format(PlayMeThumbUri, 100)); } if (square200 == null) { square200 = new Uri(string.Format(PlayMeThumbUri, 200)); } if (square320 == null) { square320 = new Uri(string.Format(PlayMeThumbUri, 320)); } if (square640 == null) { square640 = new Uri(string.Format(PlayMeThumbUri, 640)); } if (string.IsNullOrEmpty(name)) { name = "Play Me"; } } else if (seedCollection.Count(s => s.Type == SeedType.ArtistId) > 0) { var artistSeeds = seedCollection.Where(s => (s.Type == SeedType.ArtistId)).ToArray(); if (string.IsNullOrEmpty(name)) { // Derive a name var names = artistSeeds.Select(s => s.Name).Where(s => !string.IsNullOrEmpty(s)).ToArray(); name = names.Length > 0 ? string.Join(", ", names) : "Artist Mix"; } // Derive a thumbnail image var idSeed = artistSeeds.FirstOrDefault(s => !string.IsNullOrEmpty(s.Id)); if (idSeed != null && settings != null) { var builder = new ArtistImageUriWriter(settings); if (square50 == null) { square50 = builder.BuildForId(idSeed.Id, 50); } if (square100 == null) { square100 = builder.BuildForId(idSeed.Id, 100); } if (square200 == null) { square200 = builder.BuildForId(idSeed.Id, 200); } if (square320 == null) { square320 = builder.BuildForId(idSeed.Id, 320); } if (square640 == null) { square640 = builder.BuildForId(idSeed.Id, 640); } } } } return(new Mix() { Name = name, TrackCount = item.Value <int>("numbertracks"), ParentalAdvisory = parentalAdvisory, Seeds = seedCollection, Thumb50Uri = square50, Thumb100Uri = square100, Thumb200Uri = square200, Thumb320Uri = square320, Thumb640Uri = square640, Description = description, FeaturedArtists = featuredArtistsList }); }
/// <summary> /// Extracts the tracks from the json. /// </summary> /// <param name="tracksToken">The tracks token.</param> /// <param name="settings">The settings.</param> /// <returns> /// A list of tracks /// </returns> private static List<Product> ExtractTracks(JToken tracksToken, IMusicClientSettings settings) { List<Product> tracks = null; if (tracksToken != null) { tracks = new ArrayJsonProcessor().ParseList(tracksToken, MusicClientCommand.ArrayNameItems, FromJToken, settings); } return tracks; }
/// <summary> /// Makes the API request /// </summary> /// <param name="method">The method to call.</param> /// <param name="settings">The app id.</param> /// <param name="pathParams">The path params.</param> /// <param name="querystringParams">The querystring params.</param> /// <param name="callback">The callback to hit when done.</param> /// <param name="requestHeaders">HTTP headers to add to the request</param> public void SendRequestAsync( ApiMethod method, IMusicClientSettings settings, Dictionary<string, string> pathParams, Dictionary<string, string> querystringParams, Action<Response<JObject>> callback, Dictionary<string, string> requestHeaders = null) { this._lastSettings = settings; this.NextFakeResponse.DoCallback(callback); }
/// <summary> /// Makes the API request /// </summary> /// <typeparam name="T">The type of response</typeparam> /// <param name="command">The command to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="queryParams">The querystring.</param> /// <param name="rawDataHandler">The convertion handler for the data received.</param> /// <param name="requestHeaders">HTTP headers to add to the request</param> /// <param name="cancellationToken">The cancellation token to cancel operation.</param> /// <returns>A response for the API request.</returns> public async Task <Response <T> > SendRequestAsync <T>( MusicClientCommand command, IMusicClientSettings settings, List <KeyValuePair <string, string> > queryParams, Func <string, T> rawDataHandler, Dictionary <string, string> requestHeaders, CancellationToken?cancellationToken) { Uri uri = command.RawUri ?? this.UriBuilder.BuildUri(command, settings, queryParams); DebugLogger.Instance.WriteLog("Calling {0}", uri.ToString()); HttpRequestMessage request = new HttpRequestMessage(command.HttpMethod, uri); HttpMessageHandler handler = this.CreateHandler(command.FollowHttpRedirects); this.AddRequestHeaders(request, requestHeaders, settings); BuildRequestBody(command, request); using (HttpClient client = new HttpClient(handler)) { client.Timeout = TimeSpan.FromMilliseconds(MusicClient.RequestTimeout); HttpStatusCode?statusCode = null; bool? mixRadioHeaderFound = null; var activeCancellationToken = cancellationToken ?? CancellationToken.None; try { activeCancellationToken.ThrowIfCancellationRequested(); using (HttpResponseMessage response = await this._requestProxy.SendRequestAsync(client, request, activeCancellationToken).ConfigureAwait(false)) { statusCode = response.StatusCode; if (command.ExpectsMixRadioHeader) { mixRadioHeaderFound = response.Headers.Contains("X-MixRadio"); } var headers = new Dictionary <string, IEnumerable <string> >(); foreach (var header in response.Headers) { headers.Add(header.Key, header.Value.ToArray()); } //// Capture Server Time offset if we haven't already... this.DeriveServerTimeOffset(response.Headers.Date, response.Headers.Age); command.SetAdditionalResponseInfo(new ResponseInfo(response.RequestMessage.RequestUri, headers)); using (var content = response.Content) { string contentType = content.Headers.ContentType != null ? content.Headers.ContentType.MediaType : null; string responseBody = await content.ReadAsStringAsync().ConfigureAwait(false); if (!response.IsSuccessStatusCode && !IsFake404(response)) { DebugLogger.Instance.WriteException( new ApiCallFailedException(response.StatusCode), new KeyValuePair <string, string>("uri", uri.ToString()), new KeyValuePair <string, string>("errorResponseBody", responseBody), new KeyValuePair <string, string>("statusCode", statusCode.ToString()), new KeyValuePair <string, string>("mixRadioHeaderFound", mixRadioHeaderFound.HasValue ? mixRadioHeaderFound.ToString() : "unknown")); } T responseItem = rawDataHandler(responseBody); return(PrepareResponse(responseItem, statusCode, contentType, null, responseBody, command.RequestId, uri, mixRadioHeaderFound, IsFake404(response))); } } } catch (Exception ex) { if (ex is OperationCanceledException) { if (activeCancellationToken.IsCancellationRequested) { DebugLogger.Instance.WriteLog("OperationCanceledException thrown due to operation being cancelled."); return(PrepareResponse(default(T), statusCode, null, new ApiCallCancelledException(), null, command.RequestId, uri, false)); } else { DebugLogger.Instance.WriteLog("OperationCanceledException thrown without operation being cancelled."); // Because Xamarin.Android fails on limited networks by cancelling the task. return(PrepareResponse(default(T), statusCode, null, new NetworkLimitedException(), null, command.RequestId, uri, false)); } } if (mixRadioHeaderFound.HasValue && !mixRadioHeaderFound.Value) { return(PrepareResponse(default(T), statusCode, null, new NetworkLimitedException(), null, command.RequestId, uri, false)); } // This is a way to check if an SSL certificate has failed. // WebExceptionStatus.TrustFailure is not supported by PCL (http://msdn.microsoft.com/en-us/library/system.net.webexceptionstatus.aspx) var webException = ex as WebException; if (webException != null && webException.Status == WebExceptionStatus.SendFailure && !mixRadioHeaderFound.HasValue) { return(PrepareResponse(default(T), statusCode, null, new SendFailureException(), null, command.RequestId, uri, false)); } DebugLogger.Instance.WriteException( new ApiCallFailedException(statusCode), new KeyValuePair <string, string>("uri", uri.ToString()), new KeyValuePair <string, string>("statusCode", statusCode.HasValue ? statusCode.ToString() : "Timeout"), new KeyValuePair <string, string>("mixRadioHeaderFound", mixRadioHeaderFound.HasValue ? mixRadioHeaderFound.ToString() : "unknown")); return(PrepareResponse(default(T), statusCode, null, ex, null, command.RequestId, uri, mixRadioHeaderFound)); } } }
private void AddRequestHeaders(HttpRequestMessage request, Dictionary <string, string> requestHeaders, IMusicClientSettings settings) { if (!string.IsNullOrEmpty(this._userAgent)) { request.Headers.UserAgent.TryParseAdd(this._userAgent); } if (requestHeaders != null) { foreach (KeyValuePair <string, string> header in requestHeaders) { DebugLogger.Instance.WriteLog(" Request Header: {0} = {1}", header.Key, header.Value); request.Headers.Add(header.Key, header.Value); } } }
/// <summary> /// Creates a UserEvent from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A UserEvent object /// </returns> internal static UserEvent FromJToken(JToken item, IMusicClientSettings settings) { return new UserEvent { Action = ParseHelper.ParseEnumOrDefault<UserEventAction>(item.Value<string>("action")), Client = item.Value<string>("client"), ClientVersion = item.Value<string>("clientversion"), DateTime = item.Value<DateTime>("datetime"), Location = Location.FromJToken(item["location"]), Mix = Mix.FromJToken(item["mix"], settings), Offset = item.Value<int>("offset"), Product = Product.FromJToken(item["product"], settings), Target = ParseHelper.ParseEnumOrDefault<UserEventTarget>(item.Value<string>("target")), ClientType = ParseHelper.ParseEnumOrDefault<UserEventClientType>(item.Value<string>("clienttype")) }; }
/// <summary> /// Builds an API URI /// </summary> /// <param name="command">The method to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="querystringParams">The querystring parameters.</param> /// <returns> /// A Uri to call /// </returns> public Uri BuildUri(MusicClientCommand command, IMusicClientSettings settings, List <KeyValuePair <string, string> > querystringParams) { return(this._uri); }
/// <summary> /// Builds an API URI /// </summary> /// <param name="method">The method to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="pathParams">The path parameters.</param> /// <param name="querystringParams">The querystring parameters.</param> /// <returns> /// A Uri to call /// </returns> public Uri BuildUri(ApiMethod method, IMusicClientSettings settings, Dictionary<string, string> pathParams, Dictionary<string, string> querystringParams) { return this._uri; }
/// <summary> /// Makes the API request /// </summary> /// <param name="method">The method to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="pathParams">The path params.</param> /// <param name="querystringParams">The querystring params.</param> /// <param name="callback">The callback to hit when done.</param> /// <param name="requestHeaders">HTTP headers to add to the request</param> /// <exception cref="System.ArgumentNullException">Thrown when no callback is specified</exception> public void SendRequestAsync( ApiMethod method, IMusicClientSettings settings, Dictionary<string, string> pathParams, Dictionary<string, string> querystringParams, Action<Response<JObject>> callback, Dictionary<string, string> requestHeaders = null) { if (callback == null) { throw new ArgumentNullException("callback"); } Uri uri = this.UriBuilder.BuildUri(method, settings, pathParams, querystringParams); Debug.WriteLine("Calling " + uri.ToString()); WebRequest request = WebRequest.Create(uri); this.AddRequestHeaders(request, requestHeaders); request.BeginGetResponse( (IAsyncResult ar) => { WebResponse response = null; HttpWebResponse webResponse = null; JObject json = null; HttpStatusCode? statusCode = null; Exception error = null; try { response = request.EndGetResponse(ar); webResponse = response as HttpWebResponse; if (webResponse != null) { statusCode = webResponse.StatusCode; } } catch (WebException ex) { error = ex; if (ex.Response != null) { webResponse = (HttpWebResponse)ex.Response; statusCode = webResponse.StatusCode; } } string contentType = null; string result = null; if (response != null) { contentType = response.ContentType; using (Stream responseStream = response.GetResponseStream()) { result = responseStream.AsString(); if (!string.IsNullOrEmpty(result)) { try { json = JObject.Parse(result); } catch (Exception ex) { error = ex; json = null; } } } } if (json != null) { callback(new Response<JObject>(statusCode, contentType, json, method.RequestId)); } else { callback(new Response<JObject>(statusCode, error, method.RequestId)); } }, request); }
/// <summary> /// Creates an Artist from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// An Artist object /// </returns> internal static Artist FromJToken(JToken item, IMusicClientSettings settings) { // Extract thumbnails... Uri square50 = null; Uri square100 = null; Uri square200 = null; Uri square320 = null; MusicItem.ExtractThumbs(item["thumbnails"], out square50, out square100, out square200, out square320); // Derive 640 thumb Uri square640 = null; if (square320 != null) { square640 = new Uri(square320.ToString().Replace("320x320", "640x640")); } var count = item["count"]; var playCount = (count != null && count.Type != JTokenType.Null) ? count.Value<int>() : 0; return new Artist() { Id = item.Value<string>("id"), Name = item.Value<string>("name"), Country = GetCountry(item), Genres = GetGenres(item, settings), MusicBrainzId = item.Value<string>("mbid"), Origin = GetOrigin(item), Thumb50Uri = square50, Thumb100Uri = square100, Thumb200Uri = square200, Thumb320Uri = square320, Thumb640Uri = square640, PlayCount = playCount }; }
/// <summary> /// Deserializes from JSON /// </summary> /// <param name="item">The json</param> /// <param name="settings">The settings.</param> /// <returns> /// An AccessToken instance /// </returns> internal static TokenResponse FromJToken(JToken item, IMusicClientSettings settings) { return(JsonConvert.DeserializeObject <TokenResponse>(item.ToString())); }
/// <summary> /// Creates a MixGroup from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A MixGroup object /// </returns> internal static MixGroup FromJToken(JToken item, IMusicClientSettings settings) { return new MixGroup() { Id = item.Value<string>("id"), Name = item.Value<string>("name") }; }
/// <summary> /// Makes the API request /// </summary> /// <typeparam name="T">The type of response item</typeparam> /// <param name="command">The command to call.</param> /// <param name="settings">The music client settings.</param> /// <param name="queryParams">The querystring.</param> /// <param name="callback">The callback to hit when done.</param> /// <param name="requestHeaders">HTTP headers to add to the request</param> /// <exception cref="System.ArgumentNullException">Thrown when no callback is specified</exception> public void SendRequestAsync <T>( MusicClientCommand command, IMusicClientSettings settings, List <KeyValuePair <string, string> > queryParams, IResponseCallback <T> callback, Dictionary <string, string> requestHeaders = null) { if (callback == null) { throw new ArgumentNullException("callback"); } Uri uri = this.UriBuilder.BuildUri(command, settings, queryParams); DebugLogger.Instance.WriteLog("Calling {0}", uri.ToString()); TimedRequest request = new TimedRequest(uri); this.AddRequestHeaders(request.WebRequest, requestHeaders); this.TryBuildRequestBody( (IAsyncResult ar) => { if (request.HasTimedOut) { return; } WebResponse response = null; HttpWebResponse webResponse = null; T responseItem = default(T); HttpStatusCode?statusCode = null; Exception error = null; string responseBody = null; try { response = request.WebRequest.EndGetResponse(ar); webResponse = response as HttpWebResponse; if (webResponse != null) { statusCode = webResponse.StatusCode; command.SetAdditionalResponseInfo(new ResponseInfo(webResponse.ResponseUri, webResponse.Headers)); // Capture Server Time offset if we haven't already... this.DeriveServerTimeOffset(webResponse.Headers); } } catch (WebException ex) { DebugLogger.Instance.WriteVerboseInfo("Web Exception: {0} when calling {1}", ex, uri); error = ex; if (ex.Response != null) { response = ex.Response; webResponse = (HttpWebResponse)ex.Response; statusCode = webResponse.StatusCode; } } string contentType = null; if (response != null) { contentType = response.ContentType; try { using (Stream responseStream = this._gzipHandler.GetResponseStream(response)) { responseBody = responseStream.AsString(); responseItem = callback.ConvertFromRawResponse(responseBody); } } catch (Exception ex) { DebugLogger.Instance.WriteVerboseInfo("Exception: {0} trying to handle response stream when calling {1}", ex, uri); error = ex; responseItem = default(T); } } DoCallback(callback.Callback, responseItem, statusCode, contentType, error, responseBody, command.RequestId, uri, IsFake404(response)); }, () => DoCallback(callback.Callback, default(T), null, null, new ApiCallFailedException(), null, command.RequestId, uri), request, command); }
/// <summary> /// Appends the appropriate query string parameters to the url /// </summary> /// <param name="url">The url being built.</param> /// <param name="command">The command for the url being built</param> /// <param name="settings">The music client settings.</param> /// <param name="queryParams">The query string.</param> private void AppendQueryString(StringBuilder url, MusicClientCommand command, IMusicClientSettings settings, List <KeyValuePair <string, string> > queryParams) { // Add required parameters this.AddAuthorisationParams(url, settings); url.AppendFormat("&domain=music"); if (!string.IsNullOrWhiteSpace(settings.Language)) { url.AppendFormat("&lang={0}", settings.Language); } // Add other parameters... if (queryParams != null) { foreach (KeyValuePair <string, string> pair in queryParams) { url.AppendFormat("&{0}={1}", pair.Key, pair.Value == null ? string.Empty : Uri.EscapeDataString(pair.Value)); } } }
/// <summary> /// Creates a Genre from a JSON Object /// </summary> /// <param name="item">The item.</param> /// <param name="settings">The settings.</param> /// <returns> /// A Genre object /// </returns> internal static Genre FromJToken(JToken item, IMusicClientSettings settings) { var languages = item.Value<JArray>("lang"); return new Genre() { Id = item.Value<string>("id"), Name = item.Value<string>("name"), Languages = languages == null ? new List<string>() : languages.Select(x => x.Value<string>()).ToList() }; }