mirror of
https://github.com/Sonarr/Sonarr
synced 2026-05-08 13:01:10 +02:00
Merge ee210600b6 into 510cbe54e8
This commit is contained in:
commit
aeb31aa8aa
9 changed files with 79 additions and 7 deletions
|
|
@ -7,6 +7,7 @@
|
|||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
|
@ -60,6 +61,10 @@ public void SetUp()
|
|||
Mocker.GetMock<ISceneMappingService>()
|
||||
.Setup(s => s.GetSceneNames(It.IsAny<int>(), It.IsAny<List<int>>(), It.IsAny<List<int>>()))
|
||||
.Returns(new List<string>());
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.AnimeSeasonSearchFallback)
|
||||
.Returns(AnimeSeasonSearchFallback.Always);
|
||||
}
|
||||
|
||||
private void WithEpisode(int seasonNumber, int episodeNumber, int? sceneSeasonNumber, int? sceneEpisodeNumber, string airDate = null)
|
||||
|
|
|
|||
|
|
@ -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.Always); }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -421,9 +425,44 @@ private async Task<List<DownloadDecision>> SearchAnimeSeason(Series series, List
|
|||
downloadDecisions.AddRange(decisions);
|
||||
}
|
||||
|
||||
foreach (var episode in episodesToSearch)
|
||||
// Only skip per-episode fallback if we got approved season results.
|
||||
// Indexers like AB return all results for a title regardless of season
|
||||
// params, so raw result count alone is not reliable.
|
||||
// For interactive search, always run per-episode so the user can see
|
||||
// and pick individual releases regardless of whether a pack was found.
|
||||
if (!interactiveSearch && downloadDecisions.Any(d => d.Approved))
|
||||
{
|
||||
downloadDecisions.AddRange(await SearchAnime(series, episode, monitoredOnly, userInvokedSearch, interactiveSearch, true));
|
||||
_logger.Debug("Season search returned approved results for {0}, skipping per-episode search for {1} episodes", series.Title, episodesToSearch.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fallbackSetting = _configService.AnimeSeasonSearchFallback;
|
||||
var allEpisodesAired = episodesToSearch.All(e => e.AirDateUtc.HasValue && e.AirDateUtc.Value.Before(DateTime.UtcNow));
|
||||
|
||||
var shouldFallback = interactiveSearch || (fallbackSetting switch
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return DeDupeDecisions(downloadDecisions);
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ public virtual IndexerPageableRequestChain GetSearchRequests(AnimeSeasonSearchCr
|
|||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
|
||||
if (SupportsSearch && Settings.AnimeStandardFormatSearch && searchCriteria.SeasonNumber > 0)
|
||||
if (SupportsSearch && searchCriteria.SeasonNumber > 0)
|
||||
{
|
||||
AddTvIdPageableRequests(pageableRequests,
|
||||
Settings.AnimeCategories,
|
||||
|
|
|
|||
|
|
@ -87,9 +87,9 @@ public virtual IndexerPageableRequestChain GetSearchRequests(AnimeSeasonSearchCr
|
|||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
|
||||
foreach (var searchTitle in searchCriteria.SceneTitles.Select(PrepareQuery))
|
||||
if (searchCriteria.SeasonNumber > 0)
|
||||
{
|
||||
if (Settings.AnimeStandardFormatSearch && searchCriteria.SeasonNumber > 0)
|
||||
foreach (var searchTitle in searchCriteria.SceneTitles.Select(PrepareQuery))
|
||||
{
|
||||
pageableRequests.Add(GetPagedRequests($"{searchTitle}+s{searchCriteria.SeasonNumber:00}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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