From 44bec71752af0829d7dca7461dc9b03cdd2e1b89 Mon Sep 17 00:00:00 2001 From: Qstick Date: Mon, 1 May 2023 20:15:47 -0500 Subject: [PATCH] Fixed: Don't import Custom Format downgrades Closes #8197 Closes #8243 Co-Authored-By: Mark McDowall --- .../UpgradeSpecificationFixture.cs | 172 ++++++++++++++++++ .../Specifications/UpgradeSpecification.cs | 36 +++- 2 files changed, 207 insertions(+), 1 deletion(-) diff --git a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Specifications/UpgradeSpecificationFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Specifications/UpgradeSpecificationFixture.cs index a2020a741..6690453a3 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Specifications/UpgradeSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Specifications/UpgradeSpecificationFixture.cs @@ -1,6 +1,11 @@ +using System.Collections.Generic; +using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Datastore; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.MovieImport.Specifications; using NzbDrone.Core.Movies; @@ -66,5 +71,172 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Specifications Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeFalse(); } + + [Test] + public void should_return_false_if_not_a_revision_upgrade_and_prefers_propers() + { + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.PreferAndUpgrade); + + _localMovie.Movie.MovieFileId = 1; + _localMovie.Movie.MovieFile = + new MovieFile + { + Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2)) + }; + + Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeFalse(); + } + + [Test] + public void should_return_true_if_not_a_revision_upgrade_and_does_not_prefer_propers() + { + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + _localMovie.Movie.MovieFileId = 1; + _localMovie.Movie.MovieFile = + new MovieFile + { + Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2)) + }; + + Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_true_when_comparing_to_a_lower_quality_proper() + { + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + _localMovie.Quality = new QualityModel(Quality.Bluray1080p); + + _localMovie.Movie.MovieFileId = 1; + _localMovie.Movie.MovieFile = + new MovieFile + { + Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 2)) + }; + + Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_true_if_movie_file_is_null() + { + _localMovie.Movie.MovieFile = null; + _localMovie.Movie.MovieFileId = 1; + + Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_true_if_upgrade_to_custom_format_score() + { + var movieFileCustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + + var movieFile = new MovieFile + { + Quality = new QualityModel(Quality.Bluray1080p) + }; + + _movie.Profile.FormatItems = movieFileCustomFormats.Select(c => new ProfileFormatItem + { + Format = c, + Score = 10 + }) + .ToList(); + + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(movieFile)) + .Returns(movieFileCustomFormats); + + _localMovie.Quality = new QualityModel(Quality.Bluray1080p); + _localMovie.CustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + _localMovie.CustomFormatScore = 20; + + _localMovie.Movie.MovieFileId = 1; + _localMovie.Movie.MovieFile = movieFile; + + Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_true_if_not_upgrade_to_custom_format_score_but_is_upgrade_to_quality() + { + var movieFileCustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + + var movieFile = new MovieFile + { + Quality = new QualityModel(Quality.Bluray720p) + }; + + _movie.Profile.FormatItems = movieFileCustomFormats.Select(c => new ProfileFormatItem + { + Format = c, + Score = 50 + }) + .ToList(); + + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(movieFile)) + .Returns(movieFileCustomFormats); + + _localMovie.Quality = new QualityModel(Quality.Bluray1080p); + _localMovie.CustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + _localMovie.CustomFormatScore = 20; + + _localMovie.Movie.MovieFileId = 1; + _localMovie.Movie.MovieFile = movieFile; + + Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_false_if_not_upgrade_to_custom_format_score() + { + var movieFileCustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + + var movieFile = new MovieFile + { + Quality = new QualityModel(Quality.Bluray1080p) + }; + + _movie.Profile.FormatItems = movieFileCustomFormats.Select(c => new ProfileFormatItem + { + Format = c, + Score = 50 + }) + .ToList(); + + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(movieFile)) + .Returns(movieFileCustomFormats); + + _localMovie.Quality = new QualityModel(Quality.Bluray1080p); + _localMovie.CustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + _localMovie.CustomFormatScore = 20; + + _localMovie.Movie.MovieFileId = 1; + _localMovie.Movie.MovieFile = movieFile; + + Subject.IsSatisfiedBy(_localMovie, null).Accepted.Should().BeFalse(); + } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/UpgradeSpecification.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/UpgradeSpecification.cs index 6af9fdeb2..5e3b8b848 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/UpgradeSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/UpgradeSpecification.cs @@ -1,4 +1,6 @@ using NLog; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.Configuration; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; @@ -9,15 +11,23 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications { public class UpgradeSpecification : IImportDecisionEngineSpecification { + private readonly IConfigService _configService; + private readonly ICustomFormatCalculationService _formatService; private readonly Logger _logger; - public UpgradeSpecification(ICustomFormatCalculationService customFormatCalculationService, Logger logger) + public UpgradeSpecification(IConfigService configService, + ICustomFormatCalculationService formatService, + Logger logger) { + _configService = configService; + _formatService = formatService; _logger = logger; } public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem) { + var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; + var qualityProfile = localMovie.Movie.Profile; var qualityComparer = new QualityModelComparer(localMovie.Movie.Profile); if (localMovie.Movie.MovieFileId > 0) @@ -27,6 +37,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications if (movieFile == null) { _logger.Trace("Unable to get movie file details from the DB. MovieId: {0} MovieFileId: {1}", localMovie.Movie.Id, localMovie.Movie.MovieFileId); + return Decision.Accept(); } @@ -35,8 +46,31 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications if (qualityCompare < 0) { _logger.Debug("This file isn't a quality upgrade for movie. New Quality is {0}. Skipping {1}", localMovie.Quality.Quality, localMovie.Path); + return Decision.Reject("Not an upgrade for existing movie file. New Quality is {0}", localMovie.Quality.Quality); } + + // Same quality, propers/repacks are preferred and it is not a revision update. Reject revision downgrade. + + if (qualityCompare == 0 && + downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && + localMovie.Quality.Revision.CompareTo(movieFile.Quality.Revision) < 0) + { + _logger.Debug("This file isn't a quality revision upgrade for movie. Skipping {0}", localMovie.Path); + return Decision.Reject("Not a quality revision upgrade for existing movie file(s)"); + } + + var currentFormats = _formatService.ParseCustomFormat(movieFile); + var currentScore = qualityProfile.CalculateCustomFormatScore(currentFormats); + + if (qualityCompare == 0 && localMovie.CustomFormatScore < currentScore) + { + _logger.Debug("New file's custom formats [{0}] do not improve on [{1}], skipping", + localMovie.CustomFormats.ConcatToString(), + currentFormats.ConcatToString()); + + return Decision.Reject("Not a Custom Format upgrade for existing movie file(s)"); + } } return Decision.Accept();