Пример #1
0
        public void HandleAsync(EpisodeFileDeletedEvent message)
        {
            var episodeFile = message.EpisodeFile;
            var series      = _seriesService.GetSeries(message.EpisodeFile.SeriesId);

            foreach (var extra in _repository.GetFilesByEpisodeFile(episodeFile.Id))
            {
                var path = Path.Combine(series.Path, extra.RelativePath);

                if (_diskProvider.FileExists(path))
                {
                    if (PermanentlyDelete)
                    {
                        _diskProvider.DeleteFile(path);
                    }

                    else
                    {
                        // Send extra files to the recycling bin so they can be recovered if necessary
                        _recycleBinProvider.DeleteFile(path);
                    }
                }
            }

            _logger.Debug("Deleting Extra from database for episode file: {0}", episodeFile);
            _repository.DeleteForEpisodeFile(episodeFile.Id);
        }
Пример #2
0
        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);
        }
Пример #3
0
        public void DeleteEpisodeFile(Series series, EpisodeFile episodeFile)
        {
            var fullPath   = Path.Combine(series.Path, episodeFile.RelativePath);
            var rootFolder = _diskProvider.GetParentFolder(series.Path);

            if (!_diskProvider.FolderExists(rootFolder))
            {
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Series' root folder ({0}) doesn't exist.", rootFolder);
            }

            if (_diskProvider.GetDirectories(rootFolder).Empty())
            {
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Series' root folder ({0}) is empty.", rootFolder);
            }

            if (_diskProvider.FolderExists(series.Path) && _diskProvider.FileExists(fullPath))
            {
                _logger.Info("Deleting episode file: {0}", fullPath);

                var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(fullPath));

                try
                {
                    _recycleBinProvider.DeleteFile(fullPath, subfolder);
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Unable to delete episode file");
                    throw new NzbDroneClientException(HttpStatusCode.InternalServerError, "Unable to delete episode file");
                }
            }

            // Delete the episode file from the database to clean it up even if the file was already deleted
            _mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
        }
Пример #4
0
        public EpisodeFileMoveResult UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode, bool copyOnly = false)
        {
            var moveFileResult = new EpisodeFileMoveResult();
            var existingFiles  = localEpisode.Episodes
                                 .Where(e => e.EpisodeFileId > 0)
                                 .Select(e => e.EpisodeFile.Value)
                                 .GroupBy(e => e.Id);

            foreach (var existingFile in existingFiles)
            {
                var file            = existingFile.First();
                var episodeFilePath = Path.Combine(localEpisode.Series.Path, file.RelativePath);

                if (_diskProvider.FileExists(episodeFilePath))
                {
                    _logger.Debug("Removing existing episode file: {0}", file);
                    _recycleBinProvider.DeleteFile(episodeFilePath);
                }

                moveFileResult.OldFiles.Add(file);
                _mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
            }

            if (copyOnly)
            {
                moveFileResult.EpisodeFile = _episodeFileMover.CopyEpisodeFile(episodeFile, localEpisode);
            }
            else
            {
                moveFileResult.EpisodeFile = _episodeFileMover.MoveEpisodeFile(episodeFile, localEpisode);
            }

            return(moveFileResult);
        }
        public void Handle(EpisodeFileDeletedEvent message)
        {
            var episodeFile = message.EpisodeFile;

            if (message.Reason == DeleteMediaFileReason.NoLinkedEpisodes)
            {
                _logger.Debug("Removing episode file from DB as part of cleanup routine, not deleting extra files from disk.");
            }

            else
            {
                var series = _seriesService.GetSeries(message.EpisodeFile.SeriesId);

                foreach (var extra in _repository.GetFilesByEpisodeFile(episodeFile.Id))
                {
                    var path = Path.Combine(series.Path, extra.RelativePath);

                    if (_diskProvider.FileExists(path))
                    {
                        // Send to the recycling bin so they can be recovered if necessary
                        var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(path));
                        _recycleBinProvider.DeleteFile(path, subfolder);
                    }
                }
            }

            _logger.Debug("Deleting Extra from database for episode file: {0}", episodeFile);
            _repository.DeleteForEpisodeFile(episodeFile.Id);
        }
Пример #6
0
        public EpisodeFileMoveResult UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
        {
            var moveFileResult = new EpisodeFileMoveResult();
            var existingFiles  = localEpisode.Episodes
                                 .Where(e => e.EpisodeFileId > 0)
                                 .Select(e => e.EpisodeFile.Value)
                                 .GroupBy(e => e.Id);

            foreach (var existingFile in existingFiles)
            {
                var file = existingFile.First();

                if (_diskProvider.FileExists(file.Path))
                {
                    _logger.Debug("Removing existing episode file: {0}", file);
                    _recycleBinProvider.DeleteFile(file.Path);
                }

                moveFileResult.OldFiles.Add(file);
                _mediaFileService.Delete(file, true);
            }

            moveFileResult.EpisodeFile = _episodeFileMover.MoveEpisodeFile(episodeFile, localEpisode);

            return(moveFileResult);
        }
Пример #7
0
        public void Handle(BookFileDeletedEvent message)
        {
            var bookFile = message.BookFile;

            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 author = bookFile.Author.Value;

                foreach (var extra in _repository.GetFilesByBookFile(bookFile.Id))
                {
                    var path = Path.Combine(author.Path, extra.RelativePath);

                    if (_diskProvider.FileExists(path))
                    {
                        // Send to the recycling bin so they can be recovered if necessary
                        var subfolder = _diskProvider.GetParentFolder(author.Path).GetRelativePath(_diskProvider.GetParentFolder(path));
                        _recycleBinProvider.DeleteFile(path, subfolder);
                    }
                }
            }

            _logger.Debug("Deleting Extra from database for track file: {0}", bookFile);
            _repository.DeleteForBookFile(bookFile.Id);
        }
Пример #8
0
        private void DeleteEpisodeFile(int id)
        {
            var episodeFile = _mediaFileService.Get(id);

            _logger.Info("Deleting episode file: {0}", episodeFile.Path);
            _recycleBinProvider.DeleteFile(episodeFile.Path);
            _mediaFileService.Delete(episodeFile);
        }
Пример #9
0
        private void DeleteEpisodeFile(int id)
        {
            var episodeFile = _mediaFileService.Get(id);
            var series      = _seriesService.GetSeries(episodeFile.SeriesId);
            var fullPath    = Path.Combine(series.Path, episodeFile.RelativePath);

            _logger.Info("Deleting episode file: {0}", fullPath);
            _recycleBinProvider.DeleteFile(fullPath);
            _mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
        }
Пример #10
0
        private void DeleteMovieFile(int id)
        {
            var movieFile = _mediaFileService.GetMovie(id);
            var movie     = _movieService.GetMovie(movieFile.MovieId);
            var fullPath  = Path.Combine(movie.Path, movieFile.RelativePath);

            _logger.Info("Deleting movie file: {0}", fullPath);
            _recycleBinProvider.DeleteFile(fullPath);
            _mediaFileService.Delete(movieFile, DeleteMediaFileReason.Manual);
        }
Пример #11
0
        public void DeleteTrackFile(BookFile bookFile, string subfolder = "")
        {
            var fullPath = bookFile.Path;

            if (_diskProvider.FileExists(fullPath))
            {
                _logger.Info("Deleting book file: {0}", fullPath);

                try
                {
                    _recycleBinProvider.DeleteFile(fullPath, subfolder);
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Unable to delete book file");
                    throw new NzbDroneClientException(HttpStatusCode.InternalServerError, "Unable to delete book file");
                }
            }

            // Delete the track file from the database to clean it up even if the file was already deleted
            _mediaFileService.Delete(bookFile, DeleteMediaFileReason.Manual);
        }
Пример #12
0
        public MovieFileMoveResult UpgradeMovieFile(MovieFile movieFile, LocalMovie localMovie, bool copyOnly = false)
        {
            _logger.Trace("Upgrading existing movie file.");
            var moveFileResult = new MovieFileMoveResult();

            var existingFile = localMovie.Movie.MovieFile.Value;

            if (existingFile != null)
            {
                var movieFilePath = Path.Combine(localMovie.Movie.Path, existingFile.RelativePath);

                if (_diskProvider.FileExists(movieFilePath))
                {
                    _logger.Debug("Removing existing movie file: {0}", existingFile);
                    _recycleBinProvider.DeleteFile(movieFilePath);
                }

                moveFileResult.OldFiles.Add(existingFile);
                _mediaFileService.Delete(existingFile, DeleteMediaFileReason.Upgrade);
            }

            //Temporary for correctly getting path
            localMovie.Movie.MovieFileId = 1;
            localMovie.Movie.MovieFile   = movieFile;

            if (copyOnly)
            {
                moveFileResult.MovieFile = _movieFileMover.CopyMovieFile(movieFile, localMovie);
            }
            else
            {
                moveFileResult.MovieFile = _movieFileMover.MoveMovieFile(movieFile, localMovie);
            }

            //_movieFileRenamer.RenameMoviePath(localMovie.Movie, false);

            return(moveFileResult);
        }
Пример #13
0
        private void RemoveOtherExtraFile(Series series, string path)
        {
            if (!_diskProvider.FileExists(path))
            {
                return;
            }

            var relativePath   = series.Path.GetRelativePath(path);
            var otherExtraFile = _otherExtraFileService.FindByPath(series.Id, relativePath);

            if (otherExtraFile != null)
            {
                var subfolder = Path.GetDirectoryName(relativePath);
                _recycleBinProvider.DeleteFile(path, subfolder);
            }
        }
Пример #14
0
        private void RemoveOtherExtraFile(Movie movie, string path)
        {
            if (!_diskProvider.FileExists(path))
            {
                return;
            }

            var relativePath = movie.Path.GetRelativePath(path);

            var otherExtraFile = _otherExtraFileService.FindByPath(relativePath);

            if (otherExtraFile != null)
            {
                _recycleBinProvider.DeleteFile(path);
            }
        }
Пример #15
0
        private void RemoveOtherExtraFile(Movie movie, string path)
        {
            if (!_diskProvider.FileExists(path))
            {
                return;
            }

            var relativePath = movie.Path.GetRelativePath(path);

            var otherExtraFile = _otherExtraFileService.GetFilesByMovie(movie.Id).Where(e => e.RelativePath == relativePath).SingleOrDefault();

            if (otherExtraFile != null)
            {
                _recycleBinProvider.DeleteFile(path);
            }
        }
Пример #16
0
        public TrackFileMoveResult UpgradeTrackFile(TrackFile trackFile, LocalTrack localTrack, bool copyOnly = false)
        {
            var moveFileResult = new TrackFileMoveResult();
            var existingFiles  = localTrack.Tracks
                                 .Where(e => e.TrackFileId > 0)
                                 .Select(e => e.TrackFile.Value)
                                 .Where(e => e != null)
                                 .GroupBy(e => e.Id)
                                 .ToList();

            var rootFolder = _diskProvider.GetParentFolder(localTrack.Artist.Path);

            // If there are existing track files and the root folder is missing, throw, so the old file isn't left behind during the import process.
            if (existingFiles.Any() && !_diskProvider.FolderExists(rootFolder))
            {
                throw new RootFolderNotFoundException($"Root folder '{rootFolder}' was not found.");
            }

            foreach (var existingFile in existingFiles)
            {
                var file          = existingFile.First();
                var trackFilePath = file.Path;
                var subfolder     = rootFolder.GetRelativePath(_diskProvider.GetParentFolder(trackFilePath));

                if (_diskProvider.FileExists(trackFilePath))
                {
                    _logger.Debug("Removing existing track file: {0}", file);
                    _recycleBinProvider.DeleteFile(trackFilePath, subfolder);
                }

                moveFileResult.OldFiles.Add(file);
                _mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
            }

            if (copyOnly)
            {
                moveFileResult.TrackFile = _trackFileMover.CopyTrackFile(trackFile, localTrack);
            }
            else
            {
                moveFileResult.TrackFile = _trackFileMover.MoveTrackFile(trackFile, localTrack);
            }

            _audioTagService.WriteTags(trackFile, true);

            return(moveFileResult);
        }
Пример #17
0
        public EpisodeFileMoveResult UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode, bool copyOnly = false)
        {
            var moveFileResult = new EpisodeFileMoveResult();
            var existingFiles  = localEpisode.Episodes
                                 .Where(e => e.EpisodeFileId > 0)
                                 .Select(e => e.EpisodeFile.Value)
                                 .Where(e => e != null)
                                 .GroupBy(e => e.Id)
                                 .ToList();

            var rootFolder = _diskProvider.GetParentFolder(localEpisode.Series.Path);

            // If there are existing episode files and the root folder is missing, throw, so the old file isn't left behind during the import process.
            if (existingFiles.Any() && !_diskProvider.FolderExists(rootFolder))
            {
                throw new RootFolderNotFoundException($"Root folder '{rootFolder}' was not found.");
            }

            foreach (var existingFile in existingFiles)
            {
                var file            = existingFile.First();
                var episodeFilePath = Path.Combine(localEpisode.Series.Path, file.RelativePath);
                var subfolder       = rootFolder.GetRelativePath(_diskProvider.GetParentFolder(episodeFilePath));

                if (_diskProvider.FileExists(episodeFilePath))
                {
                    _logger.Debug("Removing existing episode file: {0}", file);
                    _recycleBinProvider.DeleteFile(episodeFilePath, subfolder);
                }

                moveFileResult.OldFiles.Add(file);
                _mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
            }

            if (copyOnly)
            {
                moveFileResult.EpisodeFile = _episodeFileMover.CopyEpisodeFile(episodeFile, localEpisode);
            }
            else
            {
                moveFileResult.EpisodeFile = _episodeFileMover.MoveEpisodeFile(episodeFile, localEpisode);
            }

            return(moveFileResult);
        }
Пример #18
0
        private void RemoveExistingTrackFiles(Author author, Book book)
        {
            var rootFolder    = _diskProvider.GetParentFolder(author.Path);
            var previousFiles = _mediaFileService.GetFilesByBook(book.Id);

            _logger.Debug($"Deleting {previousFiles.Count} existing files for {book}");

            foreach (var previousFile in previousFiles)
            {
                var subfolder = rootFolder.GetRelativePath(_diskProvider.GetParentFolder(previousFile.Path));
                if (_diskProvider.FileExists(previousFile.Path))
                {
                    _logger.Debug("Removing existing book file: {0}", previousFile);
                    _recycleBinProvider.DeleteFile(previousFile.Path, subfolder);
                }

                _mediaFileService.Delete(previousFile, DeleteMediaFileReason.Upgrade);
            }
        }
Пример #19
0
        private void RemoveExistingTrackFiles(Artist artist, Album album)
        {
            var rootFolder    = _diskProvider.GetParentFolder(artist.Path);
            var previousFiles = _mediaFileService.GetFilesByAlbum(album.Id);

            _logger.Debug($"Deleting {previousFiles.Count} existing files for {album}");

            foreach (var previousFile in previousFiles)
            {
                var subfolder = rootFolder.GetRelativePath(_diskProvider.GetParentFolder(previousFile.Path));
                if (_diskProvider.FileExists(previousFile.Path))
                {
                    _logger.Debug("Removing existing track file: {0}", previousFile);
                    _recycleBinProvider.DeleteFile(previousFile.Path, subfolder);
                }

                _mediaFileService.Delete(previousFile, DeleteMediaFileReason.Upgrade);
            }
        }
Пример #20
0
        public MovieFileMoveResult UpgradeMovieFile(MovieFile movieFile, LocalMovie localMovie, bool copyOnly = false)
        {
            _logger.Trace("Upgrading existing movie file.");
            var moveFileResult = new MovieFileMoveResult();

            var existingFile = localMovie.Movie.MovieFileId > 0 ? localMovie.Movie.MovieFile : null;

            var rootFolder = _diskProvider.GetParentFolder(localMovie.Movie.Path);

            // If there are existing movie files and the root folder is missing, throw, so the old file isn't left behind during the import process.
            if (existingFile != null && !_diskProvider.FolderExists(rootFolder))
            {
                throw new RootFolderNotFoundException($"Root folder '{rootFolder}' was not found.");
            }

            if (existingFile != null)
            {
                var movieFilePath = Path.Combine(localMovie.Movie.Path, existingFile.RelativePath);
                var subfolder     = rootFolder.GetRelativePath(_diskProvider.GetParentFolder(movieFilePath));

                if (_diskProvider.FileExists(movieFilePath))
                {
                    _logger.Debug("Removing existing movie file: {0}", existingFile);
                    _recycleBinProvider.DeleteFile(movieFilePath, subfolder);
                }

                moveFileResult.OldFiles.Add(existingFile);
                _mediaFileService.Delete(existingFile, DeleteMediaFileReason.Upgrade);
            }

            if (copyOnly)
            {
                moveFileResult.MovieFile = _movieFileMover.CopyMovieFile(movieFile, localMovie);
            }
            else
            {
                moveFileResult.MovieFile = _movieFileMover.MoveMovieFile(movieFile, localMovie);
            }

            return(moveFileResult);
        }
Пример #21
0
        private MetadataFile GetMetadataFile(Movie movie, List <MetadataFile> existingMetadataFiles, Func <MetadataFile, bool> predicate)
        {
            var matchingMetadataFiles = existingMetadataFiles.Where(predicate).ToList();

            if (matchingMetadataFiles.Empty())
            {
                return(null);
            }

            //Remove duplicate metadata files from DB and disk
            foreach (var file in matchingMetadataFiles.Skip(1))
            {
                var path = Path.Combine(movie.Path, file.RelativePath);

                _logger.Debug("Removing duplicate Metadata file: {0}", path);

                _recycleBinProvider.DeleteFile(path);
                _metadataFileService.Delete(file.Id);
            }

            return(matchingMetadataFiles.First());
        }
        public void DeleteMovieFile(Movie movie, MovieFile movieFile)
        {
            var fullPath   = Path.Combine(movie.Path, movieFile.RelativePath);
            var rootFolder = _diskProvider.GetParentFolder(movie.Path);

            if (!_diskProvider.FolderExists(rootFolder))
            {
                _logger.Warn("Movie's root folder ({0}) doesn't exist.", rootFolder);
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Movie's root folder ({0}) doesn't exist.", rootFolder);
            }

            if (_diskProvider.GetDirectories(rootFolder).Empty())
            {
                _logger.Warn("Movie's root folder ({0}) is empty.", rootFolder);
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Movie's root folder ({0}) is empty.", rootFolder);
            }

            if (_diskProvider.FolderExists(movie.Path) && _diskProvider.FileExists(fullPath))
            {
                _logger.Info("Deleting movie file: {0}", fullPath);

                var subfolder = _diskProvider.GetParentFolder(movie.Path).GetRelativePath(_diskProvider.GetParentFolder(fullPath));

                try
                {
                    _recycleBinProvider.DeleteFile(fullPath, subfolder);
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Unable to delete movie file");
                    throw new NzbDroneClientException(HttpStatusCode.InternalServerError, "Unable to delete movie file");
                }
            }

            // Delete the movie file from the database to clean it up even if the file was already deleted
            _mediaFileService.Delete(movieFile, DeleteMediaFileReason.Manual);

            _eventAggregator.PublishEvent(new DeleteCompletedEvent());
        }
Пример #23
0
        private void DeleteFile(BookFile bookFile, string subfolder = "")
        {
            var rootFolder = _rootFolderService.GetBestRootFolder(bookFile.Path);
            var isCalibre  = rootFolder.IsCalibreLibrary && rootFolder.CalibreSettings != null;

            try
            {
                if (!isCalibre)
                {
                    _recycleBinProvider.DeleteFile(bookFile.Path, subfolder);
                }
                else
                {
                    _calibre.DeleteBook(bookFile, rootFolder.CalibreSettings);
                }
            }
            catch (Exception e)
            {
                _logger.Error(e, "Unable to delete book file");
                throw new NzbDroneClientException(HttpStatusCode.InternalServerError, "Unable to delete book file");
            }
        }
Пример #24
0
        public string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
        {
            var existingFiles = localEpisode.Episodes
                                .Where(e => e.EpisodeFileId > 0)
                                .Select(e => e.EpisodeFile.Value)
                                .GroupBy(e => e.Id);

            foreach (var existingFile in existingFiles)
            {
                var file = existingFile.First();

                if (_diskProvider.FileExists(file.Path))
                {
                    _logger.Trace("Removing existing episode file: {0}", file);
                    _recycleBinProvider.DeleteFile(file.Path);
                }

                _mediaFileService.Delete(file, true);
            }

            _logger.Trace("Moving episode file: {0}", episodeFile);
            return(_episodeFileMover.MoveEpisodeFile(episodeFile, localEpisode));
        }
Пример #25
0
        public List <ImportResult> Import(List <ImportDecision <LocalTrack> > decisions, bool replaceExisting, DownloadClientItem downloadClientItem = null, ImportMode importMode = ImportMode.Auto)
        {
            var qualifiedImports = decisions.Where(c => c.Approved)
                                   .GroupBy(c => c.Item.Artist.Id, (i, s) => s
                                            .OrderByDescending(c => c.Item.Quality, new QualityModelComparer(s.First().Item.Artist.QualityProfile))
                                            .ThenByDescending(c => c.Item.Size))
                                   .SelectMany(c => c)
                                   .ToList();

            _logger.Debug($"Importing {qualifiedImports.Count} files. replaceExisting: {replaceExisting}");

            var importResults         = new List <ImportResult>();
            var allImportedTrackFiles = new List <TrackFile>();
            var allOldTrackFiles      = new List <TrackFile>();

            var albumDecisions = decisions.Where(e => e.Item.Album != null && e.Approved)
                                 .GroupBy(e => e.Item.Album.Id).ToList();

            foreach (var albumDecision in albumDecisions)
            {
                var album      = albumDecision.First().Item.Album;
                var newRelease = albumDecision.First().Item.Release;

                if (replaceExisting)
                {
                    var artist        = albumDecision.First().Item.Artist;
                    var rootFolder    = _diskProvider.GetParentFolder(artist.Path);
                    var previousFiles = _mediaFileService.GetFilesByAlbum(album.Id);

                    _logger.Debug($"Deleting {previousFiles.Count} existing files for {album}");

                    foreach (var previousFile in previousFiles)
                    {
                        var subfolder = rootFolder.GetRelativePath(_diskProvider.GetParentFolder(previousFile.Path));
                        if (_diskProvider.FileExists(previousFile.Path))
                        {
                            _logger.Debug("Removing existing track file: {0}", previousFile);
                            _recycleBinProvider.DeleteFile(previousFile.Path, subfolder);
                        }
                        _mediaFileService.Delete(previousFile, DeleteMediaFileReason.Upgrade);
                    }
                }

                // set the correct release to be monitored before importing the new files
                _logger.Debug("Updating release to {0} [{1} tracks]", newRelease, newRelease.TrackCount);
                album.AlbumReleases = _releaseService.SetMonitored(newRelease);

                // Publish album edited event.
                // Deliberatly don't put in the old album since we don't want to trigger an ArtistScan.
                _eventAggregator.PublishEvent(new AlbumEditedEvent(album, album));
            }

            var filesToAdd          = new List <TrackFile>(qualifiedImports.Count);
            var albumReleasesDict   = new Dictionary <int, List <AlbumRelease> >(albumDecisions.Count);
            var trackImportedEvents = new List <TrackImportedEvent>(qualifiedImports.Count);

            foreach (var importDecision in qualifiedImports.OrderBy(e => e.Item.Tracks.Select(track => track.AbsoluteTrackNumber).MinOrDefault())
                     .ThenByDescending(e => e.Item.Size))
            {
                var localTrack = importDecision.Item;
                var oldFiles   = new List <TrackFile>();

                try
                {
                    //check if already imported
                    if (importResults.SelectMany(r => r.ImportDecision.Item.Tracks)
                        .Select(e => e.Id)
                        .Intersect(localTrack.Tracks.Select(e => e.Id))
                        .Any())
                    {
                        importResults.Add(new ImportResult(importDecision, "Track has already been imported"));
                        continue;
                    }

                    // cache album releases and set artist to speed up firing the TrackImported events
                    // (otherwise they'll be retrieved from the DB for each track)
                    if (!albumReleasesDict.ContainsKey(localTrack.Album.Id))
                    {
                        albumReleasesDict.Add(localTrack.Album.Id, localTrack.Album.AlbumReleases.Value);
                    }
                    if (!localTrack.Album.AlbumReleases.IsLoaded)
                    {
                        localTrack.Album.AlbumReleases = albumReleasesDict[localTrack.Album.Id];
                    }
                    localTrack.Album.Artist = localTrack.Artist;

                    foreach (var track in localTrack.Tracks)
                    {
                        track.Artist       = localTrack.Artist;
                        track.AlbumRelease = localTrack.Release;
                        track.Album        = localTrack.Album;
                    }

                    var trackFile = new TrackFile {
                        Path         = localTrack.Path.CleanFilePath(),
                        Size         = localTrack.Size,
                        Modified     = localTrack.Modified,
                        DateAdded    = DateTime.UtcNow,
                        ReleaseGroup = localTrack.ReleaseGroup,
                        Quality      = localTrack.Quality,
                        MediaInfo    = localTrack.FileTrackInfo.MediaInfo,
                        AlbumId      = localTrack.Album.Id,
                        Artist       = localTrack.Artist,
                        Album        = localTrack.Album,
                        Tracks       = localTrack.Tracks
                    };

                    bool copyOnly;
                    switch (importMode)
                    {
                    default:
                    case ImportMode.Auto:
                        copyOnly = downloadClientItem != null && !downloadClientItem.CanMoveFiles;
                        break;

                    case ImportMode.Move:
                        copyOnly = false;
                        break;

                    case ImportMode.Copy:
                        copyOnly = true;
                        break;
                    }

                    if (!localTrack.ExistingFile)
                    {
                        trackFile.SceneName = GetSceneReleaseName(downloadClientItem, localTrack);

                        var moveResult = _trackFileUpgrader.UpgradeTrackFile(trackFile, localTrack, copyOnly);
                        oldFiles = moveResult.OldFiles;
                    }
                    else
                    {
                        // Delete existing files from the DB mapped to this path
                        var previousFile = _mediaFileService.GetFileWithPath(trackFile.Path);

                        if (previousFile != null)
                        {
                            _mediaFileService.Delete(previousFile, DeleteMediaFileReason.ManualOverride);
                        }

                        _audioTagService.WriteTags(trackFile, false);
                    }

                    filesToAdd.Add(trackFile);
                    importResults.Add(new ImportResult(importDecision));

                    if (!localTrack.ExistingFile)
                    {
                        _extraService.ImportTrack(localTrack, trackFile, copyOnly);
                    }

                    allImportedTrackFiles.Add(trackFile);
                    allOldTrackFiles.AddRange(oldFiles);

                    // create all the import events here, but we can't publish until the trackfiles have been
                    // inserted and ids created
                    trackImportedEvents.Add(new TrackImportedEvent(localTrack, trackFile, oldFiles, !localTrack.ExistingFile, downloadClientItem));
                }
                catch (RootFolderNotFoundException e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    _eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, !localTrack.ExistingFile, downloadClientItem));

                    importResults.Add(new ImportResult(importDecision, "Failed to import track, Root folder missing."));
                }
                catch (DestinationAlreadyExistsException e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    importResults.Add(new ImportResult(importDecision, "Failed to import track, Destination already exists."));
                }
                catch (UnauthorizedAccessException e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    _eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, !localTrack.ExistingFile, downloadClientItem));

                    importResults.Add(new ImportResult(importDecision, "Failed to import track, Permissions error"));
                }
                catch (Exception e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    importResults.Add(new ImportResult(importDecision, "Failed to import track"));
                }
            }

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            _mediaFileService.AddMany(filesToAdd);
            _logger.Debug($"Inserted new trackfiles in {watch.ElapsedMilliseconds}ms");
            filesToAdd.ForEach(f => f.Tracks.Value.ForEach(t => t.TrackFileId = f.Id));
            _trackService.SetFileIds(filesToAdd.SelectMany(x => x.Tracks.Value).ToList());
            _logger.Debug($"TrackFileIds updated, total {watch.ElapsedMilliseconds}ms");

            // now that trackfiles have been inserted and ids generated, publish the import events
            foreach (var trackImportedEvent in trackImportedEvents)
            {
                _eventAggregator.PublishEvent(trackImportedEvent);
            }

            var albumImports = importResults.Where(e => e.ImportDecision.Item.Album != null)
                               .GroupBy(e => e.ImportDecision.Item.Album.Id).ToList();

            foreach (var albumImport in albumImports)
            {
                var release = albumImport.First().ImportDecision.Item.Release;
                var album   = albumImport.First().ImportDecision.Item.Album;
                var artist  = albumImport.First().ImportDecision.Item.Artist;

                if (albumImport.Where(e => e.Errors.Count == 0).ToList().Count > 0 && artist != null && album != null)
                {
                    _eventAggregator.PublishEvent(new AlbumImportedEvent(
                                                      artist,
                                                      album,
                                                      release,
                                                      allImportedTrackFiles.Where(s => s.AlbumId == album.Id).ToList(),
                                                      allOldTrackFiles.Where(s => s.AlbumId == album.Id).ToList(), replaceExisting,
                                                      downloadClientItem));
                }
            }

            //Adding all the rejected decisions
            importResults.AddRange(decisions.Where(c => !c.Approved)
                                   .Select(d => new ImportResult(d, d.Rejections.Select(r => r.Reason).ToArray())));

            return(importResults);
        }
Пример #26
0
        public BookFileMoveResult UpgradeBookFile(BookFile bookFile, LocalBook localBook, bool copyOnly = false)
        {
            var moveFileResult = new BookFileMoveResult();
            var existingFiles  = localBook.Book.BookFiles.Value;

            var rootFolderPath = _diskProvider.GetParentFolder(localBook.Author.Path);
            var rootFolder     = _rootFolderService.GetBestRootFolder(rootFolderPath);
            var isCalibre      = rootFolder.IsCalibreLibrary && rootFolder.CalibreSettings != null;

            var settings = rootFolder.CalibreSettings;

            // If there are existing book files and the root folder is missing, throw, so the old file isn't left behind during the import process.
            if (existingFiles.Any() && !_diskProvider.FolderExists(rootFolderPath))
            {
                throw new RootFolderNotFoundException($"Root folder '{rootFolderPath}' was not found.");
            }

            foreach (var file in existingFiles)
            {
                var bookFilePath = file.Path;
                var subfolder    = rootFolderPath.GetRelativePath(_diskProvider.GetParentFolder(bookFilePath));

                bookFile.CalibreId = file.CalibreId;

                if (_diskProvider.FileExists(bookFilePath))
                {
                    _logger.Debug("Removing existing book file: {0} CalibreId: {1}", file, file.CalibreId);

                    if (!isCalibre)
                    {
                        _recycleBinProvider.DeleteFile(bookFilePath, subfolder);
                    }
                    else
                    {
                        var existing        = _calibre.GetBook(file.CalibreId, settings);
                        var existingFormats = existing.Formats.Keys;
                        _logger.Debug($"Removing existing formats {existingFormats.ConcatToString()} from calibre");
                        _calibre.RemoveFormats(file.CalibreId, existingFormats, settings);
                    }
                }

                moveFileResult.OldFiles.Add(file);
                _mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
            }

            if (!isCalibre)
            {
                if (copyOnly)
                {
                    moveFileResult.BookFile = _bookFileMover.CopyBookFile(bookFile, localBook);
                }
                else
                {
                    moveFileResult.BookFile = _bookFileMover.MoveBookFile(bookFile, localBook);
                }

                _metadataTagService.WriteTags(bookFile, true);
            }
            else
            {
                var source = bookFile.Path;

                moveFileResult.BookFile = _calibre.AddAndConvert(bookFile, settings);

                if (!copyOnly)
                {
                    _diskProvider.DeleteFile(source);
                }
            }

            return(moveFileResult);
        }