private ImportDecision GetDecision(LocalEpisode localEpisode, DownloadClientItem downloadClientItem, bool otherFiles) { ImportDecision decision = null; var fileEpisodeInfo = Parser.Parser.ParsePath(localEpisode.Path); localEpisode.FileEpisodeInfo = fileEpisodeInfo; localEpisode.Size = _diskProvider.GetFileSize(localEpisode.Path); try { _aggregationService.Augment(localEpisode, downloadClientItem, otherFiles); if (localEpisode.Episodes.Empty()) { if (IsPartialSeason(localEpisode)) { decision = new ImportDecision(localEpisode, new Rejection("Partial season packs are not supported")); } else if (IsSeasonExtra(localEpisode)) { decision = new ImportDecision(localEpisode, new Rejection("Extras are not supported")); } else { decision = new ImportDecision(localEpisode, new Rejection("Invalid season or episode")); } } else { decision = GetDecision(localEpisode, downloadClientItem); } } catch (AugmentingFailedException) { decision = new ImportDecision(localEpisode, new Rejection("Unable to parse file")); } catch (Exception ex) { _logger.Error(ex, "Couldn't import file. {0}", localEpisode.Path); decision = new ImportDecision(localEpisode, new Rejection("Unexpected error processing file")); } if (decision == null) { _logger.Error("Unable to make a decision on {0}", localEpisode.Path); } else if (decision.Rejections.Any()) { _logger.Debug("File rejected for the following reasons: {0}", string.Join(", ", decision.Rejections)); } else { _logger.Debug("File accepted"); } return(decision); }
private ImportDecision GetDecision(LocalMovie localMovie, DownloadClientItem downloadClientItem, bool otherFiles) { ImportDecision decision = null; var fileMovieInfo = Parser.Parser.ParseMoviePath(localMovie.Path); if (fileMovieInfo != null) { fileMovieInfo = _parsingService.EnhanceMovieInfo(fileMovieInfo); } localMovie.FileMovieInfo = fileMovieInfo; localMovie.Size = _diskProvider.GetFileSize(localMovie.Path); try { _aggregationService.Augment(localMovie, downloadClientItem, otherFiles); if (localMovie.Movie == null) { decision = new ImportDecision(localMovie, new Rejection("Invalid movie")); } else { decision = GetDecision(localMovie, downloadClientItem); } } catch (AugmentingFailedException) { decision = new ImportDecision(localMovie, new Rejection("Unable to parse file")); } catch (Exception ex) { _logger.Error(ex, "Couldn't import file. {0}", localMovie.Path); decision = new ImportDecision(localMovie, new Rejection("Unexpected error processing file")); } if (decision == null) { _logger.Error("Unable to make a decision on {0}", localMovie.Path); } else if (decision.Rejections.Any()) { _logger.Debug("File rejected for the following reasons: {0}", string.Join(", ", decision.Rejections)); } else { _logger.Debug("File accepted"); } return(decision); }
public override IEnumerable <ExtraFile> ProcessFiles(Series series, List <string> filesOnDisk, List <string> importedFiles) { _logger.Debug("Looking for existing extra files in {0}", series.Path); var extraFiles = new List <OtherExtraFile>(); var filterResult = FilterAndClean(series, filesOnDisk, importedFiles); foreach (var possibleExtraFile in filterResult.FilesOnDisk) { var extension = Path.GetExtension(possibleExtraFile); if (extension.IsNullOrWhiteSpace()) { _logger.Debug("No extension for file: {0}", possibleExtraFile); continue; } var localEpisode = new LocalEpisode { FileEpisodeInfo = Parser.Parser.ParsePath(possibleExtraFile), Series = series, Path = possibleExtraFile }; try { _aggregationService.Augment(localEpisode, null); } catch (AugmentingFailedException) { _logger.Debug("Unable to parse extra file: {0}", possibleExtraFile); continue; } if (localEpisode.Episodes.Empty()) { _logger.Debug("Cannot find related episodes for: {0}", possibleExtraFile); continue; } if (localEpisode.Episodes.DistinctBy(e => e.EpisodeFileId).Count() > 1) { _logger.Debug("Extra file: {0} does not match existing files.", possibleExtraFile); continue; } var extraFile = new OtherExtraFile { SeriesId = series.Id, SeasonNumber = localEpisode.SeasonNumber, EpisodeFileId = localEpisode.Episodes.First().EpisodeFileId, RelativePath = series.Path.GetRelativePath(possibleExtraFile), Extension = extension }; extraFiles.Add(extraFile); } _logger.Info("Found {0} existing other extra files", extraFiles.Count); _otherExtraFileService.Upsert(extraFiles); // Return files that were just imported along with files that were // previously imported so previously imported files aren't imported twice return(extraFiles.Concat(filterResult.PreviouslyImported)); }
public override IEnumerable <ExtraFile> ProcessFiles(Series series, List <string> filesOnDisk, List <string> importedFiles) { _logger.Debug("Looking for existing metadata in {0}", series.Path); var metadataFiles = new List <MetadataFile>(); var filterResult = FilterAndClean(series, filesOnDisk, importedFiles); foreach (var possibleMetadataFile in filterResult.FilesOnDisk) { // Don't process files that have known Subtitle file extensions (saves a bit of unecessary processing) if (SubtitleFileExtensions.Extensions.Contains(Path.GetExtension(possibleMetadataFile))) { continue; } foreach (var consumer in _consumers) { var metadata = consumer.FindMetadataFile(series, possibleMetadataFile); if (metadata == null) { continue; } if (metadata.Type == MetadataType.EpisodeImage || metadata.Type == MetadataType.EpisodeMetadata) { var localEpisode = new LocalEpisode { FileEpisodeInfo = Parser.Parser.ParsePath(possibleMetadataFile), Series = series, Path = possibleMetadataFile }; try { _aggregationService.Augment(localEpisode, null); } catch (AugmentingFailedException) { _logger.Debug("Unable to parse extra file: {0}", possibleMetadataFile); continue; } if (localEpisode.Episodes.Empty()) { _logger.Debug("Cannot find related episodes for: {0}", possibleMetadataFile); continue; } if (localEpisode.Episodes.DistinctBy(e => e.EpisodeFileId).Count() > 1) { _logger.Debug("Extra file: {0} does not match existing files.", possibleMetadataFile); continue; } metadata.SeasonNumber = localEpisode.SeasonNumber; metadata.EpisodeFileId = localEpisode.Episodes.First().EpisodeFileId; } metadata.Extension = Path.GetExtension(possibleMetadataFile); metadataFiles.Add(metadata); } } _logger.Info("Found {0} existing metadata files", metadataFiles.Count); _metadataFileService.Upsert(metadataFiles); // Return files that were just imported along with files that were // previously imported so previously imported files aren't imported twice return(metadataFiles.Concat(filterResult.PreviouslyImported)); }
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; } // Augment episode file so imported files have all additional information an automatic import would 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 ?? 1); if (allEpisodesImported) { trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, importedSeries.Id)); } } }
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 movie = _movieService.GetMovie(file.MovieId); var fileMovieInfo = Parser.Parser.ParseMoviePath(file.Path) ?? new ParsedMovieInfo(); var existingFile = movie.Path.IsParentPath(file.Path); TrackedDownload trackedDownload = null; var localMovie = new LocalMovie { ExistingFile = false, FileMovieInfo = fileMovieInfo, Path = file.Path, Quality = file.Quality, Languages = file.Languages, Movie = movie, Size = 0 }; if (file.DownloadId.IsNotNullOrWhiteSpace()) { trackedDownload = _trackedDownloadService.Find(file.DownloadId); localMovie.DownloadClientMovieInfo = trackedDownload?.RemoteMovie?.ParsedMovieInfo; } if (file.FolderName.IsNotNullOrWhiteSpace()) { localMovie.FolderMovieInfo = Parser.Parser.ParseMovieTitle(file.FolderName); localMovie.SceneSource = !existingFile; } localMovie = _aggregationService.Augment(localMovie, trackedDownload?.DownloadItem, false); // Apply the user-chosen values. localMovie.Movie = movie; localMovie.Quality = file.Quality; localMovie.Languages = file.Languages; //TODO: Cleanup non-tracked downloads var importDecision = new ImportDecision(localMovie); if (trackedDownload == null) { imported.AddRange(_importApprovedMovie.Import(new List<ImportDecision> { importDecision }, !existingFile, null, message.ImportMode)); } else { var importResult = _importApprovedMovie.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; var importMovie = groupedTrackedDownload.First().ImportResult.ImportDecision.LocalMovie.Movie; var outputPath = trackedDownload.ImportItem.OutputPath.FullPath; if (_diskProvider.FolderExists(outputPath)) { if (_downloadedMovieImportService.ShouldDeleteFolder( new DirectoryInfo(outputPath), importMovie) && trackedDownload.DownloadItem.CanMoveFiles) { _diskProvider.DeleteFolder(outputPath, true); } } if (groupedTrackedDownload.Select(c => c.ImportResult).Any(c => c.Result == ImportResultType.Imported)) { trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, importMovie.Id)); } } }
private ManualImportItem ProcessFile(string rootFolder, string baseFolder, string file, string downloadId, Movie movie = null) { try { var trackedDownload = GetTrackedDownload(downloadId); var relativeFile = baseFolder.GetRelativePath(file); if (movie == null) { movie = _parsingService.GetMovie(relativeFile.Split('\\', '/')[0]); } if (movie == null) { movie = _parsingService.GetMovie(relativeFile); } if (trackedDownload != null && movie == null) { movie = trackedDownload?.RemoteMovie?.Movie; } if (movie == null) { var relativeParseInfo = Parser.Parser.ParseMoviePath(relativeFile); if (relativeParseInfo != null) { movie = _movieService.FindByTitle(relativeParseInfo.PrimaryMovieTitle, relativeParseInfo.Year); } } if (movie == null) { var localMovie = new LocalMovie(); localMovie.Path = file; localMovie.FileMovieInfo = Parser.Parser.ParseMoviePath(file); localMovie.DownloadClientMovieInfo = trackedDownload?.RemoteMovie?.ParsedMovieInfo; localMovie = _aggregationService.Augment(localMovie, null, false); return(MapItem(new ImportDecision(localMovie, new Rejection("Unknown Movie")), rootFolder, downloadId, null)); } var importDecisions = _importDecisionMaker.GetImportDecisions(new List <string> { file }, movie, trackedDownload?.DownloadItem, null, SceneSource(movie, baseFolder)); if (importDecisions.Any()) { return(MapItem(importDecisions.First(), rootFolder, downloadId, null)); } } catch (Exception ex) { _logger.Warn(ex, "Failed to process file: {0}", file); } return(new ManualImportItem { DownloadId = downloadId, Path = file, RelativePath = rootFolder.GetRelativePath(file), Name = Path.GetFileNameWithoutExtension(file), Rejections = new List <Rejection>() }); }