using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Net.Http; using System.Linq; using System.Net; using System.Web; using System.Threading.Tasks; using Newtonsoft.Json; using Sony.Filtr.Contracts.Abstractions; using Sony.Filtr.DeezerAPI.Model; using Sony.Filtr.Utility.Extensions; namespace Sony.Filtr.DeezerAPI { public class DeezerApi { private readonly IRateLimiter _rateLimiter; private static readonly HttpClient _Client = new HttpClient(new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, UseCookies = false}) { BaseAddress = new Uri("http://api.deezer.com"), }; public DeezerApi(IRateLimiter rateLimiter) { _rateLimiter = rateLimiter; } private async Task GetAsync(string url) { await _rateLimiter.WaitToProceedAsync(); var response = await _Client.GetAsync(url); if (!response.IsSuccessStatusCode) { throw DeezerException.FromHttpResponseMessage(response); } var responseString = await response.Content.ReadAsStringAsync(); var error = JsonConvert.DeserializeObject(responseString); if (error?.error?.type != null) { throw new DeezerException(error.error); } var playlistResponse = JsonConvert.DeserializeObject(responseString); return playlistResponse; } private async Task ExecuteRequestAsync(HttpRequestMessage request) { await _rateLimiter.WaitToProceedAsync(); return await _Client.SendAsync(request); } public async Task> GetAllUsersPlaylistsAsync(long userId) { List playlists = new List(); var url = $"/user/{userId}/playlists"; var playlistResponse = await GetAsync(url); playlists.AddRange(playlistResponse.data); if (playlistResponse.next != null) { var next = playlistResponse.next; while (next != null) { var nextResponse = await GetAsync(next); next = nextResponse.next; playlists.AddRange(nextResponse.data); } } return playlists; } public async Task GetPlaylistAsync(long playlistId, string accessToken = null) { string pathAndQuery = $"http://api.deezer.com/playlist/{playlistId}"; var parameters = System.Web.HttpUtility.ParseQueryString(String.Empty); if (accessToken != null) { parameters["access_token"] = accessToken; } pathAndQuery += $"?{parameters.ToString()}"; return await GetAsync(pathAndQuery); } public async Task> GetAllPlaylistTracksAsync(long playlistId) { List playlistTrackItems = new List(); var playlistTracks = await GetAsync($"/playlist/{playlistId}/tracks"); if (playlistTracks?.data != null && playlistTracks.data.Any()) { playlistTrackItems.AddRange(playlistTracks.data); while (playlistTracks.next != null) { playlistTracks = await GetAsync(playlistTracks.next); playlistTrackItems.AddRange(playlistTracks.data); } } return playlistTrackItems; } public async Task GetUserFollowersAsync(long userId) { return await GetAsync($"http://api.deezer.com/user/{userId}/followers"); } public async Task GetUserAsync(long userId) { return await GetAsync($"http://api.deezer.com/user/{userId}"); } public async Task SetPlaylistInfoAsync(string accessToken, long playlistId, string title, string description, bool isPublic, bool collaborative) { string pathAndQuery = $"http://api.deezer.com/playlist/{playlistId}"; var parameters = HttpUtility.ParseQueryString(String.Empty); parameters["access_token"] = accessToken; parameters["title"] = title; parameters["description"] = description; parameters["public"] = isPublic.ToString().ToLower(); parameters["collaborative"] = collaborative.ToString().ToLower(); pathAndQuery += $"?{parameters.ToString()}"; var request = new HttpRequestMessage(HttpMethod.Post, pathAndQuery); var response = await _Client.SendAsync(request); if (!response.IsSuccessStatusCode) { throw DeezerException.FromHttpResponseMessage(response); } //TODO: Verify response data //var createResponse = await response.Content.ReadAsAsync(); return new CreateResponse(); } public async Task AddTracksAsync(string accessToken, long deezerPlaylistId, IEnumerable trackIds) { string pathAndQuery = $"http://api.deezer.com/playlist/{deezerPlaylistId}/tracks"; var parameters = HttpUtility.ParseQueryString(String.Empty); parameters["songs"] = string.Join(",", trackIds); parameters["access_token"] = accessToken; pathAndQuery += $"?{parameters.ToString()}"; var request = new HttpRequestMessage(HttpMethod.Post, pathAndQuery) {Content = new StringContent(string.Empty)}; var response = await ExecuteRequestAsync(request); if (!response.IsSuccessStatusCode) { throw DeezerException.FromHttpResponseMessage(response); } } public async Task DeletePlaylistTracksAsync(string accessToken, long playlistId, IEnumerable trackIds) { var url = $"http://api.deezer.com/playlist/{playlistId}/tracks"; var parameters = HttpUtility.ParseQueryString(String.Empty); parameters["songs"] = string.Join(",", trackIds); parameters["access_token"] = accessToken; var request = new HttpRequestMessage(HttpMethod.Delete, url += $"{parameters}"); var response = await ExecuteRequestAsync(request); if (!response.IsSuccessStatusCode) { throw DeezerException.FromHttpResponseMessage(response); } } public async Task OrderPlaylistTracksAsync(string accessToken, long playlistId, IEnumerable orderedTrackIds) { var url = $"http://api.deezer.com/playlist/{playlistId}/tracks"; var parameters = HttpUtility.ParseQueryString(String.Empty); parameters["order"] = string.Join(",", orderedTrackIds); parameters["access_token"] = accessToken; var request = new HttpRequestMessage(HttpMethod.Post, url += $"{parameters}") { Content = new StringContent(string.Empty)}; var response = await ExecuteRequestAsync(request); if (!response.IsSuccessStatusCode) { throw DeezerException.FromHttpResponseMessage(response); } } public async Task GetTrackByISRCAsync(string accessToken, string isrc) { // https://api.deezer.com/2.0/track/isrc:USWB11200587 var url = $"https://api.deezer.com/2.0/track/isrc:{isrc}"; var parameters = HttpUtility.ParseQueryString(String.Empty); parameters["access_token"] = accessToken; var responseString = await _Client.GetStringAsync(url += $"{parameters}"); var errorResponse = JsonConvert.DeserializeObject(responseString); if (errorResponse?.error != null) { return null; } return JsonConvert.DeserializeObject(responseString); } public async Task GetTrackAsync(long trackId) { return await GetAsync(string.Format("/track/{0}", trackId)); } public async Task> SearchArtistsAsync(string searchQuery, int index = 0, int limit = 0, string order = null) { var url = $"http://api.deezer.com/search/artist"; var parameters = HttpUtility.ParseQueryString(String.Empty); parameters["q"] = searchQuery; if (order != null) { parameters["order"] = order; } if (index != 0) { parameters["index"] = index.ToString(); } if (limit != 0) { parameters["limit"] = limit.ToString(); } return await GetAsync>(url += $"{parameters}"); } public async Task GetArtistTopTracksAsync(string artistId, int? limit = null) { var url = $"http://api.deezer.com/artist/{artistId}/top"; var parameters = HttpUtility.ParseQueryString(String.Empty); if (limit != null) { parameters["limit"] = limit.ToString(); } return await GetAsync(url += $"{parameters}"); } public async Task> GetMultipleTracksAsync(IEnumerable deezerTrackIds) { ConcurrentBag trackResponses = new ConcurrentBag(); await deezerTrackIds.ForEachAsync(5, async deezerTrackId => { var trackResponse = await GetTrackAsync(deezerTrackId); trackResponses.Add(trackResponse); }); return trackResponses.ToList(); } } }