diff --git a/NzbDrone.Core/Model/EpisodeParseResult.cs b/NzbDrone.Core/Model/EpisodeParseResult.cs index 79a045125..4ef644d38 100644 --- a/NzbDrone.Core/Model/EpisodeParseResult.cs +++ b/NzbDrone.Core/Model/EpisodeParseResult.cs @@ -40,6 +40,8 @@ namespace NzbDrone.Core.Model public long Size { get; set; } + public int Age { get; set; } + public override string ToString() { if (AirDate != null && EpisodeNumbers == null) diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 7a9376f76..a2d5e5ce4 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -261,6 +261,7 @@ + diff --git a/NzbDrone.Core/Providers/Core/ConfigProvider.cs b/NzbDrone.Core/Providers/Core/ConfigProvider.cs index 73dac070d..3d661c30a 100644 --- a/NzbDrone.Core/Providers/Core/ConfigProvider.cs +++ b/NzbDrone.Core/Providers/Core/ConfigProvider.cs @@ -413,6 +413,12 @@ namespace NzbDrone.Core.Providers.Core set { SetValue("AutoIgnorePreviouslyDownloadedEpisodes", value); } } + public virtual int Retention + { + get { return GetValueInt("Retention", 0); } + set { SetValue("Retention", value); } + } + public Guid UGuid { get { return Guid.Parse(GetValue("UGuid", Guid.NewGuid().ToString(), persist: true)); } diff --git a/NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs index 6422cbd14..7321c6a4c 100644 --- a/NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs +++ b/NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs @@ -11,17 +11,19 @@ namespace NzbDrone.Core.Providers.DecisionEngine private readonly UpgradeDiskSpecification _upgradeDiskSpecification; private readonly AcceptableSizeSpecification _acceptableSizeSpecification; private readonly AlreadyInQueueSpecification _alreadyInQueueSpecification; + private readonly RetentionSpecification _retentionSpecification; private static readonly Logger logger = LogManager.GetCurrentClassLogger(); [Inject] public AllowedDownloadSpecification(QualityAllowedByProfileSpecification qualityAllowedByProfileSpecification, UpgradeDiskSpecification upgradeDiskSpecification, AcceptableSizeSpecification acceptableSizeSpecification, - AlreadyInQueueSpecification alreadyInQueueSpecification) + AlreadyInQueueSpecification alreadyInQueueSpecification, RetentionSpecification retentionSpecification) { _qualityAllowedByProfileSpecification = qualityAllowedByProfileSpecification; _upgradeDiskSpecification = upgradeDiskSpecification; _acceptableSizeSpecification = acceptableSizeSpecification; _alreadyInQueueSpecification = alreadyInQueueSpecification; + _retentionSpecification = retentionSpecification; } public AllowedDownloadSpecification() @@ -32,6 +34,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine { if (!_qualityAllowedByProfileSpecification.IsSatisfiedBy(subject)) return false; if (!_upgradeDiskSpecification.IsSatisfiedBy(subject)) return false; + if (!_retentionSpecification.IsSatisfiedBy(subject)) return false; if (!_acceptableSizeSpecification.IsSatisfiedBy(subject)) return false; if (_alreadyInQueueSpecification.IsSatisfiedBy(subject)) return false; diff --git a/NzbDrone.Core/Providers/DecisionEngine/RetentionSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/RetentionSpecification.cs new file mode 100644 index 000000000..51b1c8ce1 --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/RetentionSpecification.cs @@ -0,0 +1,35 @@ +using System.Linq; +using NLog; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers.Core; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class RetentionSpecification + { + private readonly ConfigProvider _configProvider; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + public RetentionSpecification(ConfigProvider configProvider) + { + _configProvider = configProvider; + } + + public RetentionSpecification() + { + + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + logger.Trace("Checking if report meets retention requirements. {0}", subject.Age); + if (_configProvider.Retention > 0 && subject.Age > _configProvider.Retention) + { + logger.Trace("Quality {0} rejected by user's retention limit", subject.Age); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Web/Controllers/SettingsController.cs b/NzbDrone.Web/Controllers/SettingsController.cs index 2cec10c95..0bbf75d9c 100644 --- a/NzbDrone.Web/Controllers/SettingsController.cs +++ b/NzbDrone.Web/Controllers/SettingsController.cs @@ -67,6 +67,8 @@ namespace NzbDrone.Web.Controllers { return View(new IndexerSettingsModel { + Retention = _configProvider.Retention, + NzbMatrixUsername = _configProvider.NzbMatrixUsername, NzbMatrixApiKey = _configProvider.NzbMatrixApiKey, @@ -338,6 +340,8 @@ namespace NzbDrone.Web.Controllers { if (ModelState.IsValid) { + _configProvider.Retention = data.Retention; + var nzbsOrgSettings = _indexerProvider.GetSettings(typeof(NzbsOrg)); nzbsOrgSettings.Enable = data.NzbsOrgEnabled; _indexerProvider.SaveSettings(nzbsOrgSettings); diff --git a/NzbDrone.Web/Models/IndexerSettingsModel.cs b/NzbDrone.Web/Models/IndexerSettingsModel.cs index 9d0a40635..722cdc95c 100644 --- a/NzbDrone.Web/Models/IndexerSettingsModel.cs +++ b/NzbDrone.Web/Models/IndexerSettingsModel.cs @@ -76,6 +76,12 @@ namespace NzbDrone.Web.Models [Description("Enable downloading episodes from Newznab Providers")] public bool NewznabEnabled { get; set; } + [Required(ErrorMessage = "Please enter a valid number of days")] + [DataType(DataType.Text)] + [DisplayName("Retention")] + [Description("Usenet provider retention in days (0 = unlimited)")] + public int Retention { get; set; } + public List NewznabDefinitions { get; set; } } } \ No newline at end of file diff --git a/NzbDrone.Web/Views/Settings/Indexers.cshtml b/NzbDrone.Web/Views/Settings/Indexers.cshtml index a032d547b..25b47fdf8 100644 --- a/NzbDrone.Web/Views/Settings/Indexers.cshtml +++ b/NzbDrone.Web/Views/Settings/Indexers.cshtml @@ -9,14 +9,19 @@ { overflow: auto; } + + .retentionContainer + { + padding-top: 20px; + overflow: hidden; + } }
RSS feeds are checked every 25 minutes for new episodes.
@using (Html.BeginForm("SaveIndexers", "Settings", FormMethod.Post, new { id = "IndexersForm", name = "IndexersForm", @class = "settingsForm" })) - { - @Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.") + {

NZBs.org

@@ -106,7 +111,16 @@
-
+ +
+ @Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.") + + + @Html.TextBoxFor(m => m.Retention, new { @class = "inputClass" }) +
+ }