public void Execute(ManualImportCommand message) { _logger.ProgressTrace("Manually importing {0} files using mode {1}", message.Files.Count, message.ImportMode); var imported = new List <ImportResult>(); var importedTrackedDownload = new List <ManuallyImportedFile>(); for (int i = 0; i < message.Files.Count; i++) { _logger.ProgressTrace("Processing file {0} of {1}", i + 1, message.Files.Count); var file = message.Files[i]; var series = _seriesService.GetSeries(file.SeriesId); var episodes = _episodeService.GetEpisodes(file.EpisodeIds); var parsedEpisodeInfo = Parser.Parser.ParsePath(file.Path) ?? new ParsedEpisodeInfo(); var mediaInfo = _videoFileInfoReader.GetMediaInfo(file.Path); var existingFile = series.Path.IsParentPath(file.Path); var localEpisode = new LocalEpisode { ExistingFile = false, Episodes = episodes, MediaInfo = mediaInfo, ParsedEpisodeInfo = parsedEpisodeInfo, Path = file.Path, Quality = file.Quality, Series = series, Size = 0 }; //TODO: Cleanup non-tracked downloads var importDecision = new ImportDecision(localEpisode); if (file.DownloadId.IsNullOrWhiteSpace()) { imported.AddRange(_importApprovedEpisodes.Import(new List <ImportDecision> { importDecision }, !existingFile, null, message.ImportMode)); } else { var trackedDownload = _trackedDownloadService.Find(file.DownloadId); var importResult = _importApprovedEpisodes.Import(new List <ImportDecision> { importDecision }, true, trackedDownload.DownloadItem, message.ImportMode).First(); imported.Add(importResult); importedTrackedDownload.Add(new ManuallyImportedFile { TrackedDownload = trackedDownload, ImportResult = importResult }); } } _logger.ProgressTrace("Manually imported {0} files", imported.Count); foreach (var groupedTrackedDownload in importedTrackedDownload.GroupBy(i => i.TrackedDownload.DownloadItem.DownloadId).ToList()) { var trackedDownload = groupedTrackedDownload.First().TrackedDownload; if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath.FullPath)) { if (_downloadedEpisodesImportService.ShouldDeleteFolder( new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath), trackedDownload.RemoteEpisode.Series) && trackedDownload.DownloadItem.CanMoveFiles) { _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true); } } if (groupedTrackedDownload.Select(c => c.ImportResult).Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count)) { trackedDownload.State = TrackedDownloadStage.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload)); } } }
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 seriesFiles = _mediaFileService.GetFilesBySeries(series.Id); var unmappedFiles = MediaFileService.FilterExistingFiles(mediaFileList, seriesFiles, series); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(unmappedFiles, series, false); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", series, decisionsStopwatch.Elapsed); _importApprovedEpisodes.Import(decisions, false); // Update existing files that have a different file size var fileInfoStopwatch = Stopwatch.StartNew(); var filesToUpdate = new List <EpisodeFile>(); foreach (var file in seriesFiles) { var path = Path.Combine(series.Path, file.RelativePath); var fileSize = _diskProvider.GetFileSize(path); if (file.Size == fileSize) { continue; } file.Size = fileSize; if (!_updateMediaInfoService.Update(file, series)) { 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}]", series, decisionsStopwatch.Elapsed); RemoveEmptySeriesFolder(series.Path); CompletedScanning(series); }
public void Execute(ManualImportCommand message) { _logger.ProgressTrace("Manually importing {0} files using mode {1}", message.Files.Count, message.ImportMode); var imported = new List <ImportResult>(); var importedTrackedDownload = new List <ManuallyImportedFile>(); for (int i = 0; i < message.Files.Count; i++) { _logger.ProgressTrace("Processing file {0} of {1}", i + 1, message.Files.Count); var file = message.Files[i]; var series = _seriesService.GetSeries(file.SeriesId); var episodes = _episodeService.GetEpisodes(file.EpisodeIds); var fileEpisodeInfo = Parser.Parser.ParsePath(file.Path) ?? new ParsedEpisodeInfo(); var existingFile = series.Path.IsParentPath(file.Path); TrackedDownload trackedDownload = null; var localEpisode = new LocalEpisode { ExistingFile = false, Episodes = episodes, FileEpisodeInfo = fileEpisodeInfo, Path = file.Path, ReleaseGroup = file.ReleaseGroup, Quality = file.Quality, Language = file.Language, Series = series, Size = 0 }; if (file.DownloadId.IsNotNullOrWhiteSpace()) { trackedDownload = _trackedDownloadService.Find(file.DownloadId); localEpisode.DownloadClientEpisodeInfo = trackedDownload?.RemoteEpisode?.ParsedEpisodeInfo; } if (file.FolderName.IsNotNullOrWhiteSpace()) { localEpisode.FolderEpisodeInfo = Parser.Parser.ParseTitle(file.FolderName); localEpisode.SceneSource = !existingFile; } localEpisode = _aggregationService.Augment(localEpisode, trackedDownload?.DownloadItem); // Apply the user-chosen values. localEpisode.Series = series; localEpisode.Episodes = episodes; localEpisode.ReleaseGroup = file.ReleaseGroup; localEpisode.Quality = file.Quality; localEpisode.Language = file.Language; //TODO: Cleanup non-tracked downloads var importDecision = new ImportDecision(localEpisode); if (trackedDownload == null) { imported.AddRange(_importApprovedEpisodes.Import(new List <ImportDecision> { importDecision }, !existingFile, null, message.ImportMode)); } else { var importResult = _importApprovedEpisodes.Import(new List <ImportDecision> { importDecision }, true, trackedDownload.DownloadItem, message.ImportMode).First(); imported.Add(importResult); importedTrackedDownload.Add(new ManuallyImportedFile { TrackedDownload = trackedDownload, ImportResult = importResult }); } } if (imported.Any()) { _logger.ProgressTrace("Manually imported {0} files", imported.Count); } foreach (var groupedTrackedDownload in importedTrackedDownload.GroupBy(i => i.TrackedDownload.DownloadItem.DownloadId).ToList()) { var trackedDownload = groupedTrackedDownload.First().TrackedDownload; var importedSeries = imported.First().ImportDecision.LocalEpisode.Series; var outputPath = trackedDownload.ImportItem.OutputPath.FullPath; if (_diskProvider.FolderExists(outputPath)) { if (_downloadedEpisodesImportService.ShouldDeleteFolder( new DirectoryInfo(outputPath), importedSeries) && trackedDownload.DownloadItem.CanMoveFiles) { _diskProvider.DeleteFolder(outputPath, true); } } var allEpisodesImported = groupedTrackedDownload.Select(c => c.ImportResult) .Where(c => c.Result == ImportResultType.Imported) .SelectMany(c => c.ImportDecision.LocalEpisode.Episodes).Count() >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count); if (allEpisodesImported) { trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, importedSeries.Id)); } } }
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) { _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); }