mirror of
https://github.com/Sonarr/Sonarr
synced 2026-05-08 13:01:10 +02:00
Add AnimeSeasonSearchFallback enum for per-episode fallback control
Configurable setting (default: FullSeasonNotAired) that controls when per-episode fallback fires after season search finds no approved results: - Never: season search only, no fallback - Always: always fall back to per-episode - FullSeasonAired: fall back only for completed seasons - FullSeasonNotAired: fall back only for still-airing seasons (default) The default avoids wasting API hits on completed seasons where packs should exist, while still searching per-episode for airing seasons where no pack can exist yet. Based on design discussion with markus101 on Discord.
This commit is contained in:
parent
018f66ab6f
commit
32c3836a06
6 changed files with 58 additions and 5 deletions
|
|
@ -7,6 +7,7 @@
|
|||
using NzbDrone.Common.Http.Proxy;
|
||||
using NzbDrone.Core.Configuration.Events;
|
||||
using NzbDrone.Core.ImportLists;
|
||||
using NzbDrone.Core.IndexerSearch;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
|
|
@ -129,6 +130,13 @@ public int MinimumAge
|
|||
set { SetValue("MinimumAge", value); }
|
||||
}
|
||||
|
||||
public AnimeSeasonSearchFallback AnimeSeasonSearchFallback
|
||||
{
|
||||
get { return GetValueEnum("AnimeSeasonSearchFallback", AnimeSeasonSearchFallback.FullSeasonNotAired); }
|
||||
|
||||
set { SetValue("AnimeSeasonSearchFallback", value); }
|
||||
}
|
||||
|
||||
public ProperDownloadTypes DownloadPropersAndRepacks
|
||||
{
|
||||
get { return GetValueEnum("DownloadPropersAndRepacks", ProperDownloadTypes.PreferAndUpgrade); }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Http.Proxy;
|
||||
using NzbDrone.Core.ImportLists;
|
||||
using NzbDrone.Core.IndexerSearch;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
|
@ -52,6 +53,9 @@ public interface IConfigService
|
|||
string ChmodFolder { get; set; }
|
||||
string ChownGroup { get; set; }
|
||||
|
||||
// Anime Season Search
|
||||
AnimeSeasonSearchFallback AnimeSeasonSearchFallback { get; set; }
|
||||
|
||||
// Indexers
|
||||
int Retention { get; set; }
|
||||
int RssSyncInterval { get; set; }
|
||||
|
|
|
|||
10
src/NzbDrone.Core/IndexerSearch/AnimeSeasonSearchFallback.cs
Normal file
10
src/NzbDrone.Core/IndexerSearch/AnimeSeasonSearchFallback.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public enum AnimeSeasonSearchFallback
|
||||
{
|
||||
Never = 0,
|
||||
Always = 1,
|
||||
FullSeasonAired = 2,
|
||||
FullSeasonNotAired = 3
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
|
@ -32,6 +33,7 @@ public class ReleaseSearchService : ISearchForReleases
|
|||
private readonly ISeriesService _seriesService;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly IMakeDownloadDecision _makeDownloadDecision;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ReleaseSearchService(IIndexerFactory indexerFactory,
|
||||
|
|
@ -39,6 +41,7 @@ public ReleaseSearchService(IIndexerFactory indexerFactory,
|
|||
ISeriesService seriesService,
|
||||
IEpisodeService episodeService,
|
||||
IMakeDownloadDecision makeDownloadDecision,
|
||||
IConfigService configService,
|
||||
Logger logger)
|
||||
{
|
||||
_indexerFactory = indexerFactory;
|
||||
|
|
@ -46,6 +49,7 @@ public ReleaseSearchService(IIndexerFactory indexerFactory,
|
|||
_seriesService = seriesService;
|
||||
_episodeService = episodeService;
|
||||
_makeDownloadDecision = makeDownloadDecision;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
@ -430,11 +434,32 @@ private async Task<List<DownloadDecision>> SearchAnimeSeason(Series series, List
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("No approved season results for {0}, falling back to per-episode search for {1} episodes", series.Title, episodesToSearch.Count);
|
||||
var fallbackSetting = _configService.AnimeSeasonSearchFallback;
|
||||
var allEpisodesAired = episodesToSearch.All(e => e.AirDateUtc.HasValue && e.AirDateUtc.Value.Before(DateTime.UtcNow));
|
||||
|
||||
foreach (var episode in episodesToSearch)
|
||||
var shouldFallback = fallbackSetting switch
|
||||
{
|
||||
downloadDecisions.AddRange(await SearchAnime(series, episode, monitoredOnly, userInvokedSearch, interactiveSearch, true));
|
||||
AnimeSeasonSearchFallback.Never => false,
|
||||
AnimeSeasonSearchFallback.Always => true,
|
||||
AnimeSeasonSearchFallback.FullSeasonAired => allEpisodesAired,
|
||||
AnimeSeasonSearchFallback.FullSeasonNotAired => !allEpisodesAired,
|
||||
_ => !allEpisodesAired
|
||||
};
|
||||
|
||||
if (shouldFallback)
|
||||
{
|
||||
_logger.Debug("No approved season results for {0}, falling back to per-episode search for {1} episodes (fallback: {2}, allAired: {3})",
|
||||
series.Title, episodesToSearch.Count, fallbackSetting, allEpisodesAired);
|
||||
|
||||
foreach (var episode in episodesToSearch)
|
||||
{
|
||||
downloadDecisions.AddRange(await SearchAnime(series, episode, monitoredOnly, userInvokedSearch, interactiveSearch, true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("No approved season results for {0}, per-episode fallback skipped (fallback: {1}, allAired: {2})",
|
||||
series.Title, fallbackSetting, allEpisodesAired);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch;
|
||||
using Sonarr.Http.REST;
|
||||
|
||||
namespace Sonarr.Api.V3.Config
|
||||
|
|
@ -9,6 +10,7 @@ public class IndexerConfigResource : RestResource
|
|||
public int Retention { get; set; }
|
||||
public int MaximumSize { get; set; }
|
||||
public int RssSyncInterval { get; set; }
|
||||
public AnimeSeasonSearchFallback AnimeSeasonSearchFallback { get; set; }
|
||||
}
|
||||
|
||||
public static class IndexerConfigResourceMapper
|
||||
|
|
@ -20,7 +22,8 @@ public static IndexerConfigResource ToResource(IConfigService model)
|
|||
MinimumAge = model.MinimumAge,
|
||||
Retention = model.Retention,
|
||||
MaximumSize = model.MaximumSize,
|
||||
RssSyncInterval = model.RssSyncInterval
|
||||
RssSyncInterval = model.RssSyncInterval,
|
||||
AnimeSeasonSearchFallback = model.AnimeSeasonSearchFallback
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch;
|
||||
using Sonarr.Http.REST;
|
||||
|
||||
namespace Sonarr.Api.V5.Settings
|
||||
|
|
@ -9,6 +10,7 @@ public class IndexerSettingsResource : RestResource
|
|||
public int Retention { get; set; }
|
||||
public int MaximumSize { get; set; }
|
||||
public int RssSyncInterval { get; set; }
|
||||
public AnimeSeasonSearchFallback AnimeSeasonSearchFallback { get; set; }
|
||||
}
|
||||
|
||||
public static class IndexerConfigResourceMapper
|
||||
|
|
@ -20,7 +22,8 @@ public static IndexerSettingsResource ToResource(IConfigService model)
|
|||
MinimumAge = model.MinimumAge,
|
||||
Retention = model.Retention,
|
||||
MaximumSize = model.MaximumSize,
|
||||
RssSyncInterval = model.RssSyncInterval
|
||||
RssSyncInterval = model.RssSyncInterval,
|
||||
AnimeSeasonSearchFallback = model.AnimeSeasonSearchFallback
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue