public bool IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { _logger.Debug("{0} is in series folder, unpacking check", localEpisode.Path); return true; } foreach (var workingFolder in _configService.DownloadClientWorkingFolders.Split('|')) { if (Directory.GetParent(localEpisode.Path).Name.StartsWith(workingFolder)) { if (OsInfo.IsMono) { _logger.Debug("{0} is still being unpacked", localEpisode.Path); return false; } if (_diskProvider.FileGetLastWriteUtc(localEpisode.Path) > DateTime.UtcNow.AddMinutes(-5)) { _logger.Debug("{0} appears to be unpacking still", localEpisode.Path); return false; } } } return true; }
private ImportDecision GetDecision(LocalEpisode localEpisode) { var reasons = _specifications.Select(c => EvaluateSpec(c, localEpisode)) .Where(c => !string.IsNullOrWhiteSpace(c)); return new ImportDecision(localEpisode, reasons.ToArray()); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { try { if (localEpisode.ExistingFile) { _logger.Trace("Skipping free space check for existing episode"); return true; } var path = Directory.GetParent(localEpisode.Series.Path); var freeSpace = _diskProvider.GetAvailableSpace(path.FullName); if (!freeSpace.HasValue) { _logger.Trace("Free space check returned an invalid result for: {0}", path); return true; } if (freeSpace < localEpisode.Size + 100.Megabytes()) { _logger.Warn("Not enough free space to import: {0}", localEpisode); return false; } } catch (Exception ex) { _logger.ErrorException("Unable to check free disk space while importing: " + localEpisode.Path, ex); } return true; }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { _logger.Debug("{0} is in series folder, skipping unpacking check", localEpisode.Path); return Decision.Accept(); } foreach (var workingFolder in _configService.DownloadClientWorkingFolders.Split('|')) { DirectoryInfo parent = Directory.GetParent(localEpisode.Path); while (parent != null) { if (parent.Name.StartsWith(workingFolder)) { if (OsInfo.IsNotWindows) { _logger.Debug("{0} is still being unpacked", localEpisode.Path); return Decision.Reject("File is still being unpacked"); } if (_diskProvider.FileGetLastWrite(localEpisode.Path) > DateTime.UtcNow.AddMinutes(-5)) { _logger.Debug("{0} appears to be unpacking still", localEpisode.Path); return Decision.Reject("File is still being unpacked"); } } parent = parent.Parent; } } return Decision.Accept(); }
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; }
private IEnumerable<ImportDecision> GetDecisions(IEnumerable<String> videoFiles, Series series, bool sceneSource) { foreach (var file in videoFiles) { ImportDecision decision = null; try { var parsedEpisode = _parsingService.GetEpisodes(file, series, sceneSource); if (parsedEpisode != null) { parsedEpisode.Size = _diskProvider.GetFileSize(file); decision = GetDecision(parsedEpisode); } else { parsedEpisode = new LocalEpisode(); parsedEpisode.Path = file; decision = new ImportDecision(parsedEpisode, "Unable to parse file"); } } catch (Exception e) { _logger.ErrorException("Couldn't import file." + file, e); } if (decision != null) { yield return decision; } } }
public string MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) { var newFileName = _buildFileNames.BuildFilename(localEpisode.Episodes, localEpisode.Series, episodeFile); var filePath = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); MoveFile(episodeFile, localEpisode.Series, filePath); return filePath; }
public EpisodeImportedEvent(LocalEpisode episodeInfo, EpisodeFile importedEpisode, bool newDownload, string downloadClient, string downloadClientId) { EpisodeInfo = episodeInfo; ImportedEpisode = importedEpisode; NewDownload = newDownload; DownloadClient = downloadClient; DownloadClientId = downloadClientId; }
public EpisodeImportedEvent(LocalEpisode episodeInfo, EpisodeFile importedEpisode, bool newDownload, string downloadClient, string downloadId, bool isReadOnly) { EpisodeInfo = episodeInfo; ImportedEpisode = importedEpisode; NewDownload = newDownload; DownloadClient = downloadClient; DownloadId = downloadId; IsReadOnly = isReadOnly; }
public EpisodeFile CopyEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) { var newFileName = _buildFileNames.BuildFilename(localEpisode.Episodes, localEpisode.Series, episodeFile); var filePath = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); _logger.Debug("Copying episode file: {0} to {1}", episodeFile, filePath); return TransferFile(episodeFile, localEpisode.Series, localEpisode.Episodes, filePath, true); }
public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) { var newFileName = _buildFileNames.BuildFilename(localEpisode.Episodes, localEpisode.Series, episodeFile); var filePath = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); _logger.Trace("Moving episode file: {0} to {1}", episodeFile, filePath); return MoveFile(episodeFile, localEpisode.Series, filePath); }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ParsedEpisodeInfo.FullSeason) { _logger.Debug("Single episode file detected as containing all episodes in the season"); return Decision.Reject("Single episode file contains all episodes in seasons"); } return Decision.Accept(); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && e.EpisodeFile.Value.Quality > localEpisode.Quality)) { _logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path); return false; } return true; }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ParsedEpisodeInfo.FullSeason) { _logger.Debug("Single episode file detected as containing all episodes in the season"); return false; } return true; }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { if (_sameEpisodesSpecification.IsSatisfiedBy(localEpisode.Episodes)) { return Decision.Accept(); } _logger.Debug("Episode file on disk contains more episodes than this file contains"); return Decision.Reject("Episode file on disk contains more episodes than this file contains"); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { _logger.Trace("Existing file, skipping sample check"); return true; } if (localEpisode.Series.SeriesType == SeriesTypes.Daily) { _logger.Trace("Daily Series, skipping sample check"); return true; } if (localEpisode.SeasonNumber == 0) { _logger.Trace("Special, skipping sample check"); return true; } var extension = Path.GetExtension(localEpisode.Path); if (extension != null && extension.Equals(".flv", StringComparison.InvariantCultureIgnoreCase)) { _logger.Trace("Skipping sample check for .flv file"); return true; } try { var runTime = _videoFileInfoReader.GetRunTime(localEpisode.Path); if (runTime.TotalMinutes.Equals(0)) { _logger.Error("[{0}] has a runtime of 0, is it a valid video file?", localEpisode); return false; } if (runTime.TotalSeconds < 90) { _logger.Trace("[{0}] appears to be a sample. Size: {1} Runtime: {2}", localEpisode.Path, localEpisode.Size, runTime); return false; } } catch (DllNotFoundException) { _logger.Trace("Falling back to file size detection"); return CheckSize(localEpisode); } _logger.Trace("Runtime is over 90 seconds"); return true; }
public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) { var newFileName = _buildFileNames.BuildFileName(localEpisode.Episodes, localEpisode.Series, episodeFile); var filePath = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(localEpisode.Path)); EnsureEpisodeFolder(episodeFile, localEpisode, filePath); _logger.Debug("Moving episode file: {0} to {1}", episodeFile.Path, filePath); return TransferFile(episodeFile, localEpisode.Series, localEpisode.Episodes, filePath, TransferMode.Move); }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { var qualityComparer = new QualityModelComparer(localEpisode.Series.Profile); if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0)) { _logger.Debug("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path); return Decision.Reject("Not an upgrade for existing episode file(s)"); } return Decision.Accept(); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { var qualityComparer = new QualityModelComparer(localEpisode.Series.QualityProfile); if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0)) { _logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path); return false; } return true; }
public EpisodeFile CopyEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) { var newFileName = _buildFileNames.BuildFileName(localEpisode.Episodes, localEpisode.Series, episodeFile); var filePath = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(localEpisode.Path)); if (_configService.CopyUsingHardlinks) { _logger.Debug("Hardlinking episode file: {0} to {1}", episodeFile.Path, filePath); return TransferFile(episodeFile, localEpisode.Series, localEpisode.Episodes, filePath, TransferMode.HardLinkOrCopy); } _logger.Debug("Copying episode file: {0} to {1}", episodeFile.Path, filePath); return TransferFile(episodeFile, localEpisode.Series, localEpisode.Episodes, filePath, TransferMode.Copy); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { _logger.Debug("Existing file, skipping sample check"); return true; } return !_sampleService.IsSample(localEpisode.Series, localEpisode.Quality, localEpisode.Path, localEpisode.Size, localEpisode.SeasonNumber); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { _logger.Trace("{0} is in series folder, skipping in use check", localEpisode.Path); return true; } if (_diskProvider.IsFileLocked(localEpisode.Path)) { _logger.Trace("{0} is in use"); return false; } return true; }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { _logger.Debug("Skipping scene numbering check for existing episode"); return Decision.Accept(); } if (localEpisode.Episodes.Any(v => v.UnverifiedSceneNumbering)) { _logger.Debug("This file uses unverified scene numbers, will not auto-import until numbering is confirmed on TheXEM. Skipping {0}", localEpisode.Path); return Decision.Reject("This show has individual episode mappings on TheXEM but the mapping for this episode has not been confirmed yet by their administrators. TheXEM needs manual input."); } return Decision.Accept(); }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { return Decision.Accept(); } var dirInfo = new FileInfo(localEpisode.Path).Directory; if (dirInfo == null) { return Decision.Accept(); } var folderInfo = Parser.Parser.ParseTitle(dirInfo.Name); if (folderInfo == null) { return Decision.Accept(); } if (!folderInfo.EpisodeNumbers.Any()) { return Decision.Accept(); } if (folderInfo.FullSeason) { return Decision.Accept(); } var unexpected = localEpisode.ParsedEpisodeInfo.EpisodeNumbers.Where(f => !folderInfo.EpisodeNumbers.Contains(f)).ToList(); if (unexpected.Any()) { _logger.Debug("Unexpected episode number(s) in file: {0}", string.Join(", ", unexpected)); if (unexpected.Count == 1) { return Decision.Reject("Episode Number {0} was unexpected considering the {1} folder name", unexpected.First(), dirInfo.Name); } return Decision.Reject("Episode Numbers {0} were unexpected considering the {1} folder name", string.Join(", ", unexpected), dirInfo.Name); } return Decision.Accept(); }
private IEnumerable<ImportDecision> GetDecisions(IEnumerable<String> videoFiles, Series series, bool sceneSource, QualityModel quality = null) { foreach (var file in videoFiles) { ImportDecision decision = null; try { var parsedEpisode = _parsingService.GetLocalEpisode(file, series, sceneSource); if (parsedEpisode != null) { if (quality != null && new QualityModelComparer(parsedEpisode.Series.QualityProfile).Compare(quality, parsedEpisode.Quality) > 0) { _logger.Trace("Using quality from folder: {0}", quality); parsedEpisode.Quality = quality; } parsedEpisode.Size = _diskProvider.GetFileSize(file); _logger.Trace("Size: {0}", parsedEpisode.Size); decision = GetDecision(parsedEpisode); } else { parsedEpisode = new LocalEpisode(); parsedEpisode.Path = file; decision = new ImportDecision(parsedEpisode, "Unable to parse file"); } } catch (Exception e) { _logger.ErrorException("Couldn't import file." + file, e); } if (decision != null) { yield return decision; } } }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { if (_configService.SkipFreeSpaceCheckWhenImporting) { _logger.Debug("Skipping free space check when importing"); return Decision.Accept(); } try { if (localEpisode.ExistingFile) { _logger.Debug("Skipping free space check for existing episode"); return Decision.Accept(); } var path = Directory.GetParent(localEpisode.Series.Path); var freeSpace = _diskProvider.GetAvailableSpace(path.FullName); if (!freeSpace.HasValue) { _logger.Debug("Free space check returned an invalid result for: {0}", path); return Decision.Accept(); } if (freeSpace < localEpisode.Size + 100.Megabytes()) { _logger.Warn("Not enough free space ({0}) to import: {1} ({2})", freeSpace, localEpisode, localEpisode.Size); return Decision.Reject("Not enough free space"); } } catch (DirectoryNotFoundException ex) { _logger.Error("Unable to check free disk space while importing. " + ex.Message); } catch (Exception ex) { _logger.Error(ex, "Unable to check free disk space while importing: " + localEpisode.Path); } return Decision.Accept(); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.Series.SeriesType == SeriesTypes.Daily) { _logger.Trace("Daily Series, skipping sample check"); return true; } if (localEpisode.SeasonNumber == 0) { _logger.Trace("Special, skipping sample check"); return true; } if (Path.GetExtension(localEpisode.Path).Equals(".flv", StringComparison.InvariantCultureIgnoreCase)) { _logger.Trace("Skipping smaple check for .flv file"); return true; } if (localEpisode.Size > SampleSizeLimit) { return true; } var runTime = _videoFileInfoReader.GetRunTime(localEpisode.Path); if (runTime.TotalMinutes.Equals(0)) { _logger.Error("[{0}] has a runtime of 0, is it a valid video file?", localEpisode); return false; } if (runTime.TotalMinutes < 3) { _logger.Trace("[{0}] appears to be a sample. Size: {1} Runtime: {2}", localEpisode.Path, localEpisode.Size, runTime); return false; } return true; }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { if (localEpisode.ExistingFile) { _logger.Debug("Existing file, skipping sample check"); return Decision.Accept(); } var sample = _detectSample.IsSample(localEpisode.Series, localEpisode.Quality, localEpisode.Path, localEpisode.Size, localEpisode.IsSpecial); if (sample) { return Decision.Reject("Sample"); } return Decision.Accept(); }
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); }
private string GetSceneName(DownloadClientItem downloadClientItem, LocalEpisode localEpisode) { if (downloadClientItem != null) { var title = Parser.Parser.RemoveFileExtension(downloadClientItem.Title); var parsedTitle = Parser.Parser.ParseTitle(title); if (parsedTitle != null && !parsedTitle.FullSeason) { return title; } } var fileName = Path.GetFileNameWithoutExtension(localEpisode.Path.CleanFilePath()); if (SceneChecker.IsSceneTitle(fileName)) { return fileName; } return null; }