diff --git a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs index 253528207..c43178f07 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs @@ -1,3 +1,4 @@ +using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; @@ -5,6 +6,7 @@ using NzbDrone.Core.Languages; using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators { @@ -12,29 +14,35 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators public class AggregateLanguageFixture : CoreTest { private LocalEpisode _localEpisode; + private string _simpleReleaseTitle = "Series.Title.S01E01.xyz-RlsGroup"; [SetUp] public void Setup() { + var episodes = Builder.CreateListOfSize(1) + .BuildList(); + _localEpisode = Builder.CreateNew() .With(l => l.DownloadClientEpisodeInfo = null) .With(l => l.FolderEpisodeInfo = null) .With(l => l.FileEpisodeInfo = null) + .With(l => l.Episodes = episodes) .Build(); } - private ParsedEpisodeInfo GetParsedEpisodeInfo(Language language) + private ParsedEpisodeInfo GetParsedEpisodeInfo(Language language, string releaseTitle) { return new ParsedEpisodeInfo { - Language = language + Language = language, + ReleaseTitle = releaseTitle }; } [Test] public void should_return_file_language_when_only_file_info_is_known() { - _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English); + _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FileEpisodeInfo.Language); } @@ -42,8 +50,8 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators [Test] public void should_return_folder_language_when_folder_info_is_known() { - _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English); - _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English); + _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); + _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FolderEpisodeInfo.Language); } @@ -51,9 +59,9 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators [Test] public void should_return_download_client_item_language_when_download_client_item_info_is_known() { - _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English); - _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English); - _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English); + _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); + _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); + _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.DownloadClientEpisodeInfo.Language); @@ -62,11 +70,31 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators [Test] public void should_return_file_language_when_file_language_is_higher_than_others() { - _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English); - _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English); - _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.French); + _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); + _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle); + _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.French, _simpleReleaseTitle); Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FileEpisodeInfo.Language); } + + [Test] + public void should_return_english_if_parsed_language_is_in_episode_title_and_release_title_contains_episode_title() + { + _localEpisode.Episodes.First().Title = "The Swedish Job"; + _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.Swedish, "Series.Title.S01E01.The.Swedish.Job.720p.WEB-DL-RlsGrp"); + + Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(Language.English); + + } + + [Test] + public void should_return_parsed_if_parsed_language_is_not_episode_title_and_release_title_contains_episode_title() + { + _localEpisode.Episodes.First().Title = "The Swedish Job"; + _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.French, "Series.Title.S01E01.The.Swedish.Job.720p.WEB-DL-RlsGrp"); + + Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FileEpisodeInfo.Language); + + } } } diff --git a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs index 471e80cf2..df01cca43 100644 --- a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs @@ -210,7 +210,6 @@ namespace NzbDrone.Core.Test.ParserTests result.Language.Id.Should().Be(Language.Hebrew.Id); } - [TestCase("Prison.Break.S05E01.WEBRip.x264.AC3.LT.EN-CNN")] public void should_parse_language_lithuanian(string postTitle) { @@ -218,7 +217,6 @@ namespace NzbDrone.Core.Test.ParserTests result.Language.Id.Should().Be(Language.Lithuanian.Id); } - [TestCase("The.​Walking.​Dead.​S07E11.​WEB Rip.​XviD.​Louige-​CZ.​EN.​5.​1")] public void should_parse_language_czech(string postTitle) { @@ -226,7 +224,6 @@ namespace NzbDrone.Core.Test.ParserTests result.Language.Id.Should().Be(Language.Czech.Id); } - [TestCase("Russian.Puppets.S01E07.Cold.Action.HDTV.XviD-Droned")] [TestCase("Russian.Puppets.S01E07E08.Cold.Action.HDTV.XviD-Droned")] [TestCase("Russian.Puppets.S01.1080p.WEBRip.DDP5.1.x264-Drone")] @@ -235,6 +232,5 @@ namespace NzbDrone.Core.Test.ParserTests var result = Parser.Parser.ParseTitle(postTitle); result.Language.Name.Should().Be(Language.English.Name); } - } } diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs index 34aebc34d..a25e3e75e 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs @@ -1,9 +1,12 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Download; using NzbDrone.Core.Languages; +using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Tv; namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators { @@ -24,9 +27,9 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators var languages = new List { - GetLanguage(localEpisode.DownloadClientEpisodeInfo), - GetLanguage(localEpisode.FolderEpisodeInfo), - GetLanguage(localEpisode.FileEpisodeInfo) + GetLanguage(localEpisode.DownloadClientEpisodeInfo, localEpisode.Episodes), + GetLanguage(localEpisode.FolderEpisodeInfo, localEpisode.Episodes), + GetLanguage(localEpisode.FileEpisodeInfo, localEpisode.Episodes) }; var language = languages.FirstOrDefault(l => l != Language.English) ?? Language.English; @@ -38,15 +41,30 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators return localEpisode; } - private Language GetLanguage(ParsedEpisodeInfo parsedEpisodeInfo) + private Language GetLanguage(ParsedEpisodeInfo parsedEpisodeInfo, List episodes) { if (parsedEpisodeInfo == null) { - // English is the default language when otherwise unknown - return Language.English; } + var normalizedReleaseTitle = Parser.Parser.NormalizeEpisodeTitle(parsedEpisodeInfo.ReleaseTitle); + + foreach (var episode in episodes) + { + var episodeTitleLanguage = LanguageParser.ParseLanguage(episode.Title, false); + + if (episodeTitleLanguage != Language.Unknown && episodeTitleLanguage == parsedEpisodeInfo.Language) + { + // Release title contains the episode title, return english instead of the parsed language. + + if (normalizedReleaseTitle.ContainsIgnoreCase(Parser.Parser.NormalizeEpisodeTitle(episode.Title))) + { + return Language.English; + } + } + } + return parsedEpisodeInfo.Language; } } diff --git a/src/NzbDrone.Core/Parser/LanguageParser.cs b/src/NzbDrone.Core/Parser/LanguageParser.cs index d3b535a66..4a768251a 100644 --- a/src/NzbDrone.Core/Parser/LanguageParser.cs +++ b/src/NzbDrone.Core/Parser/LanguageParser.cs @@ -26,7 +26,7 @@ namespace NzbDrone.Core.Parser private static readonly Regex SubtitleLanguageRegex = new Regex(".+?[-_. ](?[a-z]{2,3})$", RegexOptions.Compiled | RegexOptions.IgnoreCase); - public static Language ParseLanguage(string title) + public static Language ParseLanguage(string title, bool defaultToEnglish = true) { foreach (var regex in CleanSeriesTitleRegex) { @@ -103,7 +103,7 @@ namespace NzbDrone.Core.Parser return regexLanguage; } - return Language.English; + return defaultToEnglish ? Language.English : Language.Unknown; } public static Language ParseSubtitleLanguage(string fileName) diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index e2516330c..dddbef00c 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -581,9 +581,8 @@ namespace NzbDrone.Core.Parser public static string NormalizeEpisodeTitle(string title) { var match = SpecialEpisodeTitleRegex - .Select(v => v.Match(title)) - .Where(v => v.Success) - .FirstOrDefault(); + .Select(v => v.Match(title)) + .FirstOrDefault(v => v.Success); if (match != null) {