mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-24 22:35:39 -04:00
Moved source code under src folder - massive change
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class AcceptableSizeSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IQualitySizeService _qualityTypeProvider;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public AcceptableSizeSpecification(IQualitySizeService qualityTypeProvider, IEpisodeService episodeService, Logger logger)
|
||||
{
|
||||
_qualityTypeProvider = qualityTypeProvider;
|
||||
_episodeService = episodeService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get { return "File size too big or small"; }
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
|
||||
_logger.Trace("Beginning size check for: {0}", subject);
|
||||
|
||||
var quality = subject.ParsedEpisodeInfo.Quality.Quality;
|
||||
|
||||
if (quality == Quality.RAWHD)
|
||||
{
|
||||
_logger.Trace("Raw-HD release found, skipping size check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (quality == Quality.Unknown)
|
||||
{
|
||||
_logger.Trace("Unknown quality. skipping size check.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var qualityType = _qualityTypeProvider.Get(quality.Id);
|
||||
|
||||
if (qualityType.MaxSize == 0)
|
||||
{
|
||||
_logger.Trace("Max size is 0 (unlimited) - skipping check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
var maxSize = qualityType.MaxSize.Megabytes();
|
||||
|
||||
//Multiply maxSize by Series.Runtime
|
||||
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;
|
||||
|
||||
//Check if there was only one episode parsed and it is the first
|
||||
if (subject.Episodes.Count == 1 && subject.Episodes.First().EpisodeNumber == 1)
|
||||
{
|
||||
maxSize = maxSize * 2;
|
||||
}
|
||||
|
||||
//If the parsed size is greater than maxSize we don't want it
|
||||
if (subject.Release.Size > maxSize)
|
||||
{
|
||||
_logger.Trace("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Release.Size, maxSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger.Trace("Item: {0}, meets size constraints.", subject);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class CutoffSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public CutoffSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
|
||||
{
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Cutoff has already been met";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||
{
|
||||
_logger.Trace("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||
|
||||
|
||||
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.QualityProfile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class DownloadDecision
|
||||
{
|
||||
public RemoteEpisode RemoteEpisode { get; private set; }
|
||||
public IEnumerable<string> Rejections { get; private set; }
|
||||
|
||||
public bool Approved
|
||||
{
|
||||
get
|
||||
{
|
||||
return !Rejections.Any();
|
||||
}
|
||||
}
|
||||
|
||||
public DownloadDecision(RemoteEpisode episode, params string[] rejections)
|
||||
{
|
||||
RemoteEpisode = episode;
|
||||
Rejections = rejections.ToList();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Approved)
|
||||
{
|
||||
return "[OK] " + RemoteEpisode;
|
||||
}
|
||||
|
||||
return "[Rejected " + Rejections.Count() + "]" + RemoteEpisode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class LanguageSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public LanguageSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Not English";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
_logger.Trace("Checking if report meets language requirements. {0}", subject.ParsedEpisodeInfo.Language);
|
||||
if (subject.ParsedEpisodeInfo.Language != Language.English)
|
||||
{
|
||||
_logger.Trace("Report Language: {0} rejected because it is not English", subject.ParsedEpisodeInfo.Language);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class NotInQueueSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NotInQueueSpecification(IProvideDownloadClient downloadClientProvider, Logger logger)
|
||||
{
|
||||
_downloadClientProvider = downloadClientProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Already in download queue.";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var downloadClient = _downloadClientProvider.GetDownloadClient();
|
||||
|
||||
if (!downloadClient.IsConfigured)
|
||||
{
|
||||
_logger.Warn("Download client {0} isn't configured yet.", downloadClient.GetType().Name);
|
||||
return true;
|
||||
}
|
||||
|
||||
var queue = downloadClient.GetQueue().Select(queueItem => Parser.Parser.ParseTitle(queueItem.Title)).Where(episodeInfo => episodeInfo != null);
|
||||
|
||||
return !IsInQueue(subject, queue);
|
||||
}
|
||||
|
||||
private bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<ParsedEpisodeInfo> queue)
|
||||
{
|
||||
var matchingTitle = queue.Where(q => String.Equals(q.SeriesTitle, newEpisode.Series.CleanTitle, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
var matchingTitleWithQuality = matchingTitle.Where(q => q.Quality >= newEpisode.ParsedEpisodeInfo.Quality);
|
||||
|
||||
if (newEpisode.Series.SeriesType == SeriesTypes.Daily)
|
||||
{
|
||||
return matchingTitleWithQuality.Any(q => q.AirDate.Value.Date == newEpisode.ParsedEpisodeInfo.AirDate.Value.Date);
|
||||
}
|
||||
|
||||
var matchingSeason = matchingTitleWithQuality.Where(q => q.SeasonNumber == newEpisode.ParsedEpisodeInfo.SeasonNumber);
|
||||
|
||||
if (newEpisode.ParsedEpisodeInfo.FullSeason)
|
||||
{
|
||||
return matchingSeason.Any();
|
||||
}
|
||||
|
||||
return matchingSeason.Any(q => q.EpisodeNumbers != null && q.EpisodeNumbers.Any(e => newEpisode.ParsedEpisodeInfo.EpisodeNumbers.Contains(e)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class NotRestrictedReleaseSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NotRestrictedReleaseSpecification(IConfigService configService, Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Contains restricted term.";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
_logger.Trace("Checking if release contains any restricted terms: {0}", subject);
|
||||
|
||||
var restrictionsString = _configService.ReleaseRestrictions;
|
||||
|
||||
if (String.IsNullOrWhiteSpace(restrictionsString))
|
||||
{
|
||||
_logger.Trace("No restrictions configured, allowing: {0}", subject);
|
||||
return true;
|
||||
}
|
||||
|
||||
var restrictions = restrictionsString.Split('\n');
|
||||
|
||||
foreach (var restriction in restrictions)
|
||||
{
|
||||
if (subject.Release.Title.ToLowerInvariant().Contains(restriction.ToLowerInvariant()))
|
||||
{
|
||||
_logger.Trace("{0} is restricted: {1}", subject, restriction);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Trace("No restrictions apply, allowing: {0}", subject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class NotSampleSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
public string RejectionReason { get { return "Sample"; } }
|
||||
|
||||
public bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (subject.Release.Title.ToLower().Contains("sample") && subject.Release.Size < 70.Megabytes())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class QualityAllowedByProfileSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public QualityAllowedByProfileSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Quality rejected by series profile";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
_logger.Trace("Checking if report meets quality requirements. {0}", subject.ParsedEpisodeInfo.Quality);
|
||||
if (!subject.Series.QualityProfile.Value.Allowed.Contains(subject.ParsedEpisodeInfo.Quality.Quality))
|
||||
{
|
||||
_logger.Trace("Quality {0} rejected by Series' quality profile", subject.ParsedEpisodeInfo.Quality);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class RetentionSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public RetentionSpecification(IConfigService configService, Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Report past retention limit.";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var age = subject.Release.Age;
|
||||
|
||||
_logger.Trace("Checking if report meets retention requirements. {0}", age);
|
||||
if (_configService.Retention > 0 && age > _configService.Retention)
|
||||
{
|
||||
_logger.Trace("Report age: {0} rejected by user's retention limit", age);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class MonitoredEpisodeSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MonitoredEpisodeSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Series or Episode is not monitored";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
_logger.Trace("Skipping monitored check during search");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!subject.Series.Monitored)
|
||||
{
|
||||
_logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.Series);
|
||||
return false;
|
||||
}
|
||||
|
||||
//return monitored if any of the episodes are monitored
|
||||
if (subject.Episodes.Any(episode => episode.Monitored))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.Debug("No episodes are monitored. skipping.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class ProperSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ProperSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, IConfigService configService, Logger logger)
|
||||
{
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Proper for old episode";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||
{
|
||||
if (_qualityUpgradableSpecification.IsProperUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||
{
|
||||
if (file.DateAdded < DateTime.Today.AddDays(-7))
|
||||
{
|
||||
_logger.Trace("Proper for old file, skipping: {0}", subject);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_configService.AutoDownloadPropers)
|
||||
{
|
||||
_logger.Trace("Auto downloading of propers is disabled");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class UpgradeHistorySpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IHistoryService _historyService;
|
||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public UpgradeHistorySpecification(IHistoryService historyService, QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
|
||||
{
|
||||
_historyService = historyService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Existing file in history is of equal or higher quality";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
_logger.Trace("Skipping history check during search");
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var episode in subject.Episodes)
|
||||
{
|
||||
var bestQualityInHistory = _historyService.GetBestQualityInHistory(episode.Id);
|
||||
if (bestQualityInHistory != null)
|
||||
{
|
||||
_logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory);
|
||||
if (!_qualityUpgradableSpecification.IsUpgradable(bestQualityInHistory, subject.ParsedEpisodeInfo.Quality))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
{
|
||||
public class DailyEpisodeMatchSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
|
||||
public DailyEpisodeMatchSpecification(Logger logger, IEpisodeService episodeService)
|
||||
{
|
||||
_logger = logger;
|
||||
_episodeService = episodeService;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Episode doesn't match";
|
||||
}
|
||||
}
|
||||
public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var dailySearchSpec = searchCriteria as DailyEpisodeSearchCriteria;
|
||||
|
||||
if (dailySearchSpec == null) return true;
|
||||
|
||||
var episode = _episodeService.GetEpisode(dailySearchSpec.Series.Id, dailySearchSpec.Airtime);
|
||||
|
||||
if (!remoteEpisode.ParsedEpisodeInfo.AirDate.HasValue || remoteEpisode.ParsedEpisodeInfo.AirDate.Value.ToString(Episode.AIR_DATE_FORMAT) != episode.AirDate)
|
||||
{
|
||||
_logger.Trace("Episode AirDate does not match searched episode number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
{
|
||||
public class SeasonMatchSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SeasonMatchSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Episode doesn't match";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var singleEpisodeSpec = searchCriteria as SeasonSearchCriteria;
|
||||
if (singleEpisodeSpec == null) return true;
|
||||
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
|
||||
{
|
||||
_logger.Trace("Season number does not match searched season number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
{
|
||||
public class SingleEpisodeMatchSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SingleEpisodeMatchSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Episode doesn't match";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchDefinitionBase searchDefinitionBase)
|
||||
{
|
||||
var singleEpisodeSpec = searchDefinitionBase as SingleEpisodeSearchDefinition;
|
||||
if (singleEpisodeSpec == null) return true;
|
||||
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
|
||||
{
|
||||
_logger.Trace("Season number does not match searched season number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!remoteEpisode.Episodes.Select(c => c.EpisodeNumber).Contains(singleEpisodeSpec.EpisodeNumber))
|
||||
{
|
||||
_logger.Trace("Episode number does not match searched episode number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
{
|
||||
public class SingleEpisodeSearchMatchSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SingleEpisodeSearchMatchSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Episode doesn't match";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var singleEpisodeSpec = searchCriteria as SingleEpisodeSearchCriteria;
|
||||
if (singleEpisodeSpec == null) return true;
|
||||
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
|
||||
{
|
||||
_logger.Trace("Season number does not match searched season number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!remoteEpisode.ParsedEpisodeInfo.EpisodeNumbers.Contains(singleEpisodeSpec.EpisodeNumber))
|
||||
{
|
||||
_logger.Trace("Episode number does not match searched episode number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class UpgradeDiskSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public UpgradeDiskSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
|
||||
{
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Existing file on disk is of equal or higher quality";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||
{
|
||||
_logger.Trace("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||
|
||||
if (!_qualityUpgradableSpecification.IsUpgradable(file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user