diff --git a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs index a004a15d8..6520b8f05 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs @@ -11,6 +11,7 @@ using NzbDrone.Core.Languages; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications; using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Profiles; using NzbDrone.Core.Profiles.Qualities; using NzbDrone.Core.Qualities; using NzbDrone.Core.Test.Framework; @@ -447,5 +448,83 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue(); } + + [Test] + public void should_return_true_if_upgrade_to_custom_format_score() + { + var episodeFileCustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + + var episodeFile = new EpisodeFile + { + Quality = new QualityModel(Quality.Bluray1080p) + }; + + _series.QualityProfile.Value.FormatItems = episodeFileCustomFormats.Select(c => new ProfileFormatItem + { + Format = c, + Score = 10 + }) + .ToList(); + + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(episodeFile)) + .Returns(episodeFileCustomFormats); + + _localEpisode.Quality = new QualityModel(Quality.Bluray1080p); + _localEpisode.CustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + _localEpisode.CustomFormatScore = 20; + + _localEpisode.Episodes = Builder.CreateListOfSize(1) + .All() + .With(e => e.EpisodeFileId = 1) + .With(e => e.EpisodeFile = new LazyLoaded(episodeFile)) + .Build() + .ToList(); + + Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_false_if_not_upgrade_to_custom_format_score() + { + var episodeFileCustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + + var episodeFile = new EpisodeFile + { + Quality = new QualityModel(Quality.Bluray1080p) + }; + + _series.QualityProfile.Value.FormatItems = episodeFileCustomFormats.Select(c => new ProfileFormatItem + { + Format = c, + Score = 50 + }) + .ToList(); + + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(episodeFile)) + .Returns(episodeFileCustomFormats); + + _localEpisode.Quality = new QualityModel(Quality.Bluray1080p); + _localEpisode.CustomFormats = Builder.CreateListOfSize(1).Build().ToList(); + _localEpisode.CustomFormatScore = 20; + + _localEpisode.Episodes = Builder.CreateListOfSize(1) + .All() + .With(e => e.EpisodeFileId = 1) + .With(e => e.EpisodeFile = new LazyLoaded(episodeFile)) + .Build() + .ToList(); + + Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse(); + } } } diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs index 4f1ddaf0e..d961dc8dc 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.DecisionEngine; @@ -13,22 +13,23 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications public class UpgradeSpecification : IImportDecisionEngineSpecification { private readonly IConfigService _configService; - private readonly ICustomFormatCalculationService _customFormatCalculationService; + private readonly ICustomFormatCalculationService _formatService; private readonly Logger _logger; public UpgradeSpecification(IConfigService configService, - ICustomFormatCalculationService customFormatCalculationService, + ICustomFormatCalculationService formatService, Logger logger) { _configService = configService; - _customFormatCalculationService = customFormatCalculationService; + _formatService = formatService; _logger = logger; } public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem) { var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; - var qualityComparer = new QualityModelComparer(localEpisode.Series.QualityProfile); + var qualityProfile = localEpisode.Series.QualityProfile.Value; + var qualityComparer = new QualityModelComparer(qualityProfile); foreach (var episode in localEpisode.Episodes.Where(e => e.EpisodeFileId > 0)) { @@ -44,13 +45,11 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications if (qualityCompare < 0) { - _logger.Debug("This file isn't a quality upgrade for all episodes. New Quality is {0}. Skipping {1}", localEpisode.Quality.Quality, localEpisode.Path); - return Decision.Reject("Not an upgrade for existing episode file(s). New Quality is {0}", localEpisode.Quality.Quality); + _logger.Debug("This file isn't a quality upgrade for all episodes. Existing quality: {0}. New Quality {1}. Skipping {2}", episodeFile.Quality.Quality, localEpisode.Quality.Quality, localEpisode.Path); + return Decision.Reject("Not an upgrade for existing episode file(s). Existing quality: {0}. New Quality {1}.", episodeFile.Quality.Quality, localEpisode.Quality.Quality); } - // Same quality, is not a language upgrade, propers/repacks are preferred and it is not a revision update - // This will allow language upgrades of a lower revision to be imported, which are allowed to be grabbed, - // they just don't import automatically. + // Same quality, propers/repacks are preferred and it is not a revision update. Reject revision downgrade. if (qualityCompare == 0 && downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && @@ -59,6 +58,18 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications _logger.Debug("This file isn't a quality revision upgrade for all episodes. Skipping {0}", localEpisode.Path); return Decision.Reject("Not a quality revision upgrade for existing episode file(s)"); } + + var currentFormats = _formatService.ParseCustomFormat(episodeFile); + var currentScore = qualityProfile.CalculateCustomFormatScore(currentFormats); + + if (localEpisode.CustomFormatScore < currentScore) + { + _logger.Debug("New file's custom formats [{0}] do not improve on [{1}], skipping", + localEpisode.CustomFormats.ConcatToString(), + currentFormats.ConcatToString()); + + return Decision.Reject("Not a Custom Format upgrade for existing episode file(s)"); + } } return Decision.Accept();