using System; using System.Net.Http; using System.Threading.Tasks; using Flurl; using Newtonsoft.Json; namespace Sony.Filtr.PlaylistGeneration.MusicInfoStore.LastFm { public class LastFmApi { private readonly string _lastFmApiKey; private readonly string _lastFmSecretKey; private readonly HttpClient _httpClient; public LastFmApi(string lastFmApiKey, string lastFmSecretKey, HttpClient httpClient) { _lastFmApiKey = lastFmApiKey; _lastFmSecretKey = lastFmSecretKey; _httpClient = httpClient; } public async Task GetArtistTopTagsAsync(string artist) { var url = $"format=json&api_key={this._lastFmApiKey}&artist={artist}&method=artist.getTopTags"; return await this.GetFromLastFM(url, $"Could not get artist top tags from lastfm. Artist: '{artist}'"); } public async Task GetTrackTopTagsAsync(string artist, string track) { var url = $"format=json&api_key={_lastFmApiKey}&artist={artist}&track={track}&method=track.getTopTags"; return await this.GetFromLastFM(url, $"Could not get track top tags from lastfm. Artist: '{artist}'. Track: '{track}'."); } public async Task GetArtistAsync(string artist, bool autoCorrect = false) { var url = $"format=json&api_key={_lastFmApiKey}&artist={artist}&autocorrect={autoCorrect}&method=artist.getInfo"; return await this.GetFromLastFM(url, $"Could not get artist info from lastfm. Artist: '{artist}'. AutoCorrect: {autoCorrect}"); } public async Task GetSimilarArtistsAsync(string artistName) { var url = $"format=json&api_key={_lastFmApiKey}&artist={artistName}&method=artist.getSimilar"; return await this.GetFromLastFM(url, $"Could not get similar artist from lastfm. Artist: '{artistName}'"); } public async Task SearchArtistAsync(string artistName) { var url = $"format=json&api_key={_lastFmApiKey}&artist={artistName}&method=artist.search"; return await this.GetFromLastFM(url, $"Could not artist search result from lastfm for artist {artistName}."); } public async Task GetTopArtistsForTagAsync(string tag) { var url = $"format=json&api_key={_lastFmApiKey}&tag={tag}&method=tag.getTopArtists"; return await this.GetFromLastFM(url, $"Could not get tag top artists from lastfm. Tag: '{tag}'"); } public async Task GetTopTracksForTagAsync(string tag, int? limit) { if (!limit.HasValue) { limit = 50; } var url = $"format=json&api_key={_lastFmApiKey}&tag={tag}&limit={limit.Value}&method=tag.getTopTracks"; return await this.GetFromLastFM(url, $"Could not get tag top tracks from lastfm for tag {tag}"); } public async Task GetSimilarTagsAsync(string tag) { var url = $"format=json&api_key={_lastFmApiKey}&tag={tag}&method=tag.getSimilar"; return await this.GetFromLastFM(url, $"Could not get tag similar tags from lastfm. Tag: '{tag}'"); } public async Task GetChartTopArtistsAsync(int? limit = null) { var url = new Url($"format=json&api_key={_lastFmApiKey}&method=chart.getTopArtists"); if (limit.HasValue) { url.SetQueryParam("limit", limit); } return await this.GetFromLastFM(url, $"Could not get top artists from lastfm"); } public async Task GetGeoTopArtistsAsync(string country, int? limit) { var url = new Url($"format=json&api_key={_lastFmApiKey}&method=geo.getTopArtists"); url.SetQueryParam("country", country); if (limit.HasValue) { url.SetQueryParam("limit", limit); } return await this.GetFromLastFM(url, $"Could not get top artists from lastfm. Country: '{country}'"); } public async Task GetTopArtistsForUserAsync(string user, int? limit = null, int? page = null) { var url = new Url($"method=library.getartists&api_key={_lastFmApiKey}&user={user}&format=json"); if (limit.HasValue) { url.SetQueryParam("limit", limit); } if (page.HasValue) { url.SetQueryParam("page", page); } return await this.GetFromLastFM(url, $"Could not get top artists from lastfm. User: '{user}'"); } private async Task GetFromLastFM(string url, string exceptionMessage) where TResponse: class { return await this.GetFromLastFM(url, response => $"{exceptionMessage} Response StatusCode: {response.StatusCode} Raw response: {response.Content.ReadAsStringAsync().Result}"); } private async Task GetFromLastFM(string url, Func exceptionMessageCreator) where TResponse: class { var response = await _httpClient.GetAsync(url); if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(json); } if (response.StatusCode == System.Net.HttpStatusCode.NotFound) { return null; } throw new Exception(exceptionMessageCreator(response)); } } }