public void Handle(MovieFileDeletedEvent message) { if (_configService.DeleteEmptyFolders) { var movie = message.MovieFile.Movie; var moviePath = movie.Path; var folder = message.MovieFile.Path.GetParentPath(); while (moviePath.IsParentPath(folder)) { if (_diskProvider.FolderExists(folder)) { _diskProvider.RemoveEmptySubfolders(folder); } folder = folder.GetParentPath(); } _diskProvider.RemoveEmptySubfolders(moviePath); if (_diskProvider.FolderEmpty(moviePath)) { _diskProvider.DeleteFolder(moviePath, true); } } }
public void Handle(EpisodeFileDeletedEvent message) { if (_configService.DeleteEmptyFolders) { var series = message.EpisodeFile.Series.Value; var seriesPath = series.Path; var folder = message.EpisodeFile.Path.GetParentPath(); while (seriesPath.IsParentPath(folder)) { if (_diskProvider.FolderExists(folder)) { _diskProvider.RemoveEmptySubfolders(folder); } folder = folder.GetParentPath(); } _diskProvider.RemoveEmptySubfolders(seriesPath); if (_diskProvider.FolderEmpty(seriesPath)) { _diskProvider.DeleteFolder(seriesPath, true); } } }
public void Scan(Series series) { var rootFolder = _rootFolderService.GetBestRootFolderPath(series.Path); var seriesFolderExists = _diskProvider.FolderExists(series.Path); if (!seriesFolderExists) { if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Series' root folder ({0}) doesn't exist.", rootFolder); _eventAggregator.PublishEvent(new SeriesScanSkippedEvent(series, SeriesScanSkippedReason.RootFolderDoesNotExist)); return; } if (_diskProvider.FolderEmpty(rootFolder)) { _logger.Warn("Series' root folder ({0}) is empty.", rootFolder); _eventAggregator.PublishEvent(new SeriesScanSkippedEvent(series, SeriesScanSkippedReason.RootFolderIsEmpty)); return; } } _logger.ProgressInfo("Scanning {0}", series.Title); if (!seriesFolderExists) { if (_configService.CreateEmptySeriesFolders) { if (_configService.DeleteEmptyFolders) { _logger.Debug("Not creating missing series folder: {0} because delete empty series folders is enabled", series.Path); } else { _logger.Debug("Creating missing series folder: {0}", series.Path); _diskProvider.CreateFolder(series.Path); SetPermissions(series.Path); } } else { _logger.Debug("Series folder doesn't exist: {0}", series.Path); } CleanMediaFiles(series, new List <string>()); CompletedScanning(series); return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = FilterPaths(series.Path, GetVideoFiles(series.Path)).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting episode files for: {0} [{1}]", series, videoFilesStopwatch.Elapsed); CleanMediaFiles(series, mediaFileList); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, series); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", series, decisionsStopwatch.Elapsed); _importApprovedEpisodes.Import(decisions, false); RemoveEmptySeriesFolder(series.Path); CompletedScanning(series); }
public void Scan(List <string> folders = null, FilterFilesType filter = FilterFilesType.Known, bool addNewAuthors = false, List <int> authorIds = null) { if (folders == null) { folders = _rootFolderService.All().Select(x => x.Path).ToList(); } if (authorIds == null) { authorIds = new List <int>(); } var mediaFileList = new List <IFileInfo>(); var musicFilesStopwatch = Stopwatch.StartNew(); foreach (var folder in folders) { // We could be scanning a root folder or a subset of a root folder. If it's a subset, // check if the root folder exists before cleaning. var rootFolder = _rootFolderService.GetBestRootFolder(folder); if (rootFolder == null) { _logger.Error("Not scanning {0}, it's not a subdirectory of a defined root folder", folder); return; } var folderExists = _diskProvider.FolderExists(folder); if (!folderExists) { if (!_diskProvider.FolderExists(rootFolder.Path)) { _logger.Warn("Authors' root folder ({0}) doesn't exist.", rootFolder); var skippedAuthors = _authorService.GetAuthors(authorIds); skippedAuthors.ForEach(x => _eventAggregator.PublishEvent(new AuthorScanSkippedEvent(x, AuthorScanSkippedReason.RootFolderDoesNotExist))); return; } if (_diskProvider.FolderEmpty(rootFolder.Path)) { _logger.Warn("Authors' root folder ({0}) is empty.", rootFolder); var skippedAuthors = _authorService.GetAuthors(authorIds); skippedAuthors.ForEach(x => _eventAggregator.PublishEvent(new AuthorScanSkippedEvent(x, AuthorScanSkippedReason.RootFolderIsEmpty))); return; } } if (!folderExists) { _logger.Debug("Specified scan folder ({0}) doesn't exist.", folder); CleanMediaFiles(folder, new List <string>()); continue; } _logger.ProgressInfo("Scanning {0}", folder); var files = FilterFiles(folder, GetBookFiles(folder)); if (!files.Any()) { _logger.Warn("Scan folder {0} is empty.", folder); continue; } CleanMediaFiles(folder, files.Select(x => x.FullName).ToList()); mediaFileList.AddRange(files); } musicFilesStopwatch.Stop(); _logger.Trace("Finished getting track files for:\n{0} [{1}]", folders.ConcatToString("\n"), musicFilesStopwatch.Elapsed); var decisionsStopwatch = Stopwatch.StartNew(); var config = new ImportDecisionMakerConfig { Filter = filter, IncludeExisting = true, AddNewAuthors = addNewAuthors }; var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, null, null, config); decisionsStopwatch.Stop(); _logger.Debug("Import decisions complete [{0}]", decisionsStopwatch.Elapsed); var importStopwatch = Stopwatch.StartNew(); _importApprovedTracks.Import(decisions, false); // decisions may have been filtered to just new files. Anything new and approved will have been inserted. // Now we need to make sure anything new but not approved gets inserted // Note that knownFiles will include anything imported just now var knownFiles = new List <BookFile>(); folders.ForEach(x => knownFiles.AddRange(_mediaFileService.GetFilesWithBasePath(x))); var newFiles = decisions .ExceptBy(x => x.Item.Path, knownFiles, x => x.Path, PathEqualityComparer.Instance) .Select(decision => new BookFile { Path = decision.Item.Path, CalibreId = decision.Item.Path.ParseCalibreId(), Size = decision.Item.Size, Modified = decision.Item.Modified, DateAdded = DateTime.UtcNow, Quality = decision.Item.Quality, MediaInfo = decision.Item.FileTrackInfo.MediaInfo, Edition = decision.Item.Edition }) .ToList(); _mediaFileService.AddMany(newFiles); _logger.Debug($"Inserted {newFiles.Count} new unmatched trackfiles"); // finally update info on size/modified for existing files var updatedFiles = knownFiles .Join(decisions, x => x.Path, x => x.Item.Path, (file, decision) => new { File = file, Item = decision.Item }, PathEqualityComparer.Instance) .Where(x => x.File.Size != x.Item.Size || Math.Abs((x.File.Modified - x.Item.Modified).TotalSeconds) > 1) .Select(x => { x.File.Size = x.Item.Size; x.File.Modified = x.Item.Modified; x.File.MediaInfo = x.Item.FileTrackInfo.MediaInfo; x.File.Quality = x.Item.Quality; return(x.File); }) .ToList(); _mediaFileService.Update(updatedFiles); _logger.Debug($"Updated info for {updatedFiles.Count} known files"); var authors = _authorService.GetAuthors(authorIds); foreach (var author in authors) { CompletedScanning(author); } importStopwatch.Stop(); _logger.Debug("Book import complete for:\n{0} [{1}]", folders.ConcatToString("\n"), importStopwatch.Elapsed); }
public void Scan(Movie movie) { var rootFolder = _rootFolderService.GetBestRootFolderPath(movie.Path); var movieFolderExists = _diskProvider.FolderExists(movie.Path); if (!movieFolderExists) { if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Movie's root folder ({0}) doesn't exist.", rootFolder); _eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderDoesNotExist)); return; } if (_diskProvider.FolderEmpty(rootFolder)) { _logger.Warn("Movie's root folder ({0}) is empty.", rootFolder); _eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderIsEmpty)); return; } } _logger.ProgressInfo("Scanning disk for {0}", movie.Title); if (!movieFolderExists) { if (_configService.CreateEmptyMovieFolders) { if (_configService.DeleteEmptyFolders) { _logger.Debug("Not creating missing movie folder: {0} because delete empty movie folders is enabled", movie.Path); } else { _logger.Debug("Creating missing movie folder: {0}", movie.Path); _diskProvider.CreateFolder(movie.Path); SetPermissions(movie.Path); } } else { _logger.Debug("Movie's folder doesn't exist: {0}", movie.Path); } CleanMediaFiles(movie, new List <string>()); CompletedScanning(movie); return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = FilterPaths(movie.Path, GetVideoFiles(movie.Path)).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting movie files for: {0} [{1}]", movie, videoFilesStopwatch.Elapsed); CleanMediaFiles(movie, mediaFileList); var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id); var unmappedFiles = MediaFileService.FilterExistingFiles(mediaFileList, movieFiles, movie); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(unmappedFiles, movie, false); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed); _importApprovedMovies.Import(decisions, false); // Update existing files that have a different file size var fileInfoStopwatch = Stopwatch.StartNew(); var filesToUpdate = new List <MovieFile>(); foreach (var file in movieFiles) { var path = Path.Combine(movie.Path, file.RelativePath); var fileSize = _diskProvider.GetFileSize(path); if (file.Size == fileSize) { continue; } file.Size = fileSize; if (!_updateMediaInfoService.Update(file, movie)) { filesToUpdate.Add(file); } } // Update any files that had a file size change, but didn't get media info updated. if (filesToUpdate.Any()) { _mediaFileService.Update(filesToUpdate); } fileInfoStopwatch.Stop(); _logger.Trace("Reprocessing existing files complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed); RemoveEmptyMovieFolder(movie.Path); CompletedScanning(movie); }