Moved source code under src folder - massive change

This commit is contained in:
Mark McDowall
2013-10-02 18:01:32 -07:00
parent 2fc8123d6b
commit 5bf0e197ec
1499 changed files with 1054 additions and 1444 deletions
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
}