mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-22 22:14:44 -04:00
Searching refactored
#ND-135 fixed
This commit is contained in:
@@ -13,106 +13,142 @@ namespace NzbDrone.Core.Providers.Search
|
||||
{
|
||||
public abstract class SearchBase
|
||||
{
|
||||
protected readonly SeriesProvider _seriesProvider;
|
||||
protected readonly EpisodeProvider _episodeProvider;
|
||||
protected readonly DownloadProvider _downloadProvider;
|
||||
protected readonly SeriesProvider _seriesProvider;
|
||||
protected readonly IndexerProvider _indexerProvider;
|
||||
protected readonly SceneMappingProvider _sceneMappingProvider;
|
||||
protected readonly UpgradePossibleSpecification _upgradePossibleSpecification;
|
||||
protected readonly AllowedDownloadSpecification _allowedDownloadSpecification;
|
||||
protected readonly SearchHistoryProvider _searchHistoryProvider;
|
||||
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
protected SearchBase(EpisodeProvider episodeProvider, DownloadProvider downloadProvider,SeriesProvider seriesProvider,
|
||||
protected SearchBase(SeriesProvider seriesProvider, EpisodeProvider episodeProvider, DownloadProvider downloadProvider,
|
||||
IndexerProvider indexerProvider, SceneMappingProvider sceneMappingProvider,
|
||||
UpgradePossibleSpecification upgradePossibleSpecification, AllowedDownloadSpecification allowedDownloadSpecification,
|
||||
AllowedDownloadSpecification allowedDownloadSpecification,
|
||||
SearchHistoryProvider searchHistoryProvider)
|
||||
{
|
||||
_seriesProvider = seriesProvider;
|
||||
_episodeProvider = episodeProvider;
|
||||
_downloadProvider = downloadProvider;
|
||||
_seriesProvider = seriesProvider;
|
||||
_indexerProvider = indexerProvider;
|
||||
_sceneMappingProvider = sceneMappingProvider;
|
||||
_upgradePossibleSpecification = upgradePossibleSpecification;
|
||||
_allowedDownloadSpecification = allowedDownloadSpecification;
|
||||
_searchHistoryProvider = searchHistoryProvider;
|
||||
}
|
||||
|
||||
protected SearchBase()
|
||||
public abstract List<EpisodeParseResult> PerformSearch(Series series, dynamic options, ProgressNotification notification);
|
||||
public abstract SearchHistoryItem CheckReport(Series series, dynamic options, EpisodeParseResult episodeParseResult,
|
||||
SearchHistoryItem item);
|
||||
|
||||
protected abstract void FinalizeSearch(Series series, dynamic options, Boolean reportsFound, ProgressNotification notification);
|
||||
|
||||
public virtual List<Int32> Search(Series series, dynamic options, ProgressNotification notification)
|
||||
{
|
||||
if (options == null)
|
||||
throw new ArgumentNullException(options);
|
||||
|
||||
var searchResult = new SearchHistory
|
||||
{
|
||||
SearchTime = DateTime.Now,
|
||||
SeriesId = series.SeriesId,
|
||||
EpisodeId = options.GetType().GetProperty("Episode") != null ? options.Episode.EpisodeId : null
|
||||
};
|
||||
|
||||
List<EpisodeParseResult> reports = PerformSearch(series, options, notification);
|
||||
|
||||
logger.Debug("Finished searching all indexers. Total {0}", reports.Count);
|
||||
notification.CurrentMessage = "Processing search results";
|
||||
|
||||
ProcessReports(series, options, reports, searchResult, notification);
|
||||
_searchHistoryProvider.Add(searchResult);
|
||||
|
||||
if(searchResult.Successes.Any())
|
||||
return searchResult.Successes;
|
||||
|
||||
FinalizeSearch(series, options, reports.Any(), notification);
|
||||
return new List<Int32>();
|
||||
}
|
||||
|
||||
protected abstract List<EpisodeParseResult> Search(Series series, dynamic options);
|
||||
protected abstract SearchHistoryItem CheckEpisode(Series series, List<Episode> episodes, EpisodeParseResult episodeParseResult,
|
||||
SearchHistoryItem item);
|
||||
|
||||
protected virtual SearchHistoryItem ProcessReport(EpisodeParseResult episodeParseResult, Series series, List<Episode> episodes)
|
||||
public virtual SearchHistory ProcessReports(Series series, dynamic options, List<EpisodeParseResult> episodeParseResults,
|
||||
SearchHistory searchResult, ProgressNotification notification)
|
||||
{
|
||||
try
|
||||
var items = new List<SearchHistoryItem>();
|
||||
searchResult.Successes = new List<Int32>();
|
||||
|
||||
foreach(var episodeParseResult in episodeParseResults
|
||||
.OrderByDescending(c => c.Quality)
|
||||
.ThenBy(c => c.EpisodeNumbers.MinOrDefault())
|
||||
.ThenBy(c => c.Age))
|
||||
{
|
||||
var item = new SearchHistoryItem
|
||||
try
|
||||
{
|
||||
ReportTitle = episodeParseResult.OriginalString,
|
||||
NzbUrl = episodeParseResult.NzbUrl,
|
||||
Indexer = episodeParseResult.Indexer,
|
||||
Quality = episodeParseResult.Quality.Quality,
|
||||
Proper = episodeParseResult.Quality.Proper,
|
||||
Size = episodeParseResult.Size,
|
||||
Age = episodeParseResult.Age,
|
||||
Language = episodeParseResult.Language
|
||||
};
|
||||
var item = new SearchHistoryItem
|
||||
{
|
||||
ReportTitle = episodeParseResult.OriginalString,
|
||||
NzbUrl = episodeParseResult.NzbUrl,
|
||||
Indexer = episodeParseResult.Indexer,
|
||||
Quality = episodeParseResult.Quality.Quality,
|
||||
Proper = episodeParseResult.Quality.Proper,
|
||||
Size = episodeParseResult.Size,
|
||||
Age = episodeParseResult.Age,
|
||||
Language = episodeParseResult.Language
|
||||
};
|
||||
|
||||
logger.Trace("Analysing report " + episodeParseResult);
|
||||
items.Add(item);
|
||||
|
||||
//Get the matching series
|
||||
episodeParseResult.Series = _seriesProvider.FindSeries(episodeParseResult.CleanTitle);
|
||||
logger.Trace("Analysing report " + episodeParseResult);
|
||||
episodeParseResult.Series = _seriesProvider.FindSeries(episodeParseResult.CleanTitle);
|
||||
|
||||
//If series is null or doesn't match the series we're looking for return
|
||||
if (episodeParseResult.Series == null || episodeParseResult.Series.SeriesId != series.SeriesId)
|
||||
{
|
||||
item.SearchError = ReportRejectionType.WrongSeries;
|
||||
return item;
|
||||
if(episodeParseResult.Series == null || episodeParseResult.Series.SeriesId != series.SeriesId)
|
||||
{
|
||||
item.SearchError = ReportRejectionType.WrongSeries;
|
||||
continue;
|
||||
}
|
||||
|
||||
episodeParseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(episodeParseResult);
|
||||
|
||||
if (searchResult.Successes.Intersect(episodeParseResult.Episodes.Select(e => e.EpisodeId)).Any())
|
||||
{
|
||||
item.SearchError = ReportRejectionType.Skipped;
|
||||
continue;
|
||||
}
|
||||
|
||||
CheckReport(series, options, episodeParseResult, item);
|
||||
if (item.SearchError != ReportRejectionType.None)
|
||||
continue;
|
||||
|
||||
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
|
||||
|
||||
if(item.SearchError == ReportRejectionType.None)
|
||||
{
|
||||
if(DownloadReport(notification, episodeParseResult, item))
|
||||
searchResult.Successes.AddRange(episodeParseResult.Episodes.Select(e => e.EpisodeId));
|
||||
}
|
||||
}
|
||||
|
||||
//If parse result doesn't have an air date or it doesn't match passed in airdate, skip the report.
|
||||
if (CheckEpisode(series, episodes, item).SearchError != ReportRejectionType.None)
|
||||
catch(Exception e)
|
||||
{
|
||||
return item;
|
||||
logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e);
|
||||
}
|
||||
|
||||
episodeParseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(episodeParseResult);
|
||||
|
||||
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
|
||||
return item;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
searchResult.SearchHistoryItems = items;
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
protected virtual SearchHistoryItem DownloadReport(ProgressNotification notification, EpisodeParseResult episodeParseResult, SearchHistoryItem item)
|
||||
public virtual Boolean DownloadReport(ProgressNotification notification, EpisodeParseResult episodeParseResult, SearchHistoryItem item)
|
||||
{
|
||||
//Todo: Customize download message per search type? (override)
|
||||
|
||||
logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult);
|
||||
try
|
||||
{
|
||||
if (_downloadProvider.DownloadReport(episodeParseResult))
|
||||
{
|
||||
notification.CurrentMessage =
|
||||
String.Format("{0} - {1} {2} Added to download queue",
|
||||
episodeParseResult.Series.Title, episodeParseResult.AirDate.Value.ToShortDateString(), episodeParseResult.Quality);
|
||||
|
||||
notification.CurrentMessage = String.Format("{0} Added to download queue", episodeParseResult);
|
||||
item.Success = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SearchError = ReportRejectionType.DownloadClientFailure;
|
||||
}
|
||||
|
||||
item.SearchError = ReportRejectionType.DownloadClientFailure;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -121,12 +157,13 @@ namespace NzbDrone.Core.Providers.Search
|
||||
item.SearchError = ReportRejectionType.DownloadClientFailure;
|
||||
}
|
||||
|
||||
return item;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual string GetSeriesTitle(Series series, int seasonNumber = -1)
|
||||
{
|
||||
public virtual string GetSearchTitle(Series series, int seasonNumber = -1)
|
||||
{
|
||||
//Todo: Add support for per season lookup (used for anime)
|
||||
//Todo: Add support for multiple names
|
||||
var title = _sceneMappingProvider.GetSceneName(series.SeriesId);
|
||||
|
||||
if (String.IsNullOrWhiteSpace(title))
|
||||
|
||||
Reference in New Issue
Block a user