mirror of
https://github.com/Radarr/Radarr
synced 2025-02-22 22:31:26 +00:00
New: Setting for absolute maximum size for a release (#2662)
* New: Setting for absolute maximum size for a release * Change to Advanced Setting
This commit is contained in:
parent
80b698a749
commit
8ee71fd0fa
9 changed files with 214 additions and 60 deletions
|
@ -1,4 +1,4 @@
|
|||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Api.Validation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
|
@ -13,6 +13,9 @@ public IndexerConfigModule(IConfigService configService)
|
|||
SharedValidator.RuleFor(c => c.MinimumAge)
|
||||
.GreaterThanOrEqualTo(0);
|
||||
|
||||
SharedValidator.RuleFor(c => c.MaximumSize)
|
||||
.GreaterThanOrEqualTo(0);
|
||||
|
||||
SharedValidator.RuleFor(c => c.Retention)
|
||||
.GreaterThanOrEqualTo(0);
|
||||
|
||||
|
@ -25,4 +28,4 @@ protected override IndexerConfigResource ToResource(IConfigService model)
|
|||
return IndexerConfigResourceMapper.ToResource(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
|
@ -7,6 +7,7 @@ namespace NzbDrone.Api.Config
|
|||
public class IndexerConfigResource : RestResource
|
||||
{
|
||||
public int MinimumAge { get; set; }
|
||||
public int MaximumSize { get; set; }
|
||||
public int Retention { get; set; }
|
||||
public int RssSyncInterval { get; set; }
|
||||
public bool PreferIndexerFlags { get; set; }
|
||||
|
@ -23,6 +24,7 @@ public static IndexerConfigResource ToResource(IConfigService model)
|
|||
return new IndexerConfigResource
|
||||
{
|
||||
MinimumAge = model.MinimumAge,
|
||||
MaximumSize = model.MaximumSize,
|
||||
Retention = model.Retention,
|
||||
RssSyncInterval = model.RssSyncInterval,
|
||||
PreferIndexerFlags = model.PreferIndexerFlags,
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
public class MaximumSizeSpecificationFixture : CoreTest<MaximumSizeSpecification>
|
||||
{
|
||||
private RemoteMovie _remoteMovie;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_remoteMovie = new RemoteMovie { Release = new ReleaseInfo() };
|
||||
}
|
||||
|
||||
private void WithMaximumSize(int size)
|
||||
{
|
||||
Mocker.GetMock<IConfigService>().SetupGet(c => c.MaximumSize).Returns(size);
|
||||
}
|
||||
|
||||
private void WithSize(int size)
|
||||
{
|
||||
_remoteMovie.Release.Size = size * 1024 * 1024;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_maximum_size_is_set_to_zero()
|
||||
{
|
||||
WithMaximumSize(0);
|
||||
WithSize(1000);
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_size_is_smaller_than_maximum_size()
|
||||
{
|
||||
WithMaximumSize(2000);
|
||||
WithSize(1999);
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_size_is_equals_to_maximum_size()
|
||||
{
|
||||
WithMaximumSize(2000);
|
||||
WithSize(2000);
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_when_size_is_bigger_than_maximum_size()
|
||||
{
|
||||
WithMaximumSize(2000);
|
||||
WithSize(2001);
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_size_is_zero()
|
||||
{
|
||||
WithMaximumSize(2000);
|
||||
WithSize(0);
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -138,6 +138,7 @@
|
|||
<Compile Include="Datastore\ReflectionStrategyFixture\Benchmarks.cs" />
|
||||
<Compile Include="Datastore\SqliteSchemaDumperTests\SqliteSchemaDumperFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\MaximumSizeSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\ProtocolSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\CutoffSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\DownloadDecisionMakerFixture.cs" />
|
||||
|
|
|
@ -106,11 +106,11 @@ public int RssSyncInterval
|
|||
set { SetValue("RssSyncInterval", value); }
|
||||
}
|
||||
|
||||
public int AvailabilityDelay
|
||||
{
|
||||
get { return GetValueInt("AvailabilityDelay",0); }
|
||||
set { SetValue("AvailabilityDelay", value); }
|
||||
}
|
||||
public int AvailabilityDelay
|
||||
{
|
||||
get { return GetValueInt("AvailabilityDelay", 0); }
|
||||
set { SetValue("AvailabilityDelay", value); }
|
||||
}
|
||||
|
||||
public int NetImportSyncInterval
|
||||
{
|
||||
|
@ -118,57 +118,64 @@ public int NetImportSyncInterval
|
|||
|
||||
set { SetValue("NetImportSyncInterval", value); }
|
||||
}
|
||||
|
||||
|
||||
public string TraktAuthToken
|
||||
{
|
||||
{
|
||||
get { return GetValue("TraktAuthToken", string.Empty); }
|
||||
|
||||
set { SetValue("TraktAuthToken", value); }
|
||||
}
|
||||
}
|
||||
|
||||
public string TraktRefreshToken
|
||||
{
|
||||
get { return GetValue("TraktRefreshToken", string.Empty); }
|
||||
|
||||
set {SetValue("TraktRefreshToken", value); }
|
||||
}
|
||||
|
||||
public int TraktTokenExpiry
|
||||
{
|
||||
get { return GetValueInt("TraktTokenExpiry", 0); }
|
||||
|
||||
set { SetValue("TraktTokenExpiry", value); }
|
||||
}
|
||||
public string TraktRefreshToken
|
||||
{
|
||||
get { return GetValue("TraktRefreshToken", string.Empty); }
|
||||
|
||||
public string NewTraktAuthToken
|
||||
{
|
||||
get {return GetValue("NewTraktAuthToken", string.Empty); }
|
||||
set { SetValue("NewTraktAuthToken", value); }
|
||||
}
|
||||
set { SetValue("TraktRefreshToken", value); }
|
||||
}
|
||||
|
||||
public string NewTraktRefreshToken
|
||||
{
|
||||
get {return GetValue("NewTraktRefreshToken", string.Empty); }
|
||||
set { SetValue("NewTraktRefreshToken", value); }
|
||||
}
|
||||
public int TraktTokenExpiry
|
||||
{
|
||||
get { return GetValueInt("TraktTokenExpiry", 0); }
|
||||
|
||||
public int NewTraktTokenExpiry
|
||||
{
|
||||
get {return GetValueInt("NewTraktTokenExpiry", 0); }
|
||||
set { SetValue("NewTraktTokenExpiry", value); }
|
||||
}
|
||||
set { SetValue("TraktTokenExpiry", value); }
|
||||
}
|
||||
|
||||
public string ListSyncLevel
|
||||
{
|
||||
get { return GetValue("ListSyncLevel", "disabled"); }
|
||||
set { SetValue("ListSyncLevel", value); }
|
||||
}
|
||||
public string NewTraktAuthToken
|
||||
{
|
||||
get { return GetValue("NewTraktAuthToken", string.Empty); }
|
||||
set { SetValue("NewTraktAuthToken", value); }
|
||||
}
|
||||
|
||||
public string ImportExclusions
|
||||
{
|
||||
get { return GetValue("ImportExclusions", string.Empty); }
|
||||
set { SetValue("ImportExclusions", value); }
|
||||
}
|
||||
public string NewTraktRefreshToken
|
||||
{
|
||||
get { return GetValue("NewTraktRefreshToken", string.Empty); }
|
||||
set { SetValue("NewTraktRefreshToken", value); }
|
||||
}
|
||||
|
||||
public int NewTraktTokenExpiry
|
||||
{
|
||||
get { return GetValueInt("NewTraktTokenExpiry", 0); }
|
||||
set { SetValue("NewTraktTokenExpiry", value); }
|
||||
}
|
||||
|
||||
public string ListSyncLevel
|
||||
{
|
||||
get { return GetValue("ListSyncLevel", "disabled"); }
|
||||
set { SetValue("ListSyncLevel", value); }
|
||||
}
|
||||
|
||||
public string ImportExclusions
|
||||
{
|
||||
get { return GetValue("ImportExclusions", string.Empty); }
|
||||
set { SetValue("ImportExclusions", value); }
|
||||
}
|
||||
|
||||
public int MaximumSize
|
||||
{
|
||||
get { return GetValueInt("MaximumSize", 0); }
|
||||
|
||||
set { SetValue("MaximumSize", value); }
|
||||
}
|
||||
|
||||
public int MinimumAge
|
||||
{
|
||||
|
@ -195,22 +202,22 @@ public bool PreferIndexerFlags
|
|||
{
|
||||
get { return GetValueBoolean("PreferIndexerFlags", false); }
|
||||
|
||||
set {SetValue("PreferIndexerFlags", value);}
|
||||
set { SetValue("PreferIndexerFlags", value); }
|
||||
}
|
||||
|
||||
public bool AllowHardcodedSubs
|
||||
{
|
||||
get { return GetValueBoolean("AllowHardcodedSubs", false); }
|
||||
public bool AllowHardcodedSubs
|
||||
{
|
||||
get { return GetValueBoolean("AllowHardcodedSubs", false); }
|
||||
|
||||
set { SetValue("AllowHardcodedSubs", value); }
|
||||
}
|
||||
set { SetValue("AllowHardcodedSubs", value); }
|
||||
}
|
||||
|
||||
public string WhitelistedHardcodedSubs
|
||||
{
|
||||
get { return GetValue("WhitelistedHardcodedSubs", ""); }
|
||||
public string WhitelistedHardcodedSubs
|
||||
{
|
||||
get { return GetValue("WhitelistedHardcodedSubs", ""); }
|
||||
|
||||
set { SetValue("WhitelistedHardcodedSubs", value); }
|
||||
}
|
||||
set { SetValue("WhitelistedHardcodedSubs", value); }
|
||||
}
|
||||
|
||||
public ParsingLeniencyType ParsingLeniency
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@ public interface IConfigService
|
|||
//Indexers
|
||||
int Retention { get; set; }
|
||||
int RssSyncInterval { get; set; }
|
||||
int MaximumSize { get; set; }
|
||||
int MinimumAge { get; set; }
|
||||
|
||||
bool PreferIndexerFlags { get; set; }
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class MaximumSizeSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MaximumSizeSpecification(IConfigService configService, Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var size = subject.Release.Size;
|
||||
var maximumSize = _configService.MaximumSize.Megabytes();
|
||||
|
||||
if (maximumSize == 0)
|
||||
{
|
||||
_logger.Debug("Maximum size is not set.");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
_logger.Debug("Release has unknown size, skipping size check.");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if release meets maximum size requirements. {0}", size.SizeSuffix());
|
||||
|
||||
if (size > maximumSize)
|
||||
{
|
||||
var message = $"{size.SizeSuffix()} is too big, maximum size is {maximumSize.SizeSuffix()}";
|
||||
|
||||
_logger.Debug(message);
|
||||
return Decision.Reject(message);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -128,6 +128,7 @@
|
|||
<Compile Include="Datastore\Migration\142_movie_extras.cs" />
|
||||
<Compile Include="Datastore\Migration\140_add_alternative_titles_table.cs" />
|
||||
<Compile Include="Datastore\Migration\141_fix_duplicate_alt_titles.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\MaximumSizeSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\RequiredIndexerFlagsSpecification.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedAlternativeTitles.cs" />
|
||||
<Compile Include="MediaFiles\MovieImport\Specifications\GrabbedReleaseQualitySpecification.cs" />
|
||||
|
|
|
@ -25,6 +25,18 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group advanced-setting">
|
||||
<label class="col-sm-3 control-label">Maximum Size</label>
|
||||
|
||||
<div class="col-sm-1 col-sm-push-2 help-inline">
|
||||
<i class="icon-sonarr-form-info" title="Maximum size for a release to be grabbed in MB. Set to zero to set to unlimited"/>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2 col-sm-pull-1">
|
||||
<input type="number" min="0" name="maximumSize" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Prefer Special Indexer Flags</label>
|
||||
<div class="col-sm-1 col-sm-push-2 help-inline">
|
||||
|
|
Loading…
Reference in a new issue