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().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.Series)
.Ignore(e => e.HasFile)
.Ignore(e => e.AbsoluteEpisodeNumberAdded)
.HasOne(s => s.EpisodeFile, s => s.EpisodeFileId);
Mapper.Entity<QualityDefinition>("QualityDefinitions").RegisterModel()

View File

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

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
@ -11,19 +11,19 @@ using NzbDrone.Core.Tv.Events;
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 IEpisodeService _episodeService;
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,
IEpisodeService episodeService,
Logger logger)
@ -31,12 +31,12 @@ namespace NzbDrone.Core.Tv
_commandQueueManager = commandQueueManager;
_episodeService = episodeService;
_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())
{
@ -48,7 +48,7 @@ namespace NzbDrone.Core.Tv
}
}
_addedEpisodesCache.Remove(seriesId.ToString());
_searchCache.Remove(seriesId.ToString());
}
public void Handle(EpisodeInfoRefreshedEvent message)
@ -61,29 +61,39 @@ namespace NzbDrone.Core.Tv
return;
}
if (message.Added.Empty())
{
_logger.Debug("No new episodes, skipping search");
return;
}
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();
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())
{
_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);
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
{

View File

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