diff --git a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs index 0c5b373f4..708e48c4e 100644 --- a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs @@ -175,6 +175,7 @@ public void should_parse_language_icelandic(string postTitle) [TestCase("[abc] My Series - 01 [简繁内封字幕]")] [TestCase("[ABC字幕组] My Series - 01 [HDTV]")] [TestCase("[喵萌奶茶屋&LoliHouse] 拳愿阿修罗 / Kengan Ashura - 17 [WebRip 1080p HEVC-10bit AAC][中日双语字幕]")] + [TestCase("Series.Towards.You.S01.国语音轨.2023.1080p.NF.WEB-DL.H264.DDP2.0-SeeWEB")] public void should_parse_language_chinese(string postTitle) { var result = LanguageParser.ParseLanguages(postTitle); diff --git a/src/NzbDrone.Core.Test/ParserTests/UnicodeReleaseParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/UnicodeReleaseParserFixture.cs index f9b8c44a3..2e3a3583b 100644 --- a/src/NzbDrone.Core.Test/ParserTests/UnicodeReleaseParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/UnicodeReleaseParserFixture.cs @@ -147,5 +147,33 @@ public void should_parse_false_positive_chinese_anime_releases(string postTitle, result.SeriesTitle.Should().Be(title); result.FullSeason.Should().BeFalse(); } + + [TestCase("【高清剧集网发布 www.DDHDTV.com】当我飞奔向你[全24集][国语音轨+简繁英字幕].Series.Towards.You.S01.2023.1080p.NF.WEB-DL.H264.DDP2.0-SeeWEB", "Series Towards You", "SeeWEB", 1)] + public void should_parse_full_season_releases(string postTitle, string title, string releaseGroup, int season) + { + postTitle = XmlCleaner.ReplaceUnicode(postTitle); + + var result = Parser.Parser.ParseTitle(postTitle); + result.Should().NotBeNull(); + result.ReleaseGroup.Should().Be(releaseGroup); + result.EpisodeNumbers.Should().BeEmpty(); + result.AbsoluteEpisodeNumbers.Should().BeEmpty(); + result.SeriesTitle.Should().Be(title); + result.FullSeason.Should().BeTrue(); + result.SeasonNumber.Should().Be(season); + } + + [TestCase("【高清剧集网发布 www.DDHDTV.com】当我飞奔向你[第01-15集][国语配音+中文字幕].Series.Towards.You.S01.2023.2160p.YK.WEB-DL.H265.AAC-BlackTV", "Series Towards You", "BlackTV", 1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 })] + public void should_parse_multi_episode_release(string postTitle, string title, string releaseGroup, int season, int[] episodes) + { + postTitle = XmlCleaner.ReplaceUnicode(postTitle); + + var result = Parser.Parser.ParseTitle(postTitle); + result.SeasonNumber.Should().Be(season); + result.EpisodeNumbers.Should().BeEquivalentTo(episodes); + result.SeriesTitle.Should().Be(title); + result.AbsoluteEpisodeNumbers.Should().BeEmpty(); + result.FullSeason.Should().BeFalse(); + } } } diff --git a/src/NzbDrone.Core/Parser/LanguageParser.cs b/src/NzbDrone.Core/Parser/LanguageParser.cs index fc99c0787..8e5e445a8 100644 --- a/src/NzbDrone.Core/Parser/LanguageParser.cs +++ b/src/NzbDrone.Core/Parser/LanguageParser.cs @@ -20,7 +20,7 @@ public static class LanguageParser new RegexReplace(@".*?[_. ](S\d{2}(?:E\d{2,4})*[_. ].*)", "$1", RegexOptions.Compiled | RegexOptions.IgnoreCase) }; - private static readonly Regex LanguageRegex = new Regex(@"(?\b(?:ing|eng)\b)|(?\b(?:ita|italian)\b)|(?(?:swiss)?german\b|videomann|ger[. ]dub|\bger\b)|(?flemish)|(?greek)|(?(?:\W|_|\b)(?:FR|VF|VF2|VFF|VFI|VFQ|TRUEFRENCH|FRENCH|FRE|FRA)(?:\W|_|\b))|(?\b(?:rus|ru)\b)|(?\b(?:HUNDUB|HUN)\b)|(?\bHebDub\b)|(?\b(?:PL\W?DUB|DUB\W?PL|LEK\W?PL|PL\W?LEK)\b)|(?\[(?:CH[ST]|BIG5|GB)\]|简|繁|字幕)|(?\bbgaudio\b)|(?\b(?:español|castellano|esp|spa(?!\(Latino\)))\b)|(?\b(?:\dx?)?(?:ukr))|(?\b(?:THAI)\b)|(?\b(?:RoDubbed|ROMANIAN)\b)|(?[-,. ]cat[. ](?:DD|subs)|\b(?:catalan|catalán)\b)|(?\b(?:lat|lav|lv)\b)|(?\b(?:tur)\b)|(?\burdu\b)|(?\b(?:romansh|rumantsch|romansch)\b)|(?\b(?:geo|ka|kat|georgian)\b)|(?\(JA\))|(?\b(?:orig|original)\b)", + private static readonly Regex LanguageRegex = new Regex(@"(?\b(?:ing|eng)\b)|(?\b(?:ita|italian)\b)|(?(?:swiss)?german\b|videomann|ger[. ]dub|\bger\b)|(?flemish)|(?greek)|(?(?:\W|_|\b)(?:FR|VF|VF2|VFF|VFI|VFQ|TRUEFRENCH|FRENCH|FRE|FRA)(?:\W|_|\b))|(?\b(?:rus|ru)\b)|(?\b(?:HUNDUB|HUN)\b)|(?\bHebDub\b)|(?\b(?:PL\W?DUB|DUB\W?PL|LEK\W?PL|PL\W?LEK)\b)|(?\[(?:CH[ST]|BIG5|GB)\]|简|繁|字幕|国语音轨[.+])|(?\bbgaudio\b)|(?\b(?:español|castellano|esp|spa(?!\(Latino\)))\b)|(?\b(?:\dx?)?(?:ukr))|(?\b(?:THAI)\b)|(?\b(?:RoDubbed|ROMANIAN)\b)|(?[-,. ]cat[. ](?:DD|subs)|\b(?:catalan|catalán)\b)|(?\b(?:lat|lav|lv)\b)|(?\b(?:tur)\b)|(?\burdu\b)|(?\b(?:romansh|rumantsch|romansch)\b)|(?\b(?:geo|ka|kat|georgian)\b)|(?\(JA\))|(?\b(?:orig|original)\b)", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex CaseSensitiveLanguageRegex = new Regex(@"(?:(?i)(?\bLT\b)|(?\bCZ\b)|(?\bPL\b)|(?\bBG\b)|(?\bSK\b)|(?\bDE\b))(?:(?i)(?![\W|_|^]SUB))", diff --git a/src/NzbDrone.Core/Parser/ParserCommon.cs b/src/NzbDrone.Core/Parser/ParserCommon.cs index 71ae8ad49..4e3b56f3c 100644 --- a/src/NzbDrone.Core/Parser/ParserCommon.cs +++ b/src/NzbDrone.Core/Parser/ParserCommon.cs @@ -23,6 +23,12 @@ internal static class ParserCommon // Some Chinese releases don't include a separation between Chinese and English titles within the same bracketed group new RegexReplace(@"^\[(?[^\]]+)\]\[(?(?[^\]]+?)\](?:\[\d{4}\])?\[第?(?[0-9]+(?:-[0-9]+)?)(?:话|集)?(?: ?END|完| ?Fin)?\]", "[${subgroup}] ${title} - ${episode} ", RegexOptions.Compiled), + // Chinese season packs, that may not actually have the full season so treated as multi-episode + new RegexReplace(@"^\[(?[^\]]+)\](?:\s?★[^\[ -]+\s?)?\[?(?:(?(?=[^\]]*?[\u4E00-\u9FCC])[^\]]*?)(?:\]\[|\s*[_/·]\s*)){0,2}(?[^\]]+?)\]?(?:\[\d{4}\])?\[(?:第|全)?(?<episode>[0-9]{1,4}-[0-9]{1,4})(?:话|集)?\](?:\[(?<language>.+?)\+.+?\])[_. ](?<title>.+?)S(?<season>[0-9]{1,2})(?<rest>.+?)$", "${title}S${season}E${episode}.${language}${rest}", RegexOptions.Compiled), + + // Chinese season packs, that actually have the full season so treated as multi-episode + new RegexReplace(@"^\[(?<subgroup>[^\]]+)\](?:\s?★[^\[ -]+\s?)?\[?(?:(?<chinesetitle>(?=[^\]]*?[\u4E00-\u9FCC])[^\]]*?)(?:\]\[|\s*[_/·]\s*)){0,2}(?<title>[^\]]+?)\]?(?:\[\d{4}\])?\[(?:全)?(?<episode>[0-9]{1,4})(?:话|集)?\](?:\[(?<language>.+?)\+.+?\])[_. ](?<title>.+?)S(?<season>[0-9]{1,2})(?<rest>.+?)$", "${title}S${season}.${language}${rest}", RegexOptions.Compiled), + // Most Chinese anime releases contain additional brackets/separators for chinese and non-chinese titles, remove junk and replace with normal anime pattern new RegexReplace(@"^\[(?<subgroup>[^\]]+)\](?:\s?★[^\[ -]+\s?)?\[?(?:(?<chinesetitle>(?=[^\]]*?[\u4E00-\u9FCC])[^\]]*?)(?:\]\[|\s*[_/·]\s*)){0,2}(?<title>[^\]]+?)\]?(?:\[\d{4}\])?\[第?(?<episode>[0-9]{1,4}(?:-[0-9]{1,4})?)(?:话|集)?(?: ?END|完| ?Fin)?\]", "[${subgroup}] ${title} - ${episode} ", RegexOptions.Compiled),