Remove Static Configuration Class and .NET Core Prep (#2122)

* Remove static configuration class that required prior knowledge of when it was initialised to dependency injected method that ensures all configuration has already occured.

* Specify a different log name for the updater, require a path when running the Jackett updater

* Update to all .NET Standard packages

* Explicitly specify the restore project style

* Move automapper out of the  DI framework and put crude detection to prevent it from initializing more than once.
This commit is contained in:
Nathan Holland
2017-11-13 21:38:38 +13:00
committed by flightlevel
parent fe504ed660
commit 1c62504b22
34 changed files with 368 additions and 364 deletions

View File

@@ -139,7 +139,7 @@ namespace Jackett
}
}
if (JackettStartup.DoSSLFix == true)
if (config.RuntimeSettings.DoSSLFix == true)
{
// http://stackoverflow.com/questions/31107851/how-to-fix-curl-35-cannot-communicate-securely-with-peer-no-common-encryptio
// https://git.fedorahosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html
@@ -148,7 +148,7 @@ namespace Jackett
easy.ForbidReuse = true;
}
if (JackettStartup.IgnoreSslErrors == true)
if (config.RuntimeSettings.IgnoreSslErrors == true)
{
easy.SetOpt(CurlOption.SslVerifyhost, false);
easy.SetOpt(CurlOption.SslVerifyPeer, false);

View File

@@ -1,44 +1,91 @@
using Autofac;
using AutoMapper;
using Jackett.Common.Models.Config;
using Jackett.Common.Plumbing;
using Jackett.Models;
using Jackett.Models.Config;
using Jackett.Services;
using Jackett.Services.Interfaces;
using Jackett.Utils.Clients;
using NLog;
using NLog.Config;
using NLog.LayoutRenderers;
using NLog.Targets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jackett.Services.Interfaces;
using Jacket.Common;
using Jackett.Models.Config;
using System.Reflection;
namespace Jackett
{
public class Engine
{
private static IContainer container = null;
private static bool _automapperInitialised = false;
public static void BuildContainer(params Autofac.Module[] ApplicationSpecificModules)
public static void BuildContainer(RuntimeSettings settings, params Autofac.Module[] ApplicationSpecificModules)
{
var builder = new ContainerBuilder();
builder.RegisterModule<JackettModule>();
foreach(var module in ApplicationSpecificModules)
SetupLogging(settings, builder);
if (_automapperInitialised == false)
{
//Automapper only likes being initialized once per app domain.
//Since we can restart Jackett from the command line it's possible that we'll build the container more than once. (tests do this too)
InitAutomapper();
_automapperInitialised = true;
}
builder.RegisterModule(new JackettModule(settings));
foreach (var module in ApplicationSpecificModules)
{
builder.RegisterModule(module);
}
SetupLogging(builder);
container = builder.Build();
}
private static void InitAutomapper()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<WebClientByteResult, WebClientStringResult>().ForMember(x => x.Content, opt => opt.Ignore()).AfterMap((be, str) =>
{
var encoding = be.Request.Encoding ?? Encoding.UTF8;
str.Content = encoding.GetString(be.Content);
});
cfg.CreateMap<WebClientStringResult, WebClientByteResult>().ForMember(x => x.Content, opt => opt.Ignore()).AfterMap((str, be) =>
{
if (!string.IsNullOrEmpty(str.Content))
{
var encoding = str.Request.Encoding ?? Encoding.UTF8;
be.Content = encoding.GetBytes(str.Content);
}
});
cfg.CreateMap<WebClientStringResult, WebClientStringResult>();
cfg.CreateMap<WebClientByteResult, WebClientByteResult>();
cfg.CreateMap<ReleaseInfo, ReleaseInfo>();
cfg.CreateMap<ReleaseInfo, TrackerCacheResult>().AfterMap((r, t) =>
{
if (r.Category != null)
{
var CategoryDesc = string.Join(", ", r.Category.Select(x => TorznabCatType.GetCatDesc(x)).Where(x => !string.IsNullOrEmpty(x)));
t.CategoryDesc = CategoryDesc;
}
else
{
t.CategoryDesc = "";
}
});
});
}
public static IContainer GetContainer()
{
return container;
}
public static IConfigurationService ConfigService
{
get
@@ -111,10 +158,10 @@ namespace Jackett
}
}
public static void SetupLogging(ContainerBuilder builder = null, string logfile = "log.txt")
private static void SetupLogging(RuntimeSettings settings, ContainerBuilder builder)
{
var logLevel = JackettStartup.TracingEnabled ? LogLevel.Debug : LogLevel.Info;
var logFileName = settings.CustomLogFileName ?? "log.txt";
var logLevel = settings.TracingEnabled ? LogLevel.Debug : LogLevel.Info;
// Add custom date time format renderer as the default is too long
ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("simpledatetime", typeof(SimpleDateTimeRenderer));
@@ -122,7 +169,7 @@ namespace Jackett
var logFile = new FileTarget();
logConfig.AddTarget("file", logFile);
logFile.Layout = "${longdate} ${level} ${message} ${exception:format=ToString}";
logFile.FileName = Path.Combine(ConfigurationService.GetAppDataFolderStatic(), logfile);
logFile.FileName = Path.Combine(settings.DataFolder, logFileName);
logFile.ArchiveFileName = "log.{#####}.txt";
logFile.ArchiveAboveSize = 500000;
logFile.MaxArchiveFiles = 5;
@@ -146,13 +193,12 @@ namespace Jackett
LogManager.Configuration = logConfig;
if (builder != null)
{
builder.RegisterInstance<Logger>(LogManager.GetCurrentClassLogger()).SingleInstance();
builder.RegisterInstance(LogManager.GetCurrentClassLogger()).SingleInstance();
}
}
public static void SetLogLevel(LogLevel level)
{
foreach (var rule in LogManager.Configuration.LoggingRules)
{
if (level == LogLevel.Debug)
@@ -169,7 +215,6 @@ namespace Jackett
rule.DisableLoggingForLevel(LogLevel.Debug);
}
}
}
LogManager.ReconfigExistingLoggers();
@@ -181,7 +226,6 @@ namespace Jackett
}
}
[LayoutRenderer("simpledatetime")]
public class SimpleDateTimeRenderer : LayoutRenderer
{

View File

@@ -13,6 +13,7 @@ using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using Jacket.Common.Utils;
namespace Jackett.Indexers
{
@@ -130,7 +131,7 @@ namespace Jackett.Indexers
var queryCollection = new NameValueCollection();
queryCollection.Add("token", token);
queryCollection.Add("format", "json_extended");
queryCollection.Add("app_id", "jackett_v" + JackettStartup.JackettVersion);
queryCollection.Add("app_id", "jackett_v" + EnvironmentUtil.JackettVersion);
queryCollection.Add("limit", "100");
queryCollection.Add("ranked", "0");

View File

@@ -115,14 +115,15 @@
<ItemGroup>
<PackageReference Include="AngleSharp" Version="0.9.9" />
<PackageReference Include="Autofac" Version="4.6.2" />
<PackageReference Include="AutoMapper" Version="6.1.1" />
<PackageReference Include="AutoMapper" Version="6.2.0" />
<PackageReference Include="BencodeNET" Version="2.2.22" />
<PackageReference Include="CloudFlareUtilities" Version="0.4.0-alpha" />
<PackageReference Include="CloudFlareUtilities" Version="0.5.0-alpha" />
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
<PackageReference Include="DotNet4.SocksProxy" Version="1.4.0.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.4.0" />
<PackageReference Include="MimeMapping" Version="1.0.1.10" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="NLog" Version="5.0.0-beta11" />
<PackageReference Include="SocksWebProxy" Version="1.0.5" />
<PackageReference Include="YamlDotNet" Version="4.2.2" />
</ItemGroup>

View File

@@ -1,79 +0,0 @@
using System;
using System.Reflection;
namespace Jacket.Common
{
public class JackettStartup
{
public static bool TracingEnabled
{
get;
set;
}
public static bool LogRequests
{
get;
set;
}
public static string ClientOverride
{
get;
set;
}
public static string ProxyConnection
{
get;
set;
}
public static bool? DoSSLFix
{
get;
set;
}
public static bool? IgnoreSslErrors
{
get;
set;
}
public static string CustomDataFolder
{
get;
set;
}
public static string BasePath
{
get;
set;
}
public static bool NoRestart
{
get;
set;
}
public static string JackettVersion
{
get
{
return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString() ?? "Unknown Version";
}
}
public static bool IsWindows
{
get
{
return Environment.OSVersion.Platform == PlatformID.Win32NT;
}
}
}
}

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jackett.Console
namespace Jackett.Common.Models.Config
{
public class ConsoleOptions
{
@@ -66,7 +66,45 @@ namespace Jackett.Console
[Option(HelpText = "Don't restart after update")]
public bool NoRestart { get; set; }
[ParserState]
public IParserState LastParserState { get; set; }
public RuntimeSettings ToRunTimeSettings()
{
var options = this;
var runtimeSettings = new RuntimeSettings();
// Logging
if (options.Logging)
runtimeSettings.LogRequests = true;
// Tracing
if (options.Tracing)
runtimeSettings.TracingEnabled = true;
if (options.ListenPublic && options.ListenPrivate)
{
Console.WriteLine("You can only use listen private OR listen publicly.");
Environment.Exit(1);
}
// SSL Fix
runtimeSettings.DoSSLFix = options.SSLFix;
// Use curl
if (options.Client != null)
runtimeSettings.ClientOverride = options.Client.ToLowerInvariant();
// Use Proxy
if (options.ProxyConnection != null)
{
runtimeSettings.ProxyConnection = options.ProxyConnection.ToLowerInvariant();
}
// Ignore SSL errors on Curl
runtimeSettings.IgnoreSslErrors = options.IgnoreSslErrors;
runtimeSettings.NoRestart = options.NoRestart;
return runtimeSettings;
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Jackett.Common.Models.Config
{
public class RuntimeSettings
{
public bool TracingEnabled { get; set; }
public bool LogRequests { get; set; }
public string ClientOverride { get; set; }
public string ProxyConnection { get; set; }
public bool? DoSSLFix { get; set; }
public bool? IgnoreSslErrors { get; set; }
public string CustomDataFolder { get; set; }
public string BasePath { get; set; }
public bool NoRestart { get; set; }
public string CustomLogFileName { get; set; }
public string DataFolder
{
get
{
if (!string.IsNullOrWhiteSpace(this.CustomDataFolder))
{
return this.CustomDataFolder;
}
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
}
else
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Jackett");
}
}
}
}
}

View File

@@ -1,4 +1,5 @@
using Jackett.Common.Models.Config;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -10,10 +11,11 @@ namespace Jackett.Models.Config
{
public class ServerConfig
{
public ServerConfig()
public ServerConfig(RuntimeSettings runtimeSettings)
{
Port = 9117;
AllowExternal = System.Environment.OSVersion.Platform == PlatformID.Unix;
RuntimeSettings = runtimeSettings;
}
public int Port { get; set; }
@@ -27,6 +29,13 @@ namespace Jackett.Models.Config
public string BasePathOverride { get; set; }
public string OmdbApiKey { get; set; }
/// <summary>
/// Ignore as we don't really want to be saving settings specified in the command line.
/// This is a bit of a hack, but in future it might not be all that bad to be able to override config values using settings that were provided at runtime. (and save them if required)
/// </summary>
[JsonIgnore]
public RuntimeSettings RuntimeSettings { get; set; }
public string ProxyUrl { get; set; }
public ProxyType ProxyType { get; set; }
public int? ProxyPort { get; set; }

View File

@@ -3,6 +3,7 @@ using Jacket.Common;
using Jackett.Services;
using Jackett.Models.Config;
using Jackett.Common.Models.Config;
using Jackett.Common.Plumbing;
namespace Jackett.Models.DTO
{
@@ -42,7 +43,7 @@ namespace Jackett.Models.DTO
updatedisabled = config.UpdateDisabled;
prerelease = config.UpdatePrerelease;
password = string.IsNullOrEmpty(config.AdminPassword) ? string.Empty : config.AdminPassword.Substring(0, 10);
logging = JackettStartup.TracingEnabled;
logging = config.RuntimeSettings.TracingEnabled;
basepathoverride = config.BasePathOverride;
omdbkey = config.OmdbApiKey;
app_version = version;

View File

@@ -16,11 +16,19 @@ using System.IO;
using Newtonsoft.Json.Linq;
using Jackett.Utils;
using System.Collections.Generic;
using Jackett.Common.Models.Config;
namespace Jackett
namespace Jackett.Common.Plumbing
{
public class JackettModule : Autofac.Module
{
private RuntimeSettings _runtimeSettings;
public JackettModule (RuntimeSettings runtimeSettings)
{
_runtimeSettings = runtimeSettings;
}
protected override void Load(ContainerBuilder builder)
{
// Just register everything! TODO: Something better and more explicit than scanning everything.
@@ -41,15 +49,16 @@ namespace Jackett
.Except<CardigannIndexer>()
.AsImplementedInterfaces().SingleInstance();
builder.RegisterInstance(_runtimeSettings);
builder.Register(ctx =>
{
return BuildServerConfig(ctx);
}).As<ServerConfig>().SingleInstance();
builder.RegisterType<HttpWebClient>();
// Register the best web client for the platform or the override
switch (JackettStartup.ClientOverride)
switch (_runtimeSettings.ClientOverride)
{
case "httpclient":
builder.RegisterType<HttpWebClient>().As<WebClient>();
@@ -77,18 +86,23 @@ namespace Jackett
builder.RegisterType<UnixLibCurlWebClient>().As<WebClient>();
break;
}
InitAutomapper();
}
private static ServerConfig BuildServerConfig(IComponentContext ctx)
private ServerConfig BuildServerConfig(IComponentContext ctx)
{
var configService = ctx.Resolve<IConfigurationService>();
// Load config
var config = configService.GetConfig<ServerConfig>();
if (config == null)
{
config = new ServerConfig();
config = new ServerConfig(_runtimeSettings);
}
else
{
//We don't load these out of the config files as it could get confusing to users who accidently save.
//In future we could flatten the serverconfig, and use command line parameters to override any configuration.
config.RuntimeSettings = _runtimeSettings;
}
if (string.IsNullOrWhiteSpace(config.APIKey))
@@ -125,43 +139,7 @@ namespace Jackett
return config;
}
private static void InitAutomapper()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<WebClientByteResult, WebClientStringResult>().ForMember(x => x.Content, opt => opt.Ignore()).AfterMap((be, str) =>
{
var encoding = be.Request.Encoding ?? Encoding.UTF8;
str.Content = encoding.GetString(be.Content);
});
cfg.CreateMap<WebClientStringResult, WebClientByteResult>().ForMember(x => x.Content, opt => opt.Ignore()).AfterMap((str, be) =>
{
if (!string.IsNullOrEmpty(str.Content))
{
var encoding = str.Request.Encoding ?? Encoding.UTF8;
be.Content = encoding.GetBytes(str.Content);
}
});
cfg.CreateMap<WebClientStringResult, WebClientStringResult>();
cfg.CreateMap<WebClientByteResult, WebClientByteResult>();
cfg.CreateMap<ReleaseInfo, ReleaseInfo>();
cfg.CreateMap<ReleaseInfo, TrackerCacheResult>().AfterMap((r, t) =>
{
if (r.Category != null)
{
var CategoryDesc = string.Join(", ", r.Category.Select(x => TorznabCatType.GetCatDesc(x)).Where(x => !string.IsNullOrEmpty(x)));
t.CategoryDesc = CategoryDesc;
}
else
{
t.CategoryDesc = "";
}
});
});
}
private static bool DetectMonoCompatabilityWithHttpClient()
{

View File

@@ -8,6 +8,9 @@ using System.Security.AccessControl;
using System.Security.Principal;
using Jackett.Services.Interfaces;
using Jacket.Common;
using Jacket.Common.Utils;
using Jackett.Common.Models.Config;
using Jackett.Models.Config;
namespace Jackett.Services
{
@@ -17,15 +20,22 @@ namespace Jackett.Services
private ISerializeService serializeService;
private Logger logger;
private IProcessService processService;
private RuntimeSettings runtimeSettings;
public ConfigurationService(ISerializeService s, IProcessService p, Logger l)
public ConfigurationService(ISerializeService s, IProcessService p, Logger l, RuntimeSettings settings)
{
serializeService = s;
logger = l;
processService = p;
runtimeSettings = settings;
CreateOrMigrateSettings();
}
public string GetAppDataFolder()
{
return runtimeSettings.DataFolder;
}
public void CreateOrMigrateSettings()
{
try
@@ -213,31 +223,6 @@ namespace Jackett.Services
}
public string GetAppDataFolder()
{
return GetAppDataFolderStatic();
}
/// <summary>
/// This is needed for the logger prior to ioc setup.
/// </summary>
/// <returns></returns>
public static string GetAppDataFolderStatic()
{
if (!string.IsNullOrWhiteSpace(JackettStartup.CustomDataFolder))
{
return JackettStartup.CustomDataFolder;
}
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
}
else
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Jackett");
}
}
public string GetIndexerConfigDir()
{
@@ -256,7 +241,7 @@ namespace Jackett.Services
public string GetVersion()
{
return JackettStartup.JackettVersion;
return EnvironmentUtil.JackettVersion;
}
}
}

View File

@@ -127,7 +127,7 @@ namespace Jackett.Services
var installDir = Path.GetDirectoryName(ExePath());
var updaterPath = Path.Combine(tempDir, "Jackett", "JackettUpdater.exe");
if (updaterPath != null)
StartUpdate(updaterPath, installDir, isWindows, JackettStartup.NoRestart);
StartUpdate(updaterPath, installDir, isWindows, config.RuntimeSettings.NoRestart);
}
catch (Exception e)
{

View File

@@ -35,7 +35,7 @@ namespace Jackett.Utils.Clients
{
ServicePointManager.DefaultConnectionLimit = 1000;
if (JackettStartup.IgnoreSslErrors == true)
if (serverConfig.RuntimeSettings.IgnoreSslErrors == true)
{
logger.Info(string.Format("HttpWebClient: Disabling certificate validation"));
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };

View File

@@ -100,7 +100,7 @@ namespace Jackett.Utils.Clients
override public void Init()
{
if (JackettStartup.IgnoreSslErrors == true)
if (serverConfig.RuntimeSettings.IgnoreSslErrors == true)
{
logger.Info(string.Format("HttpWebClient2: Disabling certificate validation"));
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };

View File

@@ -56,10 +56,10 @@ namespace Jackett.Utils.Clients
var version = Curl.Version;
logger.Info("LibCurl version " + version);
if (!JackettStartup.DoSSLFix.HasValue && version.IndexOf("NSS") > -1)
if (!serverConfig.RuntimeSettings.DoSSLFix.HasValue && version.IndexOf("NSS") > -1)
{
logger.Info("NSS Detected SSL ECC workaround enabled.");
JackettStartup.DoSSLFix = true;
serverConfig.RuntimeSettings.DoSSLFix = true;
}
}

View File

@@ -72,13 +72,13 @@ namespace Jackett.Utils.Clients
var tempFile = Path.GetTempFileName();
args.AppendFormat("--output \"{0}\" ", tempFile);
if (JackettStartup.DoSSLFix == true)
if (serverConfig.RuntimeSettings.DoSSLFix == true)
{
// http://stackoverflow.com/questions/31107851/how-to-fix-curl-35-cannot-communicate-securely-with-peer-no-common-encryptio
// https://git.fedorahosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html
args.Append("--cipher " + SSLFix.CipherList);
}
if (JackettStartup.IgnoreSslErrors == true)
if (serverConfig.RuntimeSettings.IgnoreSslErrors == true)
{
args.Append("-k ");
}
@@ -98,7 +98,7 @@ namespace Jackett.Utils.Clients
if (headSplit < 0)
throw new Exception("Invalid response");
var headers = stdout.Substring(0, headSplit);
if (JackettStartup.ProxyConnection != null)
if (serverConfig.RuntimeSettings.ProxyConnection != null)
{
// the proxy provided headers too so we need to split headers again
var headSplit1 = stdout.IndexOf("\r\n\r\n", headSplit + 4);

View File

@@ -0,0 +1,27 @@
using System;
using System.Reflection;
namespace Jacket.Common.Utils
{
public static class EnvironmentUtil
{
public static string JackettVersion
{
get
{
return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString() ?? "Unknown Version";
}
}
public static bool IsWindows
{
get
{
return Environment.OSVersion.Platform == PlatformID.Win32NT;
}
}
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,10 +12,8 @@
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<RuntimeIdentifier>win</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -59,7 +57,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConsoleOptions.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@@ -86,11 +83,6 @@
<ItemGroup>
<Content Include="jackett.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser">
<Version>1.9.71</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,7 +1,6 @@
using CommandLine;
using CommandLine.Text;
using Jackett;
using Jackett.Console;
using Jackett.Indexers;
using Jackett.Utils;
using System;
@@ -16,6 +15,9 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Jacket.Common;
using Jackett.Common.Models.Config;
using Jacket.Common.Utils;
using Jackett.Common.Plumbing;
namespace JackettConsole
{
@@ -24,64 +26,53 @@ namespace JackettConsole
static void Main(string[] args)
{
try
var optionsResult = Parser.Default.ParseArguments<ConsoleOptions>(args);
optionsResult.WithNotParsed(errors =>
{
var options = new ConsoleOptions();
if (!Parser.Default.ParseArguments(args, options) || options.ShowHelp == true)
{
if (options.LastParserState != null && options.LastParserState.Errors.Count > 0)
{
var help = new HelpText();
var errors = help.RenderParsingErrorsText(options, 2); // indent with two spaces
Console.WriteLine("Jackett v" + JackettStartup.JackettVersion);
Console.WriteLine("Switch error: " + errors);
Console.WriteLine("See --help for further details on switches.");
Environment.ExitCode = 1;
return;
}
else
{
var text = HelpText.AutoBuild(optionsResult);
text.Copyright = " ";
text.Heading = "Jackett v" + EnvironmentUtil.JackettVersion + " options:";
Console.WriteLine(text);
Environment.ExitCode = 1;
return;
});
var text = HelpText.AutoBuild(options, (HelpText current) => HelpText.DefaultParsingErrorsHandler(options, current));
text.Copyright = " ";
text.Heading = "Jackett v" + Engine.ConfigService.GetVersion() + " options:";
Console.WriteLine(text);
Environment.ExitCode = 1;
return;
}
}
else
optionsResult.WithParsed(options =>
{
try
{
SetJacketOptions(options);
var runtimeSettings = options.ToRunTimeSettings();
// Initialize autofac, logger, etc. We cannot use any calls to Engine before the container is set up.
Engine.BuildContainer(new WebApi2Module());
Engine.BuildContainer(runtimeSettings, new WebApi2Module());
if (options.Logging)
if (runtimeSettings.LogRequests)
Engine.Logger.Info("Logging enabled.");
if (options.Tracing)
if (runtimeSettings.TracingEnabled)
Engine.Logger.Info("Tracing enabled.");
if (options.IgnoreSslErrors == true)
if (runtimeSettings.IgnoreSslErrors == true)
{
Engine.Logger.Info("Jackett will ignore SSL certificate errors.");
}
if (options.SSLFix == true)
if (runtimeSettings.DoSSLFix == true)
Engine.Logger.Info("SSL ECC workaround enabled.");
else if (options.SSLFix == false)
else if (runtimeSettings.DoSSLFix == false)
Engine.Logger.Info("SSL ECC workaround has been disabled.");
// Choose Data Folder
if (!string.IsNullOrWhiteSpace(options.DataFolder))
if (!string.IsNullOrWhiteSpace(runtimeSettings.CustomDataFolder))
{
Engine.Logger.Info("Jackett Data will be stored in: " + JackettStartup.CustomDataFolder);
Engine.Logger.Info("Jackett Data will be stored in: " + runtimeSettings.CustomDataFolder);
}
// Use Proxy
if (options.ProxyConnection != null)
{
Engine.Logger.Info("Proxy enabled. " + JackettStartup.ProxyConnection);
Engine.Logger.Info("Proxy enabled. " + runtimeSettings.ProxyConnection);
}
/* ====== Actions ===== */
@@ -139,7 +130,7 @@ namespace JackettConsole
// Show Version
if (options.ShowVersion)
{
Console.WriteLine("Jackett v" + Engine.ConfigService.GetVersion());
Console.WriteLine("Jackett v" + EnvironmentUtil.JackettVersion);
return;
}
@@ -161,8 +152,7 @@ namespace JackettConsole
else
{
Engine.Logger.Error("Unable to switch to public listening without admin rights.");
Environment.ExitCode = 1;
return;
Environment.Exit(1);
}
}
@@ -186,67 +176,28 @@ namespace JackettConsole
else
{
Engine.Logger.Error("Unable to switch ports when not running as administrator");
Environment.ExitCode = 1;
return;
Environment.Exit(1);
}
}
Engine.SaveServerConfig();
}
}
Engine.Server.Initalize();
Engine.Server.Start();
Engine.RunTime.Spin();
Engine.Logger.Info("Server thread exit");
}
Engine.Server.Initalize();
Engine.Server.Start();
Engine.RunTime.Spin();
Engine.Logger.Info("Server thread exit");
}
catch (Exception e)
{
Engine.Logger.Error(e, "Top level exception");
}
}
static void SetJacketOptions(ConsoleOptions options)
{
// Logging
if (options.Logging)
JackettStartup.LogRequests = true;
// Tracing
if (options.Tracing)
JackettStartup.TracingEnabled = true;
if (options.ListenPublic && options.ListenPrivate)
{
Console.WriteLine("You can only use listen private OR listen publicly.");
Environment.ExitCode = 1;
return;
}
// SSL Fix
JackettStartup.DoSSLFix = options.SSLFix;
// Use curl
if (options.Client != null)
JackettStartup.ClientOverride = options.Client.ToLowerInvariant();
// Use Proxy
if (options.ProxyConnection != null)
{
JackettStartup.ProxyConnection = options.ProxyConnection.ToLowerInvariant();
}
catch (Exception e)
{
Engine.Logger.Error(e, "Top level exception");
}
});
}
// Ignore SSL errors on Curl
JackettStartup.IgnoreSslErrors = options.IgnoreSslErrors;
JackettStartup.NoRestart = options.NoRestart;
}
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,10 +12,8 @@
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<RuntimeIdentifier>win</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -87,11 +85,6 @@
<Name>Jackett</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="NLog">
<Version>5.0.0-beta11</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,4 +1,5 @@
using System;
using Jackett.Common.Models.Config;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
@@ -19,7 +20,7 @@ namespace Jackett.Service
protected override void OnStart(string[] args)
{
Engine.BuildContainer(new WebApi2Module());
Engine.BuildContainer(new RuntimeSettings(), new WebApi2Module());
Engine.Logger.Info("Service starting");
Engine.Server.Initalize();
Engine.Server.Start();

View File

@@ -6,6 +6,12 @@
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Indexers\**" />
<EmbeddedResource Remove="Indexers\**" />
<None Remove="Indexers\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Util\Invalid-RSS.xml" />
</ItemGroup>
@@ -16,16 +22,15 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="4.19.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
<PackageReference Include="NUnit" Version="3.8.1" />
<PackageReference Include="NUnit" Version="3.9.0" />
<PackageReference Include="NUnit.ConsoleRunner" Version="3.7.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.9.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Indexers\" />
<Folder Include="Properties\" />
</ItemGroup>

View File

@@ -11,6 +11,8 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Jackett.Services.Interfaces;
using Jackett.Common.Plumbing;
using Jackett.Common.Models.Config;
namespace Jackett.Test
{
@@ -21,10 +23,10 @@ namespace Jackett.Test
public static void SetupContainer()
{
var builder = new ContainerBuilder();
builder.RegisterModule<JackettModule>();
builder.RegisterModule(new JackettModule(new RuntimeSettings()));
builder.RegisterModule<WebApi2Module>();
builder.RegisterType<TestWebClient>().As<WebClient>().SingleInstance();
builder.RegisterInstance<Logger>(LogManager.GetCurrentClassLogger()).SingleInstance();
builder.RegisterInstance(LogManager.GetCurrentClassLogger()).SingleInstance();
builder.RegisterType<TestIndexerManagerServiceHelper>().As<IIndexerManagerService>().SingleInstance();
testContainer = builder.Build();
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,10 +12,8 @@
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<RuntimeIdentifier>win</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -119,11 +117,6 @@
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="NLog">
<Version>5.0.0-beta11</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,4 +1,5 @@
using Jackett;
using Jackett.Common.Models.Config;
using Jackett.Utils;
using Microsoft.Win32;
using System;
@@ -34,7 +35,7 @@ namespace JackettTray
toolStripMenuItemAutoStart.Visible = true;
}
Engine.BuildContainer(new WebApi2Module());
Engine.BuildContainer(new RuntimeSettings(),new WebApi2Module());
Engine.Server.Initalize();
if (!Engine.ServiceConfig.ServiceExists())

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,10 +12,8 @@
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<RuntimeIdentifier>win</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -83,11 +81,6 @@
<ItemGroup>
<Content Include="jackett.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser">
<Version>1.9.71</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,4 +1,6 @@
using CommandLine;
using CommandLine.Text;
using Jackett.Common.Models.Config;
using Jackett.Services;
using System;
using System.Collections.Generic;
@@ -22,21 +24,25 @@ namespace Jackett.Updater
private void Run(string[] args)
{
Engine.BuildContainer();
Engine.SetupLogging(null, "updater.txt");
Engine.BuildContainer(new RuntimeSettings()
{
CustomLogFileName = "updater.txt"
});
Engine.Logger.Info("Jackett Updater v" + GetCurrentVersion());
Engine.Logger.Info("Options \"" + string.Join("\" \"", args) + "\"");
try {
var options = new UpdaterConsoleOptions();
if (Parser.Default.ParseArguments(args, options))
var optionsResult = Parser.Default.ParseArguments<UpdaterConsoleOptions>(args);
optionsResult.WithParsed(options =>
{
ProcessUpdate(options);
}
else
);
optionsResult.WithNotParsed(errors =>
{
Engine.Logger.Error(HelpText.AutoBuild(optionsResult));
Engine.Logger.Error("Failed to process update arguments!");
Console.ReadKey();
}
});
}
catch (Exception e)
{
@@ -46,7 +52,7 @@ namespace Jackett.Updater
private string GetCurrentVersion()
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assembly = Assembly.GetExecutingAssembly();
var fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
return fvi.FileVersion;
}

View File

@@ -9,7 +9,7 @@ namespace Jackett.Updater
{
public class UpdaterConsoleOptions
{
[Option('p', "Path", HelpText = "Install location")]
[Option('p', "Path", HelpText = "Install location", Required = true)]
public string Path { get; set; }
[Option('t', "Type", HelpText = "Install type")]

View File

@@ -95,11 +95,11 @@ namespace Jackett.Controllers.V20
serverConfig.UpdateDisabled = updateDisabled;
serverConfig.UpdatePrerelease = preRelease;
serverConfig.BasePathOverride = basePathOverride;
JackettStartup.BasePath = Engine.Server.BasePath();
serverConfig.RuntimeSettings.BasePath = Engine.Server.BasePath();
configService.SaveConfig(serverConfig);
Engine.SetLogLevel(logging ? LogLevel.Debug : LogLevel.Info);
JackettStartup.TracingEnabled = logging;
serverConfig.RuntimeSettings.TracingEnabled = logging;
if (omdbApiKey != serverConfig.OmdbApiKey)
{
@@ -168,7 +168,7 @@ namespace Jackett.Controllers.V20
{
Thread.Sleep(500);
serverService.Stop();
Engine.BuildContainer(new WebApi2Module());
Engine.BuildContainer(serverConfig.RuntimeSettings, new WebApi2Module());
Engine.Server.Initalize();
Engine.Server.Start();
})).Start();

View File

@@ -238,7 +238,7 @@ namespace Jackett.Services
logger.Info("Starting web server at " + config.GetListenAddresses()[0]);
var startOptions = new StartOptions();
config.GetListenAddresses().ToList().ForEach(u => startOptions.Urls.Add(u));
JackettStartup.BasePath = BasePath();
config.RuntimeSettings.BasePath = BasePath();
try
{
_server = WebApp.Start<Startup>(startOptions);

View File

@@ -101,13 +101,13 @@ namespace Jackett
{
// Configure Web API for self-host.
var config = new HttpConfiguration();
var jackettServerConfig = Engine.ServerConfig;
// try to fix SocketException crashes
// based on http://stackoverflow.com/questions/23368885/signalr-owin-self-host-on-linux-mono-socketexception-when-clients-lose-connectio/30583109#30583109
try
{
object httpListener;
if (appBuilder.Properties.TryGetValue(typeof(HttpListener).FullName, out httpListener) && httpListener is HttpListener)
if (appBuilder.Properties.TryGetValue(typeof(HttpListener).FullName, out object httpListener) && httpListener is HttpListener)
{
// HttpListener should not return exceptions that occur when sending the response to the client
((HttpListener)httpListener).IgnoreWriteExceptions = true;
@@ -118,21 +118,22 @@ namespace Jackett
{
Engine.Logger.Error(e, "Error while setting HttpListener.IgnoreWriteExceptions = true");
}
appBuilder.Use<WebApiRootRedirectMiddleware>();
appBuilder.Use<LegacyApiRedirectMiddleware>();
// register exception handler
config.Filters.Add(new ApiExceptionHandler());
;
// Setup tracing if enabled
if (JackettStartup.TracingEnabled)
if (jackettServerConfig.RuntimeSettings.TracingEnabled)
{
config.EnableSystemDiagnosticsTracing();
config.Services.Replace(typeof(ITraceWriter), new WebAPIToNLogTracer());
config.Services.Replace(typeof(ITraceWriter), new WebAPIToNLogTracer(jackettServerConfig));
}
// Add request logging if enabled
if (JackettStartup.LogRequests)
if (jackettServerConfig.RuntimeSettings.LogRequests)
config.MessageHandlers.Add(new WebAPIRequestLogger());
config.DependencyResolver = new AutofacWebApiDependencyResolver(Engine.GetContainer());

View File

@@ -2,6 +2,7 @@
using System;
using System.Threading.Tasks;
using Jacket.Common;
using Jackett.Models.Config;
namespace Jackett.Utils
{
@@ -10,20 +11,21 @@ namespace Jackett.Utils
public WebApiRootRedirectMiddleware(OwinMiddleware next)
: base(next)
{
//Ideally we'd dependency inject the server config into the middleware but AutoFac's Owin package has not been updated to support Autofac > 5
}
public async override Task Invoke(IOwinContext context)
{
if (context.Request.Path != null && context.Request.Path.HasValue && context.Request.Path.Value.StartsWith(JackettStartup.BasePath, StringComparison.Ordinal))
if (context.Request.Path != null && context.Request.Path.HasValue && context.Request.Path.Value.StartsWith(Engine.ServerConfig.RuntimeSettings.BasePath, StringComparison.Ordinal))
{
context.Request.Path = new PathString(context.Request.Path.Value.Substring(JackettStartup.BasePath.Length - 1));
context.Request.Path = new PathString(context.Request.Path.Value.Substring(Engine.ServerConfig.RuntimeSettings.BasePath.Length - 1));
}
if (context.Request.Path == null || string.IsNullOrWhiteSpace(context.Request.Path.ToString()) || context.Request.Path.ToString() == "/")
{
// 301 is the status code of permanent redirect
context.Response.StatusCode = 302;
var redir = JackettStartup.BasePath + "UI/Dashboard";
var redir = Engine.ServerConfig.RuntimeSettings.BasePath + "UI/Dashboard";
Engine.Logger.Info("redirecting to " + redir);
context.Response.Headers.Set("Location", redir);
}

View File

@@ -6,15 +6,23 @@ using System.Text;
using System.Threading.Tasks;
using System.Web.Http.Tracing;
using Jacket.Common;
using Jackett.Models.Config;
namespace Jackett.Utils
{
public class WebAPIToNLogTracer : ITraceWriter
{
private ServerConfig _serverConfig;
public WebAPIToNLogTracer(ServerConfig serverConfig)
{
_serverConfig = serverConfig;
}
public void Trace(HttpRequestMessage request, string category, TraceLevel level,
Action<TraceRecord> traceAction)
{
if (JackettStartup.TracingEnabled)
if (_serverConfig.RuntimeSettings.TracingEnabled)
{
TraceRecord rec = new TraceRecord(request, category, level);
traceAction(rec);