diff --git a/frontend/src/Settings/MediaManagement/MediaManagement.js b/frontend/src/Settings/MediaManagement/MediaManagement.js
index de456f802..4d6247b4b 100644
--- a/frontend/src/Settings/MediaManagement/MediaManagement.js
+++ b/frontend/src/Settings/MediaManagement/MediaManagement.js
@@ -21,6 +21,12 @@ const rescanAfterRefreshOptions = [
{ key: 'never', value: 'Never' }
];
+const downloadPropersAndRepacksOptions = [
+ { key: 'preferAndUpgrade', value: 'Prefer and Upgrade' },
+ { key: 'doNotUpgrade', value: 'Do not Upgrade Automatically' },
+ { key: 'doNotPrefer', value: 'Do not Prefer' }
+];
+
const fileDateOptions = [
{ key: 'none', value: 'None' },
{ key: 'cinemas', value: 'In Cinemas Date' },
@@ -230,14 +236,23 @@ class MediaManagement extends Component {
isAdvanced={true}
size={sizes.MEDIUM}
>
- {translate('DownloadPropers')}
+ {translate('DownloadPropersAndRepacks')}
diff --git a/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs b/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs
index 691b7b85b..512891fcb 100644
--- a/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs
+++ b/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs
@@ -1,5 +1,6 @@
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
+using NzbDrone.Core.Qualities;
using Radarr.Http.REST;
namespace NzbDrone.Api.Config
@@ -8,7 +9,7 @@ public class MediaManagementConfigResource : RestResource
{
public bool AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
public string RecycleBin { get; set; }
- public bool AutoDownloadPropers { get; set; }
+ public ProperDownloadTypes DownloadPropersAndRepacks { get; set; }
public bool CreateEmptySeriesFolders { get; set; }
public FileDateType FileDate { get; set; }
public bool AutoRenameFolders { get; set; }
@@ -32,7 +33,7 @@ public static MediaManagementConfigResource ToResource(IConfigService model)
{
AutoUnmonitorPreviouslyDownloadedEpisodes = model.AutoUnmonitorPreviouslyDownloadedMovies,
RecycleBin = model.RecycleBin,
- AutoDownloadPropers = model.AutoDownloadPropers,
+ DownloadPropersAndRepacks = model.DownloadPropersAndRepacks,
CreateEmptySeriesFolders = model.CreateEmptyMovieFolders,
FileDate = model.FileDate,
AutoRenameFolders = model.AutoRenameFolders,
diff --git a/src/NzbDrone.Api/Profiles/ProfileResource.cs b/src/NzbDrone.Api/Profiles/ProfileResource.cs
index 4dde38175..a9f05cd2e 100644
--- a/src/NzbDrone.Api/Profiles/ProfileResource.cs
+++ b/src/NzbDrone.Api/Profiles/ProfileResource.cs
@@ -13,7 +13,6 @@ public class ProfileResource : RestResource
{
public string Name { get; set; }
public Quality Cutoff { get; set; }
- public string PreferredTags { get; set; }
public List Items { get; set; }
public int MinFormatScore { get; set; }
public int CutoffFormatScore { get; set; }
@@ -66,7 +65,6 @@ public static ProfileResource ToResource(this Profile model)
Id = model.Id,
Name = model.Name,
- PreferredTags = model.PreferredTags != null ? string.Join(",", model.PreferredTags) : "",
Cutoff = cutoff,
// Flatten groups so things don't explode
@@ -127,7 +125,6 @@ public static Profile ToModel(this ProfileResource resource)
Name = resource.Name,
Cutoff = resource.Cutoff.Id,
- PreferredTags = resource.PreferredTags.Split(',').ToList(),
Items = resource.Items.ConvertAll(ToModel),
MinFormatScore = resource.MinFormatScore,
CutoffFormatScore = resource.CutoffFormatScore,
diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs
index 4ee35f7ab..4de1b8066 100644
--- a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs
+++ b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs
@@ -6,6 +6,7 @@
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
+using NzbDrone.Core.Configuration;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Indexers;
@@ -61,7 +62,6 @@ private RemoteMovie GivenRemoteMovie(QualityModel quality, int age = 0, long siz
remoteMovie.Movie = Builder.CreateNew().With(m => m.Profile = new Profile
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
- PreferredTags = new List { "DTS-HD", "SPARKS" },
FormatItems = CustomFormatsFixture.GetSampleFormatItems(_customFormat1.Name, _customFormat2.Name),
MinFormatScore = 0
})
@@ -90,6 +90,20 @@ private void GivenPreferredDownloadProtocol(DownloadProtocol downloadProtocol)
});
}
+ [Test]
+ public void should_put_reals_before_non_reals()
+ {
+ var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.HDTV720p, new Revision(version: 1, real: 0)));
+ var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.HDTV720p, new Revision(version: 1, real: 1)));
+
+ var decisions = new List();
+ decisions.Add(new DownloadDecision(remoteMovie1));
+ decisions.Add(new DownloadDecision(remoteMovie2));
+
+ var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Real.Should().Be(1);
+ }
+
[Test]
public void should_put_propers_before_non_propers()
{
@@ -392,23 +406,6 @@ public void should_prefer_first_release_if_age_and_size_are_too_similar()
qualifiedReports.First().RemoteMovie.Release.Should().Be(remoteMovie1.Release);
}
- [Test]
- public void should_prefer_more_prioritized_words()
- {
- var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.HDTV720p));
- var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.HDTV720p));
-
- remoteMovie1.Release.Title += " DTS-HD";
- remoteMovie2.Release.Title += " DTS-HD SPARKS";
-
- var decisions = new List();
- decisions.Add(new DownloadDecision(remoteMovie1));
- decisions.Add(new DownloadDecision(remoteMovie2));
-
- var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
- qualifiedReports.First().RemoteMovie.Release.Should().Be(remoteMovie2.Release);
- }
-
[Test]
public void should_prefer_better_custom_format()
{
@@ -469,5 +466,94 @@ public void should_prefer_2_custom_formats()
var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
qualifiedReports.First().RemoteMovie.Release.Should().Be(remoteMovie2.Release);
}
+
+ [Test]
+ public void should_prefer_proper_over_score_when_download_propers_is_prefer_and_upgrade()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadPropersAndRepacks)
+ .Returns(ProperDownloadTypes.PreferAndUpgrade);
+
+ var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(1)));
+ var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(2)));
+
+ remoteMovie1.CustomFormatScore = 10;
+ remoteMovie2.CustomFormatScore = 0;
+
+ var decisions = new List();
+ decisions.Add(new DownloadDecision(remoteMovie1));
+ decisions.Add(new DownloadDecision(remoteMovie2));
+
+ var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Version.Should().Be(2);
+ }
+
+ [Test]
+ public void should_prefer_proper_over_score_when_download_propers_is_do_not_upgrade()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadPropersAndRepacks)
+ .Returns(ProperDownloadTypes.DoNotUpgrade);
+
+ var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(1)));
+ var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(2)));
+
+ remoteMovie1.CustomFormatScore = 10;
+ remoteMovie2.CustomFormatScore = 0;
+
+ var decisions = new List();
+ decisions.Add(new DownloadDecision(remoteMovie1));
+ decisions.Add(new DownloadDecision(remoteMovie2));
+
+ var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Version.Should().Be(2);
+ }
+
+ [Test]
+ public void should_prefer_score_over_proper_when_download_propers_is_do_not_prefer()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadPropersAndRepacks)
+ .Returns(ProperDownloadTypes.DoNotPrefer);
+
+ var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(1)));
+ var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(2)));
+
+ remoteMovie1.CustomFormatScore = 10;
+ remoteMovie2.CustomFormatScore = 0;
+
+ var decisions = new List();
+ decisions.Add(new DownloadDecision(remoteMovie1));
+ decisions.Add(new DownloadDecision(remoteMovie2));
+
+ var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Quality.Should().Be(Quality.WEBDL1080p);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Version.Should().Be(1);
+ qualifiedReports.First().RemoteMovie.CustomFormatScore.Should().Be(10);
+ }
+
+ [Test]
+ public void should_prefer_score_over_real_when_download_propers_is_do_not_prefer()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadPropersAndRepacks)
+ .Returns(ProperDownloadTypes.DoNotPrefer);
+
+ var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(1, 0)));
+ var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p, new Revision(1, 1)));
+
+ remoteMovie1.CustomFormatScore = 10;
+ remoteMovie2.CustomFormatScore = 0;
+
+ var decisions = new List();
+ decisions.Add(new DownloadDecision(remoteMovie1));
+ decisions.Add(new DownloadDecision(remoteMovie2));
+
+ var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Quality.Should().Be(Quality.WEBDL1080p);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Version.Should().Be(1);
+ qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Real.Should().Be(0);
+ qualifiedReports.First().RemoteMovie.CustomFormatScore.Should().Be(10);
+ }
}
}
diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs
index ea91d5f43..75b8894b7 100644
--- a/src/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs
+++ b/src/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Configuration;
@@ -51,11 +51,11 @@ public void Setup()
CustomFormatsFixture.GivenCustomFormats(_customFormat1, _customFormat2);
}
- private void GivenAutoDownloadPropers(bool autoDownloadPropers)
+ private void GivenAutoDownloadPropers(ProperDownloadTypes type)
{
Mocker.GetMock()
- .SetupGet(s => s.AutoDownloadPropers)
- .Returns(autoDownloadPropers);
+ .SetupGet(s => s.DownloadPropersAndRepacks)
+ .Returns(type);
}
[Test]
@@ -68,7 +68,7 @@ public void IsUpgradeTest(Quality current,
List newFormats,
bool expected)
{
- GivenAutoDownloadPropers(true);
+ GivenAutoDownloadPropers(ProperDownloadTypes.PreferAndUpgrade);
var profile = new Profile
{
@@ -86,9 +86,9 @@ public void IsUpgradeTest(Quality current,
}
[Test]
- public void should_return_false_if_proper_and_autoDownloadPropers_is_false()
+ public void should_return_true_if_proper_and_download_propers_is_do_not_download()
{
- GivenAutoDownloadPropers(false);
+ GivenAutoDownloadPropers(ProperDownloadTypes.DoNotUpgrade);
var profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() };
diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs
index fa401ee29..0f7ee0c1d 100644
--- a/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs
+++ b/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/DelaySpecificationFixture.cs
@@ -25,7 +25,7 @@ public class DelaySpecificationFixture : CoreTest
{
private Profile _profile;
private DelayProfile _delayProfile;
- private RemoteMovie _remoteEpisode;
+ private RemoteMovie _remoteMovie;
[SetUp]
public void Setup()
@@ -41,7 +41,7 @@ public void Setup()
.With(s => s.Profile = _profile)
.Build();
- _remoteEpisode = Builder.CreateNew()
+ _remoteMovie = Builder.CreateNew()
.With(r => r.Movie = series)
.Build();
@@ -52,12 +52,10 @@ public void Setup()
_profile.Cutoff = Quality.WEBDL720p.Id;
- _remoteEpisode.ParsedMovieInfo = new ParsedMovieInfo();
- _remoteEpisode.Release = new ReleaseInfo();
- _remoteEpisode.Release.DownloadProtocol = DownloadProtocol.Usenet;
+ _remoteMovie.ParsedMovieInfo = new ParsedMovieInfo();
+ _remoteMovie.Release = new ReleaseInfo();
+ _remoteMovie.Release.DownloadProtocol = DownloadProtocol.Usenet;
- //_remoteEpisode.Episodes = Builder.CreateListOfSize(1).Build().ToList();
- //_remoteEpisode.Episodes.First().EpisodeFileId = 0;
Mocker.GetMock()
.Setup(s => s.BestForTags(It.IsAny>()))
.Returns(_delayProfile);
@@ -70,7 +68,7 @@ public void Setup()
private void GivenExistingFile(QualityModel quality)
{
//_remoteEpisode.Episodes.First().EpisodeFileId = 1;
- _remoteEpisode.Movie.MovieFile = new MovieFile { Quality = quality };
+ _remoteMovie.Movie.MovieFile = new MovieFile { Quality = quality };
}
private void GivenUpgradeForExistingFile()
@@ -89,12 +87,12 @@ public void should_be_true_when_user_invoked_search()
[Test]
public void should_be_false_when_system_invoked_search_and_release_is_younger_than_delay()
{
- _remoteEpisode.ParsedMovieInfo.Quality = new QualityModel(Quality.SDTV);
- _remoteEpisode.Release.PublishDate = DateTime.UtcNow;
+ _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.SDTV);
+ _remoteMovie.Release.PublishDate = DateTime.UtcNow;
_delayProfile.UsenetDelay = 720;
- Subject.IsSatisfiedBy(_remoteEpisode, new MovieSearchCriteria()).Accepted.Should().BeFalse();
+ Subject.IsSatisfiedBy(_remoteMovie, new MovieSearchCriteria()).Accepted.Should().BeFalse();
}
[Test]
@@ -102,44 +100,44 @@ public void should_be_true_when_profile_does_not_have_a_delay()
{
_delayProfile.UsenetDelay = 0;
- Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
+ Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_when_quality_is_last_allowed_in_profile()
{
- _remoteEpisode.ParsedMovieInfo.Quality = new QualityModel(Quality.Bluray720p);
+ _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.Bluray720p);
- Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
+ Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_when_release_is_older_than_delay()
{
- _remoteEpisode.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p);
- _remoteEpisode.Release.PublishDate = DateTime.UtcNow.AddHours(-10);
+ _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p);
+ _remoteMovie.Release.PublishDate = DateTime.UtcNow.AddHours(-10);
_delayProfile.UsenetDelay = 60;
- Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
+ Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_false_when_release_is_younger_than_delay()
{
- _remoteEpisode.ParsedMovieInfo.Quality = new QualityModel(Quality.SDTV);
- _remoteEpisode.Release.PublishDate = DateTime.UtcNow;
+ _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.SDTV);
+ _remoteMovie.Release.PublishDate = DateTime.UtcNow;
_delayProfile.UsenetDelay = 720;
- Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
+ Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse();
}
[Test]
- public void should_be_true_when_release_is_a_proper_for_existing_episode()
+ public void should_be_true_when_release_is_a_proper_for_existing_movie()
{
- _remoteEpisode.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
- _remoteEpisode.Release.PublishDate = DateTime.UtcNow;
+ _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
+ _remoteMovie.Release.PublishDate = DateTime.UtcNow;
GivenExistingFile(new QualityModel(Quality.HDTV720p));
GivenUpgradeForExistingFile();
@@ -150,14 +148,14 @@ public void should_be_true_when_release_is_a_proper_for_existing_episode()
_delayProfile.UsenetDelay = 720;
- Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
+ Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
}
[Test]
- public void should_be_true_when_release_is_a_real_for_existing_episode()
+ public void should_be_true_when_release_is_a_real_for_existing_movie()
{
- _remoteEpisode.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(real: 1));
- _remoteEpisode.Release.PublishDate = DateTime.UtcNow;
+ _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(real: 1));
+ _remoteMovie.Release.PublishDate = DateTime.UtcNow;
GivenExistingFile(new QualityModel(Quality.HDTV720p));
GivenUpgradeForExistingFile();
@@ -168,20 +166,20 @@ public void should_be_true_when_release_is_a_real_for_existing_episode()
_delayProfile.UsenetDelay = 720;
- Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
+ Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
}
[Test]
- public void should_be_false_when_release_is_proper_for_existing_episode_of_different_quality()
+ public void should_be_false_when_release_is_proper_for_existing_movie_of_different_quality()
{
- _remoteEpisode.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
- _remoteEpisode.Release.PublishDate = DateTime.UtcNow;
+ _remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
+ _remoteMovie.Release.PublishDate = DateTime.UtcNow;
GivenExistingFile(new QualityModel(Quality.SDTV));
_delayProfile.UsenetDelay = 720;
- Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
+ Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse();
}
}
}
diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/ProperSpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/ProperSpecificationFixture.cs
index 21e9a5aff..7160fabef 100644
--- a/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/ProperSpecificationFixture.cs
+++ b/src/NzbDrone.Core.Test/DecisionEngineTests/RssSync/ProperSpecificationFixture.cs
@@ -48,13 +48,6 @@ private void WithFirstFileUpgradable()
_firstFile.Quality = new QualityModel(Quality.SDTV);
}
- private void GivenAutoDownloadPropers()
- {
- Mocker.GetMock()
- .Setup(s => s.AutoDownloadPropers)
- .Returns(true);
- }
-
[Test]
public void should_return_false_when_movieFile_was_added_more_than_7_days_ago()
{
@@ -85,6 +78,10 @@ public void should_return_true_when_episodeFile_was_added_more_than_7_days_ago_b
[Test]
public void should_return_false_when_proper_but_auto_download_propers_is_false()
{
+ Mocker.GetMock()
+ .Setup(s => s.DownloadPropersAndRepacks)
+ .Returns(ProperDownloadTypes.DoNotUpgrade);
+
_firstFile.Quality.Quality = Quality.DVD;
_firstFile.DateAdded = DateTime.Today;
@@ -94,7 +91,21 @@ public void should_return_false_when_proper_but_auto_download_propers_is_false()
[Test]
public void should_return_true_when_movieFile_was_added_today()
{
- GivenAutoDownloadPropers();
+ Mocker.GetMock()
+ .Setup(s => s.DownloadPropersAndRepacks)
+ .Returns(ProperDownloadTypes.PreferAndUpgrade);
+
+ _firstFile.Quality.Quality = Quality.DVD;
+
+ _firstFile.DateAdded = DateTime.Today;
+ Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
+ }
+
+ public void should_return_true_when_propers_are_not_preferred()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadPropersAndRepacks)
+ .Returns(ProperDownloadTypes.DoNotPrefer);
_firstFile.Quality.Quality = Quality.DVD;
diff --git a/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs
index e0c5794b1..7f7728927 100644
--- a/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs
+++ b/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs
@@ -46,7 +46,7 @@ private RemoteMovie GetRemoteMovie(QualityModel quality, Movie movie = null, Dow
movie = GetMovie(1);
}
- movie.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities(), PreferredTags = new List() };
+ movie.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() };
var remoteMovie = new RemoteMovie()
{
diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs
index 364925be2..e7a142da7 100644
--- a/src/NzbDrone.Core/Configuration/ConfigService.cs
+++ b/src/NzbDrone.Core/Configuration/ConfigService.cs
@@ -11,6 +11,7 @@
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
+using NzbDrone.Core.Qualities;
using NzbDrone.Core.Security;
namespace NzbDrone.Core.Configuration
@@ -156,11 +157,11 @@ public int MinimumAge
set { SetValue("MinimumAge", value); }
}
- public bool AutoDownloadPropers
+ public ProperDownloadTypes DownloadPropersAndRepacks
{
- get { return GetValueBoolean("AutoDownloadPropers", true); }
+ get { return GetValueEnum("DownloadPropersAndRepacks", ProperDownloadTypes.PreferAndUpgrade); }
- set { SetValue("AutoDownloadPropers", value); }
+ set { SetValue("DownloadPropersAndRepacks", value); }
}
public bool EnableCompletedDownloadHandling
diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs
index c95fde86d..c4c24136c 100644
--- a/src/NzbDrone.Core/Configuration/IConfigService.cs
+++ b/src/NzbDrone.Core/Configuration/IConfigService.cs
@@ -3,6 +3,7 @@
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
+using NzbDrone.Core.Qualities;
using NzbDrone.Core.Security;
namespace NzbDrone.Core.Configuration
@@ -29,7 +30,7 @@ public interface IConfigService
bool AutoUnmonitorPreviouslyDownloadedMovies { get; set; }
string RecycleBin { get; set; }
int RecycleBinCleanupDays { get; set; }
- bool AutoDownloadPropers { get; set; }
+ ProperDownloadTypes DownloadPropersAndRepacks { get; set; }
bool CreateEmptyMovieFolders { get; set; }
bool DeleteEmptyFolders { get; set; }
FileDateType FileDate { get; set; }
diff --git a/src/NzbDrone.Core/Datastore/Migration/183_download_propers_config.cs b/src/NzbDrone.Core/Datastore/Migration/183_download_propers_config.cs
new file mode 100644
index 000000000..72312ee1d
--- /dev/null
+++ b/src/NzbDrone.Core/Datastore/Migration/183_download_propers_config.cs
@@ -0,0 +1,44 @@
+using System.Data;
+using FluentMigrator;
+using NzbDrone.Core.Datastore.Migration.Framework;
+
+namespace NzbDrone.Core.Datastore.Migration
+{
+ [Migration(183)]
+ public class download_propers_config : NzbDroneMigrationBase
+ {
+ protected override void MainDbUpgrade()
+ {
+ Execute.WithConnection(SetMetadataFileExtension);
+ Execute.Sql("DELETE FROM Config WHERE Key = 'autodownloadpropers'");
+ Delete.Column("PreferredTags").FromTable("Profiles");
+ }
+
+ private void SetMetadataFileExtension(IDbConnection conn, IDbTransaction tran)
+ {
+ using (var cmd = conn.CreateCommand())
+ {
+ cmd.Transaction = tran;
+ cmd.CommandText = "SELECT Value FROM Config WHERE Key = 'autodownloadpropers'";
+
+ using (var reader = cmd.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ var value = reader.GetString(0);
+ var newValue = bool.Parse(value) ? "PreferAndUpgrade" : "DoNotUpgrade";
+
+ using (var updateCmd = conn.CreateCommand())
+ {
+ updateCmd.Transaction = tran;
+ updateCmd.CommandText = "INSERT INTO Config (key, value) VALUES ('downloadpropersandrepacks', ?)";
+ updateCmd.AddParameter(newValue);
+
+ updateCmd.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs
index 889b9ae19..13414c2fd 100644
--- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs
+++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs
@@ -30,7 +30,7 @@ public int Compare(DownloadDecision x, DownloadDecision y)
var comparers = new List
{
CompareQuality,
- ComparePreferredWords,
+ CompareCustomFormatScore,
CompareProtocol,
CompareIndexerFlags,
ComparePeersIfTorrent,
@@ -57,28 +57,18 @@ private int CompareAll(params int[] comparers)
private int CompareQuality(DownloadDecision x, DownloadDecision y)
{
+ if (_configService.DownloadPropersAndRepacks == ProperDownloadTypes.DoNotPrefer)
+ {
+ return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie => remoteMovie.Movie.Profile.GetIndex(remoteMovie.ParsedMovieInfo.Quality.Quality));
+ }
+
return CompareAll(CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie => remoteMovie.Movie.Profile.GetIndex(remoteMovie.ParsedMovieInfo.Quality.Quality)),
- CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie => remoteMovie.CustomFormatScore),
- CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie => remoteMovie.ParsedMovieInfo.Quality.Revision.Real),
- CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie => remoteMovie.ParsedMovieInfo.Quality.Revision.Version));
+ CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie => remoteMovie.ParsedMovieInfo.Quality.Revision));
}
- private int ComparePreferredWords(DownloadDecision x, DownloadDecision y)
+ private int CompareCustomFormatScore(DownloadDecision x, DownloadDecision y)
{
- return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie =>
- {
- var title = remoteMovie.Release.Title;
- var preferredWords = remoteMovie.Movie.Profile.PreferredTags;
-
- if (preferredWords == null)
- {
- return 0;
- }
-
- var num = preferredWords.AsEnumerable().Count(w => title.ToLower().Contains(w.ToLower()));
-
- return num;
- });
+ return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie => remoteMovie.CustomFormatScore);
}
private int CompareIndexerFlags(DownloadDecision x, DownloadDecision y)
diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs
index e748b2d64..e6a6e9872 100644
--- a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs
+++ b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/DelaySpecification.cs
@@ -46,21 +46,6 @@ public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase se
var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol);
var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol;
- // Preferred word count
- var title = subject.Release.Title;
- var preferredWords = subject.Movie.Profile?.PreferredTags;
- var preferredCount = 0;
-
- if (preferredWords == null)
- {
- preferredCount = 1;
- _logger.Debug("Preferred words is null, setting preffered count to 1.");
- }
- else
- {
- preferredCount = preferredWords.AsEnumerable().Count(w => title.ToLower().Contains(w.ToLower()));
- }
-
if (delay == 0)
{
_logger.Debug("Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol);
@@ -71,7 +56,7 @@ public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase se
var file = subject.Movie.MovieFile;
- if (isPreferredProtocol && (subject.Movie.MovieFileId != 0 && file != null) && (preferredCount > 0 || preferredWords == null))
+ if (isPreferredProtocol && (subject.Movie.MovieFileId != 0 && file != null))
{
var customFormats = _formatService.ParseCustomFormat(file);
var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile,
@@ -86,7 +71,7 @@ public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase se
if (revisionUpgrade)
{
- _logger.Debug("New quality is a better revision for existing quality and preferred word count is {0}, skipping delay", preferredCount);
+ _logger.Debug("New quality is a better revision for existing quality, skipping delay");
return Decision.Accept();
}
}
@@ -96,9 +81,9 @@ public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase se
var bestQualityInProfile = profile.LastAllowedQuality();
var isBestInProfile = comparer.Compare(subject.ParsedMovieInfo.Quality.Quality, bestQualityInProfile) >= 0;
- if (isBestInProfile && isPreferredProtocol && (preferredCount > 0 || preferredWords == null))
+ if (isBestInProfile && isPreferredProtocol)
{
- _logger.Debug("Quality is highest in profile for preferred protocol and preferred word count is {0}, will not delay.", preferredCount);
+ _logger.Debug("Quality is highest in profile for preferred protocol, will not delay.");
return Decision.Accept();
}
diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/ProperSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/ProperSpecification.cs
index 7f22ed761..74d823849 100644
--- a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/ProperSpecification.cs
+++ b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/ProperSpecification.cs
@@ -3,6 +3,7 @@
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
+using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
{
@@ -29,6 +30,14 @@ public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase se
return Decision.Accept();
}
+ var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks;
+
+ if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotPrefer)
+ {
+ _logger.Debug("Propers are not preferred, skipping check");
+ return Decision.Accept();
+ }
+
if (subject.Movie.MovieFile == null)
{
return Decision.Accept();
@@ -38,17 +47,17 @@ public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase se
if (_qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedMovieInfo.Quality))
{
+ if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade)
+ {
+ _logger.Debug("Auto downloading of propers is disabled");
+ return Decision.Reject("Proper downloading is disabled");
+ }
+
if (file.DateAdded < DateTime.Today.AddDays(-7))
{
_logger.Debug("Proper for old file, rejecting: {0}", subject);
return Decision.Reject("Proper for old file");
}
-
- if (!_configService.AutoDownloadPropers)
- {
- _logger.Debug("Auto downloading of propers is disabled");
- return Decision.Reject("Proper downloading is disabled");
- }
}
return Decision.Accept();
diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/UpgradableSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/UpgradableSpecification.cs
index 30d4c5d92..64ccae70a 100644
--- a/src/NzbDrone.Core/DecisionEngine/Specifications/UpgradableSpecification.cs
+++ b/src/NzbDrone.Core/DecisionEngine/Specifications/UpgradableSpecification.cs
@@ -47,10 +47,9 @@ public bool IsUpgradable(Profile profile, QualityModel currentQuality, List 0)
{
- _logger.Debug("New item has a better quality revision");
return true;
}
diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json
index 9474f4da8..c285eb27b 100644
--- a/src/NzbDrone.Core/Localization/Core/en.json
+++ b/src/NzbDrone.Core/Localization/Core/en.json
@@ -46,7 +46,6 @@
"AudioInfo": "Audio Info",
"Authentication": "Authentication",
"AuthenticationMethodHelpText": "Require Username and Password to access Radarr",
- "AutoDownloadPropersHelpText": "Should Radarr automatically upgrade to propers when available?",
"Automatic": "Automatic",
"AutoRedownloadFailedHelpText": "Automatically search for and attempt to download a different release",
"AutoUnmonitorPreviouslyDownloadedMoviesHelpText": "Movies deleted from disk are automatically unmonitored in Radarr",
@@ -185,7 +184,10 @@
"DownloadFailedCheckDownloadClientForMoreDetails": "Download failed: check download client for more details",
"DownloadFailedInterp": "Download failed: {0}",
"Downloading": "Downloading",
- "DownloadPropers": "Download Propers",
+ "DownloadPropersAndRepacks": "Propers and Repacks",
+ "DownloadPropersAndRepacksHelpText1": "Whether or not to automatically upgrade to Propers/Repacks",
+ "DownloadPropersAndRepacksHelpText2": "Use 'Do not Prefer' to sort by preferred word score over propers/repacks",
+ "DownloadPropersAndRepacksHelpTextWarning": "Use preferred words for automatic upgrades to propers/repacks",
"DownloadWarning": "Download warning: {0}",
"DownloadWarningCheckDownloadClientForMoreDetails": "Download warning: check download client for more details",
"Edit": "Edit",
diff --git a/src/NzbDrone.Core/Profiles/Profile.cs b/src/NzbDrone.Core/Profiles/Profile.cs
index 0952af29f..9d9e07f8b 100644
--- a/src/NzbDrone.Core/Profiles/Profile.cs
+++ b/src/NzbDrone.Core/Profiles/Profile.cs
@@ -20,7 +20,6 @@ public Profile()
public int MinFormatScore { get; set; }
public int CutoffFormatScore { get; set; }
public List FormatItems { get; set; }
- public List PreferredTags { get; set; }
public Language Language { get; set; }
public bool UpgradeAllowed { get; set; }
diff --git a/src/NzbDrone.Core/Qualities/ProperDownloadTypes.cs b/src/NzbDrone.Core/Qualities/ProperDownloadTypes.cs
new file mode 100644
index 000000000..d61101e5a
--- /dev/null
+++ b/src/NzbDrone.Core/Qualities/ProperDownloadTypes.cs
@@ -0,0 +1,9 @@
+namespace NzbDrone.Core.Qualities
+{
+ public enum ProperDownloadTypes
+ {
+ PreferAndUpgrade,
+ DoNotUpgrade,
+ DoNotPrefer
+ }
+}
diff --git a/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs b/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs
index 549d077bc..987eba574 100644
--- a/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs
+++ b/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs
@@ -1,5 +1,6 @@
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
+using NzbDrone.Core.Qualities;
using Radarr.Http.REST;
namespace Radarr.Api.V3.Config
@@ -9,7 +10,7 @@ public class MediaManagementConfigResource : RestResource
public bool AutoUnmonitorPreviouslyDownloadedMovies { get; set; }
public string RecycleBin { get; set; }
public int RecycleBinCleanupDays { get; set; }
- public bool AutoDownloadPropers { get; set; }
+ public ProperDownloadTypes DownloadPropersAndRepacks { get; set; }
public bool CreateEmptyMovieFolders { get; set; }
public bool DeleteEmptyFolders { get; set; }
public FileDateType FileDate { get; set; }
@@ -37,7 +38,7 @@ public static MediaManagementConfigResource ToResource(IConfigService model)
AutoUnmonitorPreviouslyDownloadedMovies = model.AutoUnmonitorPreviouslyDownloadedMovies,
RecycleBin = model.RecycleBin,
RecycleBinCleanupDays = model.RecycleBinCleanupDays,
- AutoDownloadPropers = model.AutoDownloadPropers,
+ DownloadPropersAndRepacks = model.DownloadPropersAndRepacks,
CreateEmptyMovieFolders = model.CreateEmptyMovieFolders,
DeleteEmptyFolders = model.DeleteEmptyFolders,
FileDate = model.FileDate,
diff --git a/src/Radarr.Api.V3/Profiles/Quality/QualityProfileResource.cs b/src/Radarr.Api.V3/Profiles/Quality/QualityProfileResource.cs
index c8a0ff899..fc2018bfc 100644
--- a/src/Radarr.Api.V3/Profiles/Quality/QualityProfileResource.cs
+++ b/src/Radarr.Api.V3/Profiles/Quality/QualityProfileResource.cs
@@ -12,7 +12,6 @@ public class QualityProfileResource : RestResource
public string Name { get; set; }
public bool UpgradeAllowed { get; set; }
public int Cutoff { get; set; }
- public string PreferredTags { get; set; }
public List Items { get; set; }
public int MinFormatScore { get; set; }
public int CutoffFormatScore { get; set; }
@@ -55,7 +54,6 @@ public static QualityProfileResource ToResource(this Profile model)
Name = model.Name,
UpgradeAllowed = model.UpgradeAllowed,
Cutoff = model.Cutoff,
- PreferredTags = model.PreferredTags != null ? string.Join(",", model.PreferredTags) : "",
Items = model.Items.ConvertAll(ToResource),
MinFormatScore = model.MinFormatScore,
CutoffFormatScore = model.CutoffFormatScore,
@@ -104,7 +102,6 @@ public static Profile ToModel(this QualityProfileResource resource)
Name = resource.Name,
UpgradeAllowed = resource.UpgradeAllowed,
Cutoff = resource.Cutoff,
- PreferredTags = resource.PreferredTags.Split(',').ToList(),
Items = resource.Items.ConvertAll(ToModel),
MinFormatScore = resource.MinFormatScore,
CutoffFormatScore = resource.CutoffFormatScore,