2020-02-09 02:35:16 +00:00
|
|
|
using System;
|
2021-05-08 20:24:18 +00:00
|
|
|
using System.Collections.Concurrent;
|
2015-07-19 00:27:41 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Threading.Tasks;
|
2018-03-10 08:05:56 +00:00
|
|
|
using Jackett.Common.Indexers;
|
|
|
|
using Jackett.Common.Indexers.Meta;
|
|
|
|
using Jackett.Common.Models;
|
|
|
|
using Jackett.Common.Models.Config;
|
|
|
|
using Jackett.Common.Services.Interfaces;
|
2021-05-08 20:24:18 +00:00
|
|
|
using Jackett.Common.Utils;
|
2018-03-10 08:05:56 +00:00
|
|
|
using Jackett.Common.Utils.Clients;
|
|
|
|
using NLog;
|
2017-07-10 20:58:44 +00:00
|
|
|
using YamlDotNet.Serialization;
|
|
|
|
using YamlDotNet.Serialization.NamingConventions;
|
2021-05-08 20:24:18 +00:00
|
|
|
using FilterFunc = Jackett.Common.Utils.FilterFunc;
|
2015-07-19 00:27:41 +00:00
|
|
|
|
2018-03-10 08:05:56 +00:00
|
|
|
namespace Jackett.Common.Services
|
2015-07-19 00:27:41 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
public class IndexerManagerService : IIndexerManagerService
|
|
|
|
{
|
2020-02-10 22:16:19 +00:00
|
|
|
private readonly ICacheService cacheService;
|
|
|
|
private readonly IIndexerConfigurationService configService;
|
|
|
|
private readonly IProtectionService protectionService;
|
|
|
|
private readonly WebClient webClient;
|
|
|
|
private readonly IProcessService processService;
|
|
|
|
private readonly IConfigurationService globalConfigService;
|
|
|
|
private readonly ServerConfig serverConfig;
|
|
|
|
private readonly Logger logger;
|
2017-07-14 05:39:52 +00:00
|
|
|
|
2020-02-10 22:16:19 +00:00
|
|
|
private readonly Dictionary<string, IIndexer> indexers = new Dictionary<string, IIndexer>();
|
2017-05-07 07:10:57 +00:00
|
|
|
private AggregateIndexer aggregateIndexer;
|
2021-05-08 20:24:18 +00:00
|
|
|
private ConcurrentDictionary<string, IWebIndexer> availableFilters = new ConcurrentDictionary<string, IWebIndexer>();
|
2015-07-19 00:27:41 +00:00
|
|
|
|
2020-05-12 19:58:48 +00:00
|
|
|
// this map is used to maintain backward compatibility when renaming the id of an indexer
|
|
|
|
// (the id is used in the torznab/download/search urls and in the indexer configuration file)
|
|
|
|
// if the indexer is removed, remove it from this list too
|
|
|
|
// use: {"<old id>", "<new id>"}
|
|
|
|
private readonly Dictionary<string, string> renamedIndexers = new Dictionary<string, string>
|
|
|
|
{
|
2020-12-20 21:09:36 +00:00
|
|
|
{"ast4u", "animeworld"},
|
2021-01-26 01:50:18 +00:00
|
|
|
{"audiobooktorrents", "abtorrents"},
|
2020-06-06 20:15:50 +00:00
|
|
|
{"broadcastthenet", "broadcasthenet"},
|
2020-09-22 22:44:59 +00:00
|
|
|
{"cili180", "cilipro"},
|
2021-03-06 16:19:42 +00:00
|
|
|
{"hdreactor", "hdhouse"},
|
2020-11-22 22:29:05 +00:00
|
|
|
{"icetorrent", "speedapp"},
|
2021-01-26 01:50:18 +00:00
|
|
|
{"kickasstorrent-kathow", "kickasstorrents-ws"},
|
2020-12-16 16:21:29 +00:00
|
|
|
{"leaguehd", "lemonhd"},
|
2020-09-22 22:44:59 +00:00
|
|
|
{"liaorencili", "cilipro"},
|
2020-06-07 00:00:01 +00:00
|
|
|
{"metaliplayro", "romanianmetaltorrents"},
|
2020-06-06 23:32:13 +00:00
|
|
|
{"nnm-club", "noname-club"},
|
2020-05-15 22:00:44 +00:00
|
|
|
{"passtheheadphones", "redacted"},
|
2020-11-22 19:26:01 +00:00
|
|
|
{"puntorrent", "puntotorrent"},
|
2020-06-06 23:46:27 +00:00
|
|
|
{"rstorrent", "redstartorrent"},
|
2020-11-22 22:29:05 +00:00
|
|
|
{"scenefz", "speedapp"},
|
2021-01-26 08:59:08 +00:00
|
|
|
{"skytorrentsclone2", "skytorrents-to"},
|
2020-05-15 21:50:04 +00:00
|
|
|
{"tehconnectionme", "anthelion"},
|
2021-01-26 01:50:18 +00:00
|
|
|
{"torrentgalaxyorg", "torrentgalaxy"},
|
2020-10-14 00:01:13 +00:00
|
|
|
{"torrentseed", "latinop2p"},
|
2020-05-15 22:13:30 +00:00
|
|
|
{"transmithenet", "nebulance"},
|
2020-11-22 22:29:05 +00:00
|
|
|
{"xtremezone", "speedapp"},
|
2020-05-15 22:13:30 +00:00
|
|
|
{"yourexotic", "exoticaz"}
|
2020-05-12 19:58:48 +00:00
|
|
|
};
|
|
|
|
|
2017-11-05 09:42:03 +00:00
|
|
|
public IndexerManagerService(IIndexerConfigurationService config, IProtectionService protectionService, WebClient webClient, Logger l, ICacheService cache, IProcessService processService, IConfigurationService globalConfigService, ServerConfig serverConfig)
|
2015-07-19 00:27:41 +00:00
|
|
|
{
|
|
|
|
configService = config;
|
2017-07-14 05:39:52 +00:00
|
|
|
this.protectionService = protectionService;
|
|
|
|
this.webClient = webClient;
|
2017-08-11 14:53:27 +00:00
|
|
|
this.processService = processService;
|
|
|
|
this.globalConfigService = globalConfigService;
|
2017-11-05 09:42:03 +00:00
|
|
|
this.serverConfig = serverConfig;
|
2015-07-19 00:27:41 +00:00
|
|
|
logger = l;
|
2015-07-28 23:56:08 +00:00
|
|
|
cacheService = cache;
|
2015-07-19 00:27:41 +00:00
|
|
|
}
|
|
|
|
|
2017-07-14 05:39:52 +00:00
|
|
|
public void InitIndexers(IEnumerable<string> path)
|
2015-07-19 00:27:41 +00:00
|
|
|
{
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Info($"Using HTTP Client: {webClient.GetType().Name}");
|
|
|
|
|
2020-05-12 19:58:48 +00:00
|
|
|
MigrateRenamedIndexers();
|
2017-07-14 05:39:52 +00:00
|
|
|
InitIndexers();
|
|
|
|
InitCardigannIndexers(path);
|
2021-05-08 20:24:18 +00:00
|
|
|
InitMetaIndexers();
|
2020-12-07 01:08:21 +00:00
|
|
|
RemoveLegacyConfigurations();
|
2017-07-14 05:39:52 +00:00
|
|
|
}
|
2015-07-28 19:22:23 +00:00
|
|
|
|
2020-05-12 19:58:48 +00:00
|
|
|
private void MigrateRenamedIndexers()
|
|
|
|
{
|
|
|
|
foreach (var oldId in renamedIndexers.Keys)
|
|
|
|
{
|
|
|
|
var oldPath = configService.GetIndexerConfigFilePath(oldId);
|
|
|
|
if (File.Exists(oldPath))
|
|
|
|
{
|
|
|
|
// if the old configuration exists, we rename it to be used by the renamed indexer
|
2020-06-07 15:51:49 +00:00
|
|
|
logger.Info($"Old configuration detected: {oldPath}");
|
2020-05-12 19:58:48 +00:00
|
|
|
var newPath = configService.GetIndexerConfigFilePath(renamedIndexers[oldId]);
|
2020-06-07 15:51:49 +00:00
|
|
|
if (File.Exists(newPath))
|
|
|
|
File.Delete(newPath);
|
2020-05-12 19:58:48 +00:00
|
|
|
File.Move(oldPath, newPath);
|
2020-06-07 15:51:49 +00:00
|
|
|
// backups
|
|
|
|
var oldPathBak = oldPath + ".bak";
|
|
|
|
var newPathBak = newPath + ".bak";
|
|
|
|
if (File.Exists(oldPathBak))
|
|
|
|
{
|
|
|
|
if (File.Exists(newPathBak))
|
|
|
|
File.Delete(newPathBak);
|
|
|
|
File.Move(oldPathBak, newPathBak);
|
|
|
|
}
|
2020-05-12 19:58:48 +00:00
|
|
|
logger.Info($"Configuration renamed: {oldPath} => {newPath}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-14 05:39:52 +00:00
|
|
|
private void InitIndexers()
|
|
|
|
{
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Info("Loading Native indexers ...");
|
2017-07-14 05:39:52 +00:00
|
|
|
|
|
|
|
var allTypes = GetType().Assembly.GetTypes();
|
|
|
|
var allIndexerTypes = allTypes.Where(p => typeof(IIndexer).IsAssignableFrom(p));
|
|
|
|
var allInstantiatableIndexerTypes = allIndexerTypes.Where(p => !p.IsInterface && !p.IsAbstract);
|
|
|
|
var allNonMetaInstantiatableIndexerTypes = allInstantiatableIndexerTypes.Where(p => !typeof(BaseMetaIndexer).IsAssignableFrom(p));
|
|
|
|
var indexerTypes = allNonMetaInstantiatableIndexerTypes.Where(p => p.Name != "CardigannIndexer");
|
2020-11-02 11:32:36 +00:00
|
|
|
var nativeIndexers = indexerTypes.Select(type =>
|
2015-07-19 13:22:50 +00:00
|
|
|
{
|
2021-05-16 18:13:54 +00:00
|
|
|
var constructorArgumentTypes = new[] { typeof(IIndexerConfigurationService), typeof(WebClient), typeof(Logger), typeof(IProtectionService), typeof(ICacheService) };
|
2017-07-14 05:39:52 +00:00
|
|
|
var constructor = type.GetConstructor(constructorArgumentTypes);
|
|
|
|
if (constructor != null)
|
|
|
|
{
|
2020-11-02 11:32:36 +00:00
|
|
|
// create own webClient instance for each indexer (separate cookies stores, etc.)
|
2017-11-05 09:42:03 +00:00
|
|
|
var indexerWebClientInstance = (WebClient)Activator.CreateInstance(webClient.GetType(), processService, logger, globalConfigService, serverConfig);
|
2017-08-11 14:53:27 +00:00
|
|
|
|
2020-12-11 22:14:21 +00:00
|
|
|
var arguments = new object[] { configService, indexerWebClientInstance, logger, protectionService, cacheService };
|
2017-07-14 05:39:52 +00:00
|
|
|
var indexer = (IIndexer)constructor.Invoke(arguments);
|
|
|
|
return indexer;
|
|
|
|
}
|
2020-09-24 20:02:45 +00:00
|
|
|
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Error($"Cannot instantiate Native indexer: {type.Name}");
|
2017-07-14 05:39:52 +00:00
|
|
|
return null;
|
2020-11-02 11:32:36 +00:00
|
|
|
}).Where(indexer => indexer != null).ToList();
|
2017-07-14 05:39:52 +00:00
|
|
|
|
2020-11-02 11:32:36 +00:00
|
|
|
foreach (var indexer in nativeIndexers)
|
2017-07-14 05:39:52 +00:00
|
|
|
{
|
2020-11-02 11:32:36 +00:00
|
|
|
indexers.Add(indexer.Id, indexer);
|
|
|
|
configService.Load(indexer);
|
2016-10-27 07:30:03 +00:00
|
|
|
}
|
2020-12-20 21:09:36 +00:00
|
|
|
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Info($"Loaded {nativeIndexers.Count} Native indexers: {string.Join(", ", nativeIndexers.Select(i => i.Id))}");
|
2016-10-27 07:30:03 +00:00
|
|
|
}
|
|
|
|
|
2017-07-14 05:39:52 +00:00
|
|
|
private void InitCardigannIndexers(IEnumerable<string> path)
|
2016-10-27 07:30:03 +00:00
|
|
|
{
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Info("Loading Cardigann indexers from: " + string.Join(", ", path));
|
2017-07-14 05:39:52 +00:00
|
|
|
|
|
|
|
var deserializer = new DeserializerBuilder()
|
2020-01-11 18:04:24 +00:00
|
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
2020-09-24 20:02:45 +00:00
|
|
|
//.IgnoreUnmatchedProperties()
|
2017-07-14 05:39:52 +00:00
|
|
|
.Build();
|
2016-10-27 07:30:03 +00:00
|
|
|
|
2017-04-15 08:45:10 +00:00
|
|
|
try
|
|
|
|
{
|
2017-07-14 05:39:52 +00:00
|
|
|
var directoryInfos = path.Select(p => new DirectoryInfo(p));
|
|
|
|
var existingDirectories = directoryInfos.Where(d => d.Exists);
|
|
|
|
var files = existingDirectories.SelectMany(d => d.GetFiles("*.yml"));
|
|
|
|
var definitions = files.Select(file =>
|
2017-04-15 08:45:10 +00:00
|
|
|
{
|
2020-02-23 20:38:59 +00:00
|
|
|
logger.Debug("Loading Cardigann definition " + file.FullName);
|
2020-02-09 02:35:16 +00:00
|
|
|
try
|
|
|
|
{
|
2020-09-24 20:02:45 +00:00
|
|
|
var definitionString = File.ReadAllText(file.FullName);
|
|
|
|
var definition = deserializer.Deserialize<IndexerDefinition>(definitionString);
|
2017-09-13 09:33:17 +00:00
|
|
|
return definition;
|
|
|
|
}
|
2020-09-24 20:02:45 +00:00
|
|
|
catch (Exception e)
|
2017-09-13 09:33:17 +00:00
|
|
|
{
|
2020-09-24 20:02:45 +00:00
|
|
|
logger.Error($"Error while parsing Cardigann definition {file.FullName}\n{e}");
|
2017-09-13 09:33:17 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}).Where(definition => definition != null);
|
2017-07-10 20:58:44 +00:00
|
|
|
|
2020-02-10 22:16:19 +00:00
|
|
|
var cardigannIndexers = definitions.Select(definition =>
|
2017-07-14 05:39:52 +00:00
|
|
|
{
|
2017-09-13 09:33:17 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// create own webClient instance for each indexer (seperate cookies stores, etc.)
|
2017-11-05 09:42:03 +00:00
|
|
|
var indexerWebClientInstance = (WebClient)Activator.CreateInstance(webClient.GetType(), processService, logger, globalConfigService, serverConfig);
|
2017-08-11 14:53:27 +00:00
|
|
|
|
2020-12-11 22:14:21 +00:00
|
|
|
IIndexer indexer = new CardigannIndexer(configService, indexerWebClientInstance, logger, protectionService, cacheService, definition);
|
2017-09-13 09:33:17 +00:00
|
|
|
configService.Load(indexer);
|
|
|
|
return indexer;
|
|
|
|
}
|
2020-09-24 20:02:45 +00:00
|
|
|
catch (Exception e)
|
2017-09-13 09:33:17 +00:00
|
|
|
{
|
2020-10-19 19:27:23 +00:00
|
|
|
logger.Error($"Error while creating Cardigann instance from definition ID={definition.Id}: {e}");
|
2017-09-13 09:33:17 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}).Where(cardigannIndexer => cardigannIndexer != null).ToList(); // Explicit conversion to list to avoid repeated resource loading
|
2017-07-14 05:39:52 +00:00
|
|
|
|
2020-11-02 11:32:36 +00:00
|
|
|
var cardigannCounter = 0;
|
|
|
|
var cardiganIds = new List<string>();
|
2017-07-14 05:39:52 +00:00
|
|
|
foreach (var indexer in cardigannIndexers)
|
|
|
|
{
|
2020-05-11 19:59:28 +00:00
|
|
|
if (indexers.ContainsKey(indexer.Id))
|
2017-04-15 08:45:10 +00:00
|
|
|
{
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Warn($"Ignoring definition ID={indexer.Id}: Indexer already exists");
|
2017-07-14 05:39:52 +00:00
|
|
|
continue;
|
2017-04-15 08:45:10 +00:00
|
|
|
}
|
2020-05-11 19:59:28 +00:00
|
|
|
indexers.Add(indexer.Id, indexer);
|
2020-11-02 11:32:36 +00:00
|
|
|
|
|
|
|
cardigannCounter++;
|
|
|
|
cardiganIds.Add(indexer.Id);
|
2016-10-29 16:01:43 +00:00
|
|
|
}
|
2020-11-02 11:32:36 +00:00
|
|
|
|
|
|
|
logger.Info($"Loaded {cardigannCounter} Cardigann indexers: {string.Join(", ", cardiganIds)}");
|
2017-04-15 08:45:10 +00:00
|
|
|
}
|
2020-09-24 20:02:45 +00:00
|
|
|
catch (Exception e)
|
2017-04-15 08:45:10 +00:00
|
|
|
{
|
2020-09-24 20:02:45 +00:00
|
|
|
logger.Error($"Error while loading Cardigann definitions: {e}");
|
2015-07-19 13:22:50 +00:00
|
|
|
}
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Info($"Loaded {indexers.Count} indexers in total");
|
2015-07-19 00:27:41 +00:00
|
|
|
}
|
|
|
|
|
2021-05-08 20:24:18 +00:00
|
|
|
public void InitMetaIndexers()
|
2017-04-30 08:06:29 +00:00
|
|
|
{
|
2021-05-08 20:24:18 +00:00
|
|
|
var (fallbackStrategyProvider, resultFilterProvider) = GetStrategyProviders();
|
2017-06-28 05:31:38 +00:00
|
|
|
|
2020-11-02 11:32:36 +00:00
|
|
|
logger.Info("Adding aggregate indexer ('all' indexer) ...");
|
2020-12-11 22:14:21 +00:00
|
|
|
aggregateIndexer = new AggregateIndexer(fallbackStrategyProvider, resultFilterProvider, configService, webClient, logger, protectionService, cacheService)
|
2020-03-26 22:15:28 +00:00
|
|
|
{
|
|
|
|
Indexers = indexers.Values
|
|
|
|
};
|
2021-05-08 20:24:18 +00:00
|
|
|
|
|
|
|
var predefinedFilters =
|
|
|
|
new[] { "public", "private", "semi-public" }
|
|
|
|
.Select(type => (filter: FilterFunc.Type.ToFilter(type), func: FilterFunc.Type.ToFunc(type)))
|
|
|
|
.Concat(
|
|
|
|
indexers.Values.SelectMany(x => x.Tags).Distinct()
|
|
|
|
.Select(tag => (filter: FilterFunc.Tag.ToFilter(tag), func: FilterFunc.Tag.ToFunc(tag)))
|
2021-05-16 18:13:54 +00:00
|
|
|
).Select(x => new KeyValuePair<string, IWebIndexer>(x.filter, CreateFilterIndexer(x.filter, x.func)));
|
2021-05-08 20:24:18 +00:00
|
|
|
|
|
|
|
availableFilters = new ConcurrentDictionary<string, IWebIndexer>(predefinedFilters);
|
2017-04-30 08:06:29 +00:00
|
|
|
}
|
|
|
|
|
2020-12-07 01:08:21 +00:00
|
|
|
public void RemoveLegacyConfigurations()
|
|
|
|
{
|
|
|
|
var directoryInfo = new DirectoryInfo(globalConfigService.GetIndexerConfigDir());
|
|
|
|
if (!directoryInfo.Exists)
|
|
|
|
return; // the directory does not exist the first start
|
|
|
|
var files = directoryInfo.GetFiles("*.json*");
|
|
|
|
foreach (var file in files)
|
|
|
|
{
|
|
|
|
var indexerId = file.Name.Replace(".bak", "").Replace(".json", "");
|
|
|
|
if (!indexers.ContainsKey(indexerId) && File.Exists(file.FullName))
|
|
|
|
{
|
|
|
|
logger.Info($"Removing old configuration file: {file.FullName}");
|
|
|
|
File.Delete(file.FullName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-19 13:22:50 +00:00
|
|
|
public IIndexer GetIndexer(string name)
|
2015-07-19 00:27:41 +00:00
|
|
|
{
|
2020-05-12 19:58:48 +00:00
|
|
|
// old id of renamed indexer is used to maintain backward compatibility
|
|
|
|
// both, the old id and the new one can be used until we remove it from renamedIndexers
|
|
|
|
var realName = name;
|
|
|
|
if (renamedIndexers.ContainsKey(name))
|
2015-07-19 17:18:54 +00:00
|
|
|
{
|
2020-05-12 19:58:48 +00:00
|
|
|
realName = renamedIndexers[name];
|
2020-09-24 20:02:45 +00:00
|
|
|
logger.Warn($@"Indexer {name} has been renamed to {realName}. Please, update the URL of the feeds.
|
|
|
|
This may stop working in the future.");
|
2015-07-19 17:18:54 +00:00
|
|
|
}
|
2020-05-12 19:58:48 +00:00
|
|
|
|
2021-05-08 20:24:18 +00:00
|
|
|
return GetWebIndexer(realName);
|
2015-07-19 13:22:50 +00:00
|
|
|
}
|
|
|
|
|
2021-05-08 20:24:18 +00:00
|
|
|
|
2017-07-10 20:58:44 +00:00
|
|
|
public IWebIndexer GetWebIndexer(string name)
|
|
|
|
{
|
|
|
|
if (indexers.ContainsKey(name))
|
|
|
|
return indexers[name] as IWebIndexer;
|
|
|
|
|
2020-09-24 20:02:45 +00:00
|
|
|
if (name == "all")
|
|
|
|
return aggregateIndexer;
|
|
|
|
|
2021-05-08 20:24:18 +00:00
|
|
|
if (availableFilters.TryGetValue(name, out var indexer))
|
|
|
|
return indexer;
|
|
|
|
|
|
|
|
if (FilterFunc.TryParse(name, out var filterFunc))
|
|
|
|
return availableFilters.GetOrAdd(name, x => CreateFilterIndexer(name, filterFunc));
|
|
|
|
|
2020-09-24 20:02:45 +00:00
|
|
|
logger.Error($"Request for unknown indexer: {name}");
|
|
|
|
throw new Exception($"Unknown indexer: {name}");
|
2017-07-10 20:58:44 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 16:08:03 +00:00
|
|
|
public IEnumerable<IIndexer> GetAllIndexers() => indexers.Values.OrderBy(_ => _.DisplayName);
|
2015-07-19 00:27:41 +00:00
|
|
|
|
2015-07-19 18:25:47 +00:00
|
|
|
public async Task TestIndexer(string name)
|
2015-07-19 00:27:41 +00:00
|
|
|
{
|
|
|
|
var indexer = GetIndexer(name);
|
2020-12-11 22:14:21 +00:00
|
|
|
var query = new TorznabQuery
|
2020-03-26 22:15:28 +00:00
|
|
|
{
|
|
|
|
QueryType = "search",
|
|
|
|
SearchTerm = "",
|
|
|
|
IsTest = true
|
|
|
|
};
|
2020-12-11 22:14:21 +00:00
|
|
|
var result = await indexer.ResultsForQuery(query);
|
|
|
|
|
|
|
|
logger.Info($"Test search in {indexer.DisplayName} => Found {result.Releases.Count()} releases");
|
|
|
|
|
2020-09-24 20:02:45 +00:00
|
|
|
if (!result.Releases.Any())
|
2015-07-19 00:27:41 +00:00
|
|
|
throw new Exception("Found no results while trying to browse this tracker");
|
|
|
|
}
|
|
|
|
|
|
|
|
public void DeleteIndexer(string name)
|
|
|
|
{
|
|
|
|
var indexer = GetIndexer(name);
|
2017-07-10 20:58:44 +00:00
|
|
|
configService.Delete(indexer);
|
|
|
|
indexer.Unconfigure();
|
2017-04-15 08:45:10 +00:00
|
|
|
}
|
2021-05-08 20:24:18 +00:00
|
|
|
|
|
|
|
private IWebIndexer CreateFilterIndexer(string filter, Func<IIndexer, bool> filterFunc)
|
|
|
|
{
|
|
|
|
var (fallbackStrategyProvider, resultFilterProvider) = GetStrategyProviders();
|
|
|
|
logger.Info($"Adding filter indexer ('{filter}' indexer) ...");
|
|
|
|
return new FilterIndexer(
|
|
|
|
filter,
|
|
|
|
fallbackStrategyProvider,
|
|
|
|
resultFilterProvider,
|
|
|
|
configService,
|
|
|
|
webClient,
|
|
|
|
logger,
|
|
|
|
protectionService,
|
|
|
|
cacheService,
|
|
|
|
filterFunc
|
|
|
|
)
|
2021-05-16 18:13:54 +00:00
|
|
|
{
|
|
|
|
Indexers = indexers.Values
|
|
|
|
};
|
2021-05-08 20:24:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private (IFallbackStrategyProvider fallbackStrategyProvider, IResultFilterProvider resultFilterProvider)
|
|
|
|
GetStrategyProviders()
|
|
|
|
{
|
|
|
|
var omdbApiKey = serverConfig.OmdbApiKey;
|
|
|
|
IFallbackStrategyProvider fallbackStrategyProvider;
|
|
|
|
IResultFilterProvider resultFilterProvider;
|
|
|
|
if (!string.IsNullOrWhiteSpace(omdbApiKey))
|
|
|
|
{
|
|
|
|
var imdbResolver = new OmdbResolver(webClient, omdbApiKey, serverConfig.OmdbApiUrl);
|
|
|
|
fallbackStrategyProvider = new ImdbFallbackStrategyProvider(imdbResolver);
|
|
|
|
resultFilterProvider = new ImdbTitleResultFilterProvider(imdbResolver);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fallbackStrategyProvider = new NoFallbackStrategyProvider();
|
|
|
|
resultFilterProvider = new NoResultFilterProvider();
|
|
|
|
}
|
|
|
|
|
|
|
|
return (fallbackStrategyProvider, resultFilterProvider);
|
|
|
|
}
|
|
|
|
|
2015-07-19 00:27:41 +00:00
|
|
|
}
|
|
|
|
}
|