diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js index bd975349c..8607be28a 100644 --- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js +++ b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js @@ -40,6 +40,7 @@ function EditDelayProfileModalContent(props) { enableTorrent, usenetDelay, torrentDelay, + bypassIfHighestQuality, tags } = item; @@ -110,6 +111,20 @@ function EditDelayProfileModalContent(props) { } + { + + {translate('BypassDelayIfHighestQuality')} + + + + } + { id === 1 ? diff --git a/src/NzbDrone.Api/Profiles/Delay/DelayProfileResource.cs b/src/NzbDrone.Api/Profiles/Delay/DelayProfileResource.cs index 802b793fb..6cb5c8f42 100644 --- a/src/NzbDrone.Api/Profiles/Delay/DelayProfileResource.cs +++ b/src/NzbDrone.Api/Profiles/Delay/DelayProfileResource.cs @@ -13,6 +13,7 @@ namespace NzbDrone.Api.Profiles.Delay public DownloadProtocol PreferredProtocol { get; set; } public int UsenetDelay { get; set; } public int TorrentDelay { get; set; } + public bool BypassIfHighestQuality { get; set; } public int Order { get; set; } public HashSet Tags { get; set; } } @@ -35,6 +36,7 @@ namespace NzbDrone.Api.Profiles.Delay PreferredProtocol = model.PreferredProtocol, UsenetDelay = model.UsenetDelay, TorrentDelay = model.TorrentDelay, + BypassIfHighestQuality = model.BypassIfHighestQuality, Order = model.Order, Tags = new HashSet(model.Tags) }; @@ -56,6 +58,7 @@ namespace NzbDrone.Api.Profiles.Delay PreferredProtocol = resource.PreferredProtocol, UsenetDelay = resource.UsenetDelay, TorrentDelay = resource.TorrentDelay, + BypassIfHighestQuality = resource.BypassIfHighestQuality, Order = resource.Order, Tags = new HashSet(resource.Tags) }; diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs index 0f7ee0c1d..84fa4f431 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs @@ -104,10 +104,22 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync } [Test] - public void should_be_true_when_quality_is_last_allowed_in_profile() + public void should_be_false_when_quality_is_last_allowed_in_profile_and_bypass_disabled() { _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.Bluray720p); + _remoteMovie.Release.PublishDate = DateTime.UtcNow; + + Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse(); + } + + [Test] + public void should_be_true_when_quality_is_last_allowed_in_profile_and_bypass_enabled() + { + _delayProfile.BypassIfHighestQuality = true; + + _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.Bluray720p); + Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue(); } diff --git a/src/NzbDrone.Core/Datastore/Migration/194_add_bypass_to_delay_profile.cs b/src/NzbDrone.Core/Datastore/Migration/194_add_bypass_to_delay_profile.cs new file mode 100644 index 000000000..bc38a3e67 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/194_add_bypass_to_delay_profile.cs @@ -0,0 +1,17 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(194)] + public class add_bypass_to_delay_profile : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("DelayProfiles").AddColumn("BypassIfHighestQuality").AsBoolean().WithDefaultValue(false); + + // Set to true for existing Delay Profiles to keep behavior the same. + Execute.Sql("UPDATE DelayProfiles SET BypassIfHighestQuality = 1;"); + } + } +} diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs index e6a6e9872..b64949879 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs @@ -1,4 +1,3 @@ -using System.Linq; using NLog; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.Download.Pending; @@ -78,13 +77,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync } // If quality meets or exceeds the best allowed quality in the profile accept it immediately - var bestQualityInProfile = profile.LastAllowedQuality(); - var isBestInProfile = comparer.Compare(subject.ParsedMovieInfo.Quality.Quality, bestQualityInProfile) >= 0; - - if (isBestInProfile && isPreferredProtocol) + if (delayProfile.BypassIfHighestQuality) { - _logger.Debug("Quality is highest in profile for preferred protocol, will not delay."); - return Decision.Accept(); + var bestQualityInProfile = profile.LastAllowedQuality(); + var isBestInProfile = comparer.Compare(subject.ParsedMovieInfo.Quality.Quality, bestQualityInProfile) >= 0; + + if (isBestInProfile && isPreferredProtocol) + { + _logger.Debug("Quality is highest in profile for preferred protocol, will not delay."); + return Decision.Accept(); + } } var oldest = _pendingReleaseService.OldestPendingRelease(subject.Movie.Id); diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 64cd2291b..9a95f02f0 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -94,6 +94,8 @@ "BranchUpdate": "Branch to use to update Radarr", "BranchUpdateMechanism": "Branch used by external update mechanism", "BuiltIn": "Built In", + "BypassDelayIfHighestQuality": "Bypass if Highest Quality", + "BypassDelayIfHighestQualityHelpText": "Bypass delay when release has the highest enabled quality in the quality profile", "BypassProxyForLocalAddresses": "Bypass Proxy for Local Addresses", "Calendar": "Calendar", "CalendarOptions": "Calendar Options", diff --git a/src/NzbDrone.Core/Profiles/Delay/DelayProfile.cs b/src/NzbDrone.Core/Profiles/Delay/DelayProfile.cs index ef20bb6a5..81100d6f5 100644 --- a/src/NzbDrone.Core/Profiles/Delay/DelayProfile.cs +++ b/src/NzbDrone.Core/Profiles/Delay/DelayProfile.cs @@ -12,6 +12,7 @@ namespace NzbDrone.Core.Profiles.Delay public int UsenetDelay { get; set; } public int TorrentDelay { get; set; } public int Order { get; set; } + public bool BypassIfHighestQuality { get; set; } public HashSet Tags { get; set; } public DelayProfile() diff --git a/src/Radarr.Api.V3/Profiles/Delay/DelayProfileResource.cs b/src/Radarr.Api.V3/Profiles/Delay/DelayProfileResource.cs index 214f85f43..7579e0c81 100644 --- a/src/Radarr.Api.V3/Profiles/Delay/DelayProfileResource.cs +++ b/src/Radarr.Api.V3/Profiles/Delay/DelayProfileResource.cs @@ -13,6 +13,7 @@ namespace Radarr.Api.V3.Profiles.Delay public DownloadProtocol PreferredProtocol { get; set; } public int UsenetDelay { get; set; } public int TorrentDelay { get; set; } + public bool BypassIfHighestQuality { get; set; } public int Order { get; set; } public HashSet Tags { get; set; } } @@ -35,6 +36,7 @@ namespace Radarr.Api.V3.Profiles.Delay PreferredProtocol = model.PreferredProtocol, UsenetDelay = model.UsenetDelay, TorrentDelay = model.TorrentDelay, + BypassIfHighestQuality = model.BypassIfHighestQuality, Order = model.Order, Tags = new HashSet(model.Tags) }; @@ -56,6 +58,7 @@ namespace Radarr.Api.V3.Profiles.Delay PreferredProtocol = resource.PreferredProtocol, UsenetDelay = resource.UsenetDelay, TorrentDelay = resource.TorrentDelay, + BypassIfHighestQuality = resource.BypassIfHighestQuality, Order = resource.Order, Tags = new HashSet(resource.Tags) };