diff --git a/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs b/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs index 366f7e3ba..2e33bc4d7 100644 --- a/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs +++ b/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs @@ -201,6 +201,121 @@ public void should_return_single_match(string parseTitle, string title, int expe seasonNumber.Should().Be(expectedSeasonNumber); } + [Test] + public void should_return_alternate_title_for_global_season() + { + var mappings = new List + { + new SceneMapping { Title = "Fudanshi Koukou Seikatsu 1", ParseTerm = "fudanshikoukouseikatsu1", SearchTerm = "Fudanshi Koukou Seikatsu 1", TvdbId = 100, SeasonNumber = null, SceneSeasonNumber = null }, + new SceneMapping { Title = "Fudanshi Koukou Seikatsu 2", ParseTerm = "fudanshikoukouseikatsu2", SearchTerm = "Fudanshi Koukou Seikatsu 2", TvdbId = 100, SeasonNumber = -1, SceneSeasonNumber = null }, + new SceneMapping { Title = "Fudanshi Koukou Seikatsu 3", ParseTerm = "fudanshikoukouseikatsu3", SearchTerm = "Fudanshi Koukou Seikatsu 3", TvdbId = 100, SeasonNumber = null, SceneSeasonNumber = -1 }, + new SceneMapping { Title = "Fudanshi Koukou Seikatsu 4", ParseTerm = "fudanshikoukouseikatsu4", SearchTerm = "Fudanshi Koukou Seikatsu 4", TvdbId = 100, SeasonNumber = -1, SceneSeasonNumber = -1 }, + }; + + Mocker.GetMock().Setup(c => c.All()).Returns(mappings); + + var names = Subject.GetSceneNames(100, new List { 10 }, new List { 10 }); + names.Should().HaveCount(4); + } + + [Test] + public void should_return_alternate_title_for_season() + { + var mappings = new List + { + new SceneMapping { Title = "Fudanshi Koukou Seikatsu", ParseTerm = "fudanshikoukouseikatsu", SearchTerm = "Fudanshi Koukou Seikatsu", TvdbId = 100, SeasonNumber = 1, SceneSeasonNumber = null } + }; + + Mocker.GetMock().Setup(c => c.All()).Returns(mappings); + + var names = Subject.GetSceneNames(100, new List { 1 }, new List { 10 }); + names.Should().HaveCount(1); + } + + [Test] + public void should_not_return_alternate_title_for_season() + { + var mappings = new List + { + new SceneMapping { Title = "Fudanshi Koukou Seikatsu", ParseTerm = "fudanshikoukouseikatsu", SearchTerm = "Fudanshi Koukou Seikatsu", TvdbId = 100, SeasonNumber = 1, SceneSeasonNumber = null } + }; + + Mocker.GetMock().Setup(c => c.All()).Returns(mappings); + + var names = Subject.GetSceneNames(100, new List { 2 }, new List { 10 }); + names.Should().BeEmpty(); + } + + [Test] + public void should_return_alternate_title_for_sceneseason() + { + var mappings = new List + { + new SceneMapping { Title = "Fudanshi Koukou Seikatsu", ParseTerm = "fudanshikoukouseikatsu", SearchTerm = "Fudanshi Koukou Seikatsu", TvdbId = 100, SeasonNumber = null, SceneSeasonNumber = 1 } + }; + + Mocker.GetMock().Setup(c => c.All()).Returns(mappings); + + var names = Subject.GetSceneNames(100, new List { 10 }, new List { 1 }); + names.Should().HaveCount(1); + } + + [Test] + public void should_not_return_alternate_title_for_sceneseason() + { + var mappings = new List + { + new SceneMapping { Title = "Fudanshi Koukou Seikatsu", ParseTerm = "fudanshikoukouseikatsu", SearchTerm = "Fudanshi Koukou Seikatsu", TvdbId = 100, SeasonNumber = null, SceneSeasonNumber = 1 } + }; + + Mocker.GetMock().Setup(c => c.All()).Returns(mappings); + + var names = Subject.GetSceneNames(100, new List { 10 }, new List { 2 }); + names.Should().BeEmpty(); + } + + [Test] + public void should_return_alternate_title_for_fairy_tail() + { + var mappings = new List + { + new SceneMapping { Title = "Fairy Tail S2", ParseTerm = "fairytails2", SearchTerm = "Fairy Tail S2", TvdbId = 100, SeasonNumber = null, SceneSeasonNumber = 2 } + }; + + Mocker.GetMock().Setup(c => c.All()).Returns(mappings); + + Subject.GetSceneNames(100, new List { 4 }, new List { 20 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 5 }, new List { 20 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 6 }, new List { 20 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 7 }, new List { 20 }).Should().BeEmpty(); + + Subject.GetSceneNames(100, new List { 20 }, new List { 1 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 20 }, new List { 2 }).Should().NotBeEmpty(); + Subject.GetSceneNames(100, new List { 20 }, new List { 3 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 20 }, new List { 4 }).Should().BeEmpty(); + } + + [Test] + public void should_return_alternate_title_for_fudanshi() + { + var mappings = new List + { + new SceneMapping { Title = "Fudanshi Koukou Seikatsu", ParseTerm = "fudanshikoukouseikatsu", SearchTerm = "Fudanshi Koukou Seikatsu", TvdbId = 100, SeasonNumber = null, SceneSeasonNumber = 1 } + }; + + Mocker.GetMock().Setup(c => c.All()).Returns(mappings); + + Subject.GetSceneNames(100, new List { 1 }, new List { 20 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 2 }, new List { 20 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 3 }, new List { 20 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 4 }, new List { 20 }).Should().BeEmpty(); + + Subject.GetSceneNames(100, new List { 1 }, new List { 1 }).Should().NotBeEmpty(); + Subject.GetSceneNames(100, new List { 2 }, new List { 2 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 3 }, new List { 3 }).Should().BeEmpty(); + Subject.GetSceneNames(100, new List { 4 }, new List { 4 }).Should().BeEmpty(); + } + private void AssertNoUpdate() { _provider1.Verify(c => c.GetSceneMappings(), Times.Once()); @@ -216,7 +331,7 @@ private void AssertMappingUpdated() foreach (var sceneMapping in _fakeMappings) { - Subject.GetSceneNamesBySeasonNumbers(sceneMapping.TvdbId, _fakeMappings.Select(m => m.SeasonNumber.Value)).Should().Contain(sceneMapping.SearchTerm); + Subject.GetSceneNames(sceneMapping.TvdbId, _fakeMappings.Select(m => m.SeasonNumber.Value).Distinct().ToList(), new List()).Should().Contain(sceneMapping.SearchTerm); Subject.FindTvdbId(sceneMapping.ParseTerm).Should().Be(sceneMapping.TvdbId); } } diff --git a/src/NzbDrone.Core.Test/IndexerSearchTests/NzbSearchServiceFixture.cs b/src/NzbDrone.Core.Test/IndexerSearchTests/NzbSearchServiceFixture.cs index c74058569..d6e151460 100644 --- a/src/NzbDrone.Core.Test/IndexerSearchTests/NzbSearchServiceFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerSearchTests/NzbSearchServiceFixture.cs @@ -52,11 +52,7 @@ public void SetUp() .Returns((i, j) => _xemEpisodes.Where(d => d.SeasonNumber == j).ToList()); Mocker.GetMock() - .Setup(s => s.GetSceneNamesBySeasonNumbers(It.IsAny(), It.IsAny>())) - .Returns(new List()); - - Mocker.GetMock() - .Setup(s => s.GetSceneNamesBySceneSeasonNumbers(It.IsAny(), It.IsAny>())) + .Setup(s => s.GetSceneNames(It.IsAny(), It.IsAny>(), It.IsAny>())) .Returns(new List()); } @@ -253,5 +249,18 @@ public void season_search_for_anime_should_not_search_for_episodes_with_files() criteria.Count.Should().Be(0); } + + [Test] + public void getscenenames_should_use_seasonnumber_if_no_scene_seasonnumber_is_available() + { + WithEpisodes(); + + var allCriteria = WatchForSearchCriteria(); + + Subject.SeasonSearch(_xemSeries.Id, 7, false, true); + + Mocker.GetMock() + .Verify(v => v.GetSceneNames(_xemSeries.Id, It.Is>(l => l.Contains(7)), It.Is>(l => l.Contains(7))), Times.Once()); + } } } diff --git a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs index e914490a7..caa04ae42 100644 --- a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs +++ b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs @@ -13,8 +13,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene { public interface ISceneMappingService { - List GetSceneNamesBySeasonNumbers(int tvdbId, IEnumerable seasonNumbers); - List GetSceneNamesBySceneSeasonNumbers(int tvdbId, IEnumerable sceneSeasonNumbers); + List GetSceneNames(int tvdbId, List seasonNumbers, List sceneSeasonNumbers); int? FindTvdbId(string title); List FindByTvdbId(int tvdbId); SceneMapping FindSceneMapping(string title); @@ -49,32 +48,21 @@ public SceneMappingService(ISceneMappingRepository repository, _findByTvdbIdCache = cacheManager.GetCacheDictionary>(GetType(), "find_tvdb_id"); } - public List GetSceneNamesBySeasonNumbers(int tvdbId, IEnumerable seasonNumbers) + public List GetSceneNames(int tvdbId, List seasonNumbers, List sceneSeasonNumbers) { - var names = FindByTvdbId(tvdbId); + var mappings = FindByTvdbId(tvdbId); - if (names == null) + if (mappings == null) { return new List(); } - return FilterNonEnglish(names.Where(s => s.SeasonNumber.HasValue && seasonNumbers.Contains(s.SeasonNumber.Value) || - s.SeasonNumber == -1) - .Select(m => m.SearchTerm).Distinct().ToList()); - } + var names = mappings.Where(n => n.SeasonNumber.HasValue && seasonNumbers.Contains(n.SeasonNumber.Value) || + n.SceneSeasonNumber.HasValue && sceneSeasonNumbers.Contains(n.SceneSeasonNumber.Value) || + (n.SeasonNumber ?? -1) == -1 && (n.SceneSeasonNumber ?? -1) == -1) + .Select(n => n.SearchTerm).Distinct().ToList(); - public List GetSceneNamesBySceneSeasonNumbers(int tvdbId, IEnumerable sceneSeasonNumbers) - { - var names = FindByTvdbId(tvdbId); - - if (names == null) - { - return new List(); - } - - return FilterNonEnglish(names.Where(s => s.SceneSeasonNumber.HasValue && sceneSeasonNumbers.Contains(s.SceneSeasonNumber.Value) || - s.SceneSeasonNumber == -1) - .Select(m => m.SearchTerm).Distinct().ToList()); + return FilterNonEnglish(names); } public int? FindTvdbId(string title) diff --git a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs index e517a5788..cff3e290c 100644 --- a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs +++ b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs @@ -233,12 +233,9 @@ private List SearchAnimeSeason(Series series, List ep var spec = new TSpec(); spec.Series = series; - spec.SceneTitles = _sceneMapping.GetSceneNamesBySeasonNumbers(series.TvdbId, episodes.Select(e => e.SeasonNumber)) - .Concat(_sceneMapping.GetSceneNamesBySceneSeasonNumbers(series.TvdbId, - episodes.Where(v => v.SceneSeasonNumber.HasValue) - .Select(e => e.SceneSeasonNumber.Value))) - .Distinct() - .ToList(); + spec.SceneTitles = _sceneMapping.GetSceneNames(series.TvdbId, + episodes.Select(e => e.SeasonNumber).Distinct().ToList(), + episodes.Select(e => e.SceneSeasonNumber ?? e.SeasonNumber).Distinct().ToList()); spec.Episodes = episodes; diff --git a/src/UI/Series/Details/EpisodeNumberCell.js b/src/UI/Series/Details/EpisodeNumberCell.js index eb6dddeba..9a84e644e 100644 --- a/src/UI/Series/Details/EpisodeNumberCell.js +++ b/src/UI/Series/Details/EpisodeNumberCell.js @@ -20,14 +20,7 @@ module.exports = NzbDroneCell.extend({ var alternateTitles = []; if (reqres.hasHandler(reqres.Requests.GetAlternateNameBySeasonNumber)) { - - if (this.model.get('sceneSeasonNumber') > 0) { - alternateTitles = reqres.request(reqres.Requests.GetAlternateNameBySceneSeasonNumber, this.model.get('seriesId'), this.model.get('sceneSeasonNumber')); - } - - if (alternateTitles.length === 0) { - alternateTitles = reqres.request(reqres.Requests.GetAlternateNameBySeasonNumber, this.model.get('seriesId'), this.model.get('seasonNumber')); - } + alternateTitles = reqres.request(reqres.Requests.GetAlternateNameBySeasonNumber, this.model.get('seriesId'), this.model.get('seasonNumber'), this.model.get('sceneSeasonNumber')); } if (this.model.get('sceneSeasonNumber') > 0 || this.model.get('sceneEpisodeNumber') > 0 || this.model.has('sceneAbsoluteEpisodeNumber') || alternateTitles.length > 0) { diff --git a/src/UI/Series/Details/SeriesDetailsLayout.js b/src/UI/Series/Details/SeriesDetailsLayout.js index 05df0fdea..f33cb0414 100644 --- a/src/UI/Series/Details/SeriesDetailsLayout.js +++ b/src/UI/Series/Details/SeriesDetailsLayout.js @@ -174,20 +174,19 @@ module.exports = Marionette.Layout.extend({ return self.episodeFileCollection.get(episodeFileId); }); - reqres.setHandler(reqres.Requests.GetAlternateNameBySeasonNumber, function(seriesId, seasonNumber) { + reqres.setHandler(reqres.Requests.GetAlternateNameBySeasonNumber, function(seriesId, seasonNumber, sceneSeasonNumber) { if (self.model.get('id') !== seriesId) { return []; } - - return _.where(self.model.get('alternateTitles'), { seasonNumber : seasonNumber }); - }); - - reqres.setHandler(reqres.Requests.GetAlternateNameBySceneSeasonNumber, function(seriesId, sceneSeasonNumber) { - if (self.model.get('id') !== seriesId) { - return []; + + if (sceneSeasonNumber === undefined) { + sceneSeasonNumber = seasonNumber; } - - return _.where(self.model.get('alternateTitles'), { sceneSeasonNumber : sceneSeasonNumber }); + + return _.where(self.model.get('alternateTitles'), + function(alt) { + return alt.sceneSeasonNumber === sceneSeasonNumber || alt.seasonNumber === seasonNumber; + }); }); $.when(this.episodeCollection.fetch(), this.episodeFileCollection.fetch()).done(function() { diff --git a/src/UI/reqres.js b/src/UI/reqres.js index 4f138dcc2..1904f3602 100644 --- a/src/UI/reqres.js +++ b/src/UI/reqres.js @@ -4,8 +4,7 @@ var reqres = new Wreqr.RequestResponse(); reqres.Requests = { GetEpisodeFileById : 'GetEpisodeFileById', - GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber', - GetAlternateNameBySceneSeasonNumber : 'GetAlternateNameBySceneSeasonNumber' + GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber' }; module.exports = reqres; \ No newline at end of file