public List <RenameEpisodeFilePreview> GetRenamePreviews(int seriesId, int seasonNumber) { var series = _seriesService.GetSeries(seriesId); var episodes = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber); var files = _mediaFileService.GetFilesBySeason(seriesId, seasonNumber); return(GetPreviews(series, episodes, files) .OrderByDescending(e => e.EpisodeNumbers.First()).ToList()); }
public List <DownloadDecision> SeasonSearch(int seriesId, int seasonNumber, bool missingOnly, bool monitoredOnly, bool userInvokedSearch, bool interactiveSearch) { var episodes = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber); if (missingOnly) { episodes = episodes.Where(e => !e.HasFile).ToList(); } return(SeasonSearch(seriesId, seasonNumber, episodes, monitoredOnly, userInvokedSearch, interactiveSearch)); }
public List <DownloadDecision> SeasonSearch(int seriesId, int seasonNumber) { var series = _seriesService.GetSeries(seriesId); var episodes = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber); var searchSpec = Get <SeasonSearchCriteria>(series, episodes); searchSpec.SeasonNumber = seasonNumber; return(Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec)); }
private List <Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, int mappedSeasonNumber, bool sceneSource, SearchCriteriaBase searchCriteria) { if (parsedEpisodeInfo.FullSeason) { if (series.UseSceneNumbering && sceneSource) { var episodes = _episodeService.GetEpisodesBySceneSeason(series.Id, mappedSeasonNumber); // If episodes were found by the scene season number return them, otherwise fallback to look-up by season number if (episodes.Any()) { return(episodes); } } return(_episodeService.GetEpisodesBySeason(series.Id, mappedSeasonNumber)); } if (parsedEpisodeInfo.IsDaily) { var episodeInfo = GetDailyEpisode(series, parsedEpisodeInfo.AirDate, parsedEpisodeInfo.DailyPart, searchCriteria); if (episodeInfo != null) { return(new List <Episode> { episodeInfo }); } return(new List <Episode>()); } if (parsedEpisodeInfo.IsAbsoluteNumbering) { return(GetAnimeEpisodes(series, parsedEpisodeInfo, mappedSeasonNumber, sceneSource, searchCriteria)); } if (parsedEpisodeInfo.IsPossibleSceneSeasonSpecial) { var parsedSpecialEpisodeInfo = ParseSpecialEpisodeTitle(parsedEpisodeInfo, parsedEpisodeInfo.ReleaseTitle, series); if (parsedSpecialEpisodeInfo != null) { // Use the season number and disable scene source since the season/episode numbers that were returned are not scene numbers return(GetStandardEpisodes(series, parsedSpecialEpisodeInfo, parsedSpecialEpisodeInfo.SeasonNumber, false, searchCriteria)); } } return(GetStandardEpisodes(series, parsedEpisodeInfo, mappedSeasonNumber, sceneSource, searchCriteria)); }
private List <Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, int mappedSeasonNumber, bool sceneSource, SearchCriteriaBase searchCriteria) { if (parsedEpisodeInfo.FullSeason) { if (series.UseSceneNumbering && sceneSource) { return(_episodeService.GetEpisodesBySceneSeason(series.Id, mappedSeasonNumber)); } else { return(_episodeService.GetEpisodesBySeason(series.Id, mappedSeasonNumber)); } } if (parsedEpisodeInfo.IsDaily) { var episodeInfo = GetDailyEpisode(series, parsedEpisodeInfo.AirDate, parsedEpisodeInfo.DailyPart, searchCriteria); if (episodeInfo != null) { return(new List <Episode> { episodeInfo }); } return(new List <Episode>()); } if (parsedEpisodeInfo.IsAbsoluteNumbering) { return(GetAnimeEpisodes(series, parsedEpisodeInfo, mappedSeasonNumber, sceneSource, searchCriteria)); } if (parsedEpisodeInfo.IsPossibleSceneSeasonSpecial) { parsedEpisodeInfo = ParseSpecialEpisodeTitle(parsedEpisodeInfo, parsedEpisodeInfo.ReleaseTitle, series) ?? parsedEpisodeInfo; } return(GetStandardEpisodes(series, parsedEpisodeInfo, mappedSeasonNumber, sceneSource, searchCriteria)); }
public void HandleAsync(DownloadFailedEvent message) { if (!_configService.AutoRedownloadFailed) { _logger.Debug("Auto redownloading failed episodes is disabled"); return; } if (message.EpisodeIds.Count == 1) { _logger.Debug("Failed download only contains one episode, searching again"); _commandExecutor.PublishCommandAsync(new EpisodeSearchCommand(message.EpisodeIds)); return; } var seasonNumber = _episodeService.GetEpisode(message.EpisodeIds.First()).SeasonNumber; var episodesInSeason = _episodeService.GetEpisodesBySeason(message.SeriesId, seasonNumber); if (message.EpisodeIds.Count == episodesInSeason.Count) { _logger.Debug("Failed download was entire season, searching again"); _commandExecutor.PublishCommandAsync(new SeasonSearchCommand { SeriesId = message.SeriesId, SeasonNumber = seasonNumber }); return; } _logger.Debug("Failed download contains multiple episodes, probably a double episode, searching again"); _commandExecutor.PublishCommandAsync(new EpisodeSearchCommand(message.EpisodeIds)); }
public List <Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, bool sceneSource, SearchCriteriaBase searchCriteria = null) { var result = new List <Episode>(); if (parsedEpisodeInfo.FullSeason) { return(_episodeService.GetEpisodesBySeason(series.Id, parsedEpisodeInfo.SeasonNumber)); } if (parsedEpisodeInfo.IsDaily) { if (series.SeriesType == SeriesTypes.Standard) { _logger.Warn("Found daily-style episode for non-daily series: {0}.", series); return(result); } var episodeInfo = GetDailyEpisode(series, parsedEpisodeInfo.AirDate, searchCriteria); if (episodeInfo != null) { result.Add(episodeInfo); } return(result); } if (parsedEpisodeInfo.IsAbsoluteNumbering) { var sceneSeasonNumber = _sceneMappingService.GetSeasonNumber(parsedEpisodeInfo.SeriesTitle); foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers) { Episode episode = null; if (parsedEpisodeInfo.Special) { episode = _episodeService.FindEpisode(series.Id, 0, absoluteEpisodeNumber); } else if (sceneSource) { if (sceneSeasonNumber.HasValue && (sceneSeasonNumber == 0 || sceneSeasonNumber > 1)) { var episodes = _episodeService.FindEpisodesBySceneNumbering(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber); if (episodes.Count == 1) { episode = episodes.First(); } if (episode == null) { episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber); } } else { episode = _episodeService.FindEpisodeBySceneNumbering(series.Id, absoluteEpisodeNumber); } } if (episode == null) { episode = _episodeService.FindEpisode(series.Id, absoluteEpisodeNumber); } if (episode != null) { _logger.Debug("Using absolute episode number {0} for: {1} - TVDB: {2}x{3:00}", absoluteEpisodeNumber, series.Title, episode.SeasonNumber, episode.EpisodeNumber); result.Add(episode); } } return(result); } if (parsedEpisodeInfo.EpisodeNumbers == null) { return(result); } foreach (var episodeNumber in parsedEpisodeInfo.EpisodeNumbers) { if (series.UseSceneNumbering && sceneSource) { List <Episode> episodes = new List <Episode>(); if (searchCriteria != null) { episodes = searchCriteria.Episodes.Where(e => e.SceneSeasonNumber == parsedEpisodeInfo.SeasonNumber && e.SceneEpisodeNumber == episodeNumber).ToList(); } if (!episodes.Any()) { episodes = _episodeService.FindEpisodesBySceneNumbering(series.Id, parsedEpisodeInfo.SeasonNumber, episodeNumber); } if (episodes != null && episodes.Any()) { _logger.Debug("Using Scene to TVDB Mapping for: {0} - Scene: {1}x{2:00} - TVDB: {3}", series.Title, episodes.First().SceneSeasonNumber, episodes.First().SceneEpisodeNumber, String.Join(", ", episodes.Select(e => String.Format("{0}x{1:00}", e.SeasonNumber, e.EpisodeNumber)))); result.AddRange(episodes); continue; } } Episode episodeInfo = null; if (searchCriteria != null) { episodeInfo = searchCriteria.Episodes.SingleOrDefault(e => e.SeasonNumber == parsedEpisodeInfo.SeasonNumber && e.EpisodeNumber == episodeNumber); } if (episodeInfo == null) { episodeInfo = _episodeService.FindEpisode(series.Id, parsedEpisodeInfo.SeasonNumber, episodeNumber); } if (episodeInfo != null) { result.Add(episodeInfo); } else { _logger.Debug("Unable to find {0}", parsedEpisodeInfo); } } return(result); }
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) { _logger.Debug("Beginning size check for: {0}", subject); var quality = subject.ParsedEpisodeInfo.Quality.Quality; if (quality == Quality.RAWHD) { _logger.Debug("Raw-HD release found, skipping size check."); return(Decision.Accept()); } if (subject.ParsedEpisodeInfo.Special) { _logger.Debug("Special release found, skipping size check."); return(Decision.Accept()); } var qualityDefinition = _qualityDefinitionService.Get(quality); var minSize = qualityDefinition.MinSize.Megabytes(); //Multiply maxSize by Series.Runtime minSize = minSize * subject.Series.Runtime * subject.Episodes.Count; //If the parsed size is smaller than minSize we don't want it if (subject.Release.Size < minSize) { _logger.Debug("Item: {0}, Size: {1:0n} is smaller than minimum allowed size ({2:0}), rejecting.", subject, subject.Release.Size, minSize); return(Decision.Reject("{0} is smaller than minimum allowed: {1}", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix())); } if (qualityDefinition.MaxSize == 0) { _logger.Debug("Max size is 0 (unlimited) - skipping check."); } else { var maxSize = qualityDefinition.MaxSize.Megabytes(); //Multiply maxSize by Series.Runtime maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count; if (subject.Episodes.Count == 1) { Episode episode = subject.Episodes.First(); List <Episode> seasonEpisodes; var seasonSearchCriteria = searchCriteria as SeasonSearchCriteria; if (seasonSearchCriteria != null && !seasonSearchCriteria.Series.UseSceneNumbering && seasonSearchCriteria.Episodes.Any(v => v.Id == episode.Id)) { seasonEpisodes = (searchCriteria as SeasonSearchCriteria).Episodes; } else { seasonEpisodes = _episodeService.GetEpisodesBySeason(episode.SeriesId, episode.SeasonNumber); } //Ensure that this is either the first episode //or is the last episode in a season that has 10 or more episodes if (seasonEpisodes.First().Id == episode.Id || (seasonEpisodes.Count() >= 10 && seasonEpisodes.Last().Id == episode.Id)) { _logger.Debug("Possible double episode, doubling allowed size."); maxSize = maxSize * 2; } } //If the parsed size is greater than maxSize we don't want it if (subject.Release.Size > maxSize) { _logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Release.Size, maxSize); return(Decision.Reject("{0} is larger than maximum allowed: {1}", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix())); } } _logger.Debug("Item: {0}, meets size constraints.", subject); return(Decision.Accept()); }
public List <DownloadDecision> SeasonSearch(int seriesId, int seasonNumber) { var series = _seriesService.GetSeries(seriesId); var episodes = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber); if (series.SeriesType == SeriesTypes.Anime) { return(SearchAnimeSeason(series, episodes)); } if (seasonNumber == 0) { // search for special episodes in season 0 return(SearchSpecial(series, episodes)); } var downloadDecisions = new List <DownloadDecision>(); if (series.UseSceneNumbering) { var sceneSeasonGroups = episodes.GroupBy(v => { if (v.SceneSeasonNumber == 0 && v.SceneEpisodeNumber == 0) { return(v.SeasonNumber); } return(v.SceneSeasonNumber); }).Distinct(); foreach (var sceneSeasonEpisodes in sceneSeasonGroups) { if (sceneSeasonEpisodes.Count() == 1) { var episode = sceneSeasonEpisodes.First(); var searchSpec = Get <SingleEpisodeSearchCriteria>(series, sceneSeasonEpisodes.ToList()); searchSpec.SeasonNumber = sceneSeasonEpisodes.Key; if (episode.SceneSeasonNumber == 0 && episode.SceneEpisodeNumber == 0) { searchSpec.EpisodeNumber = episode.EpisodeNumber; } else { searchSpec.EpisodeNumber = episode.SceneEpisodeNumber; } var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec); downloadDecisions.AddRange(decisions); } else { var searchSpec = Get <SeasonSearchCriteria>(series, sceneSeasonEpisodes.ToList()); searchSpec.SeasonNumber = sceneSeasonEpisodes.Key; var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec); downloadDecisions.AddRange(decisions); } } } else { var searchSpec = Get <SeasonSearchCriteria>(series, episodes); searchSpec.SeasonNumber = seasonNumber; var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec); downloadDecisions.AddRange(decisions); } return(downloadDecisions); }
public List <DownloadDecision> SeasonSearch(int seriesId, int seasonNumber, bool missingOnly, bool userInvokedSearch, bool interactiveSearch) { var series = _seriesService.GetSeries(seriesId); var episodes = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber); if (missingOnly) { episodes = episodes.Where(e => e.Monitored && !e.HasFile).ToList(); } if (series.SeriesType == SeriesTypes.Anime) { return(SearchAnimeSeason(series, episodes, userInvokedSearch, interactiveSearch)); } if (series.SeriesType == SeriesTypes.Daily) { return(SearchDailySeason(series, episodes, userInvokedSearch, interactiveSearch)); } if (seasonNumber == 0) { // search for special episodes in season 0 return(SearchSpecial(series, episodes, userInvokedSearch, interactiveSearch)); } var downloadDecisions = new List <DownloadDecision>(); if (series.UseSceneNumbering) { var sceneSeasonGroups = episodes.GroupBy(v => { if (v.SceneSeasonNumber.HasValue && v.SceneEpisodeNumber.HasValue) { return(v.SceneSeasonNumber.Value); } return(v.SeasonNumber); }).Distinct(); foreach (var sceneSeasonEpisodes in sceneSeasonGroups) { if (sceneSeasonEpisodes.Count() == 1) { var episode = sceneSeasonEpisodes.First(); var searchSpec = Get <SingleEpisodeSearchCriteria>(series, sceneSeasonEpisodes.ToList(), userInvokedSearch, interactiveSearch); searchSpec.SeasonNumber = sceneSeasonEpisodes.Key; searchSpec.MonitoredEpisodesOnly = true; if (episode.SceneSeasonNumber.HasValue && episode.SceneEpisodeNumber.HasValue) { searchSpec.EpisodeNumber = episode.SceneEpisodeNumber.Value; } else { searchSpec.EpisodeNumber = episode.EpisodeNumber; } var decisions = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec); downloadDecisions.AddRange(decisions); } else { var searchSpec = Get <SeasonSearchCriteria>(series, sceneSeasonEpisodes.ToList(), userInvokedSearch, interactiveSearch); searchSpec.SeasonNumber = sceneSeasonEpisodes.Key; var decisions = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec); downloadDecisions.AddRange(decisions); } } } else { var searchSpec = Get <SeasonSearchCriteria>(series, episodes, userInvokedSearch, interactiveSearch); searchSpec.SeasonNumber = seasonNumber; var decisions = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec); downloadDecisions.AddRange(decisions); } return(downloadDecisions); }
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) { _logger.Debug("Beginning size check for: {0}", subject); var quality = subject.ParsedEpisodeInfo.Quality.Quality; if (subject.ParsedEpisodeInfo.Special) { _logger.Debug("Special release found, skipping size check."); return(Decision.Accept()); } if (subject.Release.Size == 0) { _logger.Debug("Release has unknown size, skipping size check"); return(Decision.Accept()); } var qualityDefinition = _qualityDefinitionService.Get(quality); if (qualityDefinition.MinSize.HasValue) { var minSize = qualityDefinition.MinSize.Value.Megabytes(); //Multiply maxSize by Series.Runtime minSize = minSize * subject.Series.Runtime * subject.Episodes.Count; //If the parsed size is smaller than minSize we don't want it if (subject.Release.Size < minSize) { var runtimeMessage = subject.Episodes.Count == 1 ? $"{subject.Series.Runtime}min" : $"{subject.Episodes.Count}x {subject.Series.Runtime}min"; _logger.Debug("Item: {0}, Size: {1} is smaller than minimum allowed size ({2} bytes for {3}), rejecting.", subject, subject.Release.Size, minSize, runtimeMessage); return(Decision.Reject("{0} is smaller than minimum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix(), runtimeMessage)); } } if (!qualityDefinition.MaxSize.HasValue || qualityDefinition.MaxSize.Value == 0) { _logger.Debug("Max size is unlimited, skipping size check"); } else if (subject.Series.Runtime == 0) { _logger.Debug("Series runtime is 0, unable to validate size until it is available, rejecting"); return(Decision.Reject("Series runtime is 0, unable to validate size until it is available")); } else { var maxSize = qualityDefinition.MaxSize.Value.Megabytes(); //Multiply maxSize by Series.Runtime maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count; if (subject.Episodes.Count == 1 && subject.Series.SeriesType == SeriesTypes.Standard) { Episode episode = subject.Episodes.First(); List <Episode> seasonEpisodes; var seasonSearchCriteria = searchCriteria as SeasonSearchCriteria; if (seasonSearchCriteria != null && !seasonSearchCriteria.Series.UseSceneNumbering && seasonSearchCriteria.Episodes.Any(v => v.Id == episode.Id)) { seasonEpisodes = seasonSearchCriteria.Episodes; } else { seasonEpisodes = _episodeService.GetEpisodesBySeason(episode.SeriesId, episode.SeasonNumber); } //Ensure that this is either the first episode //or is the last episode in a season that has 10 or more episodes if (seasonEpisodes.First().Id == episode.Id || (seasonEpisodes.Count() >= 10 && seasonEpisodes.Last().Id == episode.Id)) { _logger.Debug("Possible double episode, doubling allowed size."); maxSize = maxSize * 2; } } //If the parsed size is greater than maxSize we don't want it if (subject.Release.Size > maxSize) { var runtimeMessage = subject.Episodes.Count == 1 ? $"{subject.Series.Runtime}min" : $"{subject.Episodes.Count}x {subject.Series.Runtime}min"; _logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2} for {3}), rejecting", subject, subject.Release.Size, maxSize, runtimeMessage); return(Decision.Reject("{0} is larger than maximum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix(), runtimeMessage)); } } _logger.Debug("Item: {0}, meets size constraints", subject); return(Decision.Accept()); }
public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem) { if (localEpisode.ExistingFile) { _logger.Debug("{0} is in series folder, skipping check", localEpisode.Path); return(Decision.Accept()); } var episodeTitleRequired = _configService.EpisodeTitleRequired; if (episodeTitleRequired == EpisodeTitleRequiredType.Never) { _logger.Debug("Episode titles are never required, skipping check"); return(Decision.Accept()); } if (!_buildFileNames.RequiresEpisodeTitle(localEpisode.Series, localEpisode.Episodes)) { _logger.Debug("File name format does not require episode title, skipping check"); return(Decision.Accept()); } var episodes = localEpisode.Episodes; var firstEpisode = episodes.First(); var episodesInSeason = _episodeService.GetEpisodesBySeason(firstEpisode.SeriesId, firstEpisode.EpisodeNumber); var allEpisodesOnTheSameDay = firstEpisode.AirDateUtc.HasValue && episodes.All(e => !e.AirDateUtc.HasValue || e.AirDateUtc.Value == firstEpisode.AirDateUtc.Value); if (episodeTitleRequired == EpisodeTitleRequiredType.BulkSeasonReleases && allEpisodesOnTheSameDay && episodesInSeason.Count(e => !e.AirDateUtc.HasValue || e.AirDateUtc.Value == firstEpisode.AirDateUtc.Value ) < 4 ) { _logger.Debug("Episode title only required for bulk season releases"); return(Decision.Accept()); } foreach (var episode in episodes) { var airDateUtc = episode.AirDateUtc; var title = episode.Title; if (airDateUtc.HasValue && airDateUtc.Value.Before(DateTime.UtcNow.AddHours(-48))) { _logger.Debug("Episode aired more than 48 hours ago"); continue; } if (title.IsNullOrWhiteSpace()) { _logger.Debug("Episode does not have a title and recently aired"); return(Decision.Reject("Episode does not have a title and recently aired")); } if (title.Equals("TBA")) { _logger.Debug("Episode has a TBA title and recently aired"); return(Decision.Reject("Episode has a TBA title and recently aired")); } } return(Decision.Accept()); }
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) { _logger.Debug("Beginning size check for: {0}", subject); var quality = subject.ParsedEpisodeInfo.Quality.Quality; if (subject.ParsedEpisodeInfo.Special) { _logger.Debug("Special release found, skipping size check."); return(Decision.Accept()); } if (subject.Release.Size == 0) { _logger.Debug("Release has unknown size, skipping size check"); return(Decision.Accept()); } var runtime = subject.Series.Runtime; if (runtime == 0) { var firstSeasonNumber = subject.Series.Seasons.Where(s => s.SeasonNumber > 0).Min(s => s.SeasonNumber); var pilotEpisode = _episodeService.GetEpisodesBySeason(subject.Series.Id, firstSeasonNumber).First(); if (subject.Episodes.First().SeasonNumber == pilotEpisode.SeasonNumber) { // If the first episode has an air date use it, otherwise use the release's publish date because like runtime it may not have updated yet. var gracePeriodEnd = (pilotEpisode.AirDateUtc ?? subject.Release.PublishDate).AddHours(24); // If episodes don't have an air date that is okay, otherwise make sure it's within 24 hours of the first episode airing. if (subject.Episodes.All(e => !e.AirDateUtc.HasValue || e.AirDateUtc.Value.Before(gracePeriodEnd))) { _logger.Debug("Series runtime is 0, but all episodes in release aired within 24 hours of first episode in season, defaulting runtime to 45 minutes"); runtime = 45; } } // Reject if the run time is still 0 if (runtime == 0) { _logger.Debug("Series runtime is 0, unable to validate size until it is available, rejecting"); return(Decision.Reject("Series runtime is 0, unable to validate size until it is available")); } } var qualityDefinition = _qualityDefinitionService.Get(quality); if (qualityDefinition.MinSize.HasValue) { var minSize = qualityDefinition.MinSize.Value.Megabytes(); // Multiply maxSize by Series.Runtime minSize = minSize * runtime * subject.Episodes.Count; // If the parsed size is smaller than minSize we don't want it if (subject.Release.Size < minSize) { var runtimeMessage = subject.Episodes.Count == 1 ? $"{runtime}min" : $"{subject.Episodes.Count}x {runtime}min"; _logger.Debug("Item: {0}, Size: {1} is smaller than minimum allowed size ({2} bytes for {3}), rejecting.", subject, subject.Release.Size, minSize, runtimeMessage); return(Decision.Reject("{0} is smaller than minimum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix(), runtimeMessage)); } } if (!qualityDefinition.MaxSize.HasValue || qualityDefinition.MaxSize.Value == 0) { _logger.Debug("Max size is unlimited, skipping size check"); } else { var maxSize = qualityDefinition.MaxSize.Value.Megabytes(); // Multiply maxSize by Series.Runtime maxSize = maxSize * runtime * subject.Episodes.Count; if (subject.Episodes.Count == 1 && subject.Series.SeriesType == SeriesTypes.Standard) { var firstEpisode = subject.Episodes.First(); var seasonEpisodes = GetSeasonEpisodes(subject, searchCriteria); // Ensure that this is either the first episode // or is the last episode in a season that has 10 or more episodes if (seasonEpisodes.First().Id == firstEpisode.Id || (seasonEpisodes.Count() >= 10 && seasonEpisodes.Last().Id == firstEpisode.Id)) { _logger.Debug("Possible double episode, doubling allowed size."); maxSize = maxSize * 2; } } // If the parsed size is greater than maxSize we don't want it if (subject.Release.Size > maxSize) { var runtimeMessage = subject.Episodes.Count == 1 ? $"{runtime}min" : $"{subject.Episodes.Count}x {runtime}min"; _logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2} for {3}), rejecting", subject, subject.Release.Size, maxSize, runtimeMessage); return(Decision.Reject("{0} is larger than maximum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix(), runtimeMessage)); } } _logger.Debug("Item: {0}, meets size constraints", subject); return(Decision.Accept()); }