using System; using System.Collections.Generic; using System.IO; using System.Linq; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Movies; using NzbDrone.Core.Movies.Events; namespace NzbDrone.Core.Extras.Files { public interface IExtraFileService where TExtraFile : ExtraFile, new() { List GetFilesByMovie(int movieId); List GetFilesByMovieFile(int movieFileId); TExtraFile FindByPath(string path); void Upsert(TExtraFile extraFile); void Upsert(List extraFiles); void Delete(int id); void DeleteMany(IEnumerable ids); } public abstract class ExtraFileService : IExtraFileService, IHandleAsync, IHandleAsync where TExtraFile : ExtraFile, new() { private readonly IExtraFileRepository _repository; private readonly IMovieService _movieService; private readonly IDiskProvider _diskProvider; private readonly IRecycleBinProvider _recycleBinProvider; private readonly Logger _logger; public ExtraFileService(IExtraFileRepository repository, IMovieService movieService, IDiskProvider diskProvider, IRecycleBinProvider recycleBinProvider, Logger logger) { _repository = repository; _movieService = movieService; _diskProvider = diskProvider; _recycleBinProvider = recycleBinProvider; _logger = logger; } public List GetFilesByMovie(int movieId) { return _repository.GetFilesByMovie(movieId); } public List GetFilesByMovieFile(int movieFileId) { return _repository.GetFilesByMovieFile(movieFileId); } public TExtraFile FindByPath(string path) { return _repository.FindByPath(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(MoviesDeletedEvent message) { _repository.DeleteForMovies(message.Movies.Select(m => m.Id).ToList()); } public void HandleAsync(MovieFileDeletedEvent message) { var movieFile = message.MovieFile; if (message.Reason == DeleteMediaFileReason.NoLinkedEpisodes) { _logger.Debug("Removing movie file from DB as part of cleanup routine, not deleting extra files from disk."); } else { var movie = _movieService.GetMovie(message.MovieFile.MovieId); foreach (var extra in _repository.GetFilesByMovieFile(movieFile.Id)) { var path = Path.Combine(movie.Path, extra.RelativePath); if (_diskProvider.FileExists(path)) { // Send to the recycling bin so they can be recovered if necessary _recycleBinProvider.DeleteFile(path); } } } _logger.Debug("Deleting Extra from database for movie file: {0}", movieFile); _repository.DeleteForMovieFile(movieFile.Id); } } }