using MoreLinq; using NLog; using Sony.Filtr.AppleMusic; using Sony.Filtr.AppleMusic.Data; using Sony.Filtr.AppleMusic.Helpers; using Sony.Filtr.AppleMusic.Playlists; using Sony.Filtr.Utility.ConsoleUtility; using Sony.Filtr.Utility.Extensions; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Sony.Filtr.Tasks.Tasks.AppleMusic { public class UpdateAppleMusicSongsTask : IScheduledTask { private readonly AppleMusicSongManager _appleMusicSongManager; private readonly AppleMusicPlaylistManager _appleMusicPlaylistManager; private readonly AppleMusicUpdateHelper _appleMusicUpdateHelper; private readonly Logger _logger; private const int _MaxSongBatchSize = 300; public UpdateAppleMusicSongsTask(AppleMusicSongManager appleMusicSongManager, AppleMusicPlaylistManager appleMusicPlaylistManager, AppleMusicUpdateHelper appleMusicUpdateHelper) { _appleMusicSongManager = appleMusicSongManager; _appleMusicPlaylistManager = appleMusicPlaylistManager; _appleMusicUpdateHelper = appleMusicUpdateHelper; _logger = LogManager.GetLogger("UpdateAppleMusicSongsTask"); } public async Task ExecuteAsync(Guid scheduledTaskLogId) { await AddMissingSongInformationAsync(); return null; } private async Task AddMissingSongInformationAsync() { var mergedStorefrontSongs = await IdentifySongsToFetchAsync(); var allSongs = await GetSongsAsync(mergedStorefrontSongs); await _appleMusicUpdateHelper.SaveSongsWithRelatedDataAsync(allSongs, _logger); } private async Task>> IdentifySongsToFetchAsync() { _logger.Debug($"Checking which songs are missing album or artist..."); var songsMissingArtist = await _appleMusicSongManager.GetSongsMissingDataAsync(); _logger.Debug($"Checking which playlist songs need information..."); var playlistSongs = await _appleMusicPlaylistManager.GetSongIdsWithoutInformationByStorefrontAsync(); var mergedStorefrontSongs = playlistSongs .Union(songsMissingArtist) .GroupBy(p => p.Key, v => v.Value) .ToDictionary(k => k.Key, v => v.SelectMany(p => p).Distinct().ToList()); var count = mergedStorefrontSongs.Sum(s => s.Value.Count); _logger.Debug($"Got {count} missing songs to get information for."); return mergedStorefrontSongs; } public async Task> GetSongsAsync(Dictionary> mergedStorefrontSongs) { ConcurrentBag allSongs = new ConcurrentBag(); foreach (var storefront in mergedStorefrontSongs) { _logger.Debug($"Fetching a total of {storefront.Value.Count} songs from API for {storefront.Key}."); try { var batches = storefront.Value.Batch(_MaxSongBatchSize).ToList(); var totalBatches = batches.Count; using (var progress = new ConsoleProgressBarCount(totalBatches)) { await batches.ForEachAsync(10, async songIdsBatch => { try { var songs = await _appleMusicUpdateHelper.FetchAppleMusicSongsAsync(storefront.Key, songIdsBatch); songs.ForEach(allSongs.Add); } catch (Exception ex) { _logger.Error(ex, "Could not load batch of songs"); } }, progress); } } catch (Exception ex) { _logger.Error(ex, $"Could not load songs from {storefront}"); } } return allSongs.ToList(); } } }