Treat XEM aliases as SceneSeasonNumber

Fixed: Aliases used incorrectly when TVDB season number matched the seaon number of the alias
Closes #1140
This commit is contained in:
Mark McDowall 2016-02-11 21:00:25 -08:00
parent 44e09e2220
commit 942be364dc
16 changed files with 80 additions and 32 deletions

View File

@ -6,5 +6,6 @@ namespace NzbDrone.Api.Series
{ {
public string Title { get; set; } public string Title { get; set; }
public int SeasonNumber { get; set; } public int SeasonNumber { get; set; }
public int SceneSeasonNumber { get; set; }
} }
} }

View File

@ -187,16 +187,15 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
{ {
var mappings = new List<SceneMapping> var mappings = new List<SceneMapping>
{ {
new SceneMapping { Title = "Working!!", ParseTerm = "working", SearchTerm = "Working!!", TvdbId = 100, SeasonNumber = -1 }, new SceneMapping { Title = "Working!!", ParseTerm = "working", SearchTerm = "Working!!", TvdbId = 100, SceneSeasonNumber = 1 },
new SceneMapping { Title = "Working!!", ParseTerm = "working", SearchTerm = "Working!!", TvdbId = 100, SeasonNumber = 1 }, new SceneMapping { Title = "Working`!!", ParseTerm = "working", SearchTerm = "Working`!!", TvdbId = 100, SceneSeasonNumber = 2 },
new SceneMapping { Title = "Working`!!", ParseTerm = "working", SearchTerm = "Working`!!", TvdbId = 100, SeasonNumber = 2 }, new SceneMapping { Title = "Working!!!", ParseTerm = "working", SearchTerm = "Working!!!", TvdbId = 100, SceneSeasonNumber = 3 },
new SceneMapping { Title = "Working!!!", ParseTerm = "working", SearchTerm = "Working!!!", TvdbId = 100, SeasonNumber = 3 },
}; };
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings); Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
var tvdbId = Subject.FindTvdbId(parseTitle); var tvdbId = Subject.FindTvdbId(parseTitle);
var seasonNumber = Subject.GetSeasonNumber(parseTitle); var seasonNumber = Subject.GetSceneSeasonNumber(parseTitle);
tvdbId.Should().Be(100); tvdbId.Should().Be(100);
seasonNumber.Should().Be(expectedSeasonNumber); seasonNumber.Should().Be(expectedSeasonNumber);
@ -217,7 +216,7 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
foreach (var sceneMapping in _fakeMappings) 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); Subject.FindTvdbId(sceneMapping.ParseTerm).Should().Be(sceneMapping.TvdbId);
} }
} }

View File

@ -52,7 +52,11 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
.Returns<int, int>((i, j) => _xemEpisodes.Where(d => d.SeasonNumber == j).ToList()); .Returns<int, int>((i, j) => _xemEpisodes.Where(d => d.SeasonNumber == j).ToList());
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSceneNames(It.IsAny<int>(), It.IsAny<IEnumerable<int>>())) .Setup(s => s.GetSceneNamesBySeasonNumbers(It.IsAny<int>(), It.IsAny<IEnumerable<int>>()))
.Returns(new List<string>());
Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSceneNamesBySceneSeasonNumbers(It.IsAny<int>(), It.IsAny<IEnumerable<int>>()))
.Returns(new List<string>()); .Returns(new List<string>());
} }

View File

@ -210,7 +210,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenAbsoluteNumberingSeries(); GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle))
.Returns(seasonNumber); .Returns(seasonNumber);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
@ -234,7 +234,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenAbsoluteNumberingSeries(); GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle))
.Returns(seasonNumber); .Returns(seasonNumber);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
@ -258,7 +258,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenAbsoluteNumberingSeries(); GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle))
.Returns(seasonNumber); .Returns(seasonNumber);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()

View File

@ -6,7 +6,6 @@ namespace NzbDrone.Core.DataAugmentation.Scene
public class SceneMapping : ModelBase public class SceneMapping : ModelBase
{ {
public string Title { get; set; } public string Title { get; set; }
public string ParseTerm { get; set; } public string ParseTerm { get; set; }
[JsonProperty("searchTitle")] [JsonProperty("searchTitle")]
@ -15,8 +14,9 @@ namespace NzbDrone.Core.DataAugmentation.Scene
public int TvdbId { get; set; } public int TvdbId { get; set; }
[JsonProperty("season")] [JsonProperty("season")]
public int SeasonNumber { get; set; } public int? SeasonNumber { get; set; }
public int? SceneSeasonNumber { get; set; }
public string Type { get; set; } public string Type { get; set; }
} }
} }

View File

@ -14,10 +14,11 @@ namespace NzbDrone.Core.DataAugmentation.Scene
{ {
public interface ISceneMappingService public interface ISceneMappingService
{ {
List<string> GetSceneNames(int tvdbId, IEnumerable<int> seasonNumbers); List<string> GetSceneNamesBySeasonNumbers(int tvdbId, IEnumerable<int> seasonNumbers);
List<string> GetSceneNamesBySceneSeasonNumbers(int tvdbId, IEnumerable<int> sceneSeasonNumbers);
int? FindTvdbId(string title); int? FindTvdbId(string title);
List<SceneMapping> FindByTvdbId(int tvdbId); List<SceneMapping> FindByTvdbId(int tvdbId);
int? GetSeasonNumber(string title); int? GetSceneSeasonNumber(string title);
} }
public class SceneMappingService : ISceneMappingService, public class SceneMappingService : ISceneMappingService,
@ -46,7 +47,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene
_findByTvdbIdCache = cacheManager.GetCacheDictionary<List<SceneMapping>>(GetType(), "find_tvdb_id"); _findByTvdbIdCache = cacheManager.GetCacheDictionary<List<SceneMapping>>(GetType(), "find_tvdb_id");
} }
public List<string> GetSceneNames(int tvdbId, IEnumerable<int> seasonNumbers) public List<string> GetSceneNamesBySeasonNumbers(int tvdbId, IEnumerable<int> seasonNumbers)
{ {
var names = _findByTvdbIdCache.Find(tvdbId.ToString()); var names = _findByTvdbIdCache.Find(tvdbId.ToString());
@ -55,11 +56,25 @@ namespace NzbDrone.Core.DataAugmentation.Scene
return new List<string>(); return new List<string>();
} }
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) s.SeasonNumber == -1)
.Select(m => m.SearchTerm).Distinct().ToList()); .Select(m => m.SearchTerm).Distinct().ToList());
} }
public List<string> GetSceneNamesBySceneSeasonNumbers(int tvdbId, IEnumerable<int> sceneSeasonNumbers)
{
var names = _findByTvdbIdCache.Find(tvdbId.ToString());
if (names == null)
{
return new List<string>();
}
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) public int? FindTvdbId(string title)
{ {
var mapping = FindMapping(title); var mapping = FindMapping(title);
@ -87,14 +102,16 @@ namespace NzbDrone.Core.DataAugmentation.Scene
return mappings; return mappings;
} }
public int? GetSeasonNumber(string title) public int? GetSceneSeasonNumber(string title)
{ {
var mapping = FindMapping(title); var mapping = FindMapping(title);
if (mapping == null) if (mapping == null)
{
return null; return null;
}
return mapping.SeasonNumber; return mapping.SceneSeasonNumber;
} }
private void UpdateMappings() private void UpdateMappings()

View File

@ -106,7 +106,7 @@ namespace NzbDrone.Core.DataAugmentation.Xem
{ {
Title = n.Key, Title = n.Key,
SearchTerm = n.Key, SearchTerm = n.Key,
SeasonNumber = seasonNumber, SceneSeasonNumber = seasonNumber,
TvdbId = series.Key TvdbId = series.Key
}); });
} }

View File

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

View File

@ -2,17 +2,14 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Queue; using NzbDrone.Core.Queue;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Core.IndexerSearch namespace NzbDrone.Core.IndexerSearch
{ {

View File

@ -233,10 +233,12 @@ namespace NzbDrone.Core.IndexerSearch
var spec = new TSpec(); var spec = new TSpec();
spec.Series = series; spec.Series = series;
spec.SceneTitles = _sceneMapping.GetSceneNames(series.TvdbId, spec.SceneTitles = _sceneMapping.GetSceneNamesBySeasonNumbers(series.TvdbId, episodes.Select(e => e.SeasonNumber))
episodes.Select(e => e.SeasonNumber) .Concat(_sceneMapping.GetSceneNamesBySceneSeasonNumbers(series.TvdbId,
.Concat(episodes.Where(v => v.SceneSeasonNumber.HasValue).Select(e => e.SceneSeasonNumber.Value) episodes.Where(v => v.SceneSeasonNumber.HasValue)
.Distinct())); .Select(e => e.SceneSeasonNumber.Value)))
.Distinct()
.ToList();
spec.Episodes = episodes; spec.Episodes = episodes;

View File

@ -274,6 +274,7 @@
<Compile Include="Datastore\Migration\091_added_indexerstatus.cs" /> <Compile Include="Datastore\Migration\091_added_indexerstatus.cs" />
<Compile Include="Datastore\Migration\093_naming_config_replace_characters.cs" /> <Compile Include="Datastore\Migration\093_naming_config_replace_characters.cs" />
<Compile Include="Datastore\Migration\092_add_unverifiedscenenumbering.cs" /> <Compile Include="Datastore\Migration\092_add_unverifiedscenenumbering.cs" />
<Compile Include="Datastore\Migration\100_add_scene_season_number.cs" />
<Compile Include="Datastore\Migration\094_add_tvmazeid.cs" /> <Compile Include="Datastore\Migration\094_add_tvmazeid.cs" />
<Compile Include="Datastore\Migration\098_remove_titans_of_tv.cs"> <Compile Include="Datastore\Migration\098_remove_titans_of_tv.cs">
<SubType>Code</SubType> <SubType>Code</SubType>

View File

@ -168,7 +168,7 @@ namespace NzbDrone.Core.Parser
if (parsedEpisodeInfo.IsAbsoluteNumbering) if (parsedEpisodeInfo.IsAbsoluteNumbering)
{ {
var sceneSeasonNumber = _sceneMappingService.GetSeasonNumber(parsedEpisodeInfo.SeriesTitle); var sceneSeasonNumber = _sceneMappingService.GetSceneSeasonNumber(parsedEpisodeInfo.SeriesTitle);
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers) foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
{ {
@ -195,8 +195,7 @@ namespace NzbDrone.Core.Parser
if (episode == null) if (episode == null)
{ {
episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, episode = _episodeService.FindEpisode(series.Id, sceneSeasonNumber.Value, absoluteEpisodeNumber);
absoluteEpisodeNumber);
} }
} }

View File

@ -22,7 +22,7 @@ module.exports = NzbDroneCell.extend({
if (reqres.hasHandler(reqres.Requests.GetAlternateNameBySeasonNumber)) { if (reqres.hasHandler(reqres.Requests.GetAlternateNameBySeasonNumber)) {
if (this.model.get('sceneSeasonNumber') > 0) { 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) { if (alternateTitles.length === 0) {

View File

@ -55,6 +55,10 @@
{{#if_eq seasonNumber compare="-1"}} {{#if_eq seasonNumber compare="-1"}}
<span class="label label-default">{{title}}</span> <span class="label label-default">{{title}}</span>
{{/if_eq}} {{/if_eq}}
{{#if_eq sceneSeasonNumber compare="-1"}}
<span class="label label-default">{{title}}</span>
{{/if_eq}}
{{/each}} {{/each}}
</div> </div>
</div> </div>

View File

@ -182,6 +182,14 @@ module.exports = Marionette.Layout.extend({
return _.where(self.model.get('alternateTitles'), { seasonNumber : seasonNumber }); 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() { $.when(this.episodeCollection.fetch(), this.episodeFileCollection.fetch()).done(function() {
var seasonCollectionView = new SeasonCollectionView({ var seasonCollectionView = new SeasonCollectionView({
collection : self.seasonCollection, collection : self.seasonCollection,

View File

@ -3,8 +3,9 @@ var Wreqr = require('./JsLibraries/backbone.wreqr');
var reqres = new Wreqr.RequestResponse(); var reqres = new Wreqr.RequestResponse();
reqres.Requests = { reqres.Requests = {
GetEpisodeFileById : 'GetEpisodeFileById', GetEpisodeFileById : 'GetEpisodeFileById',
GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber' GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber',
GetAlternateNameBySceneSeasonNumber : 'GetAlternateNameBySceneSeasonNumber'
}; };
module.exports = reqres; module.exports = reqres;