Fixed: Will no longer cause an error when trying to parse an anime episode with absolute number 0.

pull/6/head
Taloth Saldono 10 years ago
parent e978a425c2
commit 6dfbc3c290

@ -20,11 +20,11 @@ namespace NzbDrone.Api.Episodes
public Boolean HasFile { get; set; } public Boolean HasFile { get; set; }
public Boolean Monitored { get; set; } public Boolean Monitored { get; set; }
public Nullable<Int32> AbsoluteEpisodeNumber { get; set; }
public Nullable<Int32> SceneAbsoluteEpisodeNumber { get; set; } public Nullable<Int32> SceneAbsoluteEpisodeNumber { get; set; }
public Int32 SceneEpisodeNumber { get; set; } public Nullable<Int32> SceneEpisodeNumber { get; set; }
public Int32 SceneSeasonNumber { get; set; } public Nullable<Int32> SceneSeasonNumber { get; set; }
public Int32 TvDbEpisodeId { get; set; } public Int32 TvDbEpisodeId { get; set; }
public Int32? AbsoluteEpisodeNumber { get; set; }
public DateTime? EndTime { get; set; } public DateTime? EndTime { get; set; }
public DateTime? GrabDate { get; set; } public DateTime? GrabDate { get; set; }
public String SeriesTitle { get; set; } public String SeriesTitle { get; set; }

@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
.Returns(new List<String>()); .Returns(new List<String>());
} }
private void WithEpisode(int seasonNumber, int episodeNumber, int sceneSeasonNumber, int sceneEpisodeNumber) private void WithEpisode(Int32 seasonNumber, Int32 episodeNumber, Int32? sceneSeasonNumber, Int32? sceneEpisodeNumber)
{ {
var episode = Builder<Episode>.CreateNew() var episode = Builder<Episode>.CreateNew()
.With(v => v.SeriesId == _xemSeries.Id) .With(v => v.SeriesId == _xemSeries.Id)
@ -90,8 +90,8 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
WithEpisode(5, 1, 6, 12); WithEpisode(5, 1, 6, 12);
// Season 7+ maps normally, so no mapping specified. // Season 7+ maps normally, so no mapping specified.
WithEpisode(7, 1, 0, 0); WithEpisode(7, 1, null, null);
WithEpisode(7, 2, 0, 0); WithEpisode(7, 2, null, null);
} }
private List<SearchCriteriaBase> WatchForSearchCriteria() private List<SearchCriteriaBase> WatchForSearchCriteria()

@ -530,10 +530,10 @@ namespace NzbDrone.Core.Test.OrganizerTests
} }
[Test] [Test]
public void should_use_standard_naming_when_anime_episode_has_absolute_number_of_zero() public void should_use_standard_naming_when_anime_episode_has_no_absolute_number()
{ {
_series.SeriesType = SeriesTypes.Anime; _series.SeriesType = SeriesTypes.Anime;
_episode1.AbsoluteEpisodeNumber = 0; _episode1.AbsoluteEpisodeNumber = null;
_namingConfig.StandardEpisodeFormat = "{Series Title} - {season:0}x{episode:00} - {Episode Title}"; _namingConfig.StandardEpisodeFormat = "{Series Title} - {season:0}x{episode:00} - {Episode Title}";
_namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:000} - {Episode Title}"; _namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:000} - {Episode Title}";

@ -39,7 +39,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[Test] [Test]
public void should_find_episode_by_scene_numbering() public void should_find_episode_by_scene_numbering()
{ {
Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber, _episode1.SceneEpisodeNumber) Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber.Value, _episode1.SceneEpisodeNumber.Value)
.First() .First()
.Id .Id
.Should() .Should()
@ -77,7 +77,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
{ {
_episode2 = Db.Insert(_episode2); _episode2 = Db.Insert(_episode2);
Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber, _episode1.SceneEpisodeNumber) Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber.Value, _episode1.SceneEpisodeNumber.Value)
.Should() .Should()
.HaveCount(2); .HaveCount(2);
} }

@ -183,7 +183,7 @@ namespace NzbDrone.Core.Test.TvTests
Subject.RefreshEpisodeInfo(GetSeries(), GetEpisodes()); Subject.RefreshEpisodeInfo(GetSeries(), GetEpisodes());
_insertedEpisodes.All(e => e.AbsoluteEpisodeNumber == 0 || !e.AbsoluteEpisodeNumber.HasValue).Should().BeTrue(); _insertedEpisodes.All(e => !e.AbsoluteEpisodeNumber.HasValue).Should().BeTrue();
} }
[Test] [Test]
@ -197,7 +197,7 @@ namespace NzbDrone.Core.Test.TvTests
Subject.RefreshEpisodeInfo(GetAnimeSeries(), episodes); Subject.RefreshEpisodeInfo(GetAnimeSeries(), episodes);
_insertedEpisodes.All(e => e.AbsoluteEpisodeNumber > 0).Should().BeTrue(); _insertedEpisodes.All(e => e.AbsoluteEpisodeNumber.HasValue).Should().BeTrue();
_updatedEpisodes.Should().BeEmpty(); _updatedEpisodes.Should().BeEmpty();
_deletedEpisodes.Should().BeEmpty(); _deletedEpisodes.Should().BeEmpty();
} }
@ -209,7 +209,7 @@ namespace NzbDrone.Core.Test.TvTests
GivenAnimeEpisodes(episodes); GivenAnimeEpisodes(episodes);
var existingEpisodes = episodes.JsonClone(); var existingEpisodes = episodes.JsonClone();
existingEpisodes.ForEach(e => e.AbsoluteEpisodeNumber = 0); existingEpisodes.ForEach(e => e.AbsoluteEpisodeNumber = null);
Mocker.GetMock<IEpisodeService>().Setup(c => c.GetEpisodeBySeries(It.IsAny<Int32>())) Mocker.GetMock<IEpisodeService>().Setup(c => c.GetEpisodeBySeries(It.IsAny<Int32>()))
.Returns(existingEpisodes); .Returns(existingEpisodes);
@ -217,7 +217,7 @@ namespace NzbDrone.Core.Test.TvTests
Subject.RefreshEpisodeInfo(GetAnimeSeries(), episodes); Subject.RefreshEpisodeInfo(GetAnimeSeries(), episodes);
_insertedEpisodes.Should().BeEmpty(); _insertedEpisodes.Should().BeEmpty();
_updatedEpisodes.All(e => e.AbsoluteEpisodeNumber > 0).Should().BeTrue(); _updatedEpisodes.All(e => e.AbsoluteEpisodeNumber.HasValue).Should().BeTrue();
_deletedEpisodes.Should().BeEmpty(); _deletedEpisodes.Should().BeEmpty();
} }
@ -261,10 +261,9 @@ namespace NzbDrone.Core.Test.TvTests
.Build() .Build()
.ToList(); .ToList();
episodes[0].AbsoluteEpisodeNumber = 0; episodes[0].AbsoluteEpisodeNumber = null;
episodes[0].SeasonNumber.Should().NotBe(episodes[1].SeasonNumber); episodes[0].SeasonNumber.Should().NotBe(episodes[1].SeasonNumber);
episodes[0].EpisodeNumber.Should().NotBe(episodes[1].EpisodeNumber); episodes[0].EpisodeNumber.Should().NotBe(episodes[1].EpisodeNumber);
episodes[0].AbsoluteEpisodeNumber.Should().NotBe(episodes[1].AbsoluteEpisodeNumber);
GivenAnimeEpisodes(episodes); GivenAnimeEpisodes(episodes);
@ -286,17 +285,17 @@ namespace NzbDrone.Core.Test.TvTests
} }
[Test] [Test]
public void should_ignore_episodes_with_absolute_episode_of_zero_in_distinct_by_absolute() public void should_ignore_episodes_with_no_absolute_episode_in_distinct_by_absolute()
{ {
var episodes = Builder<Episode>.CreateListOfSize(10) var episodes = Builder<Episode>.CreateListOfSize(10)
.Build() .Build()
.ToList(); .ToList();
episodes[0].AbsoluteEpisodeNumber = 0; episodes[0].AbsoluteEpisodeNumber = null;
episodes[1].AbsoluteEpisodeNumber = 0; episodes[1].AbsoluteEpisodeNumber = null;
episodes[2].AbsoluteEpisodeNumber = 0; episodes[2].AbsoluteEpisodeNumber = null;
episodes[3].AbsoluteEpisodeNumber = 0; episodes[3].AbsoluteEpisodeNumber = null;
episodes[4].AbsoluteEpisodeNumber = 0; episodes[4].AbsoluteEpisodeNumber = null;
GivenAnimeEpisodes(episodes); GivenAnimeEpisodes(episodes);

@ -49,9 +49,9 @@ namespace NzbDrone.Core.DataAugmentation.Xem
foreach (var episode in episodes) foreach (var episode in episodes)
{ {
episode.SceneAbsoluteEpisodeNumber = 0; episode.SceneAbsoluteEpisodeNumber = null;
episode.SceneSeasonNumber = 0; episode.SceneSeasonNumber = null;
episode.SceneEpisodeNumber = 0; episode.SceneEpisodeNumber = null;
} }
foreach (var mapping in mappings) foreach (var mapping in mappings)

@ -0,0 +1,16 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(65)]
public class make_scene_numbering_nullable : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Execute.Sql("UPDATE Episodes SET AbsoluteEpisodeNumber = NULL WHERE AbsoluteEpisodeNumber = 0");
Execute.Sql("UPDATE Episodes SET SceneAbsoluteEpisodeNumber = NULL WHERE SceneAbsoluteEpisodeNumber = 0");
Execute.Sql("UPDATE Episodes SET SceneSeasonNumber = NULL, SceneEpisodeNumber = NULL WHERE SceneSeasonNumber = 0 AND SceneEpisodeNumber = 0");
}
}
}

@ -139,32 +139,24 @@ namespace NzbDrone.Core.Download
var downloadClientHistory = downloadClient.GetItems().ToList(); var downloadClientHistory = downloadClient.GetItems().ToList();
foreach (var downloadItem in downloadClientHistory) foreach (var downloadItem in downloadClientHistory)
{ {
try var trackingId = String.Format("{0}-{1}", downloadClient.Definition.Id, downloadItem.DownloadClientId);
{ TrackedDownload trackedDownload;
var trackingId = String.Format("{0}-{1}", downloadClient.Definition.Id, downloadItem.DownloadClientId);
TrackedDownload trackedDownload;
if (newTrackedDownloads.ContainsKey(trackingId)) continue; if (newTrackedDownloads.ContainsKey(trackingId)) continue;
if (!oldTrackedDownloads.TryGetValue(trackingId, out trackedDownload)) if (!oldTrackedDownloads.TryGetValue(trackingId, out trackedDownload))
{ {
trackedDownload = GetTrackedDownload(trackingId, downloadClient.Definition.Id, downloadItem, trackedDownload = GetTrackedDownload(trackingId, downloadClient.Definition.Id, downloadItem, grabbedHistory);
grabbedHistory);
if (trackedDownload == null) continue; if (trackedDownload == null) continue;
_logger.Debug("[{0}] Started tracking download with id {1}.", downloadItem.Title, trackingId); _logger.Debug("[{0}] Started tracking download with id {1}.", downloadItem.Title, trackingId);
stateChanged = true; stateChanged = true;
} }
trackedDownload.DownloadItem = downloadItem; trackedDownload.DownloadItem = downloadItem;
newTrackedDownloads[trackingId] = trackedDownload; newTrackedDownloads[trackingId] = trackedDownload;
}
catch (Exception e)
{
_logger.ErrorException("An error occured while tracking download." + downloadItem.Title, e);
}
} }
} }
@ -243,34 +235,42 @@ namespace NzbDrone.Core.Download
Status = TrackedDownloadStatus.Ok, Status = TrackedDownloadStatus.Ok,
}; };
var historyItems = grabbedHistory.Where(h =>
{
var downloadClientId = h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID);
if (downloadClientId == null) return false; try
{
var historyItems = grabbedHistory.Where(h =>
{
var downloadClientId = h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID);
if (downloadClientId == null) return false;
return downloadClientId.Equals(trackedDownload.DownloadItem.DownloadClientId); return downloadClientId.Equals(trackedDownload.DownloadItem.DownloadClientId);
}).ToList(); }).ToList();
var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title); var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
if (parsedEpisodeInfo == null) return null; if (parsedEpisodeInfo == null) return null;
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0); var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
if (remoteEpisode.Series == null)
{
if (historyItems.Empty()) return null;
if (remoteEpisode.Series == null) trackedDownload.Status = TrackedDownloadStatus.Warning;
{ trackedDownload.StatusMessages.Add(new TrackedDownloadStatusMessage(
if (historyItems.Empty()) return null; trackedDownload.DownloadItem.Title,
"Series title mismatch, automatic import is not possible")
);
trackedDownload.Status = TrackedDownloadStatus.Warning; remoteEpisode = _parsingService.Map(parsedEpisodeInfo, historyItems.First().SeriesId, historyItems.Select(h => h.EpisodeId));
trackedDownload.StatusMessages.Add(new TrackedDownloadStatusMessage( }
trackedDownload.DownloadItem.Title,
"Series title mismatch, automatic import is not possible")
);
remoteEpisode = _parsingService.Map(parsedEpisodeInfo, historyItems.First().SeriesId, historyItems.Select(h => h.EpisodeId)); trackedDownload.RemoteEpisode = remoteEpisode;
}
catch (Exception e)
{
_logger.DebugException("Failed to find episode for " + downloadItem.Title, e);
return null;
} }
trackedDownload.RemoteEpisode = remoteEpisode;
return trackedDownload; return trackedDownload;
} }

@ -103,7 +103,7 @@ namespace NzbDrone.Core.Download
} }
else else
{ {
if (FailedDownloadForRecentRelease(downloadClient, trackedDownload, grabbedItems)) if (FailedDownloadForRecentRelease(downloadClient, trackedDownload, grabbedItems))
{ {
_logger.Debug("[{0}] Recent release Failed, do not blacklist.", trackedDownload.DownloadItem.Title); _logger.Debug("[{0}] Recent release Failed, do not blacklist.", trackedDownload.DownloadItem.Title);
return; return;

@ -102,13 +102,14 @@ namespace NzbDrone.Core.IndexerSearch
{ {
var sceneSeasonGroups = episodes.GroupBy(v => var sceneSeasonGroups = episodes.GroupBy(v =>
{ {
if (v.SceneSeasonNumber == 0 && v.SceneEpisodeNumber == 0) if (v.SceneSeasonNumber.HasValue && v.SceneEpisodeNumber.HasValue)
{
return v.SceneSeasonNumber.Value;
}
else
{ {
return v.SeasonNumber; return v.SeasonNumber;
} }
return v.SceneSeasonNumber;
}).Distinct(); }).Distinct();
foreach (var sceneSeasonEpisodes in sceneSeasonGroups) foreach (var sceneSeasonEpisodes in sceneSeasonGroups)
@ -118,10 +119,10 @@ namespace NzbDrone.Core.IndexerSearch
var episode = sceneSeasonEpisodes.First(); var episode = sceneSeasonEpisodes.First();
var searchSpec = Get<SingleEpisodeSearchCriteria>(series, sceneSeasonEpisodes.ToList()); var searchSpec = Get<SingleEpisodeSearchCriteria>(series, sceneSeasonEpisodes.ToList());
searchSpec.SeasonNumber = sceneSeasonEpisodes.Key; searchSpec.SeasonNumber = sceneSeasonEpisodes.Key;
if (episode.SceneSeasonNumber == 0 && episode.SceneEpisodeNumber == 0) if (episode.SceneSeasonNumber.HasValue && episode.SceneEpisodeNumber.HasValue)
searchSpec.EpisodeNumber = episode.EpisodeNumber; searchSpec.EpisodeNumber = episode.SceneEpisodeNumber.Value;
else else
searchSpec.EpisodeNumber = episode.SceneEpisodeNumber; searchSpec.EpisodeNumber = episode.EpisodeNumber;
var decisions = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec); var decisions = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec);
downloadDecisions.AddRange(decisions); downloadDecisions.AddRange(decisions);
@ -152,19 +153,10 @@ namespace NzbDrone.Core.IndexerSearch
{ {
var searchSpec = Get<SingleEpisodeSearchCriteria>(series, new List<Episode>{episode}); var searchSpec = Get<SingleEpisodeSearchCriteria>(series, new List<Episode>{episode});
if (series.UseSceneNumbering) if (series.UseSceneNumbering && episode.SceneSeasonNumber.HasValue && episode.SceneEpisodeNumber.HasValue)
{ {
if (episode.SceneSeasonNumber > 0 && episode.SceneEpisodeNumber > 0) searchSpec.EpisodeNumber = episode.SceneEpisodeNumber.Value;
{ searchSpec.SeasonNumber = episode.SceneSeasonNumber.Value;
searchSpec.EpisodeNumber = episode.SceneEpisodeNumber;
searchSpec.SeasonNumber = episode.SceneSeasonNumber;
}
else
{
searchSpec.EpisodeNumber = episode.EpisodeNumber;
searchSpec.SeasonNumber = episode.SeasonNumber;
}
} }
else else
{ {
@ -187,16 +179,18 @@ namespace NzbDrone.Core.IndexerSearch
private List<DownloadDecision> SearchAnime(Series series, Episode episode) private List<DownloadDecision> SearchAnime(Series series, Episode episode)
{ {
var searchSpec = Get<AnimeEpisodeSearchCriteria>(series, new List<Episode> { episode }); var searchSpec = Get<AnimeEpisodeSearchCriteria>(series, new List<Episode> { episode });
searchSpec.AbsoluteEpisodeNumber = episode.SceneAbsoluteEpisodeNumber.GetValueOrDefault(0);
if (searchSpec.AbsoluteEpisodeNumber == 0) if (episode.SceneAbsoluteEpisodeNumber.HasValue)
{ {
searchSpec.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber.GetValueOrDefault(0); searchSpec.AbsoluteEpisodeNumber = episode.SceneAbsoluteEpisodeNumber.Value;
} }
else if (episode.AbsoluteEpisodeNumber.HasValue)
if (searchSpec.AbsoluteEpisodeNumber == 0) {
searchSpec.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber.Value;
}
else
{ {
throw new ArgumentOutOfRangeException("AbsoluteEpisodeNumber", "Can not search for an episode absolute episode number of zero"); throw new ArgumentOutOfRangeException("AbsoluteEpisodeNumber", "Can not search for an episode without an absolute episode number");
} }
return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec); return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec);
@ -232,7 +226,7 @@ namespace NzbDrone.Core.IndexerSearch
spec.Series = series; spec.Series = series;
spec.SceneTitles = _sceneMapping.GetSceneNames(series.TvdbId, spec.SceneTitles = _sceneMapping.GetSceneNames(series.TvdbId,
episodes.Select(e => e.SeasonNumber) episodes.Select(e => e.SeasonNumber)
.Concat(episodes.Select(e => e.SceneSeasonNumber) .Concat(episodes.Select(e => e.SceneSeasonNumber.Value)
.Distinct())); .Distinct()));
spec.Episodes = episodes; spec.Episodes = episodes;

@ -2,6 +2,7 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using NzbDrone.Common;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
@ -39,7 +40,11 @@ namespace NzbDrone.Core.MetadataSource.Tvdb
var episode = new Episode(); var episode = new Episode();
episode.SeasonNumber = item.TryGetValue("SeasonNumber", 0); episode.SeasonNumber = item.TryGetValue("SeasonNumber", 0);
episode.EpisodeNumber = item.TryGetValue("EpisodeNumber", 0); episode.EpisodeNumber = item.TryGetValue("EpisodeNumber", 0);
episode.AbsoluteEpisodeNumber = item.TryGetValue("absolute_number", 0);
if (item.TryGetValue("absolute_number").IsNotNullOrWhiteSpace())
{
episode.AbsoluteEpisodeNumber = item.TryGetValue("absolute_number", 0);
}
return episode; return episode;
} }

@ -229,6 +229,7 @@
<Compile Include="Datastore\Migration\061_clear_bad_scene_names.cs" /> <Compile Include="Datastore\Migration\061_clear_bad_scene_names.cs" />
<Compile Include="Datastore\Migration\060_remove_enable_from_indexers.cs" /> <Compile Include="Datastore\Migration\060_remove_enable_from_indexers.cs" />
<Compile Include="Datastore\Migration\062_convert_quality_models.cs" /> <Compile Include="Datastore\Migration\062_convert_quality_models.cs" />
<Compile Include="Datastore\Migration\065_make_scene_numbering_nullable.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />

@ -111,7 +111,7 @@ namespace NzbDrone.Core.Organizer
pattern = namingConfig.DailyEpisodeFormat; pattern = namingConfig.DailyEpisodeFormat;
} }
if (series.SeriesType == SeriesTypes.Anime && episodes.All(e => e.AbsoluteEpisodeNumber > 0)) if (series.SeriesType == SeriesTypes.Anime && episodes.All(e => e.AbsoluteEpisodeNumber.HasValue))
{ {
pattern = namingConfig.AnimeEpisodeFormat; pattern = namingConfig.AnimeEpisodeFormat;
} }

@ -27,8 +27,8 @@ namespace NzbDrone.Core.Tv
public Boolean Monitored { get; set; } public Boolean Monitored { get; set; }
public Nullable<Int32> AbsoluteEpisodeNumber { get; set; } public Nullable<Int32> AbsoluteEpisodeNumber { get; set; }
public Nullable<Int32> SceneAbsoluteEpisodeNumber { get; set; } public Nullable<Int32> SceneAbsoluteEpisodeNumber { get; set; }
public int SceneSeasonNumber { get; set; } public Nullable<Int32> SceneSeasonNumber { get; set; }
public int SceneEpisodeNumber { get; set; } public Nullable<Int32> SceneEpisodeNumber { get; set; }
public Ratings Ratings { get; set; } public Ratings Ratings { get; set; }
public List<MediaCover.MediaCover> Images { get; set; } public List<MediaCover.MediaCover> Images { get; set; }

@ -183,10 +183,10 @@ namespace NzbDrone.Core.Tv
episode.AbsoluteEpisodeNumber = tvdbEpisode.AbsoluteEpisodeNumber; episode.AbsoluteEpisodeNumber = tvdbEpisode.AbsoluteEpisodeNumber;
} }
//Return all episodes with abs 0, but distinct by abs for ones greater than 0 //Return all episodes with no abs number, but distinct for those with abs number
return traktEpisodes.Where(e => e.AbsoluteEpisodeNumber > 0) return traktEpisodes.Where(e => e.AbsoluteEpisodeNumber.HasValue)
.DistinctBy(e => e.AbsoluteEpisodeNumber) .DistinctBy(e => e.AbsoluteEpisodeNumber.Value)
.Concat(traktEpisodes.Where(e => e.AbsoluteEpisodeNumber == 0)) .Concat(traktEpisodes.Where(e => !e.AbsoluteEpisodeNumber.HasValue))
.ToList(); .ToList();
} }
@ -194,7 +194,7 @@ namespace NzbDrone.Core.Tv
{ {
if (series.SeriesType == SeriesTypes.Anime) if (series.SeriesType == SeriesTypes.Anime)
{ {
if (episode.AbsoluteEpisodeNumber > 0) if (episode.AbsoluteEpisodeNumber.HasValue)
{ {
var matchingEpisode = existingEpisodes.FirstOrDefault(e => e.AbsoluteEpisodeNumber == episode.AbsoluteEpisodeNumber); var matchingEpisode = existingEpisodes.FirstOrDefault(e => e.AbsoluteEpisodeNumber == episode.AbsoluteEpisodeNumber);
@ -209,10 +209,10 @@ namespace NzbDrone.Core.Tv
{ {
if (series.SeriesType == SeriesTypes.Anime) if (series.SeriesType == SeriesTypes.Anime)
{ {
var withAbs = episodes.Where(e => e.AbsoluteEpisodeNumber > 0) var withAbs = episodes.Where(e => e.AbsoluteEpisodeNumber.HasValue)
.OrderBy(e => e.AbsoluteEpisodeNumber); .OrderBy(e => e.AbsoluteEpisodeNumber);
var withoutAbs = episodes.Where(e => e.AbsoluteEpisodeNumber == 0) var withoutAbs = episodes.Where(e => !e.AbsoluteEpisodeNumber.HasValue)
.OrderBy(e => e.SeasonNumber) .OrderBy(e => e.SeasonNumber)
.ThenBy(e => e.EpisodeNumber); .ThenBy(e => e.EpisodeNumber);

@ -36,7 +36,7 @@ define(
episodes = this.cellValue.get(episodeField); episodes = this.cellValue.get(episodeField);
} }
if (!absoluteEpisodeNumber) { if (absoluteEpisodeNumber === undefined) {
absoluteEpisodeNumber = this.cellValue.get(absoluteEpisodeField); absoluteEpisodeNumber = this.cellValue.get(absoluteEpisodeField);
} }
@ -62,7 +62,7 @@ define(
result = '{0}x{1}'.format(seasonNumber, paddedEpisodes); result = '{0}x{1}'.format(seasonNumber, paddedEpisodes);
if (absoluteEpisodeNumber > 0 && paddedAbsoluteEpisode) { if (absoluteEpisodeNumber !== undefined && paddedAbsoluteEpisode) {
result += ' ({0})'.format(paddedAbsoluteEpisode); result += ' ({0})'.format(paddedAbsoluteEpisode);
} }
} }

@ -11,7 +11,7 @@ define(
return moment(this.airDate).format('L'); return moment(this.airDate).format('L');
} }
else if (this.series.seriesType === 'anime' && this.absoluteEpisodeNumber > 0) { else if (this.series.seriesType === 'anime' && this.absoluteEpisodeNumber !== undefined) {
return '{0}x{1} ({2})'.format(this.seasonNumber, FormatHelpers.pad(this.episodeNumber, 2), FormatHelpers.pad(this.absoluteEpisodeNumber, 2)); return '{0}x{1} ({2})'.format(this.seasonNumber, FormatHelpers.pad(this.episodeNumber, 2), FormatHelpers.pad(this.absoluteEpisodeNumber, 2));
} }

@ -42,7 +42,7 @@ define(
if (this.model.get('sceneSeasonNumber') > 0 || if (this.model.get('sceneSeasonNumber') > 0 ||
this.model.get('sceneEpisodeNumber') > 0 || this.model.get('sceneEpisodeNumber') > 0 ||
(this.model.has('sceneAbsoluteEpisodeNumber') && this.model.get('sceneAbsoluteEpisodeNumber') > 0) || this.model.has('sceneAbsoluteEpisodeNumber') ||
alternateTitles.length > 0) alternateTitles.length > 0)
{ {
this.templateFunction = Marionette.TemplateCache.get(this.template); this.templateFunction = Marionette.TemplateCache.get(this.template);

@ -15,7 +15,7 @@ define(
if (SeriesCollection.get(this.model.get('seriesId')).get('seriesType') === 'anime') { if (SeriesCollection.get(this.model.get('seriesId')).get('seriesType') === 'anime') {
if (this.model.get('seasonNumber') > 0 && this.model.get('absoluteEpisodeNumber') === 0) { if (this.model.get('seasonNumber') > 0 && !this.model.has('absoluteEpisodeNumber')) {
this.$el.html('<i class="icon-nd-form-warning" title="Episode does not have an absolute episode number"></i>'); this.$el.html('<i class="icon-nd-form-warning" title="Episode does not have an absolute episode number"></i>');
} }
} }

Loading…
Cancel
Save