Fixed: TheXEM mapping with one scene release to multiple tvdb episodes.
This commit is contained in:
parent
940f59468a
commit
e15530cee1
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.DataAugmentation.Scene;
|
using NzbDrone.Core.DataAugmentation.Scene;
|
||||||
|
@ -117,6 +118,10 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||||
{
|
{
|
||||||
GivenAbsoluteNumberingSeries();
|
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);
|
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
|
@ -253,7 +258,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||||
[TestCase(0)]
|
[TestCase(0)]
|
||||||
[TestCase(1)]
|
[TestCase(1)]
|
||||||
[TestCase(2)]
|
[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();
|
GivenAbsoluteNumberingSeries();
|
||||||
|
|
||||||
|
@ -265,6 +270,32 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||||
.Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny<int>(), seasonNumber, It.IsAny<int>()))
|
.Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny<int>(), seasonNumber, It.IsAny<int>()))
|
||||||
.Returns(Builder<Episode>.CreateListOfSize(5).Build().ToList());
|
.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);
|
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
|
|
|
@ -31,7 +31,25 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
if (!criteriaEpisodes.Intersect(remoteEpisodes).Any())
|
if (!criteriaEpisodes.Intersect(remoteEpisodes).Any())
|
||||||
{
|
{
|
||||||
_logger.Debug("Release rejected since the episode wasn't requested: {0}", remoteEpisode.ParsedEpisodeInfo);
|
_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();
|
return Decision.Accept();
|
||||||
|
|
|
@ -25,8 +25,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
}
|
}
|
||||||
|
|
||||||
var singleEpisodeSpec = searchCriteria as SingleEpisodeSearchCriteria;
|
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)
|
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
|
||||||
{
|
{
|
||||||
_logger.Debug("Season number does not match searched season number, skipping.");
|
_logger.Debug("Season number does not match searched season number, skipping.");
|
||||||
|
@ -47,5 +55,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
|
|
||||||
return Decision.Accept();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,13 +363,13 @@ namespace NzbDrone.Core.Parser
|
||||||
|
|
||||||
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
|
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
|
||||||
{
|
{
|
||||||
Episode episode = null;
|
var episodes = new List<Episode>();
|
||||||
|
|
||||||
if (parsedEpisodeInfo.Special)
|
if (parsedEpisodeInfo.Special)
|
||||||
{
|
{
|
||||||
episode = _episodeService.FindEpisode(series.Id, 0, absoluteEpisodeNumber);
|
var episode = _episodeService.FindEpisode(series.Id, 0, absoluteEpisodeNumber);
|
||||||
|
episodes.AddIfNotNull(episode);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (sceneSource)
|
else if (sceneSource)
|
||||||
{
|
{
|
||||||
// Is there a reason why we excluded season 1 from this handling before?
|
// 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 this needs to be reverted tests will need to be added
|
||||||
if (sceneSeasonNumber.HasValue)
|
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();
|
var episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);
|
||||||
}
|
episodes.AddIfNotNull(episode);
|
||||||
|
|
||||||
if (episode == null)
|
|
||||||
{
|
|
||||||
episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
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}",
|
_logger.Debug("Using absolute episode number {0} for: {1} - TVDB: {2}x{3:00}",
|
||||||
absoluteEpisodeNumber,
|
absoluteEpisodeNumber,
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Core.Tv
|
||||||
PagingSpec<Episode> EpisodesWithoutFiles(PagingSpec<Episode> pagingSpec, bool includeSpecials);
|
PagingSpec<Episode> EpisodesWithoutFiles(PagingSpec<Episode> pagingSpec, bool includeSpecials);
|
||||||
PagingSpec<Episode> EpisodesWhereCutoffUnmet(PagingSpec<Episode> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff, bool includeSpecials);
|
PagingSpec<Episode> EpisodesWhereCutoffUnmet(PagingSpec<Episode> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff, bool includeSpecials);
|
||||||
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber);
|
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);
|
List<Episode> EpisodesBetweenDates(DateTime startDate, DateTime endDate, bool includeUnmonitored);
|
||||||
void SetMonitoredFlat(Episode episode, bool monitored);
|
void SetMonitoredFlat(Episode episode, bool monitored);
|
||||||
void SetMonitoredBySeason(int seriesId, int seasonNumber, 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)
|
return Query.Where(s => s.SeriesId == seriesId)
|
||||||
.AndWhere(s => s.SceneSeasonNumber == seasonNumber)
|
.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)
|
.AndWhere(s => s.SceneAbsoluteEpisodeNumber == sceneAbsoluteEpisodeNumber)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (episodes.Empty() || episodes.Count > 1)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return episodes.Single();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Episode> EpisodesBetweenDates(DateTime startDate, DateTime endDate, bool includeUnmonitored)
|
public List<Episode> EpisodesBetweenDates(DateTime startDate, DateTime endDate, bool includeUnmonitored)
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace NzbDrone.Core.Tv
|
||||||
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
|
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
|
||||||
Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle);
|
Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle);
|
||||||
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber);
|
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 GetEpisode(int seriesId, string date);
|
||||||
Episode FindEpisode(int seriesId, string date);
|
Episode FindEpisode(int seriesId, string date);
|
||||||
List<Episode> GetEpisodeBySeries(int seriesId);
|
List<Episode> GetEpisodeBySeries(int seriesId);
|
||||||
|
@ -78,9 +78,9 @@ namespace NzbDrone.Core.Tv
|
||||||
return _episodeRepository.FindEpisodesBySceneNumbering(seriesId, seasonNumber, episodeNumber);
|
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)
|
public Episode GetEpisode(int seriesId, string date)
|
||||||
|
|
Loading…
Reference in New Issue