Anime special fixes

Fixed: Parsing of special/OVA/OVD releases
Fixed: Handling of anime releases with season number of zero
This commit is contained in:
Mark McDowall 2014-08-11 19:44:26 -07:00
parent 904ee7dc23
commit 9e0c8a60b4
4 changed files with 68 additions and 7 deletions

View File

@ -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();
}
}
}

View File

@ -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<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
}
[Test]
public void should_use_scene_numbering_when_season_0_for_anime()
{
GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle))
.Returns(0);
Mocker.GetMock<IEpisodeService>()
.Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), 0, It.IsAny<Int32>()))
.Returns(new List<Episode>());
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), 0, It.IsAny<Int32>()), Times.Once());
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), 0, It.IsAny<Int32>()), 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<IEpisodeService>()
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), 0, It.IsAny<Int32>()), Times.Never());
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), 0, It.IsAny<Int32>()), Times.Once());
}
}
}

View File

@ -31,7 +31,7 @@ namespace NzbDrone.Core.Parser
RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Anime - [SubGroup] Title Absolute Episode Number
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)(?:[-_. ]+(?<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())

View File

@ -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);