From 507e8ec81430c0ef54bb311550c70fc1a1b996a4 Mon Sep 17 00:00:00 2001
From: Qstick <qstick@gmail.com>
Date: Sun, 28 Nov 2021 01:38:04 -0600
Subject: [PATCH] New: Parse 960p as 720p instead of 480p, parse 540p

Fixes #6304
Fixes #6767
---
 .../ParserTests/QualityParserFixture.cs       |  3 +++
 src/NzbDrone.Core/Parser/QualityParser.cs     | 21 ++++++++++++++-----
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs
index e7332c930..4723ec554 100644
--- a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs
+++ b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs
@@ -87,6 +87,8 @@ namespace NzbDrone.Core.Test.ParserTests
         [TestCase("Movie.Name.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", false)]
         [TestCase("Movie.Name.S02E04.480p.WEB.DL.nSD.x264-NhaNc3", false)]
         [TestCase("[HorribleSubs] Movie Title! 2018 [Web][MKV][h264][480p][AAC 2.0][Softsubs (HorribleSubs)]", false)]
+        [TestCase("[SubsPlease] Movie Title (540p) [AB649D32].mkv", false)]
+        [TestCase("[Erai-raws] Movie Title [540p][Multiple Subtitle].mkv", false)]
         public void should_parse_webdl480p_quality(string title, bool proper)
         {
             ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R480p);
@@ -148,6 +150,7 @@ namespace NzbDrone.Core.Test.ParserTests
         [TestCase("Movie Name.S01E01.The.Insanity.Principle.720p.WEB-DL.DD5.1.H.264-BD", false)]
         [TestCase("[HorribleSubs] Movie Title! 2018 [Web][MKV][h264][720p][AAC 2.0][Softsubs (HorribleSubs)]", false)]
         [TestCase("[HorribleSubs] Movie Title! 2018 [Web][MKV][h264][AAC 2.0][Softsubs (HorribleSubs)]", false)]
+        [TestCase("Movie.Title.2013.960p.WEB-DL.AAC2.0.H.264-squalor", false)]
         public void should_parse_webdl720p_quality(string title, bool proper)
         {
             ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R720p);
diff --git a/src/NzbDrone.Core/Parser/QualityParser.cs b/src/NzbDrone.Core/Parser/QualityParser.cs
index 0c5775495..c71418dde 100644
--- a/src/NzbDrone.Core/Parser/QualityParser.cs
+++ b/src/NzbDrone.Core/Parser/QualityParser.cs
@@ -56,7 +56,7 @@ namespace NzbDrone.Core.Parser
         private static readonly Regex RealRegex = new Regex(@"\b(?<real>REAL)\b",
                                                                 RegexOptions.Compiled);
 
-        private static readonly Regex ResolutionRegex = new Regex(@"\b(?:(?<R360p>360p)|(?<R480p>480p|640x480|848x480)|(?<R576p>576p)|(?<R720p>720p|1280x720)|(?<R1080p>1080p|1920x1080|1440p|FHD|1080i|4kto1080p)|(?<R2160p>2160p|3840x2160|4k[-_. ](?:UHD|HEVC|BD|H265)|(?:UHD|HEVC|BD|H265)[-_. ]4k))\b",
+        private static readonly Regex ResolutionRegex = new Regex(@"\b(?:(?<R360p>360p)|(?<R480p>480p|640x480|848x480)|(?<R540p>540p)|(?<R576p>576p)|(?<R720p>720p|1280x720|960p)|(?<R1080p>1080p|1920x1080|1440p|FHD|1080i|4kto1080p)|(?<R2160p>2160p|3840x2160|4k[-_. ](?:UHD|HEVC|BD|H265)|(?:UHD|HEVC|BD|H265)[-_. ]4k))\b",
                                                                 RegexOptions.Compiled | RegexOptions.IgnoreCase);
 
         //Handle cases where no resolution is in the release name; assume if UHD then 4k
@@ -184,7 +184,8 @@ namespace NzbDrone.Core.Parser
                         return result;
                     }
 
-                    if (resolution == Resolution.R360p || resolution == Resolution.R480p)
+                    if (resolution == Resolution.R360p || resolution == Resolution.R480p ||
+                        resolution == Resolution.R540p)
                     {
                         result.Quality = Quality.Bluray480p;
                         return result;
@@ -397,7 +398,9 @@ namespace NzbDrone.Core.Parser
             {
                 result.SourceDetectionSource = QualityDetectionSource.Name;
 
-                if (resolution == Resolution.R360p || resolution == Resolution.R480p || resolution == Resolution.R576p || normalizedName.ContainsIgnoreCase("480p"))
+                if (resolution == Resolution.R360p || resolution == Resolution.R480p ||
+                    resolution == Resolution.R540p || resolution == Resolution.R576p ||
+                    normalizedName.ContainsIgnoreCase("480p"))
                 {
                     result.ResolutionDetectionSource = QualityDetectionSource.Name;
                     result.Quality = Quality.DVD;
@@ -434,7 +437,8 @@ namespace NzbDrone.Core.Parser
                 result.SourceDetectionSource = QualityDetectionSource.Name;
 
                 if (resolution == Resolution.R360p || resolution == Resolution.R480p ||
-                    resolution == Resolution.R576p || normalizedName.ContainsIgnoreCase("480p"))
+                    resolution == Resolution.R540p || resolution == Resolution.R576p ||
+                    normalizedName.ContainsIgnoreCase("480p"))
                 {
                     result.ResolutionDetectionSource = QualityDetectionSource.Name;
                     result.Quality = Quality.WEBDL480p;
@@ -524,7 +528,8 @@ namespace NzbDrone.Core.Parser
                     return result;
                 }
 
-                if (resolution == Resolution.R360p || resolution == Resolution.R480p)
+                if (resolution == Resolution.R360p || resolution == Resolution.R480p ||
+                    resolution == Resolution.R540p || resolution == Resolution.R576p)
                 {
                     result.ResolutionDetectionSource = QualityDetectionSource.Name;
 
@@ -657,6 +662,11 @@ namespace NzbDrone.Core.Parser
                 return Resolution.R480p;
             }
 
+            if (match.Groups["R540p"].Success)
+            {
+                return Resolution.R540p;
+            }
+
             if (match.Groups["R576p"].Success)
             {
                 return Resolution.R576p;
@@ -746,6 +756,7 @@ namespace NzbDrone.Core.Parser
         Unknown,
         R360p = 360,
         R480p = 480,
+        R540p = 540,
         R576p = 576,
         R720p = 720,
         R1080p = 1080,