diff --git a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs index 6882eadd6..960af009e 100644 --- a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs @@ -43,6 +43,11 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Series Title - S01E01 - Pilot.en.sub")] [TestCase("Series.Title.S01E01.SUBFRENCH.1080p.WEB.x264-GROUP")] [TestCase("[Judas] Series Japanese Name (Series English Name) - S02E10 [1080P][HEVC x256 10bit][Eng-Subs] (Weekly)")] + [TestCase("Detektiv.Conan.1996.S33E39.Ger.Eng.Sub.AAC.1080p.WEB.H264-WeebPinn")] + [TestCase("Detektiv.Conan.1996.S33E39.Ger.Eng.Fre.Sub.AAC.1080p.WEB.H264-WeebPinn")] + [TestCase("Detektiv.Conan.1996.S33E39.Ger.Fre.Eng.Sub.AAC.1080p.WEB.H264-WeebPinn")] + [TestCase("Detektiv.Conan.1996.S33E39.Ger.Eng.Spa.Sub.AAC.1080p.WEB.H264-WeebPinn")] + [TestCase("Detektiv.Conan.1996.S33E39.Ger.Spa.Eng.Sub.AAC.1080p.WEB.H264-WeebPinn")] public void should_parse_language_unknown(string postTitle) { var result = LanguageParser.ParseLanguages(postTitle); diff --git a/src/NzbDrone.Core/Parser/LanguageParser.cs b/src/NzbDrone.Core/Parser/LanguageParser.cs index d25c25e3c..c57f9f654 100644 --- a/src/NzbDrone.Core/Parser/LanguageParser.cs +++ b/src/NzbDrone.Core/Parser/LanguageParser.cs @@ -20,20 +20,22 @@ namespace NzbDrone.Core.Parser new RegexReplace(@".*?[_. ](S\d{2}(?:E\d{2,4})*[_. ].*)", "$1", RegexOptions.Compiled | RegexOptions.IgnoreCase) }; - private static readonly Regex LanguageRegex = new Regex(@"(?\b(?:ing|eng)(?![-_. ]subs?)\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\)|JAP|JPN)|(?[_. ]por[_. ])|(?\b(?:orig|original)\b)", + private static readonly Regex LanguagesOnlyRegex = new(@"(?\b(?:ing|eng)\b)|(?\b(?:ita|italian)\b)|(?(?:swiss)?german\b|videomann|ger[. ]dub|\bger\b)|(?flemish)|(?greek)|(?(?:_|\b)(?:FR|VF|VF2|VFF|VFI|VFQ|TRUEFRENCH|FRENCH|FRE|FRA)(?:_|\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\)|JAP|JPN)|(?[_. ]por[_. ])|(?\b(?:orig|original)\b)", RegexOptions.IgnoreCase | RegexOptions.Compiled); + + private static readonly Regex LanguageRegex = new(@$"(?:{LanguagesOnlyRegex})(?!(?:[-_. ](?:{LanguagesOnlyRegex}))*[-_. ]subs?)", 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))", + private static readonly Regex CaseSensitiveLanguageRegex = new(@"(?:(?i)(?\bLT\b)|(?\bCZ\b)|(?\bPL\b)|(?\bBG\b)|(?\bSK\b)|(?\bDE\b))(?:(?i)(?![\W|_|^]SUB))", RegexOptions.Compiled); private static readonly Regex GermanDualLanguageRegex = new(@"(?forced|foreign|default|cc|psdh|sdh))*[-_. ](?[a-z]{2,3})([-_. ](?forced|foreign|default|cc|psdh|sdh))*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex SubtitleLanguageRegex = new(".+?([-_. ](?forced|foreign|default|cc|psdh|sdh))*[-_. ](?[a-z]{2,3})([-_. ](?forced|foreign|default|cc|psdh|sdh))*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex SubtitleLanguageTitleRegex = new Regex(@".+?(\.((?forced|foreign|default|cc|psdh|sdh)|(?[a-z]{2,3})))*[-_. ](?[^.]*)(\.((?<tags2>forced|foreign|default|cc|psdh|sdh)|(?<iso_code>[a-z]{2,3})))*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex SubtitleLanguageTitleRegex = new(@".+?(\.((?<tags1>forced|foreign|default|cc|psdh|sdh)|(?<iso_code>[a-z]{2,3})))*[-_. ](?<title>[^.]*)(\.((?<tags2>forced|foreign|default|cc|psdh|sdh)|(?<iso_code>[a-z]{2,3})))*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex SubtitleTitleRegex = new Regex(@"^((?<title>.+) - )?(?<copy>(?<!\d+)\d{1,3}(?!\d+))$", RegexOptions.Compiled); + private static readonly Regex SubtitleTitleRegex = new(@"^((?<title>.+) - )?(?<copy>(?<!\d+)\d{1,3}(?!\d+))$", RegexOptions.Compiled); public static List<Language> ParseLanguages(string title) {