using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using MoreLinq; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.Core.Genres; using Sony.Filtr.Core.SpotifyCharts; using Sony.Filtr.Core.SpotifyCharts.Data; using Sony.Filtr.DistributedCaching; using Sony.Filtr.PlaylistGeneration.MusicInfoStore; using Sony.Filtr.SpotifyWebAPI; using Sony.Filtr.Utility.Extensions; using SpreadsheetLight; using Artist = Sony.Filtr.Contracts.Entities.Artist; namespace Sony.Filtr.Worker.Onetime { public class SpotifyChartGenres { private readonly SpotifyChartsManager _spotifyChartsManager; private readonly SpotifyWebApi _spotifyWebApi; private readonly LastFmManager _lastFmManager; private readonly GenreManager _genreManager; private readonly DistributedCacheHandler _distributedCacheHandler; public SpotifyChartGenres(SpotifyChartsManager spotifyChartsManager, SpotifyWebApi spotifyWebApi, LastFmManager lastFmManager, GenreManager genreManager, DistributedCacheHandler distributedCacheHandler) { _spotifyChartsManager = spotifyChartsManager; _spotifyWebApi = spotifyWebApi; _lastFmManager = lastFmManager; _genreManager = genreManager; _distributedCacheHandler = distributedCacheHandler; } public async Task ExecuteAsync() { List spotifyCharts = new List(); var chartsPerMarket = await _spotifyChartsManager.GetAvailableChartsAsync(market: null, listType: SpotifyChartsListType.Regional, timeWindow: SpotifyChartsTimeWindow.Daily); foreach(var marketCharts in chartsPerMarket) { var market = marketCharts.Key; foreach(var availableChart in marketCharts.Value.Where(p=> DateTime.Parse(p.Date) > DateTime.UtcNow.AddDays(-30))) { var date = DateTime.Parse(availableChart.Date); var chartsData = await _spotifyChartsManager.GetChartAsync(market, availableChart.ListType, availableChart.TimeWindow, date); if (chartsData != null) { spotifyCharts.Add(chartsData); } } } var app = new Application() { ID = 6 }; var allGenres = _genreManager.GetGenres(app); var genreGenreCategory = _genreManager.GetGenreCategory(app, "Genre"); var realGenres = allGenres.Where(g => g.GenreCategoryID == genreGenreCategory.ID).Select(k => k.LastFMTag).Distinct().ToList(); var trackGenres = await GetTrackGenres(spotifyCharts, realGenres); var artistGenres = await GetArtistTags(spotifyCharts, realGenres); //var tracks = await _spotifyWebApi.GetAllTracksAsync(allTracks); //var tracksLookup = tracks.ToDictionary(k => k.id, v => v); await SaveExcelAsync(spotifyCharts, trackGenres, artistGenres); } private async Task>> GetTrackGenres(List spotifyCharts, List realGenres) { ConcurrentDictionary> trackGenres = new ConcurrentDictionary>(); await spotifyCharts.SelectMany(p => p.ChartPositions).DistinctBy(p => p.ISRC).ToList().ForEachAsync(3, async track => { //var tags = _lastFmManager.GetTopTagsForTrack(track.ArtistName, track.TrackName); //var genres = await _playlistGenerationManager.GetGenresAsync(null, new Track() //{ // ArtistName = track.ArtistName, // Name = track.TrackName, //}); var cacheKey = "TopTags:" + track.ISRC; var tags = _distributedCacheHandler.Get(cacheKey) as List; if (tags == null) { try { tags = await _lastFmManager.GetTopTagsForTrackAsync(track.ArtistName, track.TrackName); tags = tags?.Intersect(realGenres, StringComparer.InvariantCultureIgnoreCase).ToList(); if (tags != null && tags.Any()) { trackGenres.TryAdd(track.ISRC, tags); } _distributedCacheHandler.Put(cacheKey, tags ?? new List()); } catch(Exception ex) { Console.WriteLine("Error:" + ex.ToString()); } } else { trackGenres.TryAdd(track.ISRC, tags); } }); return trackGenres; } private async Task>> GetArtistTags(List spotifyCharts, List realGenres) { ConcurrentDictionary> artistGenres = new ConcurrentDictionary>(); await spotifyCharts.SelectMany(p => p.ChartPositions).Select(a => a.ArtistName).Distinct().ToList().ForEachAsync(3, async artist => { //var tags = _lastFmManager.GetTopTagsForTrack(track.ArtistName, track.TrackName); //var genres = await _playlistGenerationManager.GetGenresAsync(null, new Track() //{ // ArtistName = track.ArtistName, // Name = track.TrackName, //}); var cacheKey = "TopTagsArtist:" + artist; var artistTags = _distributedCacheHandler.Get(cacheKey) as List; if (artistTags == null) { try { var artistTagResponse = await _lastFmManager.GetTagsAsync(new Artist(artist)); artistTags = artistTagResponse?.OrderByDescending(p=> p.Score).Select(t => t.Name).ToList(); artistTags = artistTags?.Intersect(realGenres, StringComparer.InvariantCultureIgnoreCase).ToList(); if (artistTags != null && artistTags.Any()) { artistGenres.TryAdd(artist, artistTags); } _distributedCacheHandler.Put(cacheKey, artistTags ?? new List()); } catch(Exception ex) { Console.WriteLine("Error:" + ex.ToString()); } } else { artistGenres.TryAdd(artist, artistTags); } }); return artistGenres; } private async Task SaveExcelAsync(List spotifyCharts, ConcurrentDictionary> trackGenres, ConcurrentDictionary> artistGenres) { var doc = new SLDocument(); doc.SetCellValue(1, 1, "Date"); doc.SetCellValue(1, 2, "Market"); doc.SetCellValue(1, 3, "Position"); doc.SetCellValue(1, 4, "Track Uri"); doc.SetCellValue(1, 5, "Artist Name"); doc.SetCellValue(1, 6, "Track Name"); doc.SetCellValue(1, 7, "Track Genre"); doc.SetCellValue(1, 8, "Artist Genre"); int index = 2; foreach (var spotifyChart in spotifyCharts.OrderBy(p=> p.Market).ThenBy(p=> p.ChartDate)) { foreach (var chartPosition in spotifyChart.ChartPositions.OrderBy(p=> p.Position)) { var trackLink = new SpotifyLink(chartPosition.TrackUrl); var trackGenre = trackGenres.GetValueOrDefault(chartPosition.ISRC)?.FirstOrDefault(); var artistGenre = artistGenres.GetValueOrDefault(chartPosition.ArtistName)?.FirstOrDefault(); doc.SetCellValue(index, 1, spotifyChart.ChartDate); doc.SetCellStyle(index, 1, new SLStyle() { FormatCode = "yyyy-mm-dd" }); doc.SetCellValue(index, 2, spotifyChart.Market); doc.SetCellValue(index, 3, chartPosition.Position); doc.SetCellValue(index, 4, trackLink.Uri); doc.SetCellValue(index, 5, chartPosition.ArtistName); doc.SetCellValue(index, 6, chartPosition.TrackName); doc.SetCellValue(index, 7, trackGenre); doc.SetCellValue(index, 8, artistGenre); index++; } } doc.SaveAs("SpotifyChartGenres.xlsx"); } } }