using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Music.Events; using System; using System.Collections.Generic; using NzbDrone.Core.Organizer; using System.Linq; using System.Text; namespace NzbDrone.Core.Music { public interface IRefreshAlbumService { void RefreshAlbumInfo(Artist artist, IEnumerable remoteAlbums); } public class RefreshAlbumService : IRefreshAlbumService { private readonly IAlbumService _albumService; private readonly IRefreshTrackService _refreshTrackService; private readonly IBuildFileNames _fileNameBuilder; private readonly IEventAggregator _eventAggregator; private readonly Logger _logger; public RefreshAlbumService(IAlbumService albumService, IBuildFileNames fileNameBuilder, IRefreshTrackService refreshTrackService, IEventAggregator eventAggregator, Logger logger) { _albumService = albumService; _fileNameBuilder = fileNameBuilder; _refreshTrackService = refreshTrackService; _eventAggregator = eventAggregator; _logger = logger; } public void RefreshAlbumInfo(Artist artist, IEnumerable remoteAlbums) { _logger.Info("Starting album info refresh for: {0}", artist); var successCount = 0; var failCount = 0; var existingAlbums = _albumService.GetAlbumsByArtist(artist.Id); var albums = artist.Albums; var updateList = new List(); var newList = new List(); var dupeFreeRemoteAlbums = remoteAlbums.DistinctBy(m => new { m.ForeignAlbumId, m.ReleaseDate }).ToList(); foreach (var album in OrderAlbums(artist, dupeFreeRemoteAlbums)) { try { var albumToUpdate = GetAlbumToUpdate(artist, album, existingAlbums); if (albumToUpdate != null) { existingAlbums.Remove(albumToUpdate); updateList.Add(albumToUpdate); } else { albumToUpdate = new Album(); albumToUpdate.Monitored = artist.Monitored; albumToUpdate.ProfileId = artist.ProfileId; albumToUpdate.Added = DateTime.UtcNow; if (string.IsNullOrWhiteSpace(albumToUpdate.Path)) { albumToUpdate.Path = _fileNameBuilder.BuildAlbumPath(artist, album); } newList.Add(albumToUpdate); } albumToUpdate.ForeignAlbumId = album.ForeignAlbumId; albumToUpdate.LastInfoSync = DateTime.UtcNow; albumToUpdate.CleanTitle = album.CleanTitle; albumToUpdate.Title = album.Title ?? "Unknown"; albumToUpdate.CleanTitle = Parser.Parser.CleanArtistTitle(albumToUpdate.Title); albumToUpdate.ArtistId = artist.Id; albumToUpdate.AlbumType = album.AlbumType; albumToUpdate.Genres = album.Genres; albumToUpdate.Images = album.Images; albumToUpdate.ReleaseDate = album.ReleaseDate; successCount++; } catch (Exception e) { _logger.Fatal(e, "An error has occurred while updating track info for artist {0}. {1}", artist, album); failCount++; } } var allAlbums = new List(); allAlbums.AddRange(newList); allAlbums.AddRange(updateList); // TODO: See if anything needs to be done here //AdjustMultiEpisodeAirTime(artist, allTracks); //AdjustDirectToDvdAirDate(artist, allTracks); _albumService.DeleteMany(existingAlbums); _albumService.UpdateMany(updateList); _albumService.InsertMany(newList); _eventAggregator.PublishEvent(new AlbumInfoRefreshedEvent(artist, newList, updateList)); if (failCount != 0) { _logger.Info("Finished album refresh for artist: {0}. Successful: {1} - Failed: {2} ", artist.Name, successCount, failCount); } else { _logger.Info("Finished album refresh for artist: {0}.", artist); } } private bool GetMonitoredStatus(Album album, IEnumerable artists) { var artist = artists.SingleOrDefault(c => c.Id == album.ArtistId); return album == null || album.Monitored; } private Album GetAlbumToUpdate(Artist artist, Album album, List existingAlbums) { return existingAlbums.FirstOrDefault(e => e.ForeignAlbumId == album.ForeignAlbumId/* && e.ReleaseDate == album.ReleaseDate*/); } private IEnumerable OrderAlbums(Artist artist, List albums) { return albums.OrderBy(e => e.ForeignAlbumId).ThenBy(e => e.ReleaseDate); } } }