diff --git a/src/NzbDrone.Api/Series/AlternateTitleResource.cs b/src/NzbDrone.Api/Series/AlternateTitleResource.cs index adc58f8d1..9cefcd842 100644 --- a/src/NzbDrone.Api/Series/AlternateTitleResource.cs +++ b/src/NzbDrone.Api/Series/AlternateTitleResource.cs @@ -6,5 +6,6 @@ namespace NzbDrone.Api.Series { public string Title { get; set; } public int SeasonNumber { get; set; } + public int SceneSeasonNumber { get; set; } } } diff --git a/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs b/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs index 771c79423..366f7e3ba 100644 --- a/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs +++ b/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs @@ -187,16 +187,15 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene { var mappings = new List { - new SceneMapping { Title = "Working!!", ParseTerm = "working", SearchTerm = "Working!!", TvdbId = 100, SeasonNumber = -1 }, - new SceneMapping { Title = "Working!!", ParseTerm = "working", SearchTerm = "Working!!", TvdbId = 100, SeasonNumber = 1 }, - new SceneMapping { Title = "Working`!!", ParseTerm = "working", SearchTerm = "Working`!!", TvdbId = 100, SeasonNumber = 2 }, - new SceneMapping { Title = "Working!!!", ParseTerm = "working", SearchTerm = "Working!!!", TvdbId = 100, SeasonNumber = 3 }, + new SceneMapping { Title = "Working!!", ParseTerm = "working", SearchTerm = "Working!!", TvdbId = 100, SceneSeasonNumber = 1 }, + new SceneMapping { Title = "Working`!!", ParseTerm = "working", SearchTerm = "Working`!!", TvdbId = 100, SceneSeasonNumber = 2 }, + new SceneMapping { Title = "Working!!!", ParseTerm = "working", SearchTerm = "Working!!!", TvdbId = 100, SceneSeasonNumber = 3 }, }; Mocker.GetMock().Setup(c => c.All()).Returns(mappings); var tvdbId = Subject.FindTvdbId(parseTitle); - var seasonNumber = Subject.GetSeasonNumber(parseTitle); + var seasonNumber = Subject.GetSceneSeasonNumber(parseTitle); tvdbId.Should().Be(100); seasonNumber.Should().Be(expectedSeasonNumber); @@ -217,7 +216,7 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene foreach (var sceneMapping in _fakeMappings) { - Subject.GetSceneNames(sceneMapping.TvdbId, _fakeMappings.Select(m => m.SeasonNumber)).Should().Contain(sceneMapping.SearchTerm); + Subject.GetSceneNamesBySeasonNumbers(sceneMapping.TvdbId, _fakeMappings.Select(m => m.SeasonNumber.Value)).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 e205026c0..49a7f96b9 100644 --- a/src/NzbDrone.Core.Test/IndexerSearchTests/NzbSearchServiceFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerSearchTests/NzbSearchServiceFixture.cs @@ -52,7 +52,11 @@ namespace NzbDrone.Core.Test.IndexerSearchTests .Returns((i, j) => _xemEpisodes.Where(d => d.SeasonNumber == j).ToList()); Mocker.GetMock() - .Setup(s => s.GetSceneNames(It.IsAny(), It.IsAny>())) + .Setup(s => s.GetSceneNamesBySeasonNumbers(It.IsAny(), It.IsAny>())) + .Returns(new List()); + + Mocker.GetMock() + .Setup(s => s.GetSceneNamesBySceneSeasonNumbers(It.IsAny(), It.IsAny>())) .Returns(new List()); } diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs index 1c473a396..f1f5b4516 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs @@ -210,7 +210,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests GivenAbsoluteNumberingSeries(); Mocker.GetMock() - .Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) + .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Returns(seasonNumber); Mocker.GetMock() @@ -234,7 +234,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests GivenAbsoluteNumberingSeries(); Mocker.GetMock() - .Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) + .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Returns(seasonNumber); Mocker.GetMock() @@ -258,7 +258,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests GivenAbsoluteNumberingSeries(); Mocker.GetMock() - .Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) + .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Returns(seasonNumber); Mocker.GetMock() diff --git a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMapping.cs b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMapping.cs index fae578450..b992aa029 100644 --- a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMapping.cs +++ b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMapping.cs @@ -6,7 +6,6 @@ namespace NzbDrone.Core.DataAugmentation.Scene public class SceneMapping : ModelBase { public string Title { get; set; } - public string ParseTerm { get; set; } [JsonProperty("searchTitle")] @@ -15,8 +14,9 @@ namespace NzbDrone.Core.DataAugmentation.Scene public int TvdbId { get; set; } [JsonProperty("season")] - public int SeasonNumber { get; set; } + public int? SeasonNumber { get; set; } + public int? SceneSeasonNumber { get; set; } public string Type { get; set; } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs index 9194ffcac..ea7cb58c7 100644 --- a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs +++ b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs @@ -14,10 +14,11 @@ namespace NzbDrone.Core.DataAugmentation.Scene { public interface ISceneMappingService { - List GetSceneNames(int tvdbId, IEnumerable seasonNumbers); + List GetSceneNamesBySeasonNumbers(int tvdbId, IEnumerable seasonNumbers); + List GetSceneNamesBySceneSeasonNumbers(int tvdbId, IEnumerable sceneSeasonNumbers); int? FindTvdbId(string title); List FindByTvdbId(int tvdbId); - int? GetSeasonNumber(string title); + int? GetSceneSeasonNumber(string title); } public class SceneMappingService : ISceneMappingService, @@ -46,7 +47,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene _findByTvdbIdCache = cacheManager.GetCacheDictionary>(GetType(), "find_tvdb_id"); } - public List GetSceneNames(int tvdbId, IEnumerable seasonNumbers) + public List GetSceneNamesBySeasonNumbers(int tvdbId, IEnumerable seasonNumbers) { var names = _findByTvdbIdCache.Find(tvdbId.ToString()); @@ -55,11 +56,25 @@ namespace NzbDrone.Core.DataAugmentation.Scene return new List(); } - return FilterNonEnglish(names.Where(s => seasonNumbers.Contains(s.SeasonNumber) || + return FilterNonEnglish(names.Where(s => s.SeasonNumber.HasValue && seasonNumbers.Contains(s.SeasonNumber.Value) || s.SeasonNumber == -1) .Select(m => m.SearchTerm).Distinct().ToList()); } + public List GetSceneNamesBySceneSeasonNumbers(int tvdbId, IEnumerable sceneSeasonNumbers) + { + var names = _findByTvdbIdCache.Find(tvdbId.ToString()); + + 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()); + } + public int? FindTvdbId(string title) { var mapping = FindMapping(title); @@ -87,14 +102,16 @@ namespace NzbDrone.Core.DataAugmentation.Scene return mappings; } - public int? GetSeasonNumber(string title) + public int? GetSceneSeasonNumber(string title) { var mapping = FindMapping(title); if (mapping == null) + { return null; + } - return mapping.SeasonNumber; + return mapping.SceneSeasonNumber; } private void UpdateMappings() diff --git a/src/NzbDrone.Core/DataAugmentation/Xem/XemProxy.cs b/src/NzbDrone.Core/DataAugmentation/Xem/XemProxy.cs index 5cf39c308..0542790cf 100644 --- a/src/NzbDrone.Core/DataAugmentation/Xem/XemProxy.cs +++ b/src/NzbDrone.Core/DataAugmentation/Xem/XemProxy.cs @@ -106,7 +106,7 @@ namespace NzbDrone.Core.DataAugmentation.Xem { Title = n.Key, SearchTerm = n.Key, - SeasonNumber = seasonNumber, + SceneSeasonNumber = seasonNumber, TvdbId = series.Key }); } diff --git a/src/NzbDrone.Core/Datastore/Migration/100_add_scene_season_number.cs b/src/NzbDrone.Core/Datastore/Migration/100_add_scene_season_number.cs new file mode 100644 index 000000000..3cd11f6f0 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/100_add_scene_season_number.cs @@ -0,0 +1,15 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(100)] + public class add_scene_season_number : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("SceneMappings").AlterColumn("SeasonNumber").AsInt32().Nullable(); + Alter.Table("SceneMappings").AddColumn("SceneSeasonNumber").AsInt32().Nullable(); + } + } +} diff --git a/src/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs b/src/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs index 752f794ad..577dc60e8 100644 --- a/src/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs +++ b/src/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs @@ -2,17 +2,14 @@ using System.Collections.Generic; using System.Linq; using NLog; -using NzbDrone.Common; using NzbDrone.Common.Extensions; using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Core.Datastore; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; using NzbDrone.Core.Messaging.Commands; -using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Queue; using NzbDrone.Core.Tv; -using NzbDrone.Core.Tv.Events; namespace NzbDrone.Core.IndexerSearch { diff --git a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs index 2e4a6c394..217bcdeb6 100644 --- a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs +++ b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs @@ -233,10 +233,12 @@ namespace NzbDrone.Core.IndexerSearch var spec = new TSpec(); spec.Series = series; - spec.SceneTitles = _sceneMapping.GetSceneNames(series.TvdbId, - episodes.Select(e => e.SeasonNumber) - .Concat(episodes.Where(v => v.SceneSeasonNumber.HasValue).Select(e => e.SceneSeasonNumber.Value) - .Distinct())); + 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.Episodes = episodes; diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 7a8e25d44..e564c5212 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -274,6 +274,7 @@ + Code diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs index 9b66aa6cf..b1418a96f 100644 --- a/src/NzbDrone.Core/Parser/ParsingService.cs +++ b/src/NzbDrone.Core/Parser/ParsingService.cs @@ -168,7 +168,7 @@ namespace NzbDrone.Core.Parser if (parsedEpisodeInfo.IsAbsoluteNumbering) { - var sceneSeasonNumber = _sceneMappingService.GetSeasonNumber(parsedEpisodeInfo.SeriesTitle); + var sceneSeasonNumber = _sceneMappingService.GetSceneSeasonNumber(parsedEpisodeInfo.SeriesTitle); foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers) { @@ -195,8 +195,7 @@ namespace NzbDrone.Core.Parser if (episode == null) { - episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, - absoluteEpisodeNumber); + episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber); } } diff --git a/src/UI/Series/Details/EpisodeNumberCell.js b/src/UI/Series/Details/EpisodeNumberCell.js index b1b5b826c..eb6dddeba 100644 --- a/src/UI/Series/Details/EpisodeNumberCell.js +++ b/src/UI/Series/Details/EpisodeNumberCell.js @@ -22,7 +22,7 @@ module.exports = NzbDroneCell.extend({ if (reqres.hasHandler(reqres.Requests.GetAlternateNameBySeasonNumber)) { if (this.model.get('sceneSeasonNumber') > 0) { - alternateTitles = reqres.request(reqres.Requests.GetAlternateNameBySeasonNumber, this.model.get('seriesId'), this.model.get('sceneSeasonNumber')); + alternateTitles = reqres.request(reqres.Requests.GetAlternateNameBySceneSeasonNumber, this.model.get('seriesId'), this.model.get('sceneSeasonNumber')); } if (alternateTitles.length === 0) { diff --git a/src/UI/Series/Details/InfoViewTemplate.hbs b/src/UI/Series/Details/InfoViewTemplate.hbs index b0bfff588..b52130246 100644 --- a/src/UI/Series/Details/InfoViewTemplate.hbs +++ b/src/UI/Series/Details/InfoViewTemplate.hbs @@ -55,6 +55,10 @@ {{#if_eq seasonNumber compare="-1"}} {{title}} {{/if_eq}} + + {{#if_eq sceneSeasonNumber compare="-1"}} + {{title}} + {{/if_eq}} {{/each}} diff --git a/src/UI/Series/Details/SeriesDetailsLayout.js b/src/UI/Series/Details/SeriesDetailsLayout.js index 5775c38a1..05df0fdea 100644 --- a/src/UI/Series/Details/SeriesDetailsLayout.js +++ b/src/UI/Series/Details/SeriesDetailsLayout.js @@ -182,6 +182,14 @@ module.exports = Marionette.Layout.extend({ return _.where(self.model.get('alternateTitles'), { seasonNumber : seasonNumber }); }); + reqres.setHandler(reqres.Requests.GetAlternateNameBySceneSeasonNumber, function(seriesId, sceneSeasonNumber) { + if (self.model.get('id') !== seriesId) { + return []; + } + + return _.where(self.model.get('alternateTitles'), { sceneSeasonNumber : sceneSeasonNumber }); + }); + $.when(this.episodeCollection.fetch(), this.episodeFileCollection.fetch()).done(function() { var seasonCollectionView = new SeasonCollectionView({ collection : self.seasonCollection, diff --git a/src/UI/reqres.js b/src/UI/reqres.js index 2d4351657..4f138dcc2 100644 --- a/src/UI/reqres.js +++ b/src/UI/reqres.js @@ -3,8 +3,9 @@ var Wreqr = require('./JsLibraries/backbone.wreqr'); var reqres = new Wreqr.RequestResponse(); reqres.Requests = { - GetEpisodeFileById : 'GetEpisodeFileById', - GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber' + GetEpisodeFileById : 'GetEpisodeFileById', + GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber', + GetAlternateNameBySceneSeasonNumber : 'GetAlternateNameBySceneSeasonNumber' }; module.exports = reqres; \ No newline at end of file