using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.Contracts.Entities.Genre; using Sony.Filtr.ErrorLogging; using Sony.Filtr.PlaylistGeneration.MusicInfoStore.LastFm; using Sony.Filtr.Utility.Extensions; using Artist = Sony.Filtr.Contracts.Entities.Artist; using Tag = Sony.Filtr.Contracts.Entities.Tag; using Track = Sony.Filtr.Contracts.Entities.Track; namespace Sony.Filtr.PlaylistGeneration.MusicInfoStore { public class LastFmManager { private readonly ErrorLoggingManager _errorLoggingManager; private readonly LastFmApi _lastFmApi; public LastFmManager(string lastFmApiKey, string lastFmSecretKey, ErrorLoggingManager errorLoggingManager, HttpClient httpClient) { _errorLoggingManager = errorLoggingManager; _lastFmApi = new LastFmApi(lastFmApiKey, lastFmSecretKey, httpClient); } public async Task GetArtistAsync(string artistName) { var lastFmArtist = await TryGetLastFmArtistAsync(artistName); if (lastFmArtist == null) { lastFmArtist = await TrySearchLastFmArtistAsync(artistName); } return lastFmArtist; } private async Task TrySearchLastFmArtistAsync(string artistName) { try { var result = await _lastFmApi.SearchArtistAsync(artistName); if (result?.Results?.ArtistMatches?.Artist != null && result.Results.ArtistMatches.Artist.Any()) { var bestArtistMatch = result.Results.ArtistMatches.Artist.FirstOrDefault(); if (bestArtistMatch != null) { var mediumImage = bestArtistMatch.Image.FirstOrDefault(i => i.Size == "medium"); return new Artist(bestArtistMatch.Name) { Listeners = 0, PlayCount = 0, ImageUrl = mediumImage?.Url }; } } } catch (Exception ex) { ErrorLoggingManager.Instance.LogError(ex); } return null; } private async Task TryGetLastFmArtistAsync(string artistName) { try { var lastFmArtist = await _lastFmApi.GetArtistAsync(artistName, autoCorrect: true); if (lastFmArtist?.Artist != null) { var mediumImage = lastFmArtist.Artist.Image.FirstOrDefault(i => i.Size == "medium"); return new Artist(lastFmArtist.Artist.Name) { Listeners = lastFmArtist?.Artist?.Stats?.Listeners ?? 0, PlayCount = lastFmArtist?.Artist?.Stats?.Playcount ?? 0, ImageUrl = mediumImage?.Url }; } } catch (Exception ex) { ErrorLoggingManager.Instance.LogError("Error when fetching artists from last.fm: " + ex); } return null; } public IEnumerable GetGenreMatches(Artist artist) { throw new NotImplementedException(); } public async Task> GetSimilarArtistsAsync(string artistName) { List similarArtists = new List(); try { var similarArtist = await _lastFmApi.GetSimilarArtistsAsync(artistName); if (similarArtist != null) { return similarArtist.SimilarArtists.Artist.Select(a => new SimilarArtistMatch(new Artist(a.Name), (int)(a.Match * 100))).ToList(); } } catch (Exception ex) { var error = string.Format("Error when fetching similar artists to {0} from last.fm", artistName); ErrorLoggingManager.Instance.LogError(new Exception(error, ex)); } return similarArtists; } public List GetSimilarArtistsByGenre(string genreName) { List similarArtists = new List(); try { var tagTopArtists = _lastFmApi.GetTopArtistsForTagAsync(genreName).Result; if (tagTopArtists?.TopArtists?.Artist != null && tagTopArtists.TopArtists.Artist.Any()) { int count = tagTopArtists.TopArtists.Artist.Count(); double percentPerArtist = (count / 100.0); foreach (var artist in tagTopArtists.TopArtists.Artist) { //NOTE: It is up to the caller to check and set "IsSony" similarArtists.Add(new SimilarArtistMatch(new Artist(artist.Name), percentPerArtist * count)); count--; } } } catch (Exception ex) { ErrorLoggingManager.Instance.LogError(ex); } return similarArtists; } public async Task> GetTagsAsync(Track track) { try { var result = await _lastFmApi.GetTrackTopTagsAsync(track.ArtistName, track.Name); if (result != null) { return result.Toptags.Tag.Select(t => new Tag() { Name = t.Name, Score = t.Count }).ToList(); } } catch (Exception ex) { _errorLoggingManager.LogError("Error when fetching genres from last.fm: " + ex); } return new List(); } //public IEnumerable GetLibraryArtists(string username) //{ // var libraryArtists = new Lastfm.Services.Library(username, _currentLastFmSession).Artists; // var pages = libraryArtists.GetPageCount(); // for (int i = 1; i <= pages; i++) // { // var libraryArtistInPage = libraryArtists.GetPage(i); // foreach (var libraryArtist in libraryArtistInPage) // { // yield return libraryArtist; // } // } //} public async Task> GetTagsAsync(Artist artist) { var tags = new List(); try { var result = await _lastFmApi.GetArtistTopTagsAsync(artist.Name); if (result?.Toptags?.Tag == null) return tags; return result.Toptags.Tag.Select(t => new Tag() { Name = t.Name, Score = t.Count, }).ToList(); } catch (Exception ex) { _errorLoggingManager.LogError("Error when fetching genres from last.fm: " + ex); } return tags; } public List> GetTopTracksForTag(string tag) { try { var tagTracksResult = _lastFmApi.GetTopTracksForTagAsync(tag, limit: 1000).Result; if (tagTracksResult?.Tracks?.Track != null && tagTracksResult.Tracks.Track.Any()) { return tagTracksResult.Tracks.Track.ItemIndex().Select(t => new RankedItem(new Track(t.Item.Artist.Name, t.Item.Name) { MBID = t.Item.Mbid }, t.Index)).ToList(); } } catch (Exception ex) { _errorLoggingManager.LogError("Error when fetching top tracks for tag from last.fm: " + ex); } return new List>(); } public async Task> GetTopTagsForTrackAsync(string artistName, string trackName) { try { var result = await _lastFmApi.GetTrackTopTagsAsync(artistName, trackName); if (result != null) { return result.Toptags.Tag.Select(t => t.Name).ToList(); } } catch (Exception ex) { _errorLoggingManager.LogError("Error when fetching top tags for track from last.fm: " + ex); } return new List(); } public async Task> GetRelatedTagsAsync(string tag) { try { var similarTags = await _lastFmApi.GetSimilarTagsAsync(tag); if (similarTags?.SimilarTags?.Tag != null && similarTags.SimilarTags.Tag.Any()) { return similarTags.SimilarTags.Tag.Select(t => new Tag() { Name = t.Name, Score = t.Count }).ToList(); } } catch (Exception ex) { _errorLoggingManager.LogError("Error when fetching related tags to tag from last.fm: " + ex); } return new List(); } public async Task> GetChartTopArtistsAsync(int? limit = null) { try { var topArtists = await _lastFmApi.GetChartTopArtistsAsync(limit); if (topArtists?.Artists != null && topArtists.Artists.Artist.Any()) { return topArtists.Artists.Artist.Select(a => a.Name).ToList(); } } catch (Exception ex) { _errorLoggingManager.LogError("Error when fetching related tags to tag from last.fm: " + ex); } return new List(); } public async Task> GetGeoTopArtistAsync(string country, int? limit = null) { try { var topArtists = await _lastFmApi.GetGeoTopArtistsAsync(country, limit); if (topArtists?.TopArtists != null && topArtists.TopArtists.Artist.Any()) { return topArtists.TopArtists.Artist.Select(a => a.Name).ToList(); } } catch (Exception ex) { _errorLoggingManager.LogError("Error when fetching related tags to tag from last.fm: " + ex); } return new List(); } } }