New: Parse episode numbers followed by '.5' as specials

Closes #5893
This commit is contained in:
Mark McDowall 2023-08-12 23:37:37 -07:00
parent 6245e8a552
commit c1442535b0
4 changed files with 30 additions and 0 deletions

View File

@ -194,6 +194,8 @@ namespace NzbDrone.Core.Test.ParserTests
result.SeasonNumber.Should().Be(seasonNumber); result.SeasonNumber.Should().Be(seasonNumber);
} }
[TestCase("[Anime Time] Series no Mayo - 12.5.mkv", "Series no Mayo", 12.5)]
[TestCase("[SubsPlease] Series Title - 26.5.1 (1080p) [29AF1C23].mkv", "Series Title", 26.5)]
[TestCase("[HorribleSubs] Show Slayer - 10.5 [1080p].mkv", "Show Slayer", 10.5)] [TestCase("[HorribleSubs] Show Slayer - 10.5 [1080p].mkv", "Show Slayer", 10.5)]
public void should_handle_anime_recap_numbering(string postTitle, string title, double specialEpisodeNumber) public void should_handle_anime_recap_numbering(string postTitle, string title, double specialEpisodeNumber)
{ {

View File

@ -193,5 +193,19 @@ namespace NzbDrone.Core.Test.ParserTests
result.AbsoluteEpisodeNumbers.Should().BeEmpty(); result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse(); result.FullSeason.Should().BeFalse();
} }
[TestCase("Series Title S01E11.5 [SP]-The Poppies Bloom Red on the Battlefield", "Series Title", 1, 11)]
public void should_parse_decimal_number_as_special(string postTitle, string title, int seasonNumber, int episodeNumber)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Should().NotBeNull();
result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(seasonNumber);
result.EpisodeNumbers.First().Should().Be(episodeNumber);
result.SeriesTitle.Should().Be(title);
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
result.Special.Should().BeTrue();
}
} }
} }

View File

@ -134,6 +134,10 @@ namespace NzbDrone.Core.Parser
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+(?<season>(?<!\d+)(?:\d{1,2}|\d{4})(?!\d+))(?:x{1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}", new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+(?<season>(?<!\d+)(?:\d{1,2}|\d{4})(?!\d+))(?:x{1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}",
RegexOptions.IgnoreCase | RegexOptions.Compiled), RegexOptions.IgnoreCase | RegexOptions.Compiled),
// Single episodes with a title (S01E05, 1x05, etc) followed by ".5 [SP]"
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)(?:\d{1,2})(?!\d+))(?:[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+|(?:[ex]|\W[ex]|_|-){1,2}\d+))(?<special>\.5[ .]\[SP\]))",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
// Single episodes with a title (S01E05, 1x05, etc) and trailing info in slashes // Single episodes with a title (S01E05, 1x05, etc) and trailing info in slashes
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)(?:\d{1,2})(?!\d+))(?:[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+|(?:[ex]|\W[ex]|_|-){1,2}\d+))).+?(?:\[.+?\])(?!\\)", new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)(?:\d{1,2})(?!\d+))(?:[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+|(?:[ex]|\W[ex]|_|-){1,2}\d+))).+?(?:\[.+?\])(?!\\)",
RegexOptions.IgnoreCase | RegexOptions.Compiled), RegexOptions.IgnoreCase | RegexOptions.Compiled),
@ -946,6 +950,11 @@ namespace NzbDrone.Core.Parser
result.EpisodeNumbers = Enumerable.Range(first, count).ToArray(); result.EpisodeNumbers = Enumerable.Range(first, count).ToArray();
lastSeasonEpisodeStringIndex = Math.Max(lastSeasonEpisodeStringIndex, episodeCaptures.Last().EndIndex()); lastSeasonEpisodeStringIndex = Math.Max(lastSeasonEpisodeStringIndex, episodeCaptures.Last().EndIndex());
if (matchGroup.Groups["special"].Success)
{
result.Special = true;
}
} }
if (absoluteEpisodeCaptures.Any()) if (absoluteEpisodeCaptures.Any())

View File

@ -265,6 +265,11 @@ namespace NzbDrone.Core.Parser
} }
} }
if (parsedEpisodeInfo.Special && mappedSeasonNumber != 0)
{
return new List<Episode>();
}
return GetStandardEpisodes(series, parsedEpisodeInfo, mappedSeasonNumber, sceneSource, searchCriteria); return GetStandardEpisodes(series, parsedEpisodeInfo, mappedSeasonNumber, sceneSource, searchCriteria);
} }