Jackett/src/Jackett/Indexers/Meta/BaseMetaIndexer.cs

113 lines
5.1 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Jackett.Models;
using Jackett.Models.IndexerConfig;
using Jackett.Services;
2017-08-07 20:33:23 +00:00
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
namespace Jackett.Indexers.Meta
{
public abstract class BaseMetaIndexer : BaseWebIndexer
{
protected BaseMetaIndexer(string name, string description, IFallbackStrategyProvider fallbackStrategyProvider, IResultFilterProvider resultFilterProvider, IIndexerConfigurationService configService, IWebClient webClient, Logger logger, ConfigurationData configData, IProtectionService p, Func<IIndexer, bool> filter)
: base(name, "http://127.0.0.1/", description, configService, webClient, logger, configData, p, null, null)
{
filterFunc = filter;
this.fallbackStrategyProvider = fallbackStrategyProvider;
this.resultFilterProvider = resultFilterProvider;
}
public override Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
return Task.FromResult(IndexerConfigurationStatus.Completed);
}
Feature/new api (#1584) * Introducing API v2 There were multiple inconsistencies in the old API and I have been toying with the idea to replace it. This will suck for everyone who was building on top of the Jackett API, however as it was probably too painful to do so I'd say no one really tried. Now API v2.0 should be much more constistent as it uses DTObjects, and instead of manually constructing a json response it is handled by the ASP.NET web api. It is much more RESTful than it was, proper GET endpoints are introduced, and updating resources are now done via POST - it might be improved by introducing other type of REST methods. I know this sucks as completely breaks backward compatibility, however it'll probably make it easier to maintain and build on top of in the long run. * Use DELETE method to unconfigure an indexer * Remove debugging format from NLog * Fixing an null exception * Properly implementing IExceptionFilter interface * Enable adding public indexers without configuration * Fix missing manual search results * Basic modularization of the JS API * Introduce API versioning * Fix redirects to the dashboard * Cleaning up a little bit * Revamping Torznab and Potato as well * Move preconditions to FilterAttributes and simplify logic * Remove legacy filtering... will move to IResultFilter * Minor adjustment on results interface * Use Interpolated strings in ResultsController * DTO-ify * Remove fallback logic from potato results * DTO everywhere!!! * DTO-ify everything! * I hope this is my last piece of modification to this PR * Remove test variables... * Left out a couple conflicts... It's late
2017-08-08 15:02:16 +00:00
protected override IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> results)
{
Feature/new api (#1584) * Introducing API v2 There were multiple inconsistencies in the old API and I have been toying with the idea to replace it. This will suck for everyone who was building on top of the Jackett API, however as it was probably too painful to do so I'd say no one really tried. Now API v2.0 should be much more constistent as it uses DTObjects, and instead of manually constructing a json response it is handled by the ASP.NET web api. It is much more RESTful than it was, proper GET endpoints are introduced, and updating resources are now done via POST - it might be improved by introducing other type of REST methods. I know this sucks as completely breaks backward compatibility, however it'll probably make it easier to maintain and build on top of in the long run. * Use DELETE method to unconfigure an indexer * Remove debugging format from NLog * Fixing an null exception * Properly implementing IExceptionFilter interface * Enable adding public indexers without configuration * Fix missing manual search results * Basic modularization of the JS API * Introduce API versioning * Fix redirects to the dashboard * Cleaning up a little bit * Revamping Torznab and Potato as well * Move preconditions to FilterAttributes and simplify logic * Remove legacy filtering... will move to IResultFilter * Minor adjustment on results interface * Use Interpolated strings in ResultsController * DTO-ify * Remove fallback logic from potato results * DTO everywhere!!! * DTO-ify everything! * I hope this is my last piece of modification to this PR * Remove test variables... * Left out a couple conflicts... It's late
2017-08-08 15:02:16 +00:00
return results;
}
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var indexers = validIndexers;
IEnumerable<Task<IEnumerable<ReleaseInfo>>> supportedTasks = indexers.Where(i => i.CanHandleQuery(query)).Select(i => i.ResultsForQuery(query)).ToList(); // explicit conversion to List to execute LINQ query
var fallbackStrategies = fallbackStrategyProvider.FallbackStrategiesForQuery(query);
var fallbackQueries = fallbackStrategies.Select(async f => await f.FallbackQueries()).SelectMany(t => t.Result);
var fallbackTasks = fallbackQueries.SelectMany(q => indexers.Where(i => !i.CanHandleQuery(query) && i.CanHandleQuery(q)).Select(i => i.ResultsForQuery(q.Clone())));
var tasks = supportedTasks.Concat(fallbackTasks.ToList()); // explicit conversion to List to execute LINQ query
2017-08-07 20:33:23 +00:00
// When there are many indexers used by a metaindexer querying each and every one of them can take very very
// long. This may result in a problem especially with Sonarr, which does consecutive searches when searching
// for a season. Also, there might be indexers that do not support fast consecutive searches.
// Therefore doing a season search in Sonarr might take for more than 90 seconds (approx. timeout in Sonarr)
// which will mark Jackett as unresponsive (and therefore deactivated).
// Although that 40 second is just an arbitrary number, doing a 40 second timeout is acceptable since an API
// not responding for 40 second.. well, no one should really use that.
// I hope in the future these queries will speed up (using caching or some other magic), however until then
// just stick with a timeout.
var aggregateTask = tasks.Until(TimeSpan.FromSeconds(40));
try
{
await aggregateTask;
}
catch
{
logger.Error(aggregateTask.Exception, "Error during request in metaindexer " + ID);
}
2017-08-07 20:33:23 +00:00
var unorderedResult = aggregateTask.Result.Flatten();
var resultFilters = resultFilterProvider.FiltersForQuery(query);
var filteredResults = resultFilters.Select(async f => await f.FilterResults(unorderedResult)).SelectMany(t => t.Result);
var uniqueFilteredResults = filteredResults.Distinct();
var orderedResults = uniqueFilteredResults.OrderByDescending(r => r.Gain);
// Limiting the response size might be interesting for use-cases where there are
// tons of trackers configured in Jackett. For now just use the limit param if
// someone wants to do that.
IEnumerable<ReleaseInfo> result = orderedResults;
if (query.Limit > 0)
result = result.Take(query.Limit);
return result;
}
public override TorznabCapabilities TorznabCaps
{
get
{
return validIndexers.Select(i => i.TorznabCaps).Aggregate(new TorznabCapabilities(), TorznabCapabilities.Concat);
}
}
public override bool IsConfigured
{
get
{
return Indexers != null;
}
}
private IEnumerable<IIndexer> validIndexers
{
get
{
if (Indexers == null)
return null;
return Indexers.Where(i => i.IsConfigured && filterFunc(i));
}
}
public IEnumerable<IIndexer> Indexers;
private Func<IIndexer, bool> filterFunc;
private IFallbackStrategyProvider fallbackStrategyProvider;
private IResultFilterProvider resultFilterProvider;
}
}