From bb5f5eeee60ceeded74637a6396d9a0e5757826f Mon Sep 17 00:00:00 2001 From: Qstick Date: Wed, 11 Nov 2020 21:37:45 -0500 Subject: [PATCH] Fixed: Correctly storing v0 version during import, allowing them to be upgraded to v1 later Fixes #5305 Co-Authored-By: Mark McDowall --- .../Aggregators/AggregateQualityFixture.cs | 60 ++++++++++++++++++- .../Aggregators/AggregateQuality.cs | 24 +++++++- .../AugmentQualityFromDownloadClientItem.cs | 7 ++- .../Quality/AugmentQualityFromFileName.cs | 7 ++- .../Quality/AugmentQualityFromFolder.cs | 7 ++- .../Quality/AugmentQualityFromReleaseName.cs | 9 ++- .../Quality/AugmentQualityResult.cs | 11 ++-- src/NzbDrone.Core/Parser/QualityParser.cs | 4 ++ src/NzbDrone.Core/Qualities/QualityModel.cs | 3 + 9 files changed, 119 insertions(+), 13 deletions(-) diff --git a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs index 657ff5333..b9439daaf 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs @@ -37,10 +37,10 @@ public void Setup() _mediaInfoAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())).Returns(AugmentQualityResult.ResolutionOnly((int)Resolution.R1080p, Confidence.MediaInfo)); _fileExtensionAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())) - .Returns(new AugmentQualityResult(Source.TV, Confidence.Fallback, (int)Resolution.R720p, Confidence.Fallback, Modifier.NONE, Confidence.Fallback, new Revision())); + .Returns(new AugmentQualityResult(Source.TV, Confidence.Fallback, (int)Resolution.R720p, Confidence.Fallback, Modifier.NONE, Confidence.Fallback, new Revision(), Confidence.Fallback)); _nameAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())) - .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, 480, Confidence.Default, Modifier.NONE, Confidence.Fallback, new Revision())); + .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, 480, Confidence.Default, Modifier.NONE, Confidence.Fallback, new Revision(), Confidence.Default)); _releaseNameAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())) .Returns(AugmentQualityResult.SourceOnly(Source.WEBDL, Confidence.MediaInfo)); @@ -114,5 +114,61 @@ public void should_return_WEBDL480p_when_file_name_has_HDTV480p_but_release_name result.Quality.ResolutionDetectionSource.Should().Be(QualityDetectionSource.Name); result.Quality.Quality.Should().Be(Quality.WEBDL480p); } + + [Test] + public void should_return_version_1_when_no_version_specified() + { + GivenAugmenters(_nameAugmenter, _releaseNameAugmenter); + + var result = Subject.Aggregate(new LocalMovie(), new DownloadClientItem(), false); + + result.Quality.Revision.Version.Should().Be(1); + result.Quality.RevisionDetectionSource.Should().Be(QualityDetectionSource.Unknown); + } + + [Test] + public void should_return_version_2_when_name_indicates_proper() + { + _nameAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())) + .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, 480, Confidence.Default, Modifier.NONE, Confidence.Default, new Revision(2), Confidence.Tag)); + + GivenAugmenters(_nameAugmenter, _releaseNameAugmenter); + + var result = Subject.Aggregate(new LocalMovie(), new DownloadClientItem(), false); + + result.Quality.Revision.Version.Should().Be(2); + result.Quality.RevisionDetectionSource.Should().Be(QualityDetectionSource.Name); + } + + [Test] + public void should_return_version_0_when_file_name_indicates_v0() + { + _nameAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())) + .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, 480, Confidence.Default, Modifier.NONE, Confidence.Default, new Revision(0), Confidence.Tag)); + + GivenAugmenters(_nameAugmenter, _releaseNameAugmenter); + + var result = Subject.Aggregate(new LocalMovie(), new DownloadClientItem(), false); + + result.Quality.Revision.Version.Should().Be(0); + result.Quality.RevisionDetectionSource.Should().Be(QualityDetectionSource.Name); + } + + [Test] + public void should_return_version_2_when_file_name_indicates_v0_and_release_name_indicates_v2() + { + _nameAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())) + .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, 480, Confidence.Default, Modifier.NONE, Confidence.Default, new Revision(0), Confidence.Tag)); + + _releaseNameAugmenter.Setup(s => s.AugmentQuality(It.IsAny(), It.IsAny())) + .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, 480, Confidence.Default, Modifier.NONE, Confidence.Default, new Revision(2), Confidence.Tag)); + + GivenAugmenters(_nameAugmenter, _releaseNameAugmenter); + + var result = Subject.Aggregate(new LocalMovie(), new DownloadClientItem(), false); + + result.Quality.Revision.Version.Should().Be(2); + result.Quality.RevisionDetectionSource.Should().Be(QualityDetectionSource.Name); + } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs index c7d1125d4..841b85da8 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs @@ -28,7 +28,8 @@ public LocalMovie Aggregate(LocalMovie localMovie, DownloadClientItem downloadCl var resolutionConfidence = Confidence.Default; var modifier = Modifier.NONE; var modifierConfidence = Confidence.Default; - var revision = new Revision(); + var revision = new Revision(1); + var revisionConfidence = Confidence.Default; foreach (var augmentQuality in _augmentQualities) { @@ -61,9 +62,24 @@ public LocalMovie Aggregate(LocalMovie localMovie, DownloadClientItem downloadCl modifierConfidence = augmentedQuality.ModifierConfidence; } - if (augmentedQuality.Revision != null && augmentedQuality.Revision > revision) + if (augmentedQuality.Revision != null) { - revision = augmentedQuality.Revision; + // Update the revision and confidence if it is higher than the current confidence, + // this will allow explicitly detected v0 to override the v1 default. + if (augmentedQuality.RevisionConfidence > revisionConfidence) + { + revision = augmentedQuality.Revision; + revisionConfidence = augmentedQuality.RevisionConfidence; + } + + // Update the revision and confidence if it is the same confidence and the revision is higher, + // this will allow the best revision to be used in the event there is a disagreement. + else if (augmentedQuality.RevisionConfidence == revisionConfidence && + augmentedQuality.Revision > revision) + { + revision = augmentedQuality.Revision; + revisionConfidence = augmentedQuality.RevisionConfidence; + } } } @@ -93,6 +109,8 @@ public LocalMovie Aggregate(LocalMovie localMovie, DownloadClientItem downloadCl quality.SourceDetectionSource = QualityDetectionSource.Name; } + quality.RevisionDetectionSource = revisionConfidence == Confidence.Tag ? QualityDetectionSource.Name : QualityDetectionSource.Unknown; + _logger.Debug("Using quality: {0}", quality); localMovie.Quality = quality; diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs index fc499f2fb..d1422a003 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs @@ -30,13 +30,18 @@ public AugmentQualityResult AugmentQuality(LocalMovie localMovie, DownloadClient ? Confidence.Tag : Confidence.Fallback; + var revisionConfidence = quality.RevisionDetectionSource == QualityDetectionSource.Name + ? Confidence.Tag + : Confidence.Fallback; + return new AugmentQualityResult(quality.Quality.Source, sourceConfidence, quality.Quality.Resolution, resolutionConfidence, quality.Quality.Modifier, modifierConfidence, - quality.Revision); + quality.Revision, + revisionConfidence); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs index 9bcec42e7..c661c014f 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs @@ -30,13 +30,18 @@ public AugmentQualityResult AugmentQuality(LocalMovie localMovie, DownloadClient ? Confidence.Tag : Confidence.Fallback; + var revisionConfidence = quality.RevisionDetectionSource == QualityDetectionSource.Name + ? Confidence.Tag + : Confidence.Fallback; + return new AugmentQualityResult(quality.Quality.Source, sourceConfidence, quality.Quality.Resolution, resolutionConfidence, quality.Quality.Modifier, modifierConfidence, - quality.Revision); + quality.Revision, + revisionConfidence); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs index be85f3c98..467acc741 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs @@ -30,13 +30,18 @@ public AugmentQualityResult AugmentQuality(LocalMovie localMovie, DownloadClient ? Confidence.Tag : Confidence.Fallback; + var revisionConfidence = quality.RevisionDetectionSource == QualityDetectionSource.Name + ? Confidence.Tag + : Confidence.Fallback; + return new AugmentQualityResult(quality.Quality.Source, sourceConfidence, quality.Quality.Resolution, resolutionConfidence, quality.Quality.Modifier, modifierConfidence, - quality.Revision); + quality.Revision, + revisionConfidence); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromReleaseName.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromReleaseName.cs index f5aa70acf..624ff785a 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromReleaseName.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromReleaseName.cs @@ -33,17 +33,24 @@ public AugmentQualityResult AugmentQuality(LocalMovie localMovie, DownloadClient } var historyQuality = QualityParser.ParseQuality(history.SourceTitle); + var sourceConfidence = historyQuality.SourceDetectionSource == QualityDetectionSource.Name ? Confidence.Tag : Confidence.Fallback; + var resolutionConfidence = historyQuality.ResolutionDetectionSource == QualityDetectionSource.Name ? Confidence.Tag : Confidence.Fallback; + var modifierConfidence = historyQuality.ModifierDetectionSource == QualityDetectionSource.Name ? Confidence.Tag : Confidence.Fallback; - return new AugmentQualityResult(historyQuality.Quality.Source, sourceConfidence, historyQuality.Quality.Resolution, resolutionConfidence, historyQuality.Quality.Modifier, modifierConfidence, historyQuality.Revision); + var revisionConfidence = historyQuality.RevisionDetectionSource == QualityDetectionSource.Name + ? Confidence.Tag + : Confidence.Fallback; + + return new AugmentQualityResult(historyQuality.Quality.Source, sourceConfidence, historyQuality.Quality.Resolution, resolutionConfidence, historyQuality.Quality.Modifier, modifierConfidence, historyQuality.Revision, revisionConfidence); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs index 144487702..872f4cff2 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs @@ -12,6 +12,7 @@ public class AugmentQualityResult public Modifier Modifier { get; set; } public Confidence ModifierConfidence { get; set; } public Revision Revision { get; set; } + public Confidence RevisionConfidence { get; set; } public AugmentQualityResult(Source source, Confidence sourceConfidence, @@ -19,7 +20,8 @@ public AugmentQualityResult(Source source, Confidence resolutionConfidence, Modifier modifier, Confidence modifierConfidence, - Revision revision) + Revision revision, + Confidence revisionConfidence) { Source = source; SourceConfidence = sourceConfidence; @@ -28,21 +30,22 @@ public AugmentQualityResult(Source source, Modifier = modifier; ModifierConfidence = modifierConfidence; Revision = revision; + RevisionConfidence = revisionConfidence; } public static AugmentQualityResult SourceOnly(Source source, Confidence sourceConfidence) { - return new AugmentQualityResult(source, sourceConfidence, 0, Confidence.Default, Modifier.NONE, Confidence.Default, null); + return new AugmentQualityResult(source, sourceConfidence, 0, Confidence.Default, Modifier.NONE, Confidence.Default, null, Confidence.Default); } public static AugmentQualityResult ResolutionOnly(int resolution, Confidence resolutionConfidence) { - return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, resolution, resolutionConfidence, Modifier.NONE, Confidence.Default, null); + return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, resolution, resolutionConfidence, Modifier.NONE, Confidence.Default, null, Confidence.Default); } public static AugmentQualityResult ModifierOnly(Modifier modifier, Confidence modifierConfidence) { - return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, 0, Confidence.Default, modifier, modifierConfidence, null); + return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, 0, Confidence.Default, modifier, modifierConfidence, null, Confidence.Default); } } } diff --git a/src/NzbDrone.Core/Parser/QualityParser.cs b/src/NzbDrone.Core/Parser/QualityParser.cs index 92afcf1a0..91a59ee93 100644 --- a/src/NzbDrone.Core/Parser/QualityParser.cs +++ b/src/NzbDrone.Core/Parser/QualityParser.cs @@ -666,12 +666,14 @@ private static QualityModel ParseQualityModifiers(string name, string normalized if (ProperRegex.IsMatch(normalizedName)) { result.Revision.Version = 2; + result.RevisionDetectionSource = QualityDetectionSource.Name; } if (RepackRegex.IsMatch(normalizedName)) { result.Revision.Version = 2; result.Revision.IsRepack = true; + result.RevisionDetectionSource = QualityDetectionSource.Name; } var versionRegexResult = VersionRegex.Match(normalizedName); @@ -679,6 +681,7 @@ private static QualityModel ParseQualityModifiers(string name, string normalized if (versionRegexResult.Success) { result.Revision.Version = Convert.ToInt32(versionRegexResult.Groups["version"].Value); + result.RevisionDetectionSource = QualityDetectionSource.Name; } // TODO: re-enable this when we have a reliable way to determine real @@ -688,6 +691,7 @@ private static QualityModel ParseQualityModifiers(string name, string normalized if (realRegexResult.Count > 0) { result.Revision.Real = realRegexResult.Count; + result.RevisionDetectionSource = QualityDetectionSource.Name; } return result; diff --git a/src/NzbDrone.Core/Qualities/QualityModel.cs b/src/NzbDrone.Core/Qualities/QualityModel.cs index 1bdb5a090..e5d9ef931 100644 --- a/src/NzbDrone.Core/Qualities/QualityModel.cs +++ b/src/NzbDrone.Core/Qualities/QualityModel.cs @@ -21,6 +21,9 @@ public class QualityModel : IEmbeddedDocument, IEquatable [JsonIgnore] public QualityDetectionSource ModifierDetectionSource { get; set; } + [JsonIgnore] + public QualityDetectionSource RevisionDetectionSource { get; set; } + public QualityModel() : this(Quality.Unknown, new Revision()) {