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