Fixed: TheXEM mapping with one scene release to multiple tvdb episodes.

This commit is contained in:
Taloth Saldono 2018-03-09 22:41:10 +01:00
parent 940f59468a
commit e15530cee1
6 changed files with 97 additions and 33 deletions

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.DataAugmentation.Scene;
@ -117,6 +118,10 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
{
GivenAbsoluteNumberingSeries();
Mocker.GetMock<IEpisodeService>()
.Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<Episode>());
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>()
@ -253,7 +258,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
[TestCase(0)]
[TestCase(1)]
[TestCase(2)]
public void should_find_episode_by_season_and_absolute_episode_number_when_scene_absolute_episode_number_returns_multiple_results(int seasonNumber)
public void should_return_episodes_when_scene_absolute_episode_number_returns_multiple_results(int seasonNumber)
{
GivenAbsoluteNumberingSeries();
@ -265,6 +270,32 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
.Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny<int>(), seasonNumber, It.IsAny<int>()))
.Returns(Builder<Episode>.CreateListOfSize(5).Build().ToList());
var result = Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
result.Should().HaveCount(5);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<int>(), seasonNumber, It.IsAny<int>()), Times.Once());
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<int>(), seasonNumber, It.IsAny<int>()), Times.Never());
}
[TestCase(0)]
[TestCase(1)]
[TestCase(2)]
public void should_find_episode_by_season_and_absolute_episode_number_when_scene_absolute_episode_number_returns_no_results(int seasonNumber)
{
GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
.Returns(seasonNumber);
Mocker.GetMock<IEpisodeService>()
.Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny<int>(), seasonNumber, It.IsAny<int>()))
.Returns(Builder<Episode>.CreateListOfSize(0).Build().ToList());
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
Mocker.GetMock<IEpisodeService>()

View File

@ -31,7 +31,25 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
if (!criteriaEpisodes.Intersect(remoteEpisodes).Any())
{
_logger.Debug("Release rejected since the episode wasn't requested: {0}", remoteEpisode.ParsedEpisodeInfo);
return Decision.Reject("Episode wasn't requested");
if (remoteEpisodes.Any())
{
var episodes = remoteEpisode.Episodes.OrderBy(v => v.SeasonNumber).ThenBy(v => v.EpisodeNumber).ToList();
if (episodes.Count > 1)
{
return Decision.Reject($"Episode wasn't requested: {episodes.First().SeasonNumber}x{episodes.First().EpisodeNumber}-{episodes.Last().EpisodeNumber}");
}
else
{
return Decision.Reject($"Episode wasn't requested: {episodes.First().SeasonNumber}x{episodes.First().EpisodeNumber}");
}
}
else
{
return Decision.Reject("Episode wasn't requested");
}
}
return Decision.Accept();

View File

@ -25,8 +25,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
}
var singleEpisodeSpec = searchCriteria as SingleEpisodeSearchCriteria;
if (singleEpisodeSpec == null) return Decision.Accept();
if (singleEpisodeSpec != null) return IsSatisfiedBy(remoteEpisode, singleEpisodeSpec);
var animeEpisodeSpec = searchCriteria as AnimeEpisodeSearchCriteria;
if (animeEpisodeSpec != null) return IsSatisfiedBy(remoteEpisode, animeEpisodeSpec);
return Decision.Accept();
}
private Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SingleEpisodeSearchCriteria singleEpisodeSpec)
{
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
{
_logger.Debug("Season number does not match searched season number, skipping.");
@ -47,5 +55,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
return Decision.Accept();
}
private Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, AnimeEpisodeSearchCriteria singleEpisodeSpec)
{
if (remoteEpisode.ParsedEpisodeInfo.FullSeason)
{
_logger.Debug("Full season result during single episode search, skipping.");
return Decision.Reject("Full season pack");
}
return Decision.Accept();
}
}
}

View File

@ -363,13 +363,13 @@ namespace NzbDrone.Core.Parser
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
{
Episode episode = null;
var episodes = new List<Episode>();
if (parsedEpisodeInfo.Special)
{
episode = _episodeService.FindEpisode(series.Id, 0, absoluteEpisodeNumber);
var episode = _episodeService.FindEpisode(series.Id, 0, absoluteEpisodeNumber);
episodes.AddIfNotNull(episode);
}
else if (sceneSource)
{
// Is there a reason why we excluded season 1 from this handling before?
@ -377,31 +377,33 @@ namespace NzbDrone.Core.Parser
// If this needs to be reverted tests will need to be added
if (sceneSeasonNumber.HasValue)
{
var episodes = _episodeService.FindEpisodesBySceneNumbering(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);
episodes = _episodeService.FindEpisodesBySceneNumbering(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);
if (episodes.Count == 1)
if (episodes.Empty())
{
episode = episodes.First();
}
if (episode == null)
{
episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);
var episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);
episodes.AddIfNotNull(episode);
}
}
else
{
episode = _episodeService.FindEpisodeBySceneNumbering(series.Id, absoluteEpisodeNumber);
episodes = _episodeService.FindEpisodesBySceneNumbering(series.Id, absoluteEpisodeNumber);
// Don't allow multiple results without a scene name mapping.
if (episodes.Count > 1)
{
episodes.Clear();
}
}
}
if (episode == null)
if (episodes.Empty())
{
episode = _episodeService.FindEpisode(series.Id, absoluteEpisodeNumber);
var episode = _episodeService.FindEpisode(series.Id, absoluteEpisodeNumber);
episodes.AddIfNotNull(episode);
}
if (episode != null)
foreach (var episode in episodes)
{
_logger.Debug("Using absolute episode number {0} for: {1} - TVDB: {2}x{3:00}",
absoluteEpisodeNumber,

View File

@ -25,7 +25,7 @@ namespace NzbDrone.Core.Tv
PagingSpec<Episode> EpisodesWithoutFiles(PagingSpec<Episode> pagingSpec, bool includeSpecials);
PagingSpec<Episode> EpisodesWhereCutoffUnmet(PagingSpec<Episode> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff, bool includeSpecials);
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber);
Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
List<Episode> EpisodesBetweenDates(DateTime startDate, DateTime endDate, bool includeUnmonitored);
void SetMonitoredFlat(Episode episode, bool monitored);
void SetMonitoredBySeason(int seriesId, int seasonNumber, bool monitored);
@ -134,21 +134,15 @@ namespace NzbDrone.Core.Tv
{
return Query.Where(s => s.SeriesId == seriesId)
.AndWhere(s => s.SceneSeasonNumber == seasonNumber)
.AndWhere(s => s.SceneEpisodeNumber == episodeNumber);
.AndWhere(s => s.SceneEpisodeNumber == episodeNumber)
.ToList();
}
public Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber)
public List<Episode> FindEpisodesBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber)
{
var episodes = Query.Where(s => s.SeriesId == seriesId)
return Query.Where(s => s.SeriesId == seriesId)
.AndWhere(s => s.SceneAbsoluteEpisodeNumber == sceneAbsoluteEpisodeNumber)
.ToList();
if (episodes.Empty() || episodes.Count > 1)
{
return null;
}
return episodes.Single();
}
public List<Episode> EpisodesBetweenDates(DateTime startDate, DateTime endDate, bool includeUnmonitored)

View File

@ -19,7 +19,7 @@ namespace NzbDrone.Core.Tv
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle);
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber);
Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
Episode GetEpisode(int seriesId, string date);
Episode FindEpisode(int seriesId, string date);
List<Episode> GetEpisodeBySeries(int seriesId);
@ -78,9 +78,9 @@ namespace NzbDrone.Core.Tv
return _episodeRepository.FindEpisodesBySceneNumbering(seriesId, seasonNumber, episodeNumber);
}
public Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber)
public List<Episode> FindEpisodesBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber)
{
return _episodeRepository.FindEpisodeBySceneNumbering(seriesId, sceneAbsoluteEpisodeNumber);
return _episodeRepository.FindEpisodesBySceneNumbering(seriesId, sceneAbsoluteEpisodeNumber);
}
public Episode GetEpisode(int seriesId, string date)