diff --git a/src/NzbDrone.Core.Test/ParserTests/MiniSeriesEpisodeParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/MiniSeriesEpisodeParserFixture.cs index 982eb61ae..0a4187518 100644 --- a/src/NzbDrone.Core.Test/ParserTests/MiniSeriesEpisodeParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/MiniSeriesEpisodeParserFixture.cs @@ -12,9 +12,9 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("The.Kennedys.Part.2.DSR.XviD-SYS", "The Kennedys", 2)] [TestCase("the-pacific-e07-720p", "the-pacific", 7)] [TestCase("Hatfields and McCoys 2012 Part 1 REPACK 720p HDTV x264 2HD", "Hatfields and McCoys 2012", 1)] - //[TestCase("Band.Of.Brothers.EP02.Day.Of.Days.DVDRiP.XviD-DEiTY", "Band.Of.Brothers", 2)] - //[TestCase("", "", 0, 0)] [TestCase("Mars.2016.E04.Power.720p.WEB-DL.DD5.1.H.264-MARS", "Mars 2016", 4)] + //[TestCase("Band.Of.Brothers.EP02.Day.Of.Days.DVDRiP.XviD-DEiTY", "Band.Of.Brothers", 2)] + //[TestCase("", "", 0)] public void should_parse_mini_series_episode(string postTitle, string title, int episodeNumber) { var result = Parser.Parser.ParseTitle(postTitle); @@ -26,5 +26,24 @@ namespace NzbDrone.Core.Test.ParserTests result.AbsoluteEpisodeNumbers.Should().BeEmpty(); result.FullSeason.Should().BeFalse(); } + + [TestCase("It's My Life.E56.190121.720p-NEXT.mp4", "It's My Life", 56, "2019-01-21")] + [TestCase("My Only One.E37.190120.1080p-NEXT.mp4", "My Only One", 37, "2019-01-20")] + [TestCase("Man.E191.190121.720p-NEXT.mp4", "Man",191, "2019-01-21")] + [TestCase("The Golden Bell Challenge.E932.190120.720p-NEXT.mp4", "The Golden Bell Challenge", 932, "2019-01-20")] + //[TestCase("", "", 0, "")] + public void should_parse_korean_series_episode(string postTitle, string title, int episodeNumber, string airdate) + { + var result = Parser.Parser.ParseTitle(postTitle); + result.Should().NotBeNull(); + result.EpisodeNumbers.Should().HaveCount(1); + result.SeasonNumber.Should().Be(1); + result.EpisodeNumbers.First().Should().Be(episodeNumber); + result.SeriesTitle.Should().Be(title); + result.AbsoluteEpisodeNumbers.Should().BeEmpty(); + result.FullSeason.Should().BeFalse(); + // We don't support both SxxExx and airdate yet + //result.AirDate.Should().Be(airdate); + } } } diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index b4243c611..9e40df9b2 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -785,6 +785,7 @@ + diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 1221a8808..4ffc20be3 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -17,6 +17,13 @@ namespace NzbDrone.Core.Parser { private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(Parser)); + private static readonly RegexReplace[] PreSubstitutionRegex = new[] + { + // Korean series without season number, replace with S01Exxx and remove airdate. + new RegexReplace(@"\.E(\d{2,4})\.\d{6}\.(.*-NEXT)$", ".S01E$1.$2", RegexOptions.Compiled), + + }; + private static readonly Regex[] ReportTitleRegex = new[] { //Anime - Absolute Episode Number + Title + Season+Episode @@ -383,6 +390,11 @@ namespace NzbDrone.Core.Parser var simpleTitle = SimpleTitleRegex.Replace(releaseTitle, string.Empty); + foreach (var replace in PreSubstitutionRegex) + { + simpleTitle = replace.Replace(simpleTitle); + } + // TODO: Quick fix stripping [url] - prefixes. simpleTitle = WebsitePrefixRegex.Replace(simpleTitle, string.Empty); diff --git a/src/NzbDrone.Core/Parser/RegexReplace.cs b/src/NzbDrone.Core/Parser/RegexReplace.cs new file mode 100644 index 000000000..04ddbc7cc --- /dev/null +++ b/src/NzbDrone.Core/Parser/RegexReplace.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace NzbDrone.Core.Parser +{ + public class RegexReplace + { + private readonly Regex _regex; + private readonly string _replacement; + + public RegexReplace(string pattern, string replacement, RegexOptions regexOptions) + { + _regex = new Regex(pattern, regexOptions); + _replacement = replacement; + } + + public string Replace(string input) + { + return _regex.Replace(input, _replacement); + } + } +}