From b6b53552615900f94c7396347b2b89b4786d5cbd Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 20 Aug 2015 22:50:26 -0700 Subject: [PATCH] New: support for REAL releases Closes #453 New: Added `Quality Real` naming Token New: Quality Full will add real to file name when applicable --- .../FileNameBuilderFixture.cs | 25 +++++++++++++++++++ .../ParserTests/ExtendedQualityParserRegex.cs | 10 ++++---- .../Organizer/FileNameBuilder.cs | 14 ++++++++++- src/NzbDrone.Core/Parser/QualityParser.cs | 20 +++++++-------- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs index 8794e55cd..3652bbbf2 100644 --- a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs @@ -57,6 +57,11 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests _episodeFile.Quality.Revision.Version = 2; } + private void GivenReal() + { + _episodeFile.Quality.Revision.Real = 1; + } + [Test] public void should_replace_Series_space_Title() { @@ -207,6 +212,16 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests .Should().Be("Proper"); } + [Test] + public void should_replace_quality_real_with_real() + { + _namingConfig.StandardEpisodeFormat = "{Quality Real}"; + GivenReal(); + + Subject.BuildFileName(new List { _episode1 }, _series, _episodeFile) + .Should().Be("REAL"); + } + [Test] public void should_replace_all_contents_in_pattern() { @@ -617,6 +632,16 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests .Should().Be("South Park - S15E06 [HDTV-720p Proper]"); } + [Test] + public void should_replace_quality_full_with_quality_title_and_real_when_a_real() + { + _namingConfig.StandardEpisodeFormat = "{Series Title} - S{season:00}E{episode:00} [{Quality Full}]"; + GivenReal(); + + Subject.BuildFileName(new List { _episode1 }, _series, _episodeFile) + .Should().Be("South Park - S15E06 [HDTV-720p REAL]"); + } + [TestCase(' ')] [TestCase('-')] [TestCase('.')] diff --git a/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs b/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs index 788b7b410..d6c52b43a 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs @@ -1,5 +1,4 @@ -using System; -using FluentAssertions; +using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Parser; using NzbDrone.Core.Test.Framework; @@ -14,18 +13,19 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Chuck.S03E17.REAL.PROPER.720p.HDTV.x264-ORENJI-RP", 1)] [TestCase("Covert.Affairs.S05E09.REAL.PROPER.HDTV.x264-KILLERS", 1)] [TestCase("Mythbusters.S14E01.REAL.PROPER.720p.HDTV.x264-KILLERS", 1)] - [TestCase("Orange.Is.the.New.Black.s02e06.real.proper.720p.webrip.x264-2hd", 1)] - [TestCase("Top.Gear.S21E07.Super.Duper.Real.Proper.HDTV.x264-FTP", 1)] + [TestCase("Orange.Is.the.New.Black.s02e06.real.proper.720p.webrip.x264-2hd", 0)] + [TestCase("Top.Gear.S21E07.Super.Duper.Real.Proper.HDTV.x264-FTP", 0)] [TestCase("Top.Gear.S21E07.PROPER.HDTV.x264-RiVER-RP", 0)] [TestCase("House.S07E11.PROPER.REAL.RERIP.1080p.BluRay.x264-TENEIGHTY", 1)] [TestCase("[MGS] - Kuragehime - Episode 02v2 - [D8B6C90D]", 0)] [TestCase("[Hatsuyuki] Tokyo Ghoul - 07 [v2][848x480][23D8F455].avi", 0)] [TestCase("[DeadFish] Barakamon - 01v3 [720p][AAC]", 0)] [TestCase("[DeadFish] Momo Kyun Sword - 01v4 [720p][AAC]", 0)] + [TestCase("The Real Housewives of Some Place - S01E01 - Why are we doing this?", 0)] public void should_parse_reality_from_title(string title, int reality) { //TODO: re-enable this when we have a reliable way to determine real - //QualityParser.ParseQuality(title).Revision.Real.Should().Be(reality); + QualityParser.ParseQuality(title).Revision.Real.Should().Be(reality); } [TestCase("Chuck.S04E05.HDTV.XviD-LOL", 1)] diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index e391ebb34..c0be11773 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -432,10 +432,12 @@ namespace NzbDrone.Core.Organizer { var qualityTitle = _qualityDefinitionService.Get(episodeFile.Quality.Quality).Title; var qualityProper = GetQualityProper(series, episodeFile.Quality); + var qualityReal = GetQualityReal(series, episodeFile.Quality); - tokenHandlers["{Quality Full}"] = m => string.Format("{0} {1}", qualityTitle, qualityProper); + tokenHandlers["{Quality Full}"] = m => String.Format("{0} {1} {2}", qualityTitle, qualityProper, qualityReal); tokenHandlers["{Quality Title}"] = m => qualityTitle; tokenHandlers["{Quality Proper}"] = m => qualityProper; + tokenHandlers["{Quality Real}"] = m => qualityReal; } private void AddMediaInfoTokens(Dictionary> tokenHandlers, EpisodeFile episodeFile) @@ -708,6 +710,16 @@ namespace NzbDrone.Core.Organizer return "Proper"; } + return String.Empty; + } + + private string GetQualityReal(Series series, QualityModel quality) + { + if (quality.Revision.Real > 0) + { + return "REAL"; + } + return string.Empty; } diff --git a/src/NzbDrone.Core/Parser/QualityParser.cs b/src/NzbDrone.Core/Parser/QualityParser.cs index 0be547684..81b3b28cc 100644 --- a/src/NzbDrone.Core/Parser/QualityParser.cs +++ b/src/NzbDrone.Core/Parser/QualityParser.cs @@ -35,8 +35,8 @@ namespace NzbDrone.Core.Parser private static readonly Regex VersionRegex = new Regex(@"\dv(?\d)\b|\[v(?\d)\]", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex RealRegex = new Regex(@"\b(?)real\b", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex RealRegex = new Regex(@"\b(?REAL)\b", + RegexOptions.Compiled); private static readonly Regex ResolutionRegex = new Regex(@"\b(?:(?<_480p>480p|640x480|848x480)|(?<_576p>576p)|(?<_720p>720p|1280x720)|(?<_1080p>1080p|1920x1080))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -56,7 +56,7 @@ namespace NzbDrone.Core.Parser name = name.Trim(); var normalizedName = name.Replace('_', ' ').Trim().ToLower(); - var result = ParseQualityModifiers(normalizedName); + var result = ParseQualityModifiers(name, normalizedName); if (RawHDRegex.IsMatch(normalizedName)) @@ -311,7 +311,7 @@ namespace NzbDrone.Core.Parser return Quality.Unknown; } - private static QualityModel ParseQualityModifiers(string normalizedName) + private static QualityModel ParseQualityModifiers(string name, string normalizedName) { var result = new QualityModel { Quality = Quality.Unknown }; @@ -329,12 +329,12 @@ namespace NzbDrone.Core.Parser //TODO: re-enable this when we have a reliable way to determine real //TODO: Only treat it as a real if it comes AFTER the season/epsiode number -// var realRegexResult = RealRegex.Matches(normalizedName); -// -// if (realRegexResult.Count > 0) -// { -// result.Revision.Real = realRegexResult.Count; -// } + var realRegexResult = RealRegex.Matches(name); + + if (realRegexResult.Count > 0) + { + result.Revision.Real = realRegexResult.Count; + } return result; }