mirror of https://github.com/Jackett/Jackett
commit
64daefb2b6
|
@ -15,5 +15,13 @@ namespace Jackett
|
||||||
{
|
{
|
||||||
ConfigData = data;
|
ConfigData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CustomException : Exception
|
||||||
|
{
|
||||||
|
public CustomException(string message)
|
||||||
|
: base(message)
|
||||||
|
{ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,7 @@
|
||||||
<Compile Include="ReleaseInfo.cs" />
|
<Compile Include="ReleaseInfo.cs" />
|
||||||
<Compile Include="ResultPage.cs" />
|
<Compile Include="ResultPage.cs" />
|
||||||
<Compile Include="Server.cs" />
|
<Compile Include="Server.cs" />
|
||||||
|
<Compile Include="ServerUtil.cs" />
|
||||||
<Compile Include="SonarApi.cs" />
|
<Compile Include="SonarApi.cs" />
|
||||||
<Compile Include="TorznabQuery.cs" />
|
<Compile Include="TorznabQuery.cs" />
|
||||||
<Compile Include="TVRage.cs" />
|
<Compile Include="TVRage.cs" />
|
||||||
|
|
|
@ -120,6 +120,19 @@ namespace Jackett
|
||||||
Console.WriteLine("Server thread exit");
|
Console.WriteLine("Server thread exit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RestartServer()
|
||||||
|
{
|
||||||
|
|
||||||
|
ServerInstance.Stop();
|
||||||
|
ServerInstance = null;
|
||||||
|
var serverTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
ServerInstance = new Server();
|
||||||
|
await ServerInstance.Start();
|
||||||
|
});
|
||||||
|
Task.WaitAll(serverTask);
|
||||||
|
}
|
||||||
|
|
||||||
static void MigrateSettingsDirectory()
|
static void MigrateSettingsDirectory()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
@ -30,8 +31,10 @@ namespace Jackett
|
||||||
// Allow all SSL.. sucks I know but mono on linux is having problems without it..
|
// Allow all SSL.. sucks I know but mono on linux is having problems without it..
|
||||||
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
|
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
|
||||||
|
|
||||||
|
ReadServerSettingsFile();
|
||||||
LoadApiKey();
|
LoadApiKey();
|
||||||
|
|
||||||
|
|
||||||
indexerManager = new IndexerManager();
|
indexerManager = new IndexerManager();
|
||||||
sonarrApi = new SonarrApi();
|
sonarrApi = new SonarrApi();
|
||||||
webApi = new WebApi(indexerManager, sonarrApi);
|
webApi = new WebApi(indexerManager, sonarrApi);
|
||||||
|
@ -68,6 +71,7 @@ namespace Jackett
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.Start();
|
listener.Start();
|
||||||
|
webApi.server = this;
|
||||||
}
|
}
|
||||||
catch (HttpListenerException ex)
|
catch (HttpListenerException ex)
|
||||||
{
|
{
|
||||||
|
@ -249,5 +253,53 @@ namespace Jackett
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public JObject ReadServerSettingsFile()
|
||||||
|
{
|
||||||
|
var path = ServerConfigFile;
|
||||||
|
JObject jsonReply = new JObject();
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
jsonReply = JObject.Parse(File.ReadAllText(path));
|
||||||
|
Port = (int)jsonReply["port"];
|
||||||
|
ListenPublic = (bool)jsonReply["public"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jsonReply["port"] = Port;
|
||||||
|
jsonReply["public"] = ListenPublic;
|
||||||
|
}
|
||||||
|
return jsonReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> ApplyPortConfiguration(JToken json)
|
||||||
|
{
|
||||||
|
JObject jsonObject = (JObject)json;
|
||||||
|
JToken jJackettPort = jsonObject.GetValue("port");
|
||||||
|
int jackettPort;
|
||||||
|
if (!ServerUtil.IsPort(jJackettPort.ToString()))
|
||||||
|
throw new CustomException("The value entered is not a valid port");
|
||||||
|
else
|
||||||
|
jackettPort = int.Parse(jJackettPort.ToString());
|
||||||
|
|
||||||
|
if (jackettPort == Port)
|
||||||
|
throw new CustomException("The current port is the same as the one being used now.");
|
||||||
|
else if (ServerUtil.RestrictedPorts.Contains(jackettPort))
|
||||||
|
throw new CustomException("This port is not allowed due to it not being safe.");
|
||||||
|
SaveSettings(jackettPort);
|
||||||
|
|
||||||
|
return Task.FromResult(jackettPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ServerConfigFile = Path.Combine(Program.AppConfigDirectory, "config.json");
|
||||||
|
|
||||||
|
private void SaveSettings(int jacketPort)
|
||||||
|
{
|
||||||
|
JObject json = new JObject();
|
||||||
|
json["port"] = jacketPort;
|
||||||
|
json["public"] = ListenPublic;
|
||||||
|
File.WriteAllText(ServerConfigFile, json.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Jackett
|
||||||
|
{
|
||||||
|
public static class ServerUtil
|
||||||
|
{
|
||||||
|
public static int[] RestrictedPorts = new int[] {
|
||||||
|
1, // tcpmux
|
||||||
|
7, // echo
|
||||||
|
9, // discard
|
||||||
|
11, // systat
|
||||||
|
13, // daytime
|
||||||
|
15, // netstat
|
||||||
|
17, // qotd
|
||||||
|
19, // chargen
|
||||||
|
20, // ftp data
|
||||||
|
21, // ftp access
|
||||||
|
22, // ssh
|
||||||
|
23, // telnet
|
||||||
|
25, // smtp
|
||||||
|
37, // time
|
||||||
|
42, // name
|
||||||
|
43, // nicname
|
||||||
|
53, // domain
|
||||||
|
77, // priv-rjs
|
||||||
|
79, // finger
|
||||||
|
87, // ttylink
|
||||||
|
95, // supdup
|
||||||
|
101, // hostriame
|
||||||
|
102, // iso-tsap
|
||||||
|
103, // gppitnp
|
||||||
|
104, // acr-nema
|
||||||
|
109, // pop2
|
||||||
|
110, // pop3
|
||||||
|
111, // sunrpc
|
||||||
|
113, // auth
|
||||||
|
115, // sftp
|
||||||
|
117, // uucp-path
|
||||||
|
119, // nntp
|
||||||
|
123, // NTP
|
||||||
|
135, // loc-srv /epmap
|
||||||
|
139, // netbios
|
||||||
|
143, // imap2
|
||||||
|
179, // BGP
|
||||||
|
389, // ldap
|
||||||
|
465, // smtp+ssl
|
||||||
|
512, // print / exec
|
||||||
|
513, // login
|
||||||
|
514, // shell
|
||||||
|
515, // printer
|
||||||
|
526, // tempo
|
||||||
|
530, // courier
|
||||||
|
531, // chat
|
||||||
|
532, // netnews
|
||||||
|
540, // uucp
|
||||||
|
556, // remotefs
|
||||||
|
563, // nntp+ssl
|
||||||
|
587, // stmp?
|
||||||
|
601, // ??
|
||||||
|
636, // ldap+ssl
|
||||||
|
993, // ldap+ssl
|
||||||
|
995, // pop3+ssl
|
||||||
|
2049, // nfs
|
||||||
|
3659, // apple-sasl / PasswordServer
|
||||||
|
4045, // lockd
|
||||||
|
6000, // X11
|
||||||
|
6665, // Alternate IRC [Apple addition]
|
||||||
|
6666, // Alternate IRC [Apple addition]
|
||||||
|
6667, // Standard IRC [Apple addition]
|
||||||
|
6668, // Alternate IRC [Apple addition]
|
||||||
|
6669, // Alternate IRC [Apple addition]};
|
||||||
|
};
|
||||||
|
public static bool IsPort(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Regex numeric = new Regex(@"^[0-9]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
if (numeric.IsMatch(value))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Convert.ToInt32(value) < 65536)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ namespace Jackett
|
||||||
{
|
{
|
||||||
static string WebContentFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WebContent");
|
static string WebContentFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WebContent");
|
||||||
static string[] StaticFiles = Directory.EnumerateFiles(WebContentFolder, "*", SearchOption.AllDirectories).ToArray();
|
static string[] StaticFiles = Directory.EnumerateFiles(WebContentFolder, "*", SearchOption.AllDirectories).ToArray();
|
||||||
|
public Server server;
|
||||||
|
|
||||||
public enum WebApiMethod
|
public enum WebApiMethod
|
||||||
{
|
{
|
||||||
|
@ -26,7 +27,10 @@ namespace Jackett
|
||||||
DeleteIndexer,
|
DeleteIndexer,
|
||||||
GetSonarrConfig,
|
GetSonarrConfig,
|
||||||
ApplySonarrConfig,
|
ApplySonarrConfig,
|
||||||
TestSonarr
|
TestSonarr,
|
||||||
|
GetJackettConfig,
|
||||||
|
ApplyJackettConfig,
|
||||||
|
JackettRestart,
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dictionary<string, WebApiMethod> WebApiMethods = new Dictionary<string, WebApiMethod> {
|
static Dictionary<string, WebApiMethod> WebApiMethods = new Dictionary<string, WebApiMethod> {
|
||||||
|
@ -37,7 +41,10 @@ namespace Jackett
|
||||||
{ "delete_indexer", WebApiMethod.DeleteIndexer },
|
{ "delete_indexer", WebApiMethod.DeleteIndexer },
|
||||||
{ "get_sonarr_config", WebApiMethod.GetSonarrConfig },
|
{ "get_sonarr_config", WebApiMethod.GetSonarrConfig },
|
||||||
{ "apply_sonarr_config", WebApiMethod.ApplySonarrConfig },
|
{ "apply_sonarr_config", WebApiMethod.ApplySonarrConfig },
|
||||||
{ "test_sonarr", WebApiMethod.TestSonarr }
|
{ "test_sonarr", WebApiMethod.TestSonarr },
|
||||||
|
{ "get_jackett_config",WebApiMethod.GetJackettConfig},
|
||||||
|
{ "apply_jackett_config",WebApiMethod.ApplyJackettConfig},
|
||||||
|
{ "jackett_restart", WebApiMethod.JackettRestart },
|
||||||
};
|
};
|
||||||
|
|
||||||
IndexerManager indexerManager;
|
IndexerManager indexerManager;
|
||||||
|
@ -127,6 +134,15 @@ namespace Jackett
|
||||||
case WebApiMethod.TestSonarr:
|
case WebApiMethod.TestSonarr:
|
||||||
handlerTask = HandleTestSonarr;
|
handlerTask = HandleTestSonarr;
|
||||||
break;
|
break;
|
||||||
|
case WebApiMethod.ApplyJackettConfig:
|
||||||
|
handlerTask = HandleApplyJackettConfig;
|
||||||
|
break;
|
||||||
|
case WebApiMethod.GetJackettConfig:
|
||||||
|
handlerTask = HandleJackettConfig;
|
||||||
|
break;
|
||||||
|
case WebApiMethod.JackettRestart:
|
||||||
|
handlerTask = HandleJackettRestart;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
handlerTask = HandleInvalidApiMethod;
|
handlerTask = HandleInvalidApiMethod;
|
||||||
break;
|
break;
|
||||||
|
@ -318,5 +334,54 @@ namespace Jackett
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Jacket port functions
|
||||||
|
Task<JToken> HandleJackettConfig(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
JObject jsonReply = new JObject();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
jsonReply["config"] = server.ReadServerSettingsFile();
|
||||||
|
jsonReply["result"] = "success";
|
||||||
|
}
|
||||||
|
catch (CustomException ex)
|
||||||
|
{
|
||||||
|
jsonReply["result"] = "error";
|
||||||
|
jsonReply["error"] = ex.Message;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
jsonReply["result"] = "error";
|
||||||
|
jsonReply["error"] = ex.Message;
|
||||||
|
}
|
||||||
|
return Task.FromResult<JToken>(jsonReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<JToken> HandleApplyJackettConfig(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
JToken jsonReply = new JObject();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var postData = await ReadPostDataJson(context.Request.InputStream);
|
||||||
|
int port = await server.ApplyPortConfiguration(postData);
|
||||||
|
jsonReply["result"] = "success";
|
||||||
|
jsonReply["port"] = port;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
jsonReply["result"] = "error";
|
||||||
|
jsonReply["error"] = ex.Message;
|
||||||
|
}
|
||||||
|
return jsonReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<JToken> HandleJackettRestart(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
Program.RestartServer();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,49 @@
|
||||||
|
|
||||||
|
|
||||||
reloadIndexers();
|
reloadIndexers();
|
||||||
|
loadJackettSettings();
|
||||||
loadSonarrInfo();
|
loadSonarrInfo();
|
||||||
|
|
||||||
|
function loadJackettSettings() {
|
||||||
|
getJackettConfig(function (data) {
|
||||||
|
$("#jackett-port").val(data.config.port);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#change-jackett-port").click(function () {
|
||||||
|
var jackett_port = $("#jackett-port").val();
|
||||||
|
var jsonObject = JSON.parse('{"port":"' + jackett_port + '"}');
|
||||||
|
|
||||||
|
var jqxhr = $.post("apply_jackett_config", JSON.stringify(jsonObject), function (data) {
|
||||||
|
|
||||||
|
if (data.result == "error") {
|
||||||
|
doNotify("Error: " + data.error, "danger", "glyphicon glyphicon-alert");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
doNotify("The port has been changed. Jackett will now restart...", "success", "glyphicon glyphicon-ok");
|
||||||
|
var jqxhr0 = $.post("jackett_restart", null, function (data_restart) { });
|
||||||
|
|
||||||
|
window.setTimeout(function () {
|
||||||
|
url = window.location.href;
|
||||||
|
window.location.href = url.substr(0, url.lastIndexOf(":") + 1) + data.port;
|
||||||
|
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
}
|
||||||
|
}).fail(function () {
|
||||||
|
doNotify("Request to Jackett server failed", "danger", "glyphicon glyphicon-alert");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function getJackettConfig(callback) {
|
||||||
|
var jqxhr = $.get("get_jackett_config", function (data) {
|
||||||
|
|
||||||
|
callback(data);
|
||||||
|
}).fail(function () {
|
||||||
|
doNotify("Error loading Jackett settings, request to Jackett server failed", "danger", "glyphicon glyphicon-alert");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function loadSonarrInfo() {
|
function loadSonarrInfo() {
|
||||||
getSonarrConfig(function (data) {
|
getSonarrConfig(function (data) {
|
||||||
$("#sonarr-host").val("");
|
$("#sonarr-host").val("");
|
||||||
|
|
|
@ -45,6 +45,12 @@
|
||||||
<span class="input-header">Jackett API Key: </span>
|
<span class="input-header">Jackett API Key: </span>
|
||||||
<input id="api-key-input" class="form-control input-right" type="text" value="" placeholder="API Key" readonly="">
|
<input id="api-key-input" class="form-control input-right" type="text" value="" placeholder="API Key" readonly="">
|
||||||
<p>Use this key when adding indexers to Sonarr. This key works for all indexers.</p>
|
<p>Use this key when adding indexers to Sonarr. This key works for all indexers.</p>
|
||||||
|
<span class="input-header">Jackett port: </span>
|
||||||
|
<input id="jackett-port" class="form-control input-right" type="text" value="" placeholder="9117">
|
||||||
|
<button id="change-jackett-port" class="btn btn-primary btn-sm">
|
||||||
|
Configure <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
<span title="Jackett will restart after changing the port" class="glyphicon glyphicon-info-sign"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
Loading…
Reference in New Issue