Fixed: Don't use language parsed from episode title during import

Closes #3893
This commit is contained in:
Mark McDowall 2020-08-02 12:42:38 -07:00
parent 5193f01c8c
commit 18708f30d9
5 changed files with 67 additions and 26 deletions

View File

@ -1,3 +1,4 @@
using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
@ -5,6 +6,7 @@ using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators; using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
{ {
@ -12,29 +14,35 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
public class AggregateLanguageFixture : CoreTest<AggregateLanguage> public class AggregateLanguageFixture : CoreTest<AggregateLanguage>
{ {
private LocalEpisode _localEpisode; private LocalEpisode _localEpisode;
private string _simpleReleaseTitle = "Series.Title.S01E01.xyz-RlsGroup";
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
var episodes = Builder<Episode>.CreateListOfSize(1)
.BuildList();
_localEpisode = Builder<LocalEpisode>.CreateNew() _localEpisode = Builder<LocalEpisode>.CreateNew()
.With(l => l.DownloadClientEpisodeInfo = null) .With(l => l.DownloadClientEpisodeInfo = null)
.With(l => l.FolderEpisodeInfo = null) .With(l => l.FolderEpisodeInfo = null)
.With(l => l.FileEpisodeInfo = null) .With(l => l.FileEpisodeInfo = null)
.With(l => l.Episodes = episodes)
.Build(); .Build();
} }
private ParsedEpisodeInfo GetParsedEpisodeInfo(Language language) private ParsedEpisodeInfo GetParsedEpisodeInfo(Language language, string releaseTitle)
{ {
return new ParsedEpisodeInfo return new ParsedEpisodeInfo
{ {
Language = language Language = language,
ReleaseTitle = releaseTitle
}; };
} }
[Test] [Test]
public void should_return_file_language_when_only_file_info_is_known() 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); Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FileEpisodeInfo.Language);
} }
@ -42,8 +50,8 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
[Test] [Test]
public void should_return_folder_language_when_folder_info_is_known() public void should_return_folder_language_when_folder_info_is_known()
{ {
_localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English); _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle);
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English); _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle);
Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FolderEpisodeInfo.Language); Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FolderEpisodeInfo.Language);
} }
@ -51,9 +59,9 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
[Test] [Test]
public void should_return_download_client_item_language_when_download_client_item_info_is_known() public void should_return_download_client_item_language_when_download_client_item_info_is_known()
{ {
_localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English); _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle);
_localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English); _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle);
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English); _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle);
Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.DownloadClientEpisodeInfo.Language); Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.DownloadClientEpisodeInfo.Language);
@ -62,11 +70,31 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
[Test] [Test]
public void should_return_file_language_when_file_language_is_higher_than_others() public void should_return_file_language_when_file_language_is_higher_than_others()
{ {
_localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English); _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle);
_localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English); _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English, _simpleReleaseTitle);
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.French); _localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.French, _simpleReleaseTitle);
Subject.Aggregate(_localEpisode, null, false).Language.Should().Be(_localEpisode.FileEpisodeInfo.Language); 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);
}
} }
} }

View File

@ -210,7 +210,6 @@ namespace NzbDrone.Core.Test.ParserTests
result.Language.Id.Should().Be(Language.Hebrew.Id); result.Language.Id.Should().Be(Language.Hebrew.Id);
} }
[TestCase("Prison.Break.S05E01.WEBRip.x264.AC3.LT.EN-CNN")] [TestCase("Prison.Break.S05E01.WEBRip.x264.AC3.LT.EN-CNN")]
public void should_parse_language_lithuanian(string postTitle) 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); result.Language.Id.Should().Be(Language.Lithuanian.Id);
} }
[TestCase("The.Walking.Dead.S07E11.WEB Rip.XviD.Louige-CZ.EN.5.1")] [TestCase("The.Walking.Dead.S07E11.WEB Rip.XviD.Louige-CZ.EN.5.1")]
public void should_parse_language_czech(string postTitle) 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); result.Language.Id.Should().Be(Language.Czech.Id);
} }
[TestCase("Russian.Puppets.S01E07.Cold.Action.HDTV.XviD-Droned")] [TestCase("Russian.Puppets.S01E07.Cold.Action.HDTV.XviD-Droned")]
[TestCase("Russian.Puppets.S01E07E08.Cold.Action.HDTV.XviD-Droned")] [TestCase("Russian.Puppets.S01E07E08.Cold.Action.HDTV.XviD-Droned")]
[TestCase("Russian.Puppets.S01.1080p.WEBRip.DDP5.1.x264-Drone")] [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); var result = Parser.Parser.ParseTitle(postTitle);
result.Language.Name.Should().Be(Language.English.Name); result.Language.Name.Should().Be(Language.English.Name);
} }
} }
} }

View File

@ -1,9 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Languages; using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators
{ {
@ -24,9 +27,9 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators
var languages = new List<Language> var languages = new List<Language>
{ {
GetLanguage(localEpisode.DownloadClientEpisodeInfo), GetLanguage(localEpisode.DownloadClientEpisodeInfo, localEpisode.Episodes),
GetLanguage(localEpisode.FolderEpisodeInfo), GetLanguage(localEpisode.FolderEpisodeInfo, localEpisode.Episodes),
GetLanguage(localEpisode.FileEpisodeInfo) GetLanguage(localEpisode.FileEpisodeInfo, localEpisode.Episodes)
}; };
var language = languages.FirstOrDefault(l => l != Language.English) ?? Language.English; var language = languages.FirstOrDefault(l => l != Language.English) ?? Language.English;
@ -38,15 +41,30 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators
return localEpisode; return localEpisode;
} }
private Language GetLanguage(ParsedEpisodeInfo parsedEpisodeInfo) private Language GetLanguage(ParsedEpisodeInfo parsedEpisodeInfo, List<Episode> episodes)
{ {
if (parsedEpisodeInfo == null) if (parsedEpisodeInfo == null)
{ {
// English is the default language when otherwise unknown
return Language.English; 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; return parsedEpisodeInfo.Language;
} }
} }

View File

@ -26,7 +26,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex SubtitleLanguageRegex = new Regex(".+?[-_. ](?<iso_code>[a-z]{2,3})$", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex SubtitleLanguageRegex = new Regex(".+?[-_. ](?<iso_code>[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) foreach (var regex in CleanSeriesTitleRegex)
{ {
@ -103,7 +103,7 @@ namespace NzbDrone.Core.Parser
return regexLanguage; return regexLanguage;
} }
return Language.English; return defaultToEnglish ? Language.English : Language.Unknown;
} }
public static Language ParseSubtitleLanguage(string fileName) public static Language ParseSubtitleLanguage(string fileName)

View File

@ -581,9 +581,8 @@ namespace NzbDrone.Core.Parser
public static string NormalizeEpisodeTitle(string title) public static string NormalizeEpisodeTitle(string title)
{ {
var match = SpecialEpisodeTitleRegex var match = SpecialEpisodeTitleRegex
.Select(v => v.Match(title)) .Select(v => v.Match(title))
.Where(v => v.Success) .FirstOrDefault(v => v.Success);
.FirstOrDefault();
if (match != null) if (match != null)
{ {