From 9e0c8a60b43e4ae2c86618064cc076ae6acba420 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 11 Aug 2014 19:44:26 -0700 Subject: [PATCH] Anime special fixes Fixed: Parsing of special/OVA/OVD releases Fixed: Handling of anime releases with season number of zero --- .../AbsoluteEpisodeNumberParserFixture.cs | 15 +++++++ .../ParsingServiceTests/GetEpisodesFixture.cs | 39 +++++++++++++++++++ src/NzbDrone.Core/Parser/Parser.cs | 9 ++++- src/NzbDrone.Core/Parser/ParsingService.cs | 12 +++--- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/NzbDrone.Core.Test/ParserTests/AbsoluteEpisodeNumberParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/AbsoluteEpisodeNumberParserFixture.cs index 9abb28e58..712eaf3b5 100644 --- a/src/NzbDrone.Core.Test/ParserTests/AbsoluteEpisodeNumberParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/AbsoluteEpisodeNumberParserFixture.cs @@ -76,5 +76,20 @@ namespace NzbDrone.Core.Test.ParserTests result.SeriesTitle.Should().Be(title.CleanSeriesTitle()); result.FullSeason.Should().BeFalse(); } + + [TestCase("[DeadFish] Kenzen Robo Daimidaler - 01 - Special [BD][720p][AAC]", "Kenzen Robo Daimidaler", 1)] + [TestCase("[DeadFish] Kenzen Robo Daimidaler - 01 - OVA [BD][720p][AAC]", "Kenzen Robo Daimidaler", 1)] + [TestCase("[DeadFish] Kenzen Robo Daimidaler - 01 - OVD [BD][720p][AAC]", "Kenzen Robo Daimidaler", 1)] + public void should_parse_absolute_specials(String postTitle, String title, Int32 absoluteEpisodeNumber) + { + var result = Parser.Parser.ParseTitle(postTitle); + result.Should().NotBeNull(); + result.AbsoluteEpisodeNumbers.Single().Should().Be(absoluteEpisodeNumber); + result.SeasonNumber.Should().Be(0); + result.EpisodeNumbers.SingleOrDefault().Should().Be(0); + result.SeriesTitle.Should().Be(title.CleanSeriesTitle()); + result.FullSeason.Should().BeFalse(); + result.Special.Should().BeTrue(); + } } } diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs index d6b0b83eb..4c621baa9 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs @@ -4,6 +4,7 @@ using System.Linq; using FizzWare.NBuilder; using Moq; using NUnit.Framework; +using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; @@ -184,5 +185,43 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests Mocker.GetMock() .Verify(v => v.FindEpisode(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once()); } + + [Test] + public void should_use_scene_numbering_when_season_0_for_anime() + { + GivenAbsoluteNumberingSeries(); + + Mocker.GetMock() + .Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) + .Returns(0); + + Mocker.GetMock() + .Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny(), 0, It.IsAny())) + .Returns(new List()); + + Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null); + + Mocker.GetMock() + .Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny(), 0, It.IsAny()), Times.Once()); + + Mocker.GetMock() + .Verify(v => v.FindEpisode(It.IsAny(), 0, It.IsAny()), Times.Once()); + } + + [Test] + public void should_look_for_episode_in_season_zero_if_absolute_special() + { + GivenAbsoluteNumberingSeries(); + + _parsedEpisodeInfo.Special = true; + + Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null); + + Mocker.GetMock() + .Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny(), 0, It.IsAny()), Times.Never()); + + Mocker.GetMock() + .Verify(v => v.FindEpisode(It.IsAny(), 0, It.IsAny()), Times.Once()); + } } } diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 70ec1e610..d1306ae51 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Parser RegexOptions.IgnoreCase | RegexOptions.Compiled), //Anime - [SubGroup] Title Absolute Episode Number - new Regex(@"^\[(?.+?)\][-_. ]?(?.+?)(?:[-_. ]+(?<absoluteepisode>\d{2,}))+.*?(?<hash>\[[a-z0-9]{8}\])?(?:$|\.mkv)", + new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)(?:[-_. ]+(?<absoluteepisode>\d{2,}))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[[a-z0-9]{8}\])?(?:$|\.mkv)", RegexOptions.IgnoreCase | RegexOptions.Compiled), //Multi-Part episodes without a title (S01E05.S01E06) @@ -59,7 +59,7 @@ namespace NzbDrone.Core.Parser RegexOptions.IgnoreCase | RegexOptions.Compiled), //Anime - Title Absolute Episode Number Hash - new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{2,3}))+.*?(?<hash>\[.{8}\])(?:$|\.)", + new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{2,3}))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[.{8}\])(?:$|\.)", RegexOptions.IgnoreCase | RegexOptions.Compiled), //Supports 103/113 naming @@ -443,6 +443,11 @@ namespace NzbDrone.Core.Parser var count = last - first + 1; result.AbsoluteEpisodeNumbers = Enumerable.Range(first, count).ToArray(); + + if (matchGroup.Groups["special"].Success) + { + result.Special = true; + } } if (!episodeCaptures.Any() && !absoluteEpisodeCaptures.Any()) diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs index d39a53064..ebe85906d 100644 --- a/src/NzbDrone.Core/Parser/ParsingService.cs +++ b/src/NzbDrone.Core/Parser/ParsingService.cs @@ -27,19 +27,16 @@ namespace NzbDrone.Core.Parser private readonly IEpisodeService _episodeService; private readonly ISeriesService _seriesService; private readonly ISceneMappingService _sceneMappingService; - private readonly IDiskProvider _diskProvider; private readonly Logger _logger; public ParsingService(IEpisodeService episodeService, ISeriesService seriesService, ISceneMappingService sceneMappingService, - IDiskProvider diskProvider, Logger logger) { _episodeService = episodeService; _seriesService = seriesService; _sceneMappingService = sceneMappingService; - _diskProvider = diskProvider; _logger = logger; } @@ -158,9 +155,14 @@ namespace NzbDrone.Core.Parser { Episode episode = null; - if (sceneSource) + if (parsedEpisodeInfo.Special) { - if (sceneSeasonNumber.HasValue && sceneSeasonNumber > 1) + episode = _episodeService.FindEpisode(series.Id, 0, absoluteEpisodeNumber); + } + + else if (sceneSource) + { + if (sceneSeasonNumber.HasValue && (sceneSeasonNumber == 0 || sceneSeasonNumber > 1)) { var episodes = _episodeService.FindEpisodesBySceneNumbering(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);