New: Search for recently aired anime episodes with added absolute episode number

Closes #2044
This commit is contained in:
Mark McDowall 2024-02-25 15:16:06 -08:00 committed by Mark McDowall
parent 33b44a8a53
commit 6dc0a88004
6 changed files with 79 additions and 31 deletions

View File

@ -453,5 +453,33 @@ namespace NzbDrone.Core.Test.TvTests
_updatedEpisodes.First().EpisodeNumber.Should().Be(episodes[1].EpisodeNumber); _updatedEpisodes.First().EpisodeNumber.Should().Be(episodes[1].EpisodeNumber);
_updatedEpisodes.First().AbsoluteEpisodeNumber.Should().Be(episodes[1].AbsoluteEpisodeNumber); _updatedEpisodes.First().AbsoluteEpisodeNumber.Should().Be(episodes[1].AbsoluteEpisodeNumber);
} }
[Test]
public void should_mark_updated_episodes_that_have_newly_added_absolute_episode_number()
{
var episodes = Builder<Episode>.CreateListOfSize(3)
.Build()
.ToList();
var existingEpisodes = new List<Episode>
{
episodes[0],
episodes[1]
};
existingEpisodes[0].AbsoluteEpisodeNumber = null;
Mocker.GetMock<IEpisodeService>().Setup(c => c.GetEpisodeBySeries(It.IsAny<int>()))
.Returns(existingEpisodes);
Subject.RefreshEpisodeInfo(GetAnimeSeries(), episodes);
_updatedEpisodes.First().SeasonNumber.Should().Be(episodes[1].SeasonNumber);
_updatedEpisodes.First().EpisodeNumber.Should().Be(episodes[1].EpisodeNumber);
_updatedEpisodes.First().AbsoluteEpisodeNumber.Should().NotBeNull();
_updatedEpisodes.First().AbsoluteEpisodeNumberAdded.Should().BeTrue();
_insertedEpisodes.Any(e => e.AbsoluteEpisodeNumberAdded).Should().BeFalse();
}
} }
} }

View File

@ -126,6 +126,7 @@ namespace NzbDrone.Core.Datastore
.Ignore(e => e.SeriesTitle) .Ignore(e => e.SeriesTitle)
.Ignore(e => e.Series) .Ignore(e => e.Series)
.Ignore(e => e.HasFile) .Ignore(e => e.HasFile)
.Ignore(e => e.AbsoluteEpisodeNumberAdded)
.HasOne(s => s.EpisodeFile, s => s.EpisodeFileId); .HasOne(s => s.EpisodeFile, s => s.EpisodeFileId);
Mapper.Entity<QualityDefinition>("QualityDefinitions").RegisterModel() Mapper.Entity<QualityDefinition>("QualityDefinitions").RegisterModel()

View File

@ -46,6 +46,7 @@ namespace NzbDrone.Core.Tv
public Series Series { get; set; } public Series Series { get; set; }
public bool HasFile => EpisodeFileId > 0; public bool HasFile => EpisodeFileId > 0;
public bool AbsoluteEpisodeNumberAdded { get; set; }
public override string ToString() public override string ToString()
{ {

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
@ -11,19 +11,19 @@ using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Core.Tv namespace NzbDrone.Core.Tv
{ {
public interface IEpisodeAddedService public interface IEpisodeRefreshedService
{ {
void SearchForRecentlyAdded(int seriesId); void Search(int seriesId);
} }
public class EpisodeAddedService : IHandle<EpisodeInfoRefreshedEvent>, IEpisodeAddedService public class EpisodeRefreshedService : IEpisodeRefreshedService, IHandle<EpisodeInfoRefreshedEvent>
{ {
private readonly IManageCommandQueue _commandQueueManager; private readonly IManageCommandQueue _commandQueueManager;
private readonly IEpisodeService _episodeService; private readonly IEpisodeService _episodeService;
private readonly Logger _logger; private readonly Logger _logger;
private readonly ICached<List<int>> _addedEpisodesCache; private readonly ICached<List<int>> _searchCache;
public EpisodeAddedService(ICacheManager cacheManager, public EpisodeRefreshedService(ICacheManager cacheManager,
IManageCommandQueue commandQueueManager, IManageCommandQueue commandQueueManager,
IEpisodeService episodeService, IEpisodeService episodeService,
Logger logger) Logger logger)
@ -31,12 +31,12 @@ namespace NzbDrone.Core.Tv
_commandQueueManager = commandQueueManager; _commandQueueManager = commandQueueManager;
_episodeService = episodeService; _episodeService = episodeService;
_logger = logger; _logger = logger;
_addedEpisodesCache = cacheManager.GetCache<List<int>>(GetType()); _searchCache = cacheManager.GetCache<List<int>>(GetType());
} }
public void SearchForRecentlyAdded(int seriesId) public void Search(int seriesId)
{ {
var previouslyAired = _addedEpisodesCache.Find(seriesId.ToString()); var previouslyAired = _searchCache.Find(seriesId.ToString());
if (previouslyAired != null && previouslyAired.Any()) if (previouslyAired != null && previouslyAired.Any())
{ {
@ -48,7 +48,7 @@ namespace NzbDrone.Core.Tv
} }
} }
_addedEpisodesCache.Remove(seriesId.ToString()); _searchCache.Remove(seriesId.ToString());
} }
public void Handle(EpisodeInfoRefreshedEvent message) public void Handle(EpisodeInfoRefreshedEvent message)
@ -61,29 +61,39 @@ namespace NzbDrone.Core.Tv
return; return;
} }
if (message.Added.Empty()) var previouslyAired = message.Added.Where(a =>
{ a.AirDateUtc.HasValue &&
_logger.Debug("No new episodes, skipping search"); a.AirDateUtc.Value.Between(DateTime.UtcNow.AddDays(-14), DateTime.UtcNow.AddDays(1)) &&
return; a.Monitored)
} .ToList();
if (message.Added.None(a => a.AirDateUtc.HasValue))
{
_logger.Debug("No new episodes have an air date");
return;
}
var previouslyAired = message.Added.Where(a => a.AirDateUtc.HasValue
&& a.AirDateUtc.Value.Between(DateTime.UtcNow.AddDays(-14), DateTime.UtcNow.AddDays(1))
&& a.Monitored).ToList();
if (previouslyAired.Empty()) if (previouslyAired.Empty())
{ {
_logger.Debug("Newly added episodes all air in the future"); _logger.Debug("Newly added episodes all air in the future");
return; _searchCache.Set(message.Series.Id.ToString(), previouslyAired.Select(e => e.Id).ToList());
} }
_addedEpisodesCache.Set(message.Series.Id.ToString(), previouslyAired.Select(e => e.Id).ToList()); var absoluteEpisodeNumberAdded = message.Updated.Where(a =>
a.AbsoluteEpisodeNumberAdded &&
a.AirDateUtc.HasValue &&
a.AirDateUtc.Value.Between(DateTime.UtcNow.AddDays(-14), DateTime.UtcNow.AddDays(1)) &&
a.Monitored)
.ToList();
if (absoluteEpisodeNumberAdded.Empty())
{
_logger.Debug("No updated episodes recently aired and had absolute episode number added");
}
var toSearch = new List<int>();
toSearch.AddRange(previouslyAired.Select(e => e.Id));
toSearch.AddRange(absoluteEpisodeNumberAdded.Select(e => e.Id));
if (toSearch.Any())
{
_searchCache.Set(message.Series.Id.ToString(), toSearch.Distinct().ToList());
}
} }
} }
} }

View File

@ -59,6 +59,14 @@ namespace NzbDrone.Core.Tv
{ {
existingEpisodes.Remove(episodeToUpdate); existingEpisodes.Remove(episodeToUpdate);
updateList.Add(episodeToUpdate); updateList.Add(episodeToUpdate);
// Anime series with newly added absolute episode number
if (series.SeriesType == SeriesTypes.Anime &&
!episodeToUpdate.AbsoluteEpisodeNumber.HasValue &&
episode.AbsoluteEpisodeNumber.HasValue)
{
episodeToUpdate.AbsoluteEpisodeNumberAdded = true;
}
} }
else else
{ {

View File

@ -13,7 +13,7 @@ namespace NzbDrone.Core.Tv
private readonly IEpisodeMonitoredService _episodeMonitoredService; private readonly IEpisodeMonitoredService _episodeMonitoredService;
private readonly ISeriesService _seriesService; private readonly ISeriesService _seriesService;
private readonly IManageCommandQueue _commandQueueManager; private readonly IManageCommandQueue _commandQueueManager;
private readonly IEpisodeAddedService _episodeAddedService; private readonly IEpisodeRefreshedService _episodeRefreshedService;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger; private readonly Logger _logger;
@ -21,14 +21,14 @@ namespace NzbDrone.Core.Tv
public SeriesScannedHandler(IEpisodeMonitoredService episodeMonitoredService, public SeriesScannedHandler(IEpisodeMonitoredService episodeMonitoredService,
ISeriesService seriesService, ISeriesService seriesService,
IManageCommandQueue commandQueueManager, IManageCommandQueue commandQueueManager,
IEpisodeAddedService episodeAddedService, IEpisodeRefreshedService episodeRefreshedService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
Logger logger) Logger logger)
{ {
_episodeMonitoredService = episodeMonitoredService; _episodeMonitoredService = episodeMonitoredService;
_seriesService = seriesService; _seriesService = seriesService;
_commandQueueManager = commandQueueManager; _commandQueueManager = commandQueueManager;
_episodeAddedService = episodeAddedService; _episodeRefreshedService = episodeRefreshedService;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_logger = logger; _logger = logger;
} }
@ -39,7 +39,7 @@ namespace NzbDrone.Core.Tv
if (addOptions == null) if (addOptions == null)
{ {
_episodeAddedService.SearchForRecentlyAdded(series.Id); _episodeRefreshedService.Search(series.Id);
return; return;
} }