diff --git a/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs index 6b72c48c8..6107308b5 100644 --- a/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs @@ -33,6 +33,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("2019_08_20_1080_all.mp4", "", 2019, 8, 20)] [TestCase("Series and Title 20201013 Ep7432 [720p WebRip (x264)] [SUBS]", "Series and Title", 2020, 10, 13)] [TestCase("Series Title (1955) - 1954-01-23 05 00 00 - Cottage for Sale.ts", "Series Title (1955)", 1954, 1, 23)] + [TestCase("Series Title - 30-04-2024 HDTV 1080p H264 AAC", "Series Title", 2024, 4, 30)] // [TestCase("", "", 0, 0, 0)] public void should_parse_daily_episode(string postTitle, string title, int year, int month, int day) @@ -100,5 +101,13 @@ namespace NzbDrone.Core.Test.ParserTests Parser.Parser.ParseTitle(title).Should().BeNull(); } + + [TestCase("Tmc - Quotidien - 05-06-2024 HDTV 1080p H264 AAC")] + + // [TestCase("", "", 0, 0, 0)] + public void should_not_parse_ambiguous_daily_episode(string postTitle) + { + Parser.Parser.ParseTitle(postTitle).Should().BeNull(); + } } } diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index fb483a4a2..9fbe43b7a 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -339,7 +339,7 @@ namespace NzbDrone.Core.Parser // 4 digit episode number // Episodes with a title, Single episodes (S01E05, 1x05, etc) & Multi-episode (S01E05E06, S01E05-06, S01E05 E06, etc) - new Regex(@"^(?.+?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)\W?(?!\\)", + new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]|\d{1,2}-))+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)\W?(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), // Episodes with airdate (2018.04.28) @@ -350,7 +350,11 @@ namespace NzbDrone.Core.Parser new Regex(@"^(?<title>.+?)[_. ](?<absoluteepisode>\d{1,4})(?:[_. ]+)(?:BLM|B[oö]l[uü]m)", RegexOptions.IgnoreCase | RegexOptions.Compiled), // Episodes with airdate (04.28.2018) - new Regex(@"^(?<title>.+?)?\W*(?<airmonth>[0-1][0-9])[-_. ]+(?<airday>[0-3][0-9])[-_. ]+(?<airyear>\d{4})(?!\d+)", + new Regex(@"^(?<title>.+?)?\W*(?<ambiguousairmonth>[0-1][0-9])[-_. ]+(?<ambiguousairday>[0-3][0-9])[-_. ]+(?<airyear>\d{4})(?!\d+)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + // Episodes with airdate (28.04.2018) + new Regex(@"^(?<title>.+?)?\W*(?<ambiguousairday>[0-3][0-9])[-_. ]+(?<ambiguousairmonth>[0-1][0-9])[-_. ]+(?<airyear>\d{4})(?!\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled), // Episodes with airdate (20180428) @@ -362,7 +366,7 @@ namespace NzbDrone.Core.Parser RegexOptions.IgnoreCase | RegexOptions.Compiled), // Supports 1103/1113 naming - new Regex(@"^(?<title>.+?)?(?:(?:[-_. ](?<![()\[!]))*(?<season>(?<!\d+|\(|\[|e|x)\d{2})(?<episode>(?<!e|x)(?:[1-9][0-9]|[0][1-9])(?!p|i|\d+|\)|\]|\W\d+|\W(?:e|ep|x)\d+)))+([-_. ]+|$)(?!\\)", + new Regex(@"^(?<title>.+?)?(?:(?:[-_. ](?<![()\[!]))*(?<!\d{1,2}-)(?<season>(?<!\d+|\(|\[|e|x)\d{2})(?<episode>(?<!e|x)(?:[1-9][0-9]|[0][1-9])(?!p|i|\d+|\)|\]|\W\d+|\W(?:e|ep|x)\d+)))+([-_. ]+|$)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), // Dutch/Flemish release titles @@ -1128,15 +1132,36 @@ namespace NzbDrone.Core.Parser else { // Try to Parse as a daily show - var airmonth = Convert.ToInt32(matchCollection[0].Groups["airmonth"].Value); - var airday = Convert.ToInt32(matchCollection[0].Groups["airday"].Value); - // Swap day and month if month is bigger than 12 (scene fail) - if (airmonth > 12) + var airmonth = 0; + var airday = 0; + + if (matchCollection[0].Groups["ambiguousairmonth"].Success && + matchCollection[0].Groups["ambiguousairday"].Success) { - var tempDay = airday; - airday = airmonth; - airmonth = tempDay; + var ambiguousAirMonth = Convert.ToInt32(matchCollection[0].Groups["ambiguousairmonth"].Value); + var ambiguousAirDay = Convert.ToInt32(matchCollection[0].Groups["ambiguousairday"].Value); + + if (ambiguousAirDay <= 12 && ambiguousAirMonth <= 12) + { + throw new InvalidDateException("Ambiguous Date, cannot validate month and day with {0} and {1}", ambiguousAirMonth, ambiguousAirDay); + } + + airmonth = ambiguousAirMonth; + airday = ambiguousAirDay; + } + else + { + airmonth = Convert.ToInt32(matchCollection[0].Groups["airmonth"].Value); + airday = Convert.ToInt32(matchCollection[0].Groups["airday"].Value); + + // Swap day and month if month is bigger than 12 (scene fail) + if (airmonth > 12) + { + var tempDay = airday; + airday = airmonth; + airmonth = tempDay; + } } DateTime airDate;