Jackett/src/Jackett/Services/IndexerManagerService.cs

220 lines
8.0 KiB
C#
Raw Normal View History

2015-07-19 00:27:41 +00:00
using Autofac;
2015-07-19 13:22:50 +00:00
using Jackett.Indexers;
2015-07-19 00:27:41 +00:00
using Jackett.Models;
using Jackett.Utils;
2015-07-28 19:22:23 +00:00
using Jackett.Utils.Clients;
2015-07-19 00:59:30 +00:00
using Newtonsoft.Json.Linq;
2015-07-19 00:27:41 +00:00
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jackett.Services
{
public interface IIndexerManagerService
{
2015-07-19 18:25:47 +00:00
Task TestIndexer(string name);
2015-07-19 00:27:41 +00:00
void DeleteIndexer(string name);
2015-07-19 13:22:50 +00:00
IIndexer GetIndexer(string name);
IEnumerable<IIndexer> GetAllIndexers();
void SaveConfig(IIndexer indexer, JToken obj);
void InitIndexers();
void InitCardigannIndexers(string path);
2016-12-05 12:03:30 +00:00
void SortIndexers();
2015-07-19 00:27:41 +00:00
}
public class IndexerManagerService : IIndexerManagerService
{
private IContainer container;
private IConfigurationService configService;
private Logger logger;
2015-07-19 17:18:54 +00:00
private Dictionary<string, IIndexer> indexers = new Dictionary<string, IIndexer>();
private ICacheService cacheService;
2015-07-19 00:27:41 +00:00
public IndexerManagerService(IContainer c, IConfigurationService config, Logger l, ICacheService cache)
2015-07-19 00:27:41 +00:00
{
container = c;
configService = config;
logger = l;
cacheService = cache;
2015-07-19 00:27:41 +00:00
}
protected void LoadIndexerConfig(IIndexer idx)
{
var configFilePath = GetIndexerConfigFilePath(idx);
if (File.Exists(configFilePath))
{
try
{
var fileStr = File.ReadAllText(configFilePath);
var jsonString = JToken.Parse(fileStr);
idx.LoadFromSavedConfiguration(jsonString);
}
catch (Exception ex)
{
logger.Error(ex, "Failed loading configuration for {0}, you must reconfigure this indexer", idx.DisplayName);
}
}
}
2015-07-19 13:22:50 +00:00
public void InitIndexers()
2015-07-19 00:27:41 +00:00
{
2015-07-28 19:22:23 +00:00
logger.Info("Using HTTP Client: " + container.Resolve<IWebClient>().GetType().Name);
foreach (var idx in container.Resolve<IEnumerable<IIndexer>>().Where(p => p.ID != "cardigannindexer").OrderBy(_ => _.DisplayName))
2015-07-19 13:22:50 +00:00
{
2015-07-19 19:28:08 +00:00
indexers.Add(idx.ID, idx);
LoadIndexerConfig(idx);
}
}
public void InitCardigannIndexers(string path)
{
logger.Info("Loading Cardigann definitions from: " + path);
try
{
if (!Directory.Exists(path))
return;
DirectoryInfo d = new DirectoryInfo(path);
foreach (var file in d.GetFiles("*.yml"))
{
logger.Info("Loading Cardigann definition " + file.FullName);
string DefinitionString = File.ReadAllText(file.FullName);
CardigannIndexer idx = new CardigannIndexer(this, container.Resolve<IWebClient>(), logger, container.Resolve<IProtectionService>(), DefinitionString);
if (indexers.ContainsKey(idx.ID))
{
logger.Debug(string.Format("Ignoring definition ID={0}, file={1}: Indexer already exists", idx.ID, file.FullName));
}
else
{
indexers.Add(idx.ID, idx);
LoadIndexerConfig(idx);
}
}
}
catch (Exception ex)
{
logger.Error(ex, "Error while loading Cardigann definitions: "+ ex.Message);
2015-07-19 13:22:50 +00:00
}
2015-07-19 00:27:41 +00:00
}
2015-07-19 13:22:50 +00:00
public IIndexer GetIndexer(string name)
2015-07-19 00:27:41 +00:00
{
if (indexers.ContainsKey(name))
2015-07-19 17:18:54 +00:00
{
return indexers[name];
2015-07-19 17:18:54 +00:00
}
else
2015-07-19 13:22:50 +00:00
{
logger.Error("Request for unknown indexer: " + name);
throw new Exception("Unknown indexer: " + name);
}
}
public IEnumerable<IIndexer> GetAllIndexers()
{
2015-07-19 17:18:54 +00:00
return indexers.Values;
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);
var browseQuery = new TorznabQuery();
2016-12-06 17:24:40 +00:00
browseQuery.IsTest = true;
2015-07-19 00:27:41 +00:00
var results = await indexer.PerformQuery(browseQuery);
results = indexer.CleanLinks(results);
logger.Info(string.Format("Found {0} releases from {1}", results.Count(), indexer.DisplayName));
if (results.Count() == 0)
2015-07-19 00:27:41 +00:00
throw new Exception("Found no results while trying to browse this tracker");
cacheService.CacheRssResults(indexer, results);
2015-07-19 00:27:41 +00:00
}
public void DeleteIndexer(string name)
{
var indexer = GetIndexer(name);
2015-07-19 17:18:54 +00:00
var configPath = GetIndexerConfigFilePath(indexer);
2015-07-19 00:27:41 +00:00
File.Delete(configPath);
2015-07-19 19:38:41 +00:00
indexers[name] = container.ResolveNamed<IIndexer>(indexer.ID);
2015-07-19 00:27:41 +00:00
}
2015-07-19 13:22:50 +00:00
private string GetIndexerConfigFilePath(IIndexer indexer)
2015-07-19 00:27:41 +00:00
{
2015-07-19 19:28:08 +00:00
return Path.Combine(configService.GetIndexerConfigDir(), indexer.ID + ".json");
2015-07-19 00:27:41 +00:00
}
2015-07-19 00:59:30 +00:00
2015-07-19 13:22:50 +00:00
public void SaveConfig(IIndexer indexer, JToken obj)
2015-07-19 00:59:30 +00:00
{
var uID = Guid.NewGuid().ToString("N");
2015-07-19 00:59:30 +00:00
var configFilePath = GetIndexerConfigFilePath(indexer);
var configFilePathBak = configFilePath + ".bak";
var configFilePathTmp = configFilePath + "." + uID + ".tmp";
var content = obj.ToString();
logger.Debug(string.Format("Saving new config file: {0}", configFilePathTmp));
if (string.IsNullOrWhiteSpace(content))
{
throw new Exception(string.Format("New config content for {0} is empty, please report this bug.", indexer.ID));
}
2016-11-10 08:16:00 +00:00
if (content.Contains("\x00"))
{
2016-11-10 08:16:00 +00:00
throw new Exception(string.Format("New config content for {0} contains 0x00, please report this bug. Content: {1}", indexer.ID, content));
}
// make sure the config directory exists
2015-07-19 00:59:30 +00:00
if (!Directory.Exists(configService.GetIndexerConfigDir()))
Directory.CreateDirectory(configService.GetIndexerConfigDir());
// create new temporary config file
File.WriteAllText(configFilePathTmp, content);
var fileInfo = new FileInfo(configFilePathTmp);
if (fileInfo.Length == 0)
{
throw new Exception(string.Format("New config file {0} is empty, please report this bug.", configFilePathTmp));
}
// create backup file
File.Delete(configFilePathBak);
if (File.Exists(configFilePath))
{
try
{
File.Move(configFilePath, configFilePathBak);
}
catch (IOException ex)
{
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePath, configFilePathBak, ex.ToString()));
}
}
// replace the actual config file
File.Delete(configFilePath);
try
{
File.Move(configFilePathTmp, configFilePath);
}
catch (IOException ex)
{
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePathTmp, configFilePath, ex.ToString()));
}
2016-12-05 12:03:30 +00:00
}
public void SortIndexers()
{
// Apparently Dictionary are ordered but can't be sorted again
// This will recreate the indexers Dictionary to workaround this limitation
Dictionary<string, IIndexer> newIndexers = new Dictionary<string, IIndexer>();
foreach (var indexer in indexers.OrderBy(_ => _.Value.DisplayName))
newIndexers.Add(indexer.Key, indexer.Value);
indexers = newIndexers;
}
2015-07-19 00:27:41 +00:00
}
}