using System; using System.Collections.Generic; using System.IO; using System.Linq; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Music; using NzbDrone.Core.Music.Events; namespace NzbDrone.Core.Extras.Files { public interface IExtraFileService where TExtraFile : ExtraFile, new() { List GetFilesByArtist(int artistId); List GetFilesByTrackFile(int trackFileId); TExtraFile FindByPath(int artistId, string path); void Upsert(TExtraFile extraFile); void Upsert(List extraFiles); void Delete(int id); void DeleteMany(IEnumerable ids); } public abstract class ExtraFileService : IExtraFileService, IHandleAsync, IHandle where TExtraFile : ExtraFile, new() { private readonly IExtraFileRepository _repository; private readonly IArtistService _artistService; private readonly IDiskProvider _diskProvider; private readonly IRecycleBinProvider _recycleBinProvider; private readonly Logger _logger; public ExtraFileService(IExtraFileRepository repository, IArtistService artistService, IDiskProvider diskProvider, IRecycleBinProvider recycleBinProvider, Logger logger) { _repository = repository; _artistService = artistService; _diskProvider = diskProvider; _recycleBinProvider = recycleBinProvider; _logger = logger; } public List GetFilesByArtist(int artistId) { return _repository.GetFilesByArtist(artistId); } public List GetFilesByTrackFile(int trackFileId) { return _repository.GetFilesByTrackFile(trackFileId); } public TExtraFile FindByPath(int artistId, string path) { return _repository.FindByPath(artistId, path); } public void Upsert(TExtraFile extraFile) { Upsert(new List { extraFile }); } public void Upsert(List extraFiles) { extraFiles.ForEach(m => { m.LastUpdated = DateTime.UtcNow; if (m.Id == 0) { m.Added = m.LastUpdated; } }); _repository.InsertMany(extraFiles.Where(m => m.Id == 0).ToList()); _repository.UpdateMany(extraFiles.Where(m => m.Id > 0).ToList()); } public void Delete(int id) { _repository.Delete(id); } public void DeleteMany(IEnumerable ids) { _repository.DeleteMany(ids); } public void HandleAsync(ArtistsDeletedEvent message) { _repository.DeleteForArtists(message.Artists.Select(x => x.Id).ToList()); } public void Handle(TrackFileDeletedEvent message) { var trackFile = message.TrackFile; if (message.Reason == DeleteMediaFileReason.NoLinkedEpisodes) { _logger.Debug("Removing track file from DB as part of cleanup routine, not deleting extra files from disk."); } else { var artist = trackFile.Artist.Value; foreach (var extra in _repository.GetFilesByTrackFile(trackFile.Id)) { var path = Path.Combine(artist.Path, extra.RelativePath); if (_diskProvider.FileExists(path)) { // Send to the recycling bin so they can be recovered if necessary var subfolder = _diskProvider.GetParentFolder(artist.Path).GetRelativePath(_diskProvider.GetParentFolder(path)); _recycleBinProvider.DeleteFile(path, subfolder); } } } _logger.Debug("Deleting Extra from database for track file: {0}", trackFile); _repository.DeleteForTrackFile(trackFile.Id); } } }