diff --git a/Build.bat b/Build.bat
new file mode 100644
index 000000000..8ee0b9dc0
--- /dev/null
+++ b/Build.bat
@@ -0,0 +1,15 @@
+
+rmdir /s /q build
+cd src
+Msbuild Jackett.sln /t:Clean,Build /p:Configuration=Release
+cd ..
+
+xcopy src\Jackett.Console\bin\Release Build\ /e /y
+copy /Y src\Jackett.Service\bin\Release\JackettService.exe build\JackettService.exe
+copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build\JackettService.exe.config
+copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build\JackettTray.exe
+copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build\JackettTray.exe.config
+cd build
+del *.pdb
+del *.xml
+cd ..
diff --git a/Installer.iss b/Installer.iss
new file mode 100644
index 000000000..9c6361bc4
--- /dev/null
+++ b/Installer.iss
@@ -0,0 +1,58 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define MyAppName "Jackett"
+#define MyAppVersion "0.5"
+#define MyAppPublisher "Jackett Inc."
+#define MyAppURL "https://github.com/zone117x/Jackett"
+#define MyAppExeName "JackettTray.exe"
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{C2A9FC00-AA48-4F17-9A72-62FBCEE2785B}
+AppName={#MyAppName}
+AppVersion={#MyAppVersion}
+;AppVerName={#MyAppName} {#MyAppVersion}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppURL}
+AppSupportURL={#MyAppURL}
+AppUpdatesURL={#MyAppURL}
+DefaultDirName={pf}\{#MyAppName}
+DefaultGroupName={#MyAppName}
+DisableProgramGroupPage=yes
+OutputBaseFilename=setup
+SetupIconFile=O:\Documents\JackettKayo\src\Jackett.Console\jackett.ico
+Compression=lzma
+SolidCompression=yes
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Tasks]
+Name: "windowsService"; Description: "Install as a Windows Service"
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Files]
+Source: "O:\Documents\JackettKayo\Build\JackettTray.exe"; DestDir: "{app}"; Flags: ignoreversion
+Source: "O:\Documents\JackettKayo\Build\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+[Icons]
+Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
+Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
+Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
+
+[Run]
+Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
+
+[Run]
+Filename: "{app}\JackettConsole.exe"; Parameters: "/u"; Flags: waituntilterminated;
+Filename: "{app}\JackettConsole.exe"; Parameters: "/r"; Flags: waituntilterminated;
+Filename: "{app}\JackettConsole.exe"; Parameters: "/i"; Flags: waituntilterminated; Tasks: windowsService
+
+[UninstallRun]
+Filename: "{app}\JackettConsole.exe"; Parameters: "/u"; Flags: waituntilterminated skipifdoesntexist
+
+
diff --git a/src/Jackett.Console/App.config b/src/Jackett.Console/App.config
new file mode 100644
index 000000000..da396d090
--- /dev/null
+++ b/src/Jackett.Console/App.config
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Console/Jackett.Console.csproj b/src/Jackett.Console/Jackett.Console.csproj
new file mode 100644
index 000000000..918f669ff
--- /dev/null
+++ b/src/Jackett.Console/Jackett.Console.csproj
@@ -0,0 +1,134 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {4E2A81DA-E235-4A88-AD20-38AABBFBF33C}
+ Exe
+ Properties
+ Jackett.Console
+ JackettConsole
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ jackett.ico
+
+
+ JackettConsole.Program
+
+
+
+ False
+ ..\packages\Autofac.3.5.0\lib\net40\Autofac.dll
+
+
+ ..\packages\Autofac.Owin.3.1.0\lib\net45\Autofac.Integration.Owin.dll
+
+
+ False
+ ..\packages\Autofac.WebApi2.3.4.0\lib\net45\Autofac.Integration.WebApi.dll
+
+
+ ..\packages\Autofac.WebApi2.Owin.3.2.0\lib\net45\Autofac.Integration.WebApi.Owin.dll
+
+
+ ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.FileSystems.3.0.1\lib\net45\Microsoft.Owin.FileSystems.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.Host.HttpListener.2.0.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.StaticFiles.3.0.1\lib\net45\Microsoft.Owin.StaticFiles.dll
+ True
+
+
+ ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+ False
+ ..\packages\NLog.4.0.1\lib\net45\NLog.dll
+
+
+ ..\packages\Owin.1.0\lib\net40\Owin.dll
+ True
+
+
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
+ True
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
+ True
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {e636d5f8-68b4-4903-b4ed-ccfd9c9e899f}
+ Jackett
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Console/Program.cs b/src/Jackett.Console/Program.cs
new file mode 100644
index 000000000..99a610f7c
--- /dev/null
+++ b/src/Jackett.Console/Program.cs
@@ -0,0 +1,50 @@
+using Jackett;
+using Jackett.Indexers;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace JackettConsole
+{
+ public class Program
+ {
+ static void Main(string[] args)
+ {
+ try
+ {
+ if (args.Length > 0)
+ {
+ switch (args[0].ToLowerInvariant())
+ {
+ case "/i":
+ Engine.ServiceConfig.Install();
+ return;
+ case "/r":
+ Engine.Server.ReserveUrls();
+ return;
+ case "/u":
+ Engine.Server.ReserveUrls(false);
+ Engine.ServiceConfig.Uninstall();
+ return;
+ }
+ }
+
+ Engine.Server.Start();
+ Engine.Logger.Info("Running in headless mode.");
+ Engine.RunTime.Spin();
+ Engine.Logger.Info("Server thread exit");
+ }
+ catch(Exception e)
+ {
+ Engine.Logger.Error(e, "Top level exception");
+ }
+ }
+ }
+}
+
diff --git a/src/Jackett.Console/Properties/AssemblyInfo.cs b/src/Jackett.Console/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..0c11610e1
--- /dev/null
+++ b/src/Jackett.Console/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Jackett.Console")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Jackett.Console")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("4e2a81da-e235-4a88-ad20-38aabbfbf33c")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Jackett/WebContent/favicon.ico b/src/Jackett.Console/jackett.ico
similarity index 100%
rename from src/Jackett/WebContent/favicon.ico
rename to src/Jackett.Console/jackett.ico
diff --git a/src/Jackett.Console/packages.config b/src/Jackett.Console/packages.config
new file mode 100644
index 000000000..90c9bc1e4
--- /dev/null
+++ b/src/Jackett.Console/packages.config
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Service/App.config b/src/Jackett.Service/App.config
new file mode 100644
index 000000000..e74e545f8
--- /dev/null
+++ b/src/Jackett.Service/App.config
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Service/Jackett.Service.csproj b/src/Jackett.Service/Jackett.Service.csproj
new file mode 100644
index 000000000..b9614e42a
--- /dev/null
+++ b/src/Jackett.Service/Jackett.Service.csproj
@@ -0,0 +1,137 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BF611F7B-4658-4CB8-AA9E-0736FADAA3BA}
+ WinExe
+ Properties
+ Jackett.Service
+ JackettService
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ jackett.ico
+
+
+
+ False
+ ..\packages\Autofac.3.5.0\lib\net40\Autofac.dll
+
+
+ ..\packages\Autofac.Owin.3.1.0\lib\net45\Autofac.Integration.Owin.dll
+
+
+ False
+ ..\packages\Autofac.WebApi2.3.4.0\lib\net45\Autofac.Integration.WebApi.dll
+
+
+ ..\packages\Autofac.WebApi2.Owin.3.2.0\lib\net45\Autofac.Integration.WebApi.Owin.dll
+
+
+ False
+ ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
+
+
+ False
+ ..\packages\Microsoft.Owin.FileSystems.3.0.1\lib\net45\Microsoft.Owin.FileSystems.dll
+
+
+ ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll
+
+
+ False
+ ..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll
+
+
+ False
+ ..\packages\Microsoft.Owin.StaticFiles.3.0.1\lib\net45\Microsoft.Owin.StaticFiles.dll
+
+
+ False
+ ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll
+
+
+ False
+ ..\packages\NLog.4.0.1\lib\net45\NLog.dll
+
+
+ False
+ ..\packages\Owin.1.0\lib\net40\Owin.dll
+
+
+
+
+ False
+ ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
+
+
+ False
+ ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
+
+
+ False
+ ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
+
+
+
+
+
+
+
+
+
+
+
+ Component
+
+
+ Service.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {e636d5f8-68b4-4903-b4ed-ccfd9c9e899f}
+ Jackett
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Service/Program.cs b/src/Jackett.Service/Program.cs
new file mode 100644
index 000000000..22c25af4b
--- /dev/null
+++ b/src/Jackett.Service/Program.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.ServiceProcess;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Service
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ static void Main()
+ {
+ ServiceBase[] ServicesToRun;
+ ServicesToRun = new ServiceBase[]
+ {
+ new Service()
+ };
+ ServiceBase.Run(ServicesToRun);
+ }
+ }
+}
diff --git a/src/Jackett.Service/Properties/AssemblyInfo.cs b/src/Jackett.Service/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..246a632ba
--- /dev/null
+++ b/src/Jackett.Service/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Jackett.Service")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Jackett.Service")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("bf611f7b-4658-4cb8-aa9e-0736fadaa3ba")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Jackett.Service/Service.Designer.cs b/src/Jackett.Service/Service.Designer.cs
new file mode 100644
index 000000000..0e2f0f42d
--- /dev/null
+++ b/src/Jackett.Service/Service.Designer.cs
@@ -0,0 +1,37 @@
+namespace Jackett.Service
+{
+ partial class Service
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ this.ServiceName = "Jackett";
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Jackett.Service/Service.cs b/src/Jackett.Service/Service.cs
new file mode 100644
index 000000000..47690ab21
--- /dev/null
+++ b/src/Jackett.Service/Service.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Linq;
+using System.ServiceProcess;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Service
+{
+ public partial class Service : ServiceBase
+ {
+ public Service()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnStart(string[] args)
+ {
+ Engine.Logger.Info("Service starting");
+ Engine.Server.Start();
+ Engine.Logger.Info("Service started");
+ }
+
+ protected override void OnStop()
+ {
+ Engine.Logger.Info("Service stopping");
+ Engine.Server.Stop();
+ }
+ }
+}
diff --git a/src/Jackett/jacket_large.ico b/src/Jackett.Service/jackett.ico
similarity index 100%
rename from src/Jackett/jacket_large.ico
rename to src/Jackett.Service/jackett.ico
diff --git a/src/Jackett.Service/packages.config b/src/Jackett.Service/packages.config
new file mode 100644
index 000000000..c44eef52e
--- /dev/null
+++ b/src/Jackett.Service/packages.config
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Tray/App.config b/src/Jackett.Tray/App.config
new file mode 100644
index 000000000..88fa4027b
--- /dev/null
+++ b/src/Jackett.Tray/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Tray/Jackett.Tray.csproj b/src/Jackett.Tray/Jackett.Tray.csproj
new file mode 100644
index 000000000..0e3f38375
--- /dev/null
+++ b/src/Jackett.Tray/Jackett.Tray.csproj
@@ -0,0 +1,96 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {FF9025B1-EC14-4AA9-8081-9F69C5E35B63}
+ WinExe
+ Properties
+ Jackett.Tray
+ JackettTray
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ jackett.ico
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Main.cs
+
+
+
+
+ Main.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett/Main.Designer.cs b/src/Jackett.Tray/Main.Designer.cs
similarity index 98%
rename from src/Jackett/Main.Designer.cs
rename to src/Jackett.Tray/Main.Designer.cs
index d881a2821..71457c20d 100644
--- a/src/Jackett/Main.Designer.cs
+++ b/src/Jackett.Tray/Main.Designer.cs
@@ -1,6 +1,4 @@
-#if !__MonoCS__
-
-namespace Jackett
+namespace JackettTray
{
partial class Main
{
@@ -99,5 +97,4 @@ namespace Jackett
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemShutdown;
}
-}
-#endif
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/Jackett/Main.cs b/src/Jackett.Tray/Main.cs
similarity index 89%
rename from src/Jackett/Main.cs
rename to src/Jackett.Tray/Main.cs
index 250aff2ce..a1a51b09f 100644
--- a/src/Jackett/Main.cs
+++ b/src/Jackett.Tray/Main.cs
@@ -13,7 +13,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
-namespace Jackett
+namespace JackettTray
{
public partial class Main : Form
{
@@ -28,13 +28,13 @@ namespace Jackett
toolStripMenuItemWebUI.Click += toolStripMenuItemWebUI_Click;
toolStripMenuItemShutdown.Click += toolStripMenuItemShutdown_Click;
- if (Program.IsFirstRun)
- AutoStart = true;
+ //if (Server.IsFirstRun)
+ // AutoStart = true;
}
void toolStripMenuItemWebUI_Click(object sender, EventArgs e)
{
- Process.Start("http://127.0.0.1:" + Server.Port);
+ // Process.Start("http://127.0.0.1:" + Server.Port);
}
void toolStripMenuItemShutdown_Click(object sender, EventArgs e)
@@ -84,12 +84,12 @@ namespace Jackett
private void CreateShortcut()
{
- var appPath = Assembly.GetExecutingAssembly().Location;
+ /* var appPath = Assembly.GetExecutingAssembly().Location;
var shell = new IWshRuntimeLibrary.WshShell();
var shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(ShortcutPath);
shortcut.Description = Assembly.GetExecutingAssembly().GetName().Name;
shortcut.TargetPath = appPath;
- shortcut.Save();
+ shortcut.Save();*/
}
}
}
diff --git a/src/Jackett/Main.resx b/src/Jackett.Tray/Main.resx
similarity index 100%
rename from src/Jackett/Main.resx
rename to src/Jackett.Tray/Main.resx
diff --git a/src/Jackett.Tray/Program.cs b/src/Jackett.Tray/Program.cs
new file mode 100644
index 000000000..b902536cd
--- /dev/null
+++ b/src/Jackett.Tray/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace JackettTray
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Main());
+ }
+ }
+}
diff --git a/src/Jackett.Tray/Properties/AssemblyInfo.cs b/src/Jackett.Tray/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..0f6590c99
--- /dev/null
+++ b/src/Jackett.Tray/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Jackett.Tray")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Jackett.Tray")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ff9025b1-ec14-4aa9-8081-9f69c5e35b63")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Jackett.Tray/Properties/Resources.Designer.cs b/src/Jackett.Tray/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..b6ce33f0b
--- /dev/null
+++ b/src/Jackett.Tray/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Jackett.Tray.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Jackett.Tray.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/src/Jackett.Tray/Properties/Resources.resx b/src/Jackett.Tray/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/src/Jackett.Tray/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/Jackett.Tray/Properties/Settings.Designer.cs b/src/Jackett.Tray/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..c110e9e5e
--- /dev/null
+++ b/src/Jackett.Tray/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Jackett.Tray.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/src/Jackett.Tray/Properties/Settings.settings b/src/Jackett.Tray/Properties/Settings.settings
new file mode 100644
index 000000000..39645652a
--- /dev/null
+++ b/src/Jackett.Tray/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/Jackett.Tray/jackett.ico b/src/Jackett.Tray/jackett.ico
new file mode 100644
index 000000000..6392acc61
Binary files /dev/null and b/src/Jackett.Tray/jackett.ico differ
diff --git a/src/Jackett.sln b/src/Jackett.sln
index a7c6e3384..7e7f1ea9b 100644
--- a/src/Jackett.sln
+++ b/src/Jackett.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.31101.0
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett", "Jackett\Jackett.csproj", "{E636D5F8-68B4-4903-B4ED-CCFD9C9E899F}"
EndProject
@@ -13,6 +13,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
..\README.md = ..\README.md
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett.Console", "Jackett.Console\Jackett.Console.csproj", "{4E2A81DA-E235-4A88-AD20-38AABBFBF33C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett.Service", "Jackett.Service\Jackett.Service.csproj", "{BF611F7B-4658-4CB8-AA9E-0736FADAA3BA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett.Tray", "Jackett.Tray\Jackett.Tray.csproj", "{FF9025B1-EC14-4AA9-8081-9F69C5E35B63}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +33,18 @@ Global
{74420A79-CC16-442C-8B1E-7C1B913844F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4E2A81DA-E235-4A88-AD20-38AABBFBF33C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4E2A81DA-E235-4A88-AD20-38AABBFBF33C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4E2A81DA-E235-4A88-AD20-38AABBFBF33C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4E2A81DA-E235-4A88-AD20-38AABBFBF33C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BF611F7B-4658-4CB8-AA9E-0736FADAA3BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BF611F7B-4658-4CB8-AA9E-0736FADAA3BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BF611F7B-4658-4CB8-AA9E-0736FADAA3BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BF611F7B-4658-4CB8-AA9E-0736FADAA3BA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FF9025B1-EC14-4AA9-8081-9F69C5E35B63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FF9025B1-EC14-4AA9-8081-9F69C5E35B63}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FF9025B1-EC14-4AA9-8081-9F69C5E35B63}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FF9025B1-EC14-4AA9-8081-9F69C5E35B63}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Jackett/ApiKey.cs b/src/Jackett/ApiKey.cs
deleted file mode 100644
index 86848899a..000000000
--- a/src/Jackett/ApiKey.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jackett
-{
- public class ApiKey
- {
-
- public static string CurrentKey;
-
- const string chars = "abcdefghijklmnopqrstuvwxyz0123456789";
-
- public static string Generate()
- {
- var randBytes = new byte[32];
- var rngCsp = new RNGCryptoServiceProvider();
- rngCsp.GetBytes(randBytes);
- var key = "";
- foreach (var b in randBytes)
- {
- key += chars[b % chars.Length];
- }
- return key;
-
- }
- }
-}
diff --git a/src/Jackett/App.config b/src/Jackett/App.config
index 56ebf3f29..547fa70d5 100644
--- a/src/Jackett/App.config
+++ b/src/Jackett/App.config
@@ -9,7 +9,27 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Jackett/WebContent/animate.css b/src/Jackett/Content/animate.css
similarity index 100%
rename from src/Jackett/WebContent/animate.css
rename to src/Jackett/Content/animate.css
diff --git a/src/Jackett/WebContent/binding_dark.png b/src/Jackett/Content/binding_dark.png
similarity index 100%
rename from src/Jackett/WebContent/binding_dark.png
rename to src/Jackett/Content/binding_dark.png
diff --git a/src/Jackett/WebContent/bootstrap-notify.js b/src/Jackett/Content/bootstrap-notify.js
similarity index 100%
rename from src/Jackett/WebContent/bootstrap-notify.js
rename to src/Jackett/Content/bootstrap-notify.js
diff --git a/src/Jackett/WebContent/bootstrap/bootstrap.min.css b/src/Jackett/Content/bootstrap/bootstrap.min.css
similarity index 100%
rename from src/Jackett/WebContent/bootstrap/bootstrap.min.css
rename to src/Jackett/Content/bootstrap/bootstrap.min.css
diff --git a/src/Jackett/WebContent/bootstrap/bootstrap.min.js b/src/Jackett/Content/bootstrap/bootstrap.min.js
similarity index 100%
rename from src/Jackett/WebContent/bootstrap/bootstrap.min.js
rename to src/Jackett/Content/bootstrap/bootstrap.min.js
diff --git a/src/Jackett/WebContent/common.js b/src/Jackett/Content/common.js
similarity index 100%
rename from src/Jackett/WebContent/common.js
rename to src/Jackett/Content/common.js
diff --git a/src/Jackett/WebContent/congruent_outline.png b/src/Jackett/Content/congruent_outline.png
similarity index 100%
rename from src/Jackett/WebContent/congruent_outline.png
rename to src/Jackett/Content/congruent_outline.png
diff --git a/src/Jackett/WebContent/crissXcross.png b/src/Jackett/Content/crissXcross.png
similarity index 100%
rename from src/Jackett/WebContent/crissXcross.png
rename to src/Jackett/Content/crissXcross.png
diff --git a/src/Jackett/WebContent/custom.css b/src/Jackett/Content/custom.css
similarity index 100%
rename from src/Jackett/WebContent/custom.css
rename to src/Jackett/Content/custom.css
diff --git a/src/Jackett/WebContent/custom.js b/src/Jackett/Content/custom.js
similarity index 91%
rename from src/Jackett/WebContent/custom.js
rename to src/Jackett/Content/custom.js
index c79c6fa97..7ecf926b6 100644
--- a/src/Jackett/WebContent/custom.js
+++ b/src/Jackett/Content/custom.js
@@ -13,14 +13,14 @@ $("#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) {
+ var jqxhr = $.post("admin/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) { });
+ var jqxhr0 = $.post("admin/jackett_restart", null, function (data_restart) { });
window.setTimeout(function () {
url = window.location.href;
@@ -35,7 +35,7 @@ $("#change-jackett-port").click(function () {
});
function getJackettConfig(callback) {
- var jqxhr = $.get("get_jackett_config", function (data) {
+ var jqxhr = $.get("admin/get_jackett_config", function (data) {
callback(data);
}).fail(function () {
@@ -47,7 +47,7 @@ function reloadIndexers() {
$('#indexers').hide();
$('#indexers > .indexer').remove();
$('#unconfigured-indexers').empty();
- var jqxhr = $.get("get_indexers", function (data) {
+ var jqxhr = $.get("admin/get_indexers", function (data) {
$("#api-key-input").val(data.api_key);
$("#app-version").html(data.app_version);
displayIndexers(data.items);
@@ -82,7 +82,7 @@ function prepareDeleteButtons() {
var $btn = $(btn);
var id = $btn.data("id");
$btn.click(function () {
- var jqxhr = $.post("delete_indexer", JSON.stringify({ indexer: id }), function (data) {
+ var jqxhr = $.post("admin/delete_indexer", JSON.stringify({ indexer: id }), function (data) {
if (data.result == "error") {
doNotify("Delete error for " + id + "\n" + data.error, "danger", "glyphicon glyphicon-alert");
}
@@ -114,7 +114,7 @@ function prepareTestButtons() {
var id = $btn.data("id");
$btn.click(function () {
doNotify("Test started for " + id, "info", "glyphicon glyphicon-transfer");
- var jqxhr = $.post("test_indexer", JSON.stringify({ indexer: id }), function (data) {
+ var jqxhr = $.post("admin/test_indexer", JSON.stringify({ indexer: id }), function (data) {
if (data.result == "error") {
doNotify("Test failed for " + data.name + "\n" + data.error, "danger", "glyphicon glyphicon-alert");
}
@@ -130,7 +130,7 @@ function prepareTestButtons() {
function displayIndexerSetup(id) {
- var jqxhr = $.post("get_config_form", JSON.stringify({ indexer: id }), function (data) {
+ var jqxhr = $.post("admin/get_config_form", JSON.stringify({ indexer: id }), function (data) {
if (data.result == "error") {
doNotify("Error: " + data.error, "danger", "glyphicon glyphicon-alert");
return;
@@ -200,7 +200,7 @@ function populateSetupForm(indexerId, name, config) {
$goButton.prop('disabled', true);
$goButton.html($('#templates > .spinner')[0].outerHTML);
- var jqxhr = $.post("configure_indexer", JSON.stringify(data), function (data) {
+ var jqxhr = $.post("admin/configure_indexer", JSON.stringify(data), function (data) {
if (data.result == "error") {
if (data.config) {
populateConfigItems(configForm, data.config);
diff --git a/src/Jackett/Content/favicon.ico b/src/Jackett/Content/favicon.ico
new file mode 100644
index 000000000..6392acc61
Binary files /dev/null and b/src/Jackett/Content/favicon.ico differ
diff --git a/src/Jackett/WebContent/fonts/glyphicons-halflings-regular.woff b/src/Jackett/Content/fonts/glyphicons-halflings-regular.woff
similarity index 100%
rename from src/Jackett/WebContent/fonts/glyphicons-halflings-regular.woff
rename to src/Jackett/Content/fonts/glyphicons-halflings-regular.woff
diff --git a/src/Jackett/WebContent/handlebars-v3.0.1.js b/src/Jackett/Content/handlebars-v3.0.1.js
similarity index 100%
rename from src/Jackett/WebContent/handlebars-v3.0.1.js
rename to src/Jackett/Content/handlebars-v3.0.1.js
diff --git a/src/Jackett/WebContent/index.html b/src/Jackett/Content/index.html
similarity index 100%
rename from src/Jackett/WebContent/index.html
rename to src/Jackett/Content/index.html
diff --git a/src/Jackett/WebContent/jacket_medium.png b/src/Jackett/Content/jacket_medium.png
similarity index 100%
rename from src/Jackett/WebContent/jacket_medium.png
rename to src/Jackett/Content/jacket_medium.png
diff --git a/src/Jackett/WebContent/jquery-2.1.3.min.js b/src/Jackett/Content/jquery-2.1.3.min.js
similarity index 100%
rename from src/Jackett/WebContent/jquery-2.1.3.min.js
rename to src/Jackett/Content/jquery-2.1.3.min.js
diff --git a/src/Jackett/WebContent/logos/alpharatio.png b/src/Jackett/Content/logos/alpharatio.png
similarity index 100%
rename from src/Jackett/WebContent/logos/alpharatio.png
rename to src/Jackett/Content/logos/alpharatio.png
diff --git a/src/Jackett/WebContent/logos/animebytes.png b/src/Jackett/Content/logos/animebytes.png
similarity index 100%
rename from src/Jackett/WebContent/logos/animebytes.png
rename to src/Jackett/Content/logos/animebytes.png
diff --git a/src/Jackett/WebContent/logos/beyondhd.png b/src/Jackett/Content/logos/beyondhd.png
similarity index 100%
rename from src/Jackett/WebContent/logos/beyondhd.png
rename to src/Jackett/Content/logos/beyondhd.png
diff --git a/src/Jackett/WebContent/logos/bithdtv.png b/src/Jackett/Content/logos/bithdtv.png
similarity index 100%
rename from src/Jackett/WebContent/logos/bithdtv.png
rename to src/Jackett/Content/logos/bithdtv.png
diff --git a/src/Jackett/WebContent/logos/bitmetv.png b/src/Jackett/Content/logos/bitmetv.png
similarity index 100%
rename from src/Jackett/WebContent/logos/bitmetv.png
rename to src/Jackett/Content/logos/bitmetv.png
diff --git a/src/Jackett/WebContent/logos/frenchtorrentdb.png b/src/Jackett/Content/logos/frenchtorrentdb.png
similarity index 100%
rename from src/Jackett/WebContent/logos/frenchtorrentdb.png
rename to src/Jackett/Content/logos/frenchtorrentdb.png
diff --git a/src/Jackett/WebContent/logos/freshon.png b/src/Jackett/Content/logos/freshon.png
similarity index 100%
rename from src/Jackett/WebContent/logos/freshon.png
rename to src/Jackett/Content/logos/freshon.png
diff --git a/src/Jackett/WebContent/logos/hdtorrents.png b/src/Jackett/Content/logos/hdtorrents.png
similarity index 100%
rename from src/Jackett/WebContent/logos/hdtorrents.png
rename to src/Jackett/Content/logos/hdtorrents.png
diff --git a/src/Jackett/WebContent/logos/iptorrents.png b/src/Jackett/Content/logos/iptorrents.png
similarity index 100%
rename from src/Jackett/WebContent/logos/iptorrents.png
rename to src/Jackett/Content/logos/iptorrents.png
diff --git a/src/Jackett/WebContent/logos/morethantv.png b/src/Jackett/Content/logos/morethantv.png
similarity index 100%
rename from src/Jackett/WebContent/logos/morethantv.png
rename to src/Jackett/Content/logos/morethantv.png
diff --git a/src/Jackett/WebContent/logos/rarbg.png b/src/Jackett/Content/logos/rarbg.png
similarity index 100%
rename from src/Jackett/WebContent/logos/rarbg.png
rename to src/Jackett/Content/logos/rarbg.png
diff --git a/src/Jackett/WebContent/logos/sceneaccess.png b/src/Jackett/Content/logos/sceneaccess.png
similarity index 100%
rename from src/Jackett/WebContent/logos/sceneaccess.png
rename to src/Jackett/Content/logos/sceneaccess.png
diff --git a/src/Jackett/WebContent/logos/scenetime.png b/src/Jackett/Content/logos/scenetime.png
similarity index 100%
rename from src/Jackett/WebContent/logos/scenetime.png
rename to src/Jackett/Content/logos/scenetime.png
diff --git a/src/Jackett/WebContent/logos/showrss.png b/src/Jackett/Content/logos/showrss.png
similarity index 100%
rename from src/Jackett/WebContent/logos/showrss.png
rename to src/Jackett/Content/logos/showrss.png
diff --git a/src/Jackett/WebContent/logos/strike.png b/src/Jackett/Content/logos/strike.png
similarity index 100%
rename from src/Jackett/WebContent/logos/strike.png
rename to src/Jackett/Content/logos/strike.png
diff --git a/src/Jackett/WebContent/logos/t411.png b/src/Jackett/Content/logos/t411.png
similarity index 100%
rename from src/Jackett/WebContent/logos/t411.png
rename to src/Jackett/Content/logos/t411.png
diff --git a/src/Jackett/WebContent/logos/thepiratebay.png b/src/Jackett/Content/logos/thepiratebay.png
similarity index 100%
rename from src/Jackett/WebContent/logos/thepiratebay.png
rename to src/Jackett/Content/logos/thepiratebay.png
diff --git a/src/Jackett/WebContent/logos/torrentday.png b/src/Jackett/Content/logos/torrentday.png
similarity index 100%
rename from src/Jackett/WebContent/logos/torrentday.png
rename to src/Jackett/Content/logos/torrentday.png
diff --git a/src/Jackett/WebContent/logos/torrentleech.png b/src/Jackett/Content/logos/torrentleech.png
similarity index 100%
rename from src/Jackett/WebContent/logos/torrentleech.png
rename to src/Jackett/Content/logos/torrentleech.png
diff --git a/src/Jackett/WebContent/logos/torrentshack.png b/src/Jackett/Content/logos/torrentshack.png
similarity index 100%
rename from src/Jackett/WebContent/logos/torrentshack.png
rename to src/Jackett/Content/logos/torrentshack.png
diff --git a/src/Jackett/WebContent/logos/torrentz.png b/src/Jackett/Content/logos/torrentz.png
similarity index 100%
rename from src/Jackett/WebContent/logos/torrentz.png
rename to src/Jackett/Content/logos/torrentz.png
diff --git a/src/Jackett/WebContent/setup_indexer.html b/src/Jackett/Content/setup_indexer.html
similarity index 100%
rename from src/Jackett/WebContent/setup_indexer.html
rename to src/Jackett/Content/setup_indexer.html
diff --git a/src/Jackett/Controllers/APIController.cs b/src/Jackett/Controllers/APIController.cs
new file mode 100644
index 000000000..d2ac760f9
--- /dev/null
+++ b/src/Jackett/Controllers/APIController.cs
@@ -0,0 +1,73 @@
+using Jackett.Models;
+using Jackett.Services;
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Http;
+
+namespace Jackett.Controllers
+{
+ public class APIController : ApiController
+ {
+ private IIndexerManagerService indexerService;
+ private Logger logger;
+
+ public APIController(IIndexerManagerService i, Logger l)
+ {
+ indexerService = i;
+ logger = l;
+ }
+
+ [HttpGet]
+ public async Task Call(string indexerName)
+ {
+ var indexer = indexerService.GetIndexer(indexerName);
+ var torznabQuery = TorznabQuery.FromHttpQuery(HttpUtility.ParseQueryString(Request.RequestUri.Query));
+
+ if (torznabQuery.RageIDLookupEnabled && indexer.RequiresRageIDLookupDisabled)
+ {
+ throw new ArgumentException("This indexer requires RageID lookup disabled");
+ }
+
+ var releases = await indexer.PerformQuery(torznabQuery);
+
+ logger.Debug(string.Format("Found {0} releases from {1}", releases.Length, indexer.DisplayName));
+ var severUrl = string.Format("{0}://{1}:{2}/", Request.RequestUri.Scheme, Request.RequestUri.Host, Request.RequestUri.Port);
+
+ var resultPage = new ResultPage(new ChannelInfo
+ {
+ Title = indexer.DisplayName,
+ Description = indexer.DisplayDescription,
+ Link = indexer.SiteLink,
+ ImageUrl = new Uri(severUrl + "logos/" + indexer.DisplayName + ".png"),
+ ImageTitle = indexer.DisplayName,
+ ImageLink = indexer.SiteLink,
+ ImageDescription = indexer.DisplayName
+ });
+
+ // add Jackett proxy to download links...
+ foreach (var release in releases)
+ {
+ if (release.Link == null || release.Link.Scheme == "magnet")
+ continue;
+ var originalLink = release.Link;
+ var encodedLink = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(originalLink.ToString())) + "/download.torrent";
+ var proxyLink = string.Format("{0}api/{1}/download/{2}", severUrl, indexer.DisplayName.ToLowerInvariant(), encodedLink);
+ release.Link = new Uri(proxyLink);
+ }
+
+ resultPage.Releases.AddRange(releases);
+ var xml = resultPage.ToXml(new Uri(severUrl));
+ // Force the return as XML
+ return new HttpResponseMessage()
+ {
+ Content = new StringContent(xml, Encoding.UTF8, "application/rss+xml")
+ };
+ }
+ }
+}
diff --git a/src/Jackett/Controllers/AdminController.cs b/src/Jackett/Controllers/AdminController.cs
new file mode 100644
index 000000000..c529fe846
--- /dev/null
+++ b/src/Jackett/Controllers/AdminController.cs
@@ -0,0 +1,210 @@
+using Autofac;
+using Jackett.Models;
+using Jackett.Services;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web.Http;
+
+namespace Jackett.Controllers
+{
+ [RoutePrefix("admin")]
+ public class AdminController : ApiController
+ {
+ private IConfigurationService config;
+ private IIndexerManagerService indexerService;
+ private IServerService serverService;
+
+ public AdminController(IConfigurationService config, IIndexerManagerService i, IServerService ss)
+ {
+ this.config = config;
+ indexerService = i;
+ serverService = ss;
+ }
+
+ private async Task ReadPostDataJson()
+ {
+ var content = await Request.Content.ReadAsStringAsync();
+ return JObject.Parse(content);
+ }
+
+ [Route("get_config_form")]
+ [HttpGet]
+ public async Task GetConfigForm()
+ {
+ var jsonReply = new JObject();
+ try
+ {
+ var postData = await ReadPostDataJson();
+ var indexer = indexerService.GetIndexer((string)postData["indexer"]);
+ var config = await indexer.GetConfigurationForSetup();
+ jsonReply["config"] = config.ToJson();
+ jsonReply["name"] = indexer.DisplayName;
+ jsonReply["result"] = "success";
+ }
+ catch (Exception ex)
+ {
+ jsonReply["result"] = "error";
+ jsonReply["error"] = ex.Message;
+ }
+ return Json(jsonReply);
+ }
+
+ [Route("configure_indexer")]
+ [HttpPost]
+ public async Task Configure()
+ {
+ JToken jsonReply = new JObject();
+ try
+ {
+ var postData = await ReadPostDataJson();
+ string indexerString = (string)postData["indexer"];
+ var indexer = indexerService.GetIndexer((string)postData["indexer"]);
+ jsonReply["name"] = indexer.DisplayName;
+ await indexer.ApplyConfiguration(postData["config"]);
+ indexerService.TestIndexer((string)postData["indexer"]);
+ jsonReply["result"] = "success";
+ }
+ catch (Exception ex)
+ {
+ jsonReply["result"] = "error";
+ jsonReply["error"] = ex.Message;
+ if (ex is ExceptionWithConfigData)
+ {
+ jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson();
+ }
+ }
+ return Json(jsonReply);
+ }
+
+
+
+ [Route("get_indexers")]
+ [HttpGet]
+ public IHttpActionResult Indexers()
+ {
+ var jsonReply = new JObject();
+ try
+ {
+ jsonReply["result"] = "success";
+ jsonReply["api_key"] = serverService.Config.APIKey;
+ jsonReply["app_version"] = config.GetVersion();
+ JArray items = new JArray();
+
+ foreach (var indexer in indexerService.GetAllIndexers())
+ {
+ var item = new JObject();
+ item["id"] = indexer.GetType().Name.ToLowerInvariant();
+ item["name"] = indexer.DisplayName;
+ item["description"] = indexer.DisplayDescription;
+ item["configured"] = indexer.IsConfigured;
+ item["site_link"] = indexer.SiteLink;
+ items.Add(item);
+ }
+ jsonReply["items"] = items;
+ }
+ catch (Exception ex)
+ {
+ jsonReply["result"] = "error";
+ jsonReply["error"] = ex.Message;
+ }
+ return Json(jsonReply);
+ }
+
+ [Route("test_indexer")]
+ [HttpPost]
+ public async Task Test()
+ {
+ JToken jsonReply = new JObject();
+ try
+ {
+ var postData = await ReadPostDataJson();
+ string indexerString = (string)postData["indexer"];
+ indexerService.TestIndexer(indexerString);
+ jsonReply["result"] = "success";
+ }
+ catch (Exception ex)
+ {
+ jsonReply["result"] = "error";
+ jsonReply["error"] = ex.Message;
+ }
+ return Json(jsonReply);
+ }
+
+ [Route("delete_indexer")]
+ [HttpPost]
+ public async Task Delete()
+ {
+ var jsonReply = new JObject();
+ try
+ {
+ var postData = await ReadPostDataJson();
+ string indexerString = (string)postData["indexer"];
+ indexerService.DeleteIndexer(indexerString);
+ }
+ catch (Exception ex)
+ {
+ jsonReply["result"] = "error";
+ jsonReply["error"] = ex.Message;
+ }
+ return Json(jsonReply);
+ }
+
+ [Route("get_jackett_config")]
+ [HttpGet]
+ public IHttpActionResult GetConfig()
+ {
+ var jsonReply = new JObject();
+ try
+ {
+ jsonReply["config"] = config.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 Json(jsonReply);
+ }
+
+ [Route("apply_jackett_config")]
+ [HttpPost]
+ public async Task SetConfig()
+ {
+ var jsonReply = new JObject();
+ try
+ {
+ var postData = await ReadPostDataJson();
+ // int port = await WebServer.ApplyPortConfiguration(postData);
+ jsonReply["result"] = "success";
+ // jsonReply["port"] = port;
+ }
+ catch (Exception ex)
+ {
+ jsonReply["result"] = "error";
+ jsonReply["error"] = ex.Message;
+ }
+ return Json(jsonReply);
+ }
+
+
+ [Route("jackett_restart")]
+ [HttpPost]
+ public IHttpActionResult Restart()
+ {
+ return null;
+ }
+ }
+}
+
diff --git a/src/Jackett/Controllers/DownloadController.cs b/src/Jackett/Controllers/DownloadController.cs
new file mode 100644
index 000000000..235abc255
--- /dev/null
+++ b/src/Jackett/Controllers/DownloadController.cs
@@ -0,0 +1,48 @@
+using Jackett.Services;
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Http;
+
+namespace Jackett.Controllers
+{
+ public class DownloadController : ApiController
+ {
+ private Logger logger;
+ private IIndexerManagerService indexerService;
+
+ public DownloadController(IIndexerManagerService i, Logger l)
+ {
+ logger = l;
+ indexerService = i;
+ }
+
+ [HttpGet]
+ public async Task Download(string indexerName, string path)
+ {
+ try
+ {
+ var indexer = indexerService.GetIndexer(indexerName);
+ var remoteFile = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path));
+ var downloadBytes = await indexer.Download(new Uri(remoteFile));
+
+ var result = new HttpResponseMessage(HttpStatusCode.OK);
+ result.Content = new ByteArrayContent(downloadBytes);
+ result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-bittorrent");
+ return result;
+ }
+ catch (Exception e)
+ {
+ logger.Error(e, "Error downloading " + indexerName + " " + path);
+ return new HttpResponseMessage(HttpStatusCode.NotFound);
+ }
+ }
+ }
+}
diff --git a/src/Jackett/CookieContainerExtensions.cs b/src/Jackett/CookieContainerExtensions.cs
index 447c3be30..070a326fa 100644
--- a/src/Jackett/CookieContainerExtensions.cs
+++ b/src/Jackett/CookieContainerExtensions.cs
@@ -1,4 +1,5 @@
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,8 +12,7 @@ namespace Jackett
{
public static class CookieContainerExtensions
{
-
- public static void FillFromJson(this CookieContainer cookies, Uri uri, JToken json)
+ public static void FillFromJson(this CookieContainer cookies, Uri uri, JToken json, Logger logger)
{
if (json["cookies"] != null)
{
@@ -43,12 +43,17 @@ namespace Jackett
}
catch (CookieException ex)
{
- Program.LoggerInstance.Info("(Non-critical) Problem loading cookie {0}, {1}, {2}", uri, c, ex.Message);
+ logger.Info("(Non-critical) Problem loading cookie {0}, {1}, {2}", uri, c, ex.Message);
}
}
}
}
+ public static void DumpToJson(this CookieContainer cookies, string uri, JToken json)
+ {
+ DumpToJson(cookies, new Uri(uri), json);
+ }
+
public static void DumpToJson(this CookieContainer cookies, Uri uri, JToken json)
{
json["cookie_header"] = cookies.GetCookieHeader(uri);
diff --git a/src/Jackett/DataUrl.cs b/src/Jackett/DataUrl.cs
index 339858836..3ff22beeb 100644
--- a/src/Jackett/DataUrl.cs
+++ b/src/Jackett/DataUrl.cs
@@ -10,7 +10,6 @@ namespace Jackett
{
public class DataUrl
{
-
public static string ReadFileToDataUrl(string file)
{
string mime = MimeMapping.GetMimeMapping(file);
diff --git a/src/Jackett/Engine.cs b/src/Jackett/Engine.cs
new file mode 100644
index 000000000..7fffd41a8
--- /dev/null
+++ b/src/Jackett/Engine.cs
@@ -0,0 +1,111 @@
+using Autofac;
+using Jackett.Services;
+using NLog;
+using NLog.Config;
+using NLog.Targets;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett
+{
+ public class Engine
+ {
+ private static IContainer container = null;
+
+ static Engine()
+ {
+ var builder = new ContainerBuilder();
+ builder.RegisterModule();
+ container = builder.Build();
+
+ // Register the container in itself to allow for late resolves
+ var secondaryBuilder = new ContainerBuilder();
+ secondaryBuilder.RegisterInstance(container).SingleInstance();
+ SetupLogging(secondaryBuilder);
+ secondaryBuilder.Update(container);
+
+ Logger.Info("Starting Jackett " + ConfigService.GetVersion());
+ }
+
+ public static IContainer GetContainer()
+ {
+ return container;
+ }
+
+ public static bool IsWindows {
+ get {
+ return Environment.OSVersion.Platform == PlatformID.Win32NT;
+ }
+ }
+
+ public static IConfigurationService ConfigService
+ {
+ get
+ {
+ return container.Resolve();
+ }
+ }
+
+ public static IServiceConfigService ServiceConfig
+ {
+ get
+ {
+ return container.Resolve();
+ }
+ }
+
+ public static IServerService Server
+ {
+ get
+ {
+ return container.Resolve();
+ }
+ }
+
+ public static IRunTimeService RunTime
+ {
+ get
+ {
+ return container.Resolve();
+ }
+ }
+
+ public static Logger Logger
+ {
+ get
+ {
+ return container.Resolve();
+ }
+ }
+
+ private static void SetupLogging(ContainerBuilder builder)
+ {
+ var logConfig = new LoggingConfiguration();
+
+ var logFile = new FileTarget();
+ logConfig.AddTarget("file", logFile);
+ logFile.Layout = "${longdate} ${level} ${message} ${exception:format=ToString}";
+ logFile.FileName = Path.Combine(ConfigurationService.GetAppDataFolderStatic(), "log.txt");
+ logFile.ArchiveFileName = "log.{#####}.txt";
+ logFile.ArchiveAboveSize = 500000;
+ logFile.MaxArchiveFiles = 1;
+ logFile.KeepFileOpen = false;
+ logFile.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence;
+ var logFileRule = new LoggingRule("*", LogLevel.Debug, logFile);
+ logConfig.LoggingRules.Add(logFileRule);
+
+ var logConsole = new ConsoleTarget();
+ logConfig.AddTarget("console", logConsole);
+ logConsole.Layout = "${longdate} ${level} ${message} ${exception:format=ToString}";
+ var logConsoleRule = new LoggingRule("*", LogLevel.Debug, logConsole);
+ logConfig.LoggingRules.Add(logConsoleRule);
+
+ LogManager.Configuration = logConfig;
+ builder.RegisterInstance(LogManager.GetCurrentClassLogger()).SingleInstance();
+ }
+ }
+}
diff --git a/src/Jackett/ExceptionWithConfigData.cs b/src/Jackett/ExceptionWithConfigData.cs
index 60cf8deae..9280d5f14 100644
--- a/src/Jackett/ExceptionWithConfigData.cs
+++ b/src/Jackett/ExceptionWithConfigData.cs
@@ -1,4 +1,5 @@
-using System;
+using Jackett.Models;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
diff --git a/src/Jackett/IndexerManager.cs b/src/Jackett/IndexerManager.cs
deleted file mode 100644
index e5f3d8f62..000000000
--- a/src/Jackett/IndexerManager.cs
+++ /dev/null
@@ -1,107 +0,0 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jackett
-{
- public class IndexerManager
- {
-
- static string IndexerConfigDirectory = Path.Combine(Program.AppConfigDirectory, "Indexers");
-
- public Dictionary Indexers { get; private set; }
-
- public IndexerManager()
- {
- Indexers = new Dictionary();
- LoadMissingIndexers();
- }
-
- void LoadMissingIndexers()
- {
- var implementedIndexerTypes = AppDomain.CurrentDomain.GetAssemblies()
- .SelectMany(s => s.GetTypes())
- .Where(p => typeof(IndexerInterface).IsAssignableFrom(p) && !p.IsInterface)
- .ToArray();
-
- foreach (var t in implementedIndexerTypes)
- {
- LoadIndexer(t);
- }
- }
-
- void LoadIndexer(Type indexerType)
- {
- var name = indexerType.Name.Trim().ToLower();
-
- if (Indexers.ContainsKey(name))
- return;
-
- IndexerInterface newIndexer = (IndexerInterface)Activator.CreateInstance(indexerType);
- newIndexer.OnSaveConfigurationRequested += newIndexer_OnSaveConfigurationRequested;
- newIndexer.OnResultParsingError += newIndexer_OnResultParsingError;
-
- var configFilePath = GetIndexerConfigFilePath(newIndexer);
- if (File.Exists(configFilePath))
- {
- var jsonString = JObject.Parse(File.ReadAllText(configFilePath));
- newIndexer.LoadFromSavedConfiguration(jsonString);
- }
-
- Indexers.Add(name, newIndexer);
- }
-
- void newIndexer_OnResultParsingError(IndexerInterface indexer, string results, Exception ex)
- {
- var fileName = string.Format("Error on {0} for {1}.txt", DateTime.Now.ToString("yyyyMMddHHmmss"), indexer.DisplayName);
- var spacing = string.Join("", Enumerable.Repeat(Environment.NewLine, 5));
- var fileContents = string.Format("{0}{1}{2}", ex, spacing, results);
- File.WriteAllText(Path.Combine(Program.AppConfigDirectory, fileName), fileContents);
- }
-
- string GetIndexerConfigFilePath(IndexerInterface indexer)
- {
- return Path.Combine(IndexerConfigDirectory, indexer.GetType().Name.ToLower() + ".json");
- }
-
- void newIndexer_OnSaveConfigurationRequested(IndexerInterface indexer, JToken obj)
- {
- var configFilePath = GetIndexerConfigFilePath(indexer);
- if (!Directory.Exists(IndexerConfigDirectory))
- Directory.CreateDirectory(IndexerConfigDirectory);
- File.WriteAllText(configFilePath, obj.ToString());
- }
-
- public IndexerInterface GetIndexer(string name)
- {
- IndexerInterface indexer;
- if (!Indexers.TryGetValue(name, out indexer))
- throw new Exception(string.Format("No indexer with ID '{0}'", name));
- return indexer;
- }
-
- public void DeleteIndexer(string name)
- {
- var indexer = GetIndexer(name);
- var configPath = GetIndexerConfigFilePath(indexer);
- File.Delete(configPath);
- Indexers.Remove(name);
- LoadMissingIndexers();
- }
-
- public async Task TestIndexer(IndexerInterface indexer)
- {
- var browseQuery = new TorznabQuery();
- var results = await indexer.PerformQuery(browseQuery);
- Program.LoggerInstance.Debug(string.Format("Found {0} releases from {1}", results.Length, indexer.DisplayName));
- if (results.Length == 0)
- throw new Exception("Found no results while trying to browse this tracker");
-
- }
-
- }
-}
diff --git a/src/Jackett/Indexers/AlphaRatio.cs b/src/Jackett/Indexers/AlphaRatio.cs
index 4967c3364..e4883f83d 100644
--- a/src/Jackett/Indexers/AlphaRatio.cs
+++ b/src/Jackett/Indexers/AlphaRatio.cs
@@ -9,10 +9,13 @@ using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Net.Http.Headers;
+using Jackett.Models;
+using Jackett.Utils;
+using NLog;
namespace Jackett.Indexers
{
- public class AlphaRatio : IndexerInterface
+ public class AlphaRatio : IIndexer
{
public string DisplayName
{
@@ -32,8 +35,8 @@ namespace Jackett.Indexers
public bool RequiresRageIDLookupDisabled { get { return true; } }
- public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnSaveConfigurationRequested;
+ public event Action OnResultParsingError;
public bool IsConfigured { get; private set; }
@@ -54,9 +57,11 @@ namespace Jackett.Indexers
HttpClient client;
string cookieHeader;
+ private Logger logger;
- public AlphaRatio()
+ public AlphaRatio(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -100,7 +105,7 @@ namespace Jackett.Indexers
configSaveData = new JObject();
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
// If Windows use .net http
var response = await client.SendAsync(message);
@@ -144,7 +149,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(SiteLink, jsonConfig);
+ cookies.FillFromJson(SiteLink, jsonConfig, logger);
cookieHeader = cookies.GetCookieHeader(SiteLink);
IsConfigured = true;
}
@@ -167,7 +172,7 @@ namespace Jackett.Indexers
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString);
string results;
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
var request = CreateHttpRequest(new Uri(episodeSearchUrl));
request.Method = HttpMethod.Get;
@@ -234,7 +239,7 @@ namespace Jackett.Indexers
public async Task Download(Uri link)
{
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
return await client.GetByteArrayAsync(link);
}
diff --git a/src/Jackett/Indexers/AnimeBytes.cs b/src/Jackett/Indexers/AnimeBytes.cs
index 739b45611..c5360a0f8 100644
--- a/src/Jackett/Indexers/AnimeBytes.cs
+++ b/src/Jackett/Indexers/AnimeBytes.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -15,7 +18,7 @@ using System.Web;
namespace Jackett.Indexers
{
- public class AnimeBytes : IndexerInterface
+ public class AnimeBytes : IIndexer
{
class ConfigurationDataBasicLoginAnimeBytes : ConfigurationDataBasicLogin
{
@@ -38,8 +41,8 @@ namespace Jackett.Indexers
private static List cache = new List();
private static readonly TimeSpan cacheTime = new TimeSpan(0, 9, 0);
- public event Action OnResultParsingError;
- public event Action OnSaveConfigurationRequested;
+ public event Action OnResultParsingError;
+ public event Action OnSaveConfigurationRequested;
static string chromeUserAgent = BrowserUtil.ChromeUserAgent;
@@ -71,9 +74,11 @@ namespace Jackett.Indexers
CookieContainer cookieContainer;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public AnimeBytes()
+ public AnimeBytes(Logger l)
{
+ logger = l;
IsConfigured = false;
cookieContainer = new CookieContainer();
handler = new HttpClientHandler
@@ -164,7 +169,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookieContainer.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookieContainer.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
AllowRaws = jsonConfig["raws"].Value();
}
diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs
new file mode 100644
index 000000000..1de82fb31
--- /dev/null
+++ b/src/Jackett/Indexers/BaseIndexer.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Jackett.Models;
+using Newtonsoft.Json.Linq;
+using NLog;
+
+namespace Jackett.Indexers
+{
+ public abstract class BaseIndexer: IIndexer
+ {
+ public string DisplayDescription { get; private set; }
+ public string DisplayName { get; private set; }
+ public bool IsConfigured { get; protected set; }
+ public Uri SiteLink { get; private set; }
+ public bool RequiresRageIDLookupDisabled { get; private set; }
+
+ public abstract Task ApplyConfiguration(JToken configJson);
+ public abstract Task Download(Uri link);
+ public abstract Task GetConfigurationForSetup();
+ public abstract void LoadFromSavedConfiguration(JToken jsonConfig);
+ public abstract Task PerformQuery(TorznabQuery query);
+
+ private Logger logger;
+
+ public BaseIndexer(string name, string description, Uri link, Logger logger)
+ {
+ DisplayName = name;
+ DisplayDescription = description;
+ SiteLink = link;
+ this.logger = logger;
+ }
+
+ protected void LogParseError(string results, Exception ex)
+ {
+ var fileName = string.Format("Error on {0} for {1}.txt", DateTime.Now.ToString("yyyyMMddHHmmss"), DisplayName);
+ var spacing = string.Join("", Enumerable.Repeat(Environment.NewLine, 5));
+ var fileContents = string.Format("{0}{1}{2}", ex, spacing, results);
+ logger.Error(fileName + fileContents);
+ }
+ }
+}
diff --git a/src/Jackett/Indexers/BeyondHD.cs b/src/Jackett/Indexers/BeyondHD.cs
index 25293f406..f55a5bdb5 100644
--- a/src/Jackett/Indexers/BeyondHD.cs
+++ b/src/Jackett/Indexers/BeyondHD.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,11 +14,11 @@ using System.Web;
namespace Jackett.Indexers
{
- public class BeyondHD : IndexerInterface
+ public class BeyondHD : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
@@ -43,9 +46,11 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public BeyondHD()
+ public BeyondHD(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -70,7 +75,7 @@ namespace Jackett.Indexers
var jsonCookie = new JObject();
jsonCookie["cookie_header"] = config.CookieHeader;
- cookies.FillFromJson(new Uri(BaseUrl), jsonCookie);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonCookie, logger);
var responseContent = await client.GetStringAsync(BaseUrl);
@@ -94,7 +99,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/BitHdtv.cs b/src/Jackett/Indexers/BitHdtv.cs
index 86a8f213c..a7319e23c 100644
--- a/src/Jackett/Indexers/BitHdtv.cs
+++ b/src/Jackett/Indexers/BitHdtv.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,9 +15,9 @@ using System.Web;
namespace Jackett.Indexers
{
- public class BitHdtv : IndexerInterface
+ public class BitHdtv : IIndexer
{
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
@@ -41,9 +44,11 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger loggger;
- public BitHdtv()
+ public BitHdtv(Logger l)
{
+ loggger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -97,13 +102,13 @@ namespace Jackett.Indexers
}
}
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
public bool IsConfigured { get; private set; }
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, loggger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/BitMeTV.cs b/src/Jackett/Indexers/BitMeTV.cs
index 42d6f2bfc..fc845d2db 100644
--- a/src/Jackett/Indexers/BitMeTV.cs
+++ b/src/Jackett/Indexers/BitMeTV.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -11,9 +14,9 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
-namespace Jackett
+namespace Jackett.Indexers
{
- public class BitMeTV : IndexerInterface
+ public class BitMeTV : IIndexer
{
class BmtvConfig : ConfigurationData
{
@@ -48,12 +51,14 @@ namespace Jackett
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnSaveConfigurationRequested;
+ public event Action OnResultParsingError;
- public BitMeTV()
+ public BitMeTV(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -124,7 +129,7 @@ namespace Jackett
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/FrenchTorrentDb.cs b/src/Jackett/Indexers/FrenchTorrentDb.cs
index 6eae903c6..d03eecceb 100644
--- a/src/Jackett/Indexers/FrenchTorrentDb.cs
+++ b/src/Jackett/Indexers/FrenchTorrentDb.cs
@@ -1,4 +1,6 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@@ -10,11 +12,11 @@ using System.Web;
namespace Jackett.Indexers
{
- class FrenchTorrentDb : IndexerInterface
+ class FrenchTorrentDb : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
class ConfigurationDataBasicLoginFrenchTorrentDb : ConfigurationData
{
diff --git a/src/Jackett/Indexers/Freshon.cs b/src/Jackett/Indexers/Freshon.cs
index e2b18cc78..d5080b10e 100644
--- a/src/Jackett/Indexers/Freshon.cs
+++ b/src/Jackett/Indexers/Freshon.cs
@@ -1,5 +1,9 @@
using CsQuery;
+using Jackett.Indexers;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -14,9 +18,9 @@ using System.Web.UI.WebControls;
namespace Jackett
{
- public class Freshon : IndexerInterface
+ public class Freshon : IIndexer
{
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
static string BaseUrl = "https://freshon.tv";
static string LoginUrl = BaseUrl + "/login.php";
@@ -39,10 +43,12 @@ namespace Jackett
public bool RequiresRageIDLookupDisabled { get { return true; } }
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
+ private Logger logger;
- public Freshon()
+ public Freshon(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -94,8 +100,8 @@ namespace Jackett
var configSaveData = new JObject();
cookies.DumpToJson(SiteLink, configSaveData);
- if (OnSaveConfigurationRequested != null)
- OnSaveConfigurationRequested(this, configSaveData);
+ // if (OnSaveConfigurationRequested != null)
+ // OnSaveConfigurationRequested(this, configSaveData);
IsConfigured = true;
}
@@ -103,7 +109,7 @@ namespace Jackett
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/HDTorrents.cs b/src/Jackett/Indexers/HDTorrents.cs
index b14945c7f..9655ec244 100644
--- a/src/Jackett/Indexers/HDTorrents.cs
+++ b/src/Jackett/Indexers/HDTorrents.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,26 +15,27 @@ using System.Web;
namespace Jackett.Indexers
{
- public class HDTorrents : IndexerInterface
+ public class HDTorrents : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
const string DefaultUrl = "http://hdts.ru"; // Of the accessible domains the .ru seems the most reliable. https://hdts.ru | https://hd-torrents.org | https://hd-torrents.net | https://hd-torrents.me
string BaseUrl = DefaultUrl;
static string chromeUserAgent = BrowserUtil.ChromeUserAgent;
private string SearchUrl = DefaultUrl + "/torrents.php?search={0}&active=1&options=0&category%5B%5D=59&category%5B%5D=60&category%5B%5D=30&category%5B%5D=38&page={1}";
private static string LoginUrl = DefaultUrl + "/login.php";
- private static string LoginPostUrl = DefaultUrl + "/login.php?returnto=index.php";
private const int MAXPAGES = 3;
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public HDTorrents()
+ public HDTorrents(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -124,7 +128,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(SiteLink, jsonConfig);
+ cookies.FillFromJson(SiteLink, jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/IndexerInterface.cs b/src/Jackett/Indexers/IIndexer.cs
similarity index 74%
rename from src/Jackett/IndexerInterface.cs
rename to src/Jackett/Indexers/IIndexer.cs
index abbc9e8f0..ab5e1840a 100644
--- a/src/Jackett/IndexerInterface.cs
+++ b/src/Jackett/Indexers/IIndexer.cs
@@ -1,4 +1,5 @@
-using Newtonsoft.Json.Linq;
+using Jackett.Models;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -6,16 +7,10 @@ using System.Text;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
-namespace Jackett
+namespace Jackett.Indexers
{
- public interface IndexerInterface
+ public interface IIndexer
{
-
- // Invoked when the indexer configuration has been applied and verified so the cookie needs to be saved
- event Action OnSaveConfigurationRequested;
-
- event Action OnResultParsingError;
-
string DisplayName { get; }
string DisplayDescription { get; }
Uri SiteLink { get; }
diff --git a/src/Jackett/Indexers/IPTorrents.cs b/src/Jackett/Indexers/IPTorrents.cs
index b374366b3..00ff0ca5a 100644
--- a/src/Jackett/Indexers/IPTorrents.cs
+++ b/src/Jackett/Indexers/IPTorrents.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,11 +15,11 @@ using System.Web;
namespace Jackett.Indexers
{
- public class IPTorrents : IndexerInterface
+ public class IPTorrents : IIndexer
{
- public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnSaveConfigurationRequested;
+ public event Action OnResultParsingError;
public string DisplayName { get { return "IPTorrents"; } }
@@ -38,9 +41,11 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public IPTorrents()
+ public IPTorrents(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -112,7 +117,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(Newtonsoft.Json.Linq.JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/Master.cs b/src/Jackett/Indexers/Master.cs
new file mode 100644
index 000000000..b563b69cd
--- /dev/null
+++ b/src/Jackett/Indexers/Master.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Indexers
+{
+ class Master
+ {
+
+
+
+ }
+}
diff --git a/src/Jackett/Indexers/MoreThanTV.cs b/src/Jackett/Indexers/MoreThanTV.cs
index b742192f4..0c158e524 100644
--- a/src/Jackett/Indexers/MoreThanTV.cs
+++ b/src/Jackett/Indexers/MoreThanTV.cs
@@ -1,5 +1,7 @@
using CsQuery;
+using Jackett.Models;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.IO;
@@ -12,7 +14,7 @@ using System.Web;
namespace Jackett.Indexers
{
- public class MoreThanTV : IndexerInterface
+ public class MoreThanTV : IIndexer
{
public string DisplayName
{
@@ -31,8 +33,8 @@ namespace Jackett.Indexers
public bool RequiresRageIDLookupDisabled { get { return true; } }
- public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnSaveConfigurationRequested;
+ public event Action OnResultParsingError;
public bool IsConfigured { get; private set; }
@@ -49,12 +51,14 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ private Logger logger;
string cookieHeader;
int retries = 3;
- public MoreThanTV()
+ public MoreThanTV(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -90,7 +94,7 @@ namespace Jackett.Indexers
var configSaveData = new JObject();
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
// If Windows use .net http
var response = await client.PostAsync(LoginUrl, content);
@@ -126,7 +130,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(SiteLink, jsonConfig);
+ cookies.FillFromJson(SiteLink, jsonConfig, logger);
cookieHeader = cookies.GetCookieHeader(SiteLink);
IsConfigured = true;
}
@@ -150,7 +154,7 @@ namespace Jackett.Indexers
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString);
string results;
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
results = await client.GetStringAsync(episodeSearchUrl, retries);
}
@@ -217,7 +221,7 @@ namespace Jackett.Indexers
public async Task Download(Uri link)
{
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
return await client.GetByteArrayAsync(link);
}
diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs
index 45358119d..9495d9475 100644
--- a/src/Jackett/Indexers/Rarbg.cs
+++ b/src/Jackett/Indexers/Rarbg.cs
@@ -1,4 +1,6 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@@ -10,11 +12,11 @@ using System.Threading.Tasks;
namespace Jackett.Indexers
{
- public class Rarbg : IndexerInterface
+ public class Rarbg : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
diff --git a/src/Jackett/Indexers/SceneAccess.cs b/src/Jackett/Indexers/SceneAccess.cs
index 75d29d1f9..b748423a9 100644
--- a/src/Jackett/Indexers/SceneAccess.cs
+++ b/src/Jackett/Indexers/SceneAccess.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -10,11 +13,11 @@ using System.Threading.Tasks;
namespace Jackett.Indexers
{
- class SceneAccess : IndexerInterface
+ class SceneAccess : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
@@ -48,9 +51,11 @@ namespace Jackett.Indexers
HttpClientHandler handler;
HttpClient client;
string cookieHeader;
+ private Logger logger;
- public SceneAccess()
+ public SceneAccess(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -84,7 +89,7 @@ namespace Jackett.Indexers
string responseContent;
var configSaveData = new JObject();
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
// If Windows use .net http
var response = await client.PostAsync(LoginUrl, content);
@@ -118,7 +123,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
cookieHeader = cookies.GetCookieHeader(SiteLink);
IsConfigured = true;
}
@@ -134,7 +139,7 @@ namespace Jackett.Indexers
var searchUrl = string.Format(SearchUrl, searchSection, searchCategory, searchString);
string results;
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
results = await client.GetStringAsync(searchUrl);
}
@@ -189,7 +194,7 @@ namespace Jackett.Indexers
public async Task Download(Uri link)
{
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
return await client.GetByteArrayAsync(link);
}
diff --git a/src/Jackett/Indexers/SceneTime.cs b/src/Jackett/Indexers/SceneTime.cs
index c64742cec..1ac3fcddb 100644
--- a/src/Jackett/Indexers/SceneTime.cs
+++ b/src/Jackett/Indexers/SceneTime.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,11 +15,11 @@ using System.Web;
namespace Jackett.Indexers
{
- public class SceneTime : IndexerInterface
+ public class SceneTime : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
@@ -45,10 +48,12 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public SceneTime()
+ public SceneTime(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -101,7 +106,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/ShowRSS.cs b/src/Jackett/Indexers/ShowRSS.cs
index 3f3ef5ca9..30d9b7357 100644
--- a/src/Jackett/Indexers/ShowRSS.cs
+++ b/src/Jackett/Indexers/ShowRSS.cs
@@ -1,4 +1,6 @@
-using Newtonsoft.Json.Linq;
+using Jackett.Models;
+using Jackett.Utils;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,11 +14,11 @@ using System.Xml;
namespace Jackett.Indexers
{
- public class ShowRSS : IndexerInterface
+ public class ShowRSS : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
diff --git a/src/Jackett/Indexers/Strike.cs b/src/Jackett/Indexers/Strike.cs
index b2418548c..594f9c391 100644
--- a/src/Jackett/Indexers/Strike.cs
+++ b/src/Jackett/Indexers/Strike.cs
@@ -1,4 +1,5 @@
-using Newtonsoft.Json.Linq;
+using Jackett.Models;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -11,11 +12,11 @@ using System.Web;
namespace Jackett.Indexers
{
- public class Strike : IndexerInterface
+ public class Strike : IIndexer
{
- public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnSaveConfigurationRequested;
+ public event Action OnResultParsingError;
public string DisplayName
{
diff --git a/src/Jackett/Indexers/T411.cs b/src/Jackett/Indexers/T411.cs
index 085971a09..8371acb93 100644
--- a/src/Jackett/Indexers/T411.cs
+++ b/src/Jackett/Indexers/T411.cs
@@ -1,4 +1,6 @@
-using Newtonsoft.Json.Linq;
+using Jackett.Models;
+using Jackett.Utils;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,12 +14,12 @@ using System.Web;
namespace Jackett.Indexers
{
- public class T411 : IndexerInterface
+ public class T411 : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
diff --git a/src/Jackett/Indexers/ThePirateBay.cs b/src/Jackett/Indexers/ThePirateBay.cs
index 8dd1070c5..c133f55d4 100644
--- a/src/Jackett/Indexers/ThePirateBay.cs
+++ b/src/Jackett/Indexers/ThePirateBay.cs
@@ -1,4 +1,6 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@@ -13,12 +15,12 @@ using System.Web;
namespace Jackett.Indexers
{
- public class ThePirateBay : IndexerInterface
+ public class ThePirateBay : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName { get { return "The Pirate Bay"; } }
@@ -101,7 +103,7 @@ namespace Jackett.Indexers
string results;
- if (Program.IsWindows)
+ if (Engine.IsWindows)
{
results = await client.GetStringAsync(episodeSearchUrl);
}
@@ -175,7 +177,7 @@ namespace Jackett.Indexers
}
catch (Exception ex)
{
- OnResultParsingError(this, results, ex);
+ // OnResultParsingError(this, results, ex);
throw ex;
}
return releases.ToArray();
diff --git a/src/Jackett/Indexers/TorrentDay.cs b/src/Jackett/Indexers/TorrentDay.cs
index 5cbec6a05..019ac070b 100644
--- a/src/Jackett/Indexers/TorrentDay.cs
+++ b/src/Jackett/Indexers/TorrentDay.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,11 +15,11 @@ using System.Web;
namespace Jackett.Indexers
{
- public class TorrentDay : IndexerInterface
+ public class TorrentDay : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
@@ -47,9 +50,11 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public TorrentDay()
+ public TorrentDay(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -120,7 +125,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/TorrentLeech.cs b/src/Jackett/Indexers/TorrentLeech.cs
index 15de57ff7..d1ac3218d 100644
--- a/src/Jackett/Indexers/TorrentLeech.cs
+++ b/src/Jackett/Indexers/TorrentLeech.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,11 +15,11 @@ using System.Web;
namespace Jackett.Indexers
{
- public class TorrentLeech : IndexerInterface
+ public class TorrentLeech : IIndexer
{
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
public string DisplayName
{
@@ -45,9 +48,11 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
- public TorrentLeech()
+ public TorrentLeech(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -103,7 +108,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/TorrentShack.cs b/src/Jackett/Indexers/TorrentShack.cs
index a6141c45d..ec41b0164 100644
--- a/src/Jackett/Indexers/TorrentShack.cs
+++ b/src/Jackett/Indexers/TorrentShack.cs
@@ -1,5 +1,8 @@
using CsQuery;
+using Jackett.Models;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
+using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -12,11 +15,11 @@ using System.Web;
namespace Jackett.Indexers
{
- public class TorrentShack : IndexerInterface
+ public class TorrentShack : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
@@ -43,11 +46,13 @@ namespace Jackett.Indexers
CookieContainer cookies;
HttpClientHandler handler;
HttpClient client;
+ Logger logger;
public bool IsConfigured { get; private set; }
- public TorrentShack()
+ public TorrentShack(Logger l)
{
+ logger = l;
IsConfigured = false;
cookies = new CookieContainer();
handler = new HttpClientHandler
@@ -105,7 +110,7 @@ namespace Jackett.Indexers
public void LoadFromSavedConfiguration(JToken jsonConfig)
{
- cookies.FillFromJson(new Uri(BaseUrl), jsonConfig);
+ cookies.FillFromJson(new Uri(BaseUrl), jsonConfig, logger);
IsConfigured = true;
}
diff --git a/src/Jackett/Indexers/Torrentz.cs b/src/Jackett/Indexers/Torrentz.cs
index de45011c3..b3991179c 100644
--- a/src/Jackett/Indexers/Torrentz.cs
+++ b/src/Jackett/Indexers/Torrentz.cs
@@ -1,4 +1,6 @@
-using Newtonsoft.Json.Linq;
+using Jackett.Models;
+using Jackett.Utils;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -11,11 +13,11 @@ using System.Xml;
namespace Jackett.Indexers
{
- public class Torrentz : IndexerInterface
+ public class Torrentz : IIndexer
{
- public event Action OnSaveConfigurationRequested;
+ public event Action OnSaveConfigurationRequested;
- public event Action OnResultParsingError;
+ public event Action OnResultParsingError;
public string DisplayName
{
diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj
index baeba57d8..ca06f9283 100644
--- a/src/Jackett/Jackett.csproj
+++ b/src/Jackett/Jackett.csproj
@@ -5,7 +5,7 @@
Debug
AnyCPU
{E636D5F8-68B4-4903-B4ED-CCFD9C9E899F}
- WinExe
+ Library
Properties
Jackett
Jackett
@@ -48,25 +48,79 @@
4
- jacket_large.ico
+
+
- Jackett.Program
+
+
+
+ ..\packages\Autofac.3.5.2\lib\net40\Autofac.dll
+ True
+
+
+ ..\packages\Autofac.Owin.3.1.0\lib\net45\Autofac.Integration.Owin.dll
+
+
+ False
+ ..\packages\Autofac.WebApi2.3.4.0\lib\net45\Autofac.Integration.WebApi.dll
+
+
+ ..\packages\Autofac.WebApi2.Owin.3.2.0\lib\net45\Autofac.Integration.WebApi.Owin.dll
+
..\packages\CsQuery.1.3.4\lib\net40\CsQuery.dll
+
+ ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.FileSystems.3.0.1\lib\net45\Microsoft.Owin.FileSystems.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.Host.HttpListener.2.0.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll
+ True
+
+
+ ..\packages\Microsoft.Owin.StaticFiles.3.0.1\lib\net45\Microsoft.Owin.StaticFiles.dll
+ True
+
..\packages\NLog.Windows.Forms.2.0.0.0\lib\net35\NLog.Windows.Forms.dll
True
+
+ ..\packages\Owin.1.0\lib\net40\Owin.dll
+ True
+
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
+ True
+
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
+ True
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
+ True
+
@@ -81,20 +135,28 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
@@ -102,6 +164,7 @@
+
@@ -115,33 +178,29 @@
-
- Form
-
-
- Main.cs
-
-
-
+
+
True
True
Resources.resx
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
PreserveNewest
@@ -149,126 +208,122 @@
-
- Main.cs
-
ResXFileCodeGenerator
Resources.Designer.cs
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
diff --git a/src/Jackett/JackettModule.cs b/src/Jackett/JackettModule.cs
new file mode 100644
index 000000000..f658d48c8
--- /dev/null
+++ b/src/Jackett/JackettModule.cs
@@ -0,0 +1,30 @@
+using Autofac;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autofac.Integration.WebApi;
+using Jackett.Indexers;
+
+namespace Jackett
+{
+ public class JackettModule: Module
+ {
+ protected override void Load(ContainerBuilder builder)
+ {
+ // Just register everything!
+ var thisAssembly = typeof(JackettModule).Assembly;
+ builder.RegisterAssemblyTypes(thisAssembly).Except().AsImplementedInterfaces().SingleInstance();
+ builder.RegisterApiControllers(thisAssembly).InstancePerRequest();
+
+ // Register indexers
+ foreach(var indexer in thisAssembly.GetTypes()
+ .Where(p => typeof(IIndexer).IsAssignableFrom(p) && !p.IsInterface)
+ .ToArray())
+ {
+ builder.RegisterType(indexer).Named(indexer.Name.ToLowerInvariant()).SingleInstance();
+ }
+ }
+ }
+}
diff --git a/src/Jackett/CachedResult.cs b/src/Jackett/Models/CachedResult.cs
similarity index 96%
rename from src/Jackett/CachedResult.cs
rename to src/Jackett/Models/CachedResult.cs
index 925d9a139..24feea319 100644
--- a/src/Jackett/CachedResult.cs
+++ b/src/Jackett/Models/CachedResult.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public class CachedResult
{
diff --git a/src/Jackett/ChannelInfo.cs b/src/Jackett/Models/ChannelInfo.cs
similarity index 96%
rename from src/Jackett/ChannelInfo.cs
rename to src/Jackett/Models/ChannelInfo.cs
index a42421e01..e9afa5112 100644
--- a/src/Jackett/ChannelInfo.cs
+++ b/src/Jackett/Models/ChannelInfo.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public class ChannelInfo
{
diff --git a/src/Jackett/Models/Config/ServerConfig.cs b/src/Jackett/Models/Config/ServerConfig.cs
new file mode 100644
index 000000000..932a7143f
--- /dev/null
+++ b/src/Jackett/Models/Config/ServerConfig.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Models.Config
+{
+ public class ServerConfig
+ {
+ public ServerConfig()
+ {
+ Port = 9117;
+ }
+
+ public int Port { get; set; }
+ public bool AllowExternal { get; set; }
+ public string APIKey { get; set; }
+
+ public string GetListenAddress(bool? external = null)
+ {
+
+ if (external == null)
+ {
+ external = AllowExternal;
+ }
+ return "http://" + (external.Value ? "*" : "localhost") + ":" + Port + "/";
+ }
+
+ public string GenerateApi()
+ {
+ var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
+ var randBytes = new byte[32];
+ var rngCsp = new RNGCryptoServiceProvider();
+ rngCsp.GetBytes(randBytes);
+ var key = "";
+ foreach (var b in randBytes)
+ {
+ key += chars[b % chars.Length];
+ }
+ return key;
+ }
+ }
+}
diff --git a/src/Jackett/ConfigurationData.cs b/src/Jackett/Models/ConfigurationData.cs
similarity index 99%
rename from src/Jackett/ConfigurationData.cs
rename to src/Jackett/Models/ConfigurationData.cs
index 971698b0c..41b6b0055 100644
--- a/src/Jackett/ConfigurationData.cs
+++ b/src/Jackett/Models/ConfigurationData.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public abstract class ConfigurationData
{
diff --git a/src/Jackett/ConfigurationDataBasicLogin.cs b/src/Jackett/Models/ConfigurationDataBasicLogin.cs
similarity index 96%
rename from src/Jackett/ConfigurationDataBasicLogin.cs
rename to src/Jackett/Models/ConfigurationDataBasicLogin.cs
index 19a2ab0ff..66afbffe3 100644
--- a/src/Jackett/ConfigurationDataBasicLogin.cs
+++ b/src/Jackett/Models/ConfigurationDataBasicLogin.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public class ConfigurationDataBasicLogin : ConfigurationData
{
diff --git a/src/Jackett/ConfigurationDataCookie.cs b/src/Jackett/Models/ConfigurationDataCookie.cs
similarity index 98%
rename from src/Jackett/ConfigurationDataCookie.cs
rename to src/Jackett/Models/ConfigurationDataCookie.cs
index c184dfc5a..afa3e46e5 100644
--- a/src/Jackett/ConfigurationDataCookie.cs
+++ b/src/Jackett/Models/ConfigurationDataCookie.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public class ConfigurationDataCookie : ConfigurationData
diff --git a/src/Jackett/ConfigurationDataUrl.cs b/src/Jackett/Models/ConfigurationDataUrl.cs
similarity index 96%
rename from src/Jackett/ConfigurationDataUrl.cs
rename to src/Jackett/Models/ConfigurationDataUrl.cs
index e302cf2fd..08e80a76a 100644
--- a/src/Jackett/ConfigurationDataUrl.cs
+++ b/src/Jackett/Models/ConfigurationDataUrl.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public class ConfigurationDataUrl : ConfigurationData
{
diff --git a/src/Jackett/ReleaseInfo.cs b/src/Jackett/Models/ReleaseInfo.cs
similarity index 99%
rename from src/Jackett/ReleaseInfo.cs
rename to src/Jackett/Models/ReleaseInfo.cs
index a6845102a..b81d810e7 100644
--- a/src/Jackett/ReleaseInfo.cs
+++ b/src/Jackett/Models/ReleaseInfo.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public class ReleaseInfo: ICloneable
diff --git a/src/Jackett/ResultPage.cs b/src/Jackett/Models/ResultPage.cs
similarity index 99%
rename from src/Jackett/ResultPage.cs
rename to src/Jackett/Models/ResultPage.cs
index f9d4b9b2e..fe238e225 100644
--- a/src/Jackett/ResultPage.cs
+++ b/src/Jackett/Models/ResultPage.cs
@@ -9,7 +9,7 @@ using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
-namespace Jackett
+namespace Jackett.Models
{
public class ResultPage
{
diff --git a/src/Jackett/TorznabQuery.cs b/src/Jackett/Models/TorznabQuery.cs
similarity index 98%
rename from src/Jackett/TorznabQuery.cs
rename to src/Jackett/Models/TorznabQuery.cs
index ae3e18785..c1e61d632 100644
--- a/src/Jackett/TorznabQuery.cs
+++ b/src/Jackett/Models/TorznabQuery.cs
@@ -1,4 +1,5 @@
-using System;
+using Jackett.Utils;
+using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
@@ -6,7 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Models
{
public class TorznabQuery
{
diff --git a/src/Jackett/Program.cs b/src/Jackett/Program.cs
deleted file mode 100644
index 7dcd24db9..000000000
--- a/src/Jackett/Program.cs
+++ /dev/null
@@ -1,179 +0,0 @@
-using Jackett.Indexers;
-using Newtonsoft.Json.Linq;
-using NLog;
-using NLog.Config;
-using NLog.Targets;
-using NLog.Windows.Forms;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace Jackett
-{
- class Program
- {
- public static string AppConfigDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
-
- public static Server ServerInstance { get; private set; }
-
- public static bool IsFirstRun { get; private set; }
-
- public static Logger LoggerInstance { get; private set; }
-
- public static ManualResetEvent ExitEvent { get; private set; }
-
- public static bool IsWindows { get { return Environment.OSVersion.Platform == PlatformID.Win32NT; } }
-
-
-
- static void Main(string[] args)
- {
- ExitEvent = new ManualResetEvent(false);
-
- MigrateSettingsDirectory();
-
- try
- {
- if (!Directory.Exists(AppConfigDirectory))
- {
- IsFirstRun = true;
- Directory.CreateDirectory(AppConfigDirectory);
- }
- Console.WriteLine("App config/log directory: " + AppConfigDirectory);
- }
- catch (Exception ex)
- {
- Console.WriteLine("Missing settings directory: " + AppConfigDirectory);
- Console.WriteLine("Could not create settings directory. " + ex.Message);
- Application.Exit();
- return;
- }
-
- var logConfig = new LoggingConfiguration();
-
- var logFile = new FileTarget();
- logConfig.AddTarget("file", logFile);
- logFile.Layout = "${longdate} ${level} ${message} \n ${exception:format=ToString}\n";
- logFile.FileName = Path.Combine(AppConfigDirectory, "log.txt");
- logFile.ArchiveFileName = "log.{#####}.txt";
- logFile.ArchiveAboveSize = 500000;
- logFile.MaxArchiveFiles = 1;
- logFile.KeepFileOpen = false;
- logFile.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence;
- var logFileRule = new LoggingRule("*", LogLevel.Debug, logFile);
- logConfig.LoggingRules.Add(logFileRule);
-
- if (Program.IsWindows)
- {
-#if !__MonoCS__
- var logAlert = new MessageBoxTarget();
- logConfig.AddTarget("alert", logAlert);
- logAlert.Layout = "${message}";
- logAlert.Caption = "Alert";
- var logAlertRule = new LoggingRule("*", LogLevel.Fatal, logAlert);
- logConfig.LoggingRules.Add(logAlertRule);
-#endif
- }
-
- var logConsole = new ConsoleTarget();
- logConfig.AddTarget("console", logConsole);
- logConsole.Layout = "${longdate} ${level} ${message} ${exception:format=ToString}";
- var logConsoleRule = new LoggingRule("*", LogLevel.Debug, logConsole);
- logConfig.LoggingRules.Add(logConsoleRule);
-
- LogManager.Configuration = logConfig;
- LoggerInstance = LogManager.GetCurrentClassLogger();
-
- ReadSettingsFile();
-
- var serverTask = Task.Run(async () =>
- {
- ServerInstance = new Server();
- await ServerInstance.Start();
- });
-
- try
- {
- if (Program.IsWindows)
- {
-#if !__MonoCS__
- Application.Run(new Main());
-#endif
- }
- }
- catch (Exception)
- {
-
- }
-
- Console.WriteLine("Running in headless mode.");
-
-
-
- Task.WaitAll(serverTask);
- 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()
- {
- try
- {
- string oldDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Jackett");
- if (Directory.Exists(oldDir) && !Directory.Exists(AppConfigDirectory))
- {
- Directory.Move(oldDir, AppConfigDirectory);
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("ERROR could not migrate settings directory " + ex);
- }
- }
-
- static void ReadSettingsFile()
- {
- var path = Path.Combine(AppConfigDirectory, "config.json");
- if (!File.Exists(path))
- {
- JObject f = new JObject();
- f.Add("port", Server.DefaultPort);
- f.Add("public", true);
- File.WriteAllText(path, f.ToString());
- }
-
- var configJson = JObject.Parse(File.ReadAllText(path));
- int port = (int)configJson.GetValue("port");
- Server.Port = port;
-
- Server.ListenPublic = (bool)configJson.GetValue("public");
-
- Console.WriteLine("Config file path: " + path);
- }
-
- static public void RestartAsAdmin()
- {
- var startInfo = new ProcessStartInfo(Application.ExecutablePath.ToString()) { Verb = "runas" };
- Process.Start(startInfo);
- Environment.Exit(0);
- }
- }
-}
diff --git a/src/Jackett/Server.cs b/src/Jackett/Server.cs
deleted file mode 100644
index 598f992c6..000000000
--- a/src/Jackett/Server.cs
+++ /dev/null
@@ -1,301 +0,0 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using System.Web;
-using System.Windows.Forms;
-
-namespace Jackett
-{
- public class Server
- {
- public const int DefaultPort = 9117;
- public static int Port = DefaultPort;
- public static bool ListenPublic = true;
-
- HttpListener listener;
- IndexerManager indexerManager;
- WebApi webApi;
-
-
- public Server()
- {
- // Allow all SSL.. sucks I know but mono on linux is having problems without it..
- ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
-
- ReadServerSettingsFile();
- LoadApiKey();
-
- indexerManager = new IndexerManager();
- webApi = new WebApi(indexerManager);
- }
-
- void LoadApiKey()
- {
- var apiKeyFile = Path.Combine(Program.AppConfigDirectory, "api_key.txt");
- if (File.Exists(apiKeyFile))
- ApiKey.CurrentKey = File.ReadAllText(apiKeyFile).Trim();
- else
- {
- ApiKey.CurrentKey = ApiKey.Generate();
- File.WriteAllText(apiKeyFile, ApiKey.CurrentKey);
- }
- }
-
- public async Task Start()
- {
- Program.LoggerInstance.Info("Starting HTTP server on port " + Port + " listening " + (ListenPublic ? "publicly" : "privately"));
-
- try
- {
- listener = new HttpListener();
-
- if (ListenPublic)
- {
- listener.Prefixes.Add(string.Format("http://*:{0}/", Port));
- }
- else
- {
- listener.Prefixes.Add(string.Format("http://127.0.0.1:{0}/", Port));
- }
-
- listener.Start();
- webApi.server = this;
- }
- catch (HttpListenerException ex)
- {
- if (ex.ErrorCode == 5)
- {
- var errorStr = "App must be ran as admin for permission to use port "
- + Port + Environment.NewLine + "Restart app with admin privileges?";
- if (Program.IsWindows)
- {
- var dialogResult = MessageBox.Show(errorStr, "Error", MessageBoxButtons.YesNo);
- if (dialogResult == DialogResult.No)
- {
- Application.Exit();
- return;
- }
- else
- {
- Program.RestartAsAdmin();
- }
- }
- }
- else
- {
- Program.LoggerInstance.FatalException("Failed to start HTTP server. " + ex.Message, ex);
- }
- }
- catch (Exception ex)
- {
- Program.LoggerInstance.ErrorException("Error starting HTTP server: " + ex.Message, ex);
- return;
- }
-
- Program.LoggerInstance.Info("Server started on port " + Port);
- Program.LoggerInstance.Info("Accepting only requests from local system: " + (!ListenPublic));
-
- while (true)
- {
- Exception error = null;
- try
- {
- error = null;
- var context = await listener.GetContextAsync();
- ProcessHttpRequest(context);
- }
- catch (ObjectDisposedException ex)
- {
- Program.LoggerInstance.ErrorException("Critical error, HTTP listener was destroyed", ex);
- Process.GetCurrentProcess().Kill();
- }
- catch (Exception ex)
- {
- error = ex;
- Program.LoggerInstance.ErrorException("Error processing HTTP request", ex);
- }
-
- if (error != null)
- await Task.Delay(TimeSpan.FromSeconds(5));
- }
- }
-
- public void Stop()
- {
- listener.Stop();
- listener.Abort();
- }
-
- async void ProcessHttpRequest(HttpListenerContext context)
- {
- Program.LoggerInstance.Trace("Received request: " + context.Request.Url.ToString());
- Exception exception = null;
- try
- {
- if (await webApi.HandleRequest(context))
- {
-
- }
- else if (context.Request.Url.AbsolutePath.StartsWith("/api/"))
- {
- await ProcessTorznab(context);
- }
- else
- {
- var responseBytes = Encoding.UTF8.GetBytes("Invalid request");
- await context.Response.OutputStream.WriteAsync(responseBytes, 0, responseBytes.Length);
- }
- }
- catch (Exception ex)
- {
- exception = ex;
- Program.LoggerInstance.ErrorException(ex.Message + ex.ToString(), ex);
- }
-
- if (exception != null)
- {
- try
- {
- var errorBytes = Encoding.UTF8.GetBytes(exception.Message);
- await context.Response.OutputStream.WriteAsync(errorBytes, 0, errorBytes.Length);
- }
- catch (Exception)
- {
- }
- }
-
- try
- {
- context.Response.Close();
- }
- catch (Exception)
- {
- }
-
- }
-
- async Task ProcessTorznab(HttpListenerContext context)
- {
-
- var query = HttpUtility.ParseQueryString(context.Request.Url.Query);
- var inputStream = context.Request.InputStream;
-
- var indexerId = context.Request.Url.Segments[2].TrimEnd('/').ToLower();
- var indexer = indexerManager.GetIndexer(indexerId);
-
- if (context.Request.Url.Segments.Length > 4 && context.Request.Url.Segments[3] == "download/")
- {
- var downloadSegment = HttpServerUtility.UrlTokenDecode(context.Request.Url.Segments[4].TrimEnd('/'));
- var downloadLink = Encoding.UTF8.GetString(downloadSegment);
- var downloadBytes = await indexer.Download(new Uri(downloadLink));
- await context.Response.OutputStream.WriteAsync(downloadBytes, 0, downloadBytes.Length);
- return;
- }
-
- var torznabQuery = TorznabQuery.FromHttpQuery(query);
-
- if (torznabQuery.RageIDLookupEnabled && indexer.RequiresRageIDLookupDisabled)
- {
- throw new ArgumentException("This indexer requires RageID lookup disabled");
- }
-
- var releases = await indexer.PerformQuery(torznabQuery);
-
- Program.LoggerInstance.Debug(string.Format("Found {0} releases from {1}", releases.Length, indexer.DisplayName));
-
- var severUrl = string.Format("{0}://{1}:{2}/", context.Request.Url.Scheme, context.Request.Url.Host, context.Request.Url.Port);
-
- var resultPage = new ResultPage(new ChannelInfo
- {
- Title = indexer.DisplayName,
- Description = indexer.DisplayDescription,
- Link = indexer.SiteLink,
- ImageUrl = new Uri(severUrl + "logos/" + indexerId + ".png"),
- ImageTitle = indexer.DisplayName,
- ImageLink = indexer.SiteLink,
- ImageDescription = indexer.DisplayName
- });
-
- // add Jackett proxy to download links...
- foreach (var release in releases)
- {
- if (release.Link == null || release.Link.Scheme == "magnet")
- continue;
- var originalLink = release.Link;
- var encodedLink = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(originalLink.ToString())) + "/download.torrent";
- var proxyLink = string.Format("{0}api/{1}/download/{2}", severUrl, indexerId, encodedLink);
- release.Link = new Uri(proxyLink);
- }
-
- resultPage.Releases.AddRange(releases);
-
- var xml = resultPage.ToXml(new Uri(severUrl));
-
- var responseBytes = Encoding.UTF8.GetBytes(xml);
- context.Response.ContentEncoding = Encoding.UTF8;
- context.Response.ContentLength64 = responseBytes.LongLength;
- context.Response.ContentType = "application/rss+xml";
- await context.Response.OutputStream.WriteAsync(responseBytes, 0, responseBytes.Length);
-
- }
-
-
-
-
- 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 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());
- }
-
- }
-}
diff --git a/src/Jackett/Services/ConfigurationService.cs b/src/Jackett/Services/ConfigurationService.cs
new file mode 100644
index 000000000..dd6b8a8d8
--- /dev/null
+++ b/src/Jackett/Services/ConfigurationService.cs
@@ -0,0 +1,187 @@
+using Newtonsoft.Json.Linq;
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Jackett.Services
+{
+ public interface IConfigurationService
+ {
+ string GetContentFolder();
+ string GetVersion();
+ string GetIndexerConfigDir();
+ string GetAppDataFolder();
+ JObject ReadServerSettingsFile();
+ string GetSonarrConfigFile();
+ T GetConfig();
+ void SaveConfig(T config);
+ string ApplicationFolder();
+ }
+
+ public class ConfigurationService: IConfigurationService
+ {
+ private ISerializeService serializeService;
+ private Logger logger;
+
+ public ConfigurationService(ISerializeService s, Logger l)
+ {
+ serializeService = s;
+ logger = l;
+ CreateOrMigrateSettings();
+ }
+
+ private void CreateOrMigrateSettings()
+ {
+ try
+ {
+ if (!Directory.Exists(GetAppDataFolder()))
+ {
+ Directory.CreateDirectory(GetAppDataFolder());
+ }
+
+ logger.Debug("App config/log directory: " + GetAppDataFolder());
+ }
+ catch (Exception ex)
+ {
+ throw new Exception("Could not create settings directory. " + ex.Message);
+ }
+
+ try
+ {
+ string oldDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
+ if (Directory.Exists(oldDir))
+ {
+ foreach (var file in Directory.GetFiles(oldDir, "*", SearchOption.AllDirectories))
+ {
+ var path = file.Replace(oldDir, "");
+ var destFolder = GetAppDataFolder()+ path;
+ if (!Directory.Exists(Path.GetDirectoryName(destFolder)))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(destFolder));
+ }
+ File.Move(file, destFolder);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ logger.Error("ERROR could not migrate settings directory " + ex);
+ }
+ }
+
+ public T GetConfig()
+ {
+ var type = typeof(T);
+ var fullPath = Path.Combine(GetAppDataFolder(), type.Name + ".json");
+ try
+ {
+ if (!File.Exists(fullPath))
+ {
+ logger.Debug("Config file does not exist: " + fullPath);
+ return default(T);
+ }
+
+ return serializeService.DeSerialise(File.ReadAllText(fullPath));
+ }
+ catch(Exception e)
+ {
+ logger.Error(e, "Error reading config file " + fullPath);
+ return default(T);
+ }
+ }
+
+ public void SaveConfig(T config)
+ {
+ var type = typeof(T);
+ var fullPath = Path.Combine(GetAppDataFolder(), type.Name + ".json");
+ try
+ {
+ var json = serializeService.Serialise(config);
+ if (!Directory.Exists(GetAppDataFolder()))
+ Directory.CreateDirectory(GetAppDataFolder());
+ File.WriteAllText(fullPath, json);
+ }
+ catch (Exception e)
+ {
+ logger.Error(e, "Error reading config file " + fullPath);
+ }
+ }
+
+ public string ApplicationFolder()
+ {
+ return Path.GetDirectoryName(Application.ExecutablePath);
+ }
+
+ public string GetContentFolder()
+ {
+ // If we are debugging we can use the non copied content.
+ var dir = Path.Combine(ApplicationFolder(), "Content");
+ if (!Directory.Exists(dir))
+ {
+ dir = Path.Combine(ApplicationFolder(), "..\\..\\..\\Jackett\\Content");
+ }
+
+ return dir;
+ }
+
+ public string GetVersion()
+ {
+ return Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ }
+
+ public string GetAppDataFolder()
+ {
+ return GetAppDataFolderStatic();
+ }
+
+ ///
+ /// This is needed for the logger prior to ioc setup.
+ ///
+ ///
+ public static string GetAppDataFolderStatic()
+ {
+ return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Jackett");
+ }
+
+ public string GetIndexerConfigDir()
+ {
+ return Path.Combine(GetAppDataFolder(), "Indexers");
+ }
+
+ public string GetConfigFile()
+ {
+ return Path.Combine(GetAppDataFolder(), "config.json");
+ }
+
+ public string GetSonarrConfigFile()
+ {
+ return Path.Combine(GetAppDataFolder(), "sonarr_api.json");
+ }
+
+
+ public JObject ReadServerSettingsFile()
+ {
+ var path = GetConfigFile();
+ 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;
+ }
+ }
+}
diff --git a/src/Jackett/Services/IndexerManagerService.cs b/src/Jackett/Services/IndexerManagerService.cs
new file mode 100644
index 000000000..718ea39da
--- /dev/null
+++ b/src/Jackett/Services/IndexerManagerService.cs
@@ -0,0 +1,101 @@
+using Autofac;
+using Jackett.Indexers;
+using Jackett.Models;
+using Newtonsoft.Json.Linq;
+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
+ {
+ void TestIndexer(string name);
+ void DeleteIndexer(string name);
+ IIndexer GetIndexer(string name);
+ IEnumerable GetAllIndexers();
+ void SaveConfig(IIndexer indexer, JToken obj);
+ void InitIndexers();
+ }
+
+ public class IndexerManagerService : IIndexerManagerService
+ {
+ private IContainer container;
+ private IConfigurationService configService;
+ private Logger logger;
+
+ public IndexerManagerService(IContainer c, IConfigurationService config, Logger l)
+ {
+ container = c;
+ configService = config;
+ logger = l;
+ }
+
+ public void InitIndexers()
+ {
+ // Load the existing config for each indexer
+ foreach (var indexer in GetAllIndexers())
+ {
+ var configFilePath = GetIndexerConfigFilePath(indexer);
+ if (File.Exists(configFilePath))
+ {
+ var jsonString = JObject.Parse(File.ReadAllText(configFilePath));
+ indexer.LoadFromSavedConfiguration(jsonString);
+ }
+ }
+ }
+
+ public IIndexer GetIndexer(string name)
+ {
+ var indexer = GetAllIndexers().Where(i => string.Equals(i.DisplayName, name, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
+ if (indexer == null)
+ {
+ logger.Error("Request for unknown indexer: " + name);
+ throw new Exception("Unknown indexer: " + name);
+ }
+ return indexer;
+ }
+
+ public IEnumerable GetAllIndexers()
+ {
+
+ return container.Resolve>().OrderBy(_ => _.DisplayName);
+ }
+
+ public async void TestIndexer(string name)
+ {
+ var indexer = GetIndexer(name);
+ var browseQuery = new TorznabQuery();
+ var results = await indexer.PerformQuery(browseQuery);
+ logger.Debug(string.Format("Found {0} releases from {1}", results.Length, indexer.DisplayName));
+ if (results.Length == 0)
+ throw new Exception("Found no results while trying to browse this tracker");
+ }
+
+ public void DeleteIndexer(string name)
+ {
+ var indexer = GetIndexer(name);
+ var configPath = configService.GetIndexerConfigDir();
+ File.Delete(configPath);
+ //Indexers.Remove(name);
+ //LoadMissingIndexers();
+ }
+
+ private string GetIndexerConfigFilePath(IIndexer indexer)
+ {
+ return Path.Combine(configService.GetIndexerConfigDir(), indexer.GetType().Name.ToLower() + ".json");
+ }
+
+ public void SaveConfig(IIndexer indexer, JToken obj)
+ {
+ var configFilePath = GetIndexerConfigFilePath(indexer);
+ if (!Directory.Exists(configService.GetIndexerConfigDir()))
+ Directory.CreateDirectory(configService.GetIndexerConfigDir());
+ File.WriteAllText(configFilePath, obj.ToString());
+ }
+ }
+}
diff --git a/src/Jackett/Services/ProcessService.cs b/src/Jackett/Services/ProcessService.cs
new file mode 100644
index 000000000..1ef3bac96
--- /dev/null
+++ b/src/Jackett/Services/ProcessService.cs
@@ -0,0 +1,64 @@
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Services
+{
+ public interface IProcessService
+ {
+ void StartProcessAndLog(string exe, string args);
+ }
+
+ public class ProcessService : IProcessService
+ {
+ private Logger logger;
+
+ public ProcessService(Logger l)
+ {
+ logger = l;
+ }
+
+ public void StartProcessAndLog(string exe, string args)
+ {
+ var startInfo = new ProcessStartInfo()
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ FileName = exe,
+ Arguments = args,
+ RedirectStandardError = true,
+ RedirectStandardOutput = true,
+ RedirectStandardInput = true
+ };
+
+ var proc = Process.Start(startInfo);
+ proc.OutputDataReceived += proc_OutputDataReceived;
+ proc.ErrorDataReceived += proc_ErrorDataReceived;
+ proc.BeginErrorReadLine();
+ proc.BeginOutputReadLine();
+ proc.WaitForExit();
+ proc.OutputDataReceived -= proc_OutputDataReceived;
+ proc.ErrorDataReceived -= proc_ErrorDataReceived;
+ }
+
+ void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ if (!string.IsNullOrWhiteSpace(e.Data))
+ {
+ logger.Error(e.Data);
+ }
+ }
+
+ void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ if (!string.IsNullOrWhiteSpace(e.Data))
+ {
+ logger.Debug(e.Data);
+ }
+ }
+ }
+}
diff --git a/src/Jackett/Services/SerializeService.cs b/src/Jackett/Services/SerializeService.cs
new file mode 100644
index 000000000..dacbf9ebb
--- /dev/null
+++ b/src/Jackett/Services/SerializeService.cs
@@ -0,0 +1,35 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Services
+{
+ public interface ISerializeService
+ {
+ string Serialise(object obj);
+ T DeSerialise(string json);
+ }
+
+ class SerializeService : ISerializeService
+ {
+ public string Serialise(object obj)
+ {
+ return JsonConvert.SerializeObject(obj,Formatting.Indented);
+ }
+
+ public T DeSerialise(string json)
+ {
+ try
+ {
+ return JsonConvert.DeserializeObject(json);
+ }
+ catch
+ {
+ return default(T);
+ }
+ }
+ }
+}
diff --git a/src/Jackett/Services/ServerService.cs b/src/Jackett/Services/ServerService.cs
new file mode 100644
index 000000000..2ad5724d8
--- /dev/null
+++ b/src/Jackett/Services/ServerService.cs
@@ -0,0 +1,136 @@
+using Autofac;
+using Jackett.Models.Config;
+using Jackett.Services;
+using Microsoft.Owin.Hosting;
+using Newtonsoft.Json.Linq;
+using NLog;
+using NLog.Config;
+using NLog.Targets;
+using NLog.Windows.Forms;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Services
+{
+ public interface IServerService
+ {
+ void Start();
+ void Stop();
+ void ReserveUrls(bool doInstall = true);
+ ServerConfig Config { get; }
+ }
+
+ public class ServerService : IServerService
+ {
+ private ServerConfig config;
+
+ private IDisposable _server = null;
+
+ private IIndexerManagerService indexerService;
+ private IProcessService processService;
+ private ISerializeService serializeService;
+ private IConfigurationService configService;
+ private Logger logger;
+
+ public ServerService(IIndexerManagerService i, IProcessService p, ISerializeService s, IConfigurationService c, Logger l)
+ {
+ indexerService = i;
+ processService = p;
+ serializeService = s;
+ configService = c;
+ logger = l;
+
+ LoadConfig();
+ }
+
+ public ServerConfig Config
+ {
+ get { return config; }
+ }
+
+ private void LoadConfig()
+ {
+ // Load config
+ config = configService.GetConfig();
+ if (config == null)
+ {
+ config = new ServerConfig();
+ }
+
+ if (string.IsNullOrWhiteSpace(config.APIKey))
+ {
+ // Check for legacy key config
+ var apiKeyFile = Path.Combine(configService.GetAppDataFolder(), "api_key.txt");
+ if (File.Exists(apiKeyFile))
+ {
+ config.APIKey = File.ReadAllText(apiKeyFile);
+ }
+
+ // Check for legacy settings
+
+ var path = Path.Combine(configService.GetAppDataFolder(), "config.json"); ;
+ var jsonReply = new JObject();
+ if (File.Exists(path))
+ {
+ jsonReply = JObject.Parse(File.ReadAllText(path));
+ config.Port = (int)jsonReply["port"];
+ config.AllowExternal = (bool)jsonReply["public"];
+ }
+
+ if (string.IsNullOrWhiteSpace(config.APIKey))
+ {
+ config.APIKey = config.GenerateApi();
+ }
+
+ configService.SaveConfig(config);
+ }
+ }
+
+ public void Start()
+ {
+ // Allow all SSL.. sucks I know but mono on linux is having problems without it..
+ ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
+
+ // Load indexers
+ indexerService.InitIndexers();
+
+ // Start the server
+ logger.Debug("Starting web server at " + config.GetListenAddress());
+ _server = WebApp.Start(url: config.GetListenAddress());
+ logger.Debug("Web server started");
+ }
+
+ public void ReserveUrls(bool doInstall = true)
+ {
+ logger.Debug("Unreserving Urls");
+ RunNetSh(string.Format("http delete urlacl {0}", config.GetListenAddress(false)));
+ RunNetSh(string.Format("http delete urlacl {0}", config.GetListenAddress(true)));
+ if (doInstall)
+ {
+ logger.Debug("Reserving Urls");
+ RunNetSh(string.Format("http add urlacl {0} sddl=D:(A;;GX;;;S-1-1-0)", config.GetListenAddress()));
+ logger.Debug("Urls reserved");
+ }
+ }
+
+ private void RunNetSh(string args)
+ {
+ processService.StartProcessAndLog("netsh.exe", args);
+ }
+
+ public void Stop()
+ {
+ if (_server != null)
+ {
+ _server.Dispose();
+ }
+ }
+ }
+}
diff --git a/src/Jackett/Services/ServiceConfigService.cs b/src/Jackett/Services/ServiceConfigService.cs
new file mode 100644
index 000000000..12886e931
--- /dev/null
+++ b/src/Jackett/Services/ServiceConfigService.cs
@@ -0,0 +1,114 @@
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration.Install;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.ServiceProcess;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Services
+{
+ public interface IServiceConfigService
+ {
+ void Install();
+ void Uninstall();
+ }
+
+ class ServiceConfigService : IServiceConfigService
+ {
+ private const string NAME = "Jackett";
+ private const string DESCRIPTION = "Additional indexers for Sonarr";
+ private const string SERVICEEXE = "JackettService.exe";
+
+ private IConfigurationService configService;
+ private Logger logger;
+
+ public ServiceConfigService(IConfigurationService c, Logger l)
+ {
+ configService = c;
+ logger = l;
+ }
+
+ public bool Exists()
+ {
+ return GetService(NAME) != null;
+ }
+
+ public ServiceController GetService(string serviceName)
+ {
+ return ServiceController.GetServices().FirstOrDefault(c => String.Equals(c.ServiceName, serviceName, StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ public void Install()
+ {
+ if (Exists())
+ {
+
+ }
+ else
+ {
+ var installer = new ServiceProcessInstaller
+ {
+ Account = ServiceAccount.NetworkService
+ };
+
+ var serviceInstaller = new ServiceInstaller();
+
+ var exePath = Path.Combine(configService.ApplicationFolder(), SERVICEEXE);
+ if (!File.Exists(exePath) && Debugger.IsAttached)
+ {
+ exePath = Path.Combine(configService.ApplicationFolder(), "..\\..\\..\\Jackett.Service\\bin\\Debug", SERVICEEXE);
+ }
+
+ string[] cmdline = { @"/assemblypath=" + exePath};
+
+ var context = new InstallContext("jackettservice_install.log", cmdline);
+ serviceInstaller.Context = context;
+ serviceInstaller.DisplayName = NAME;
+ serviceInstaller.ServiceName = NAME;
+ serviceInstaller.Description = DESCRIPTION;
+ serviceInstaller.StartType = ServiceStartMode.Automatic;
+ serviceInstaller.Parent = installer;
+
+ serviceInstaller.Install(new ListDictionary());
+ }
+ }
+
+ public void Uninstall()
+ {
+ Stop();
+
+ var serviceInstaller = new ServiceInstaller();
+
+ var context = new InstallContext("jackettservice_uninstall.log", null);
+ serviceInstaller.Context = context;
+ serviceInstaller.ServiceName = NAME;
+ serviceInstaller.Uninstall(null);
+
+ logger.Info("The service was uninstalled.");
+
+ }
+
+ public void Stop()
+ {
+ var service = GetService(NAME);
+ if (service.Status != ServiceControllerStatus.Stopped)
+ {
+ service.Stop();
+ service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60));
+
+ service.Refresh();
+ if (service.Status == ServiceControllerStatus.Stopped)
+ logger.Info("Service stopped.");
+ else
+ logger.Error("Failed to stop the service");
+ }
+ else
+ logger.Warn("The service was already stopped");
+ }
+ }
+}
diff --git a/src/Jackett/Services/SpinService.cs b/src/Jackett/Services/SpinService.cs
new file mode 100644
index 000000000..8d8e5d0b0
--- /dev/null
+++ b/src/Jackett/Services/SpinService.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Jackett.Services
+{
+ public interface IRunTimeService
+ {
+ void Spin();
+ }
+
+ class RunTimeService : IRunTimeService
+ {
+ private bool isRunning = true;
+
+ public void Spin()
+ {
+ while (isRunning)
+ {
+ Thread.Sleep(2000);
+ }
+ }
+ }
+}
diff --git a/src/Jackett/Startup.cs b/src/Jackett/Startup.cs
new file mode 100644
index 000000000..43b456328
--- /dev/null
+++ b/src/Jackett/Startup.cs
@@ -0,0 +1,57 @@
+using Owin;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web.Http;
+using Autofac.Integration.WebApi;
+using Microsoft.Owin;
+using Jackett;
+using Microsoft.Owin.StaticFiles;
+using Microsoft.Owin.FileSystems;
+using Autofac;
+using Jackett.Services;
+
+[assembly: OwinStartup(typeof(Startup))]
+namespace Jackett
+{
+ public class Startup
+ {
+ public void Configuration(IAppBuilder appBuilder)
+ {
+ // Configure Web API for self-host.
+ var config = new HttpConfiguration();
+ config.DependencyResolver = new AutofacWebApiDependencyResolver(Engine.GetContainer());
+ config.MapHttpAttributeRoutes();
+
+ config.Routes.MapHttpRoute(
+ name: "Admin",
+ routeTemplate: "admin/{action}",
+ defaults: new { controller = "Admin" }
+ );
+
+ config.Routes.MapHttpRoute(
+ name: "api",
+ routeTemplate: "api/{indexerName}",
+ defaults: new { controller = "API", action = "Call" }
+ );
+
+ config.Routes.MapHttpRoute(
+ name: "download",
+ routeTemplate: "api/{indexerName}/download/{path}/download.torrent",
+ defaults: new { controller = "Download", action = "Download" }
+ );
+
+ appBuilder.UseFileServer(new FileServerOptions
+ {
+ RequestPath = new PathString(string.Empty),
+ FileSystem = new PhysicalFileSystem(Engine.ConfigService.GetContentFolder()),
+ EnableDirectoryBrowsing = true,
+ });
+
+ appBuilder.UseWebApi(config);
+ }
+ }
+}
diff --git a/src/Jackett/BrowserUtil.cs b/src/Jackett/Utils/BrowserUtil.cs
similarity index 94%
rename from src/Jackett/BrowserUtil.cs
rename to src/Jackett/Utils/BrowserUtil.cs
index 82154b176..669b1e346 100644
--- a/src/Jackett/BrowserUtil.cs
+++ b/src/Jackett/Utils/BrowserUtil.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Utils
{
public static class BrowserUtil
{
diff --git a/src/Jackett/ParseUtil.cs b/src/Jackett/Utils/ParseUtil.cs
similarity index 98%
rename from src/Jackett/ParseUtil.cs
rename to src/Jackett/Utils/ParseUtil.cs
index 9b62c0027..c96e2be7a 100644
--- a/src/Jackett/ParseUtil.cs
+++ b/src/Jackett/Utils/ParseUtil.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Utils
{
public static class ParseUtil
{
diff --git a/src/Jackett/ServerUtil.cs b/src/Jackett/Utils/ServerUtil.cs
similarity index 99%
rename from src/Jackett/ServerUtil.cs
rename to src/Jackett/Utils/ServerUtil.cs
index 8f3e6c02f..a65f1f2f7 100644
--- a/src/Jackett/ServerUtil.cs
+++ b/src/Jackett/Utils/ServerUtil.cs
@@ -5,7 +5,7 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-namespace Jackett
+namespace Jackett.Utils
{
public static class ServerUtil
{
diff --git a/src/Jackett/WebApi.cs b/src/Jackett/WebApi.cs
deleted file mode 100644
index 2f56a5d58..000000000
--- a/src/Jackett/WebApi.cs
+++ /dev/null
@@ -1,325 +0,0 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Reflection;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-using System.Web;
-
-namespace Jackett
-{
- public class WebApi
- {
- static string WebContentFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WebContent");
- static string[] StaticFiles = Directory.EnumerateFiles(WebContentFolder, "*", SearchOption.AllDirectories).ToArray();
- public Server server;
-
- public enum WebApiMethod
- {
- GetConfigForm,
- ConfigureIndexer,
- GetIndexers,
- TestIndexer,
- DeleteIndexer,
- GetSonarrConfig,
- ApplySonarrConfig,
- GetJackettConfig,
- ApplyJackettConfig,
- JackettRestart,
- }
-
- static Dictionary WebApiMethods = new Dictionary {
- { "get_config_form", WebApiMethod.GetConfigForm },
- { "configure_indexer", WebApiMethod.ConfigureIndexer },
- { "get_indexers", WebApiMethod.GetIndexers },
- { "test_indexer", WebApiMethod.TestIndexer },
- { "delete_indexer", WebApiMethod.DeleteIndexer },
- { "get_sonarr_config", WebApiMethod.GetSonarrConfig },
- { "apply_sonarr_config", WebApiMethod.ApplySonarrConfig },
- { "get_jackett_config",WebApiMethod.GetJackettConfig},
- { "apply_jackett_config",WebApiMethod.ApplyJackettConfig},
- { "jackett_restart", WebApiMethod.JackettRestart },
- };
-
- IndexerManager indexerManager;
-
- public WebApi(IndexerManager indexerManager)
- {
- this.indexerManager = indexerManager;
- }
-
- public async Task HandleRequest(HttpListenerContext context)
- {
- string path = context.Request.Url.AbsolutePath.TrimStart('/');
- if (path == "")
- path = "index.html";
-
- var sysPath = Path.Combine(WebContentFolder, path.Replace("/", Path.DirectorySeparatorChar.ToString()));
- if (Array.IndexOf(StaticFiles, sysPath) > -1)
- {
- await ServeStaticFile(context, path);
- return true;
- }
-
- WebApi.WebApiMethod apiMethod;
- if (WebApi.WebApiMethods.TryGetValue(path, out apiMethod))
- {
- await ProcessWebApiRequest(context, apiMethod);
- return true;
- }
-
- return false;
- }
-
- async Task ServeStaticFile(HttpListenerContext context, string file)
- {
- var contentFile = File.ReadAllBytes(Path.Combine(WebContentFolder, file));
- context.Response.ContentType = MimeMapping.GetMimeMapping(file);
- context.Response.StatusCode = (int)HttpStatusCode.OK;
- try
- {
- await context.Response.OutputStream.WriteAsync(contentFile, 0, contentFile.Length);
- }
- catch (HttpListenerException)
- {
- }
- }
-
- async Task ReadPostDataJson(Stream stream)
- {
- string postData = await new StreamReader(stream).ReadToEndAsync();
- return JObject.Parse(postData);
- }
-
- delegate Task HandlerTask(HttpListenerContext context);
-
- async Task ProcessWebApiRequest(HttpListenerContext context, WebApiMethod method)
- {
- context.Response.ContentType = "text/json";
- context.Response.StatusCode = (int)HttpStatusCode.OK;
-
- HandlerTask handlerTask;
-
- switch (method)
- {
- case WebApiMethod.GetConfigForm:
- handlerTask = HandleConfigForm;
- break;
- case WebApiMethod.ConfigureIndexer:
- handlerTask = HandleConfigureIndexer;
- break;
- case WebApiMethod.GetIndexers:
- handlerTask = HandleGetIndexers;
- break;
- case WebApiMethod.TestIndexer:
- handlerTask = HandleTestIndexer;
- break;
- case WebApiMethod.DeleteIndexer:
- handlerTask = HandleDeleteIndexer;
- break;
- case WebApiMethod.ApplyJackettConfig:
- handlerTask = HandleApplyJackettConfig;
- break;
- case WebApiMethod.GetJackettConfig:
- handlerTask = HandleJackettConfig;
- break;
- case WebApiMethod.JackettRestart:
- handlerTask = HandleJackettRestart;
- break;
- default:
- handlerTask = HandleInvalidApiMethod;
- break;
- }
- JToken jsonReply = await handlerTask(context);
- await ReplyWithJson(context, jsonReply, method.ToString());
- }
-
- async Task ReplyWithJson(HttpListenerContext context, JToken json, string apiCall)
- {
- try
- {
- byte[] jsonBytes = Encoding.UTF8.GetBytes(json.ToString());
- await context.Response.OutputStream.WriteAsync(jsonBytes, 0, jsonBytes.Length);
- }
- catch (Exception ex)
- {
- Console.WriteLine("Error writing json to stream for API call " + apiCall + Environment.NewLine + ex.ToString());
- }
- }
-
- Task HandleInvalidApiMethod(HttpListenerContext context)
- {
- JToken jsonReply = new JObject();
- jsonReply["result"] = "error";
- jsonReply["error"] = "Invalid API method";
- return Task.FromResult(jsonReply);
- }
-
- async Task HandleConfigForm(HttpListenerContext context)
- {
- JToken jsonReply = new JObject();
- try
- {
- var postData = await ReadPostDataJson(context.Request.InputStream);
- string indexerString = (string)postData["indexer"];
- var indexer = indexerManager.GetIndexer(indexerString);
- var config = await indexer.GetConfigurationForSetup();
- jsonReply["config"] = config.ToJson();
- jsonReply["name"] = indexer.DisplayName;
- jsonReply["result"] = "success";
- }
- catch (Exception ex)
- {
- jsonReply["result"] = "error";
- jsonReply["error"] = ex.Message;
- }
- return jsonReply;
- }
-
- async Task HandleConfigureIndexer(HttpListenerContext context)
- {
- JToken jsonReply = new JObject();
- try
- {
- var postData = await ReadPostDataJson(context.Request.InputStream);
- string indexerString = (string)postData["indexer"];
- var indexer = indexerManager.GetIndexer(indexerString);
- jsonReply["name"] = indexer.DisplayName;
- await indexer.ApplyConfiguration(postData["config"]);
- await indexerManager.TestIndexer(indexer);
- jsonReply["result"] = "success";
- }
- catch (Exception ex)
- {
- jsonReply["result"] = "error";
- jsonReply["error"] = ex.Message;
- if (ex is ExceptionWithConfigData)
- {
- jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson();
- }
- }
- return jsonReply;
- }
-
- Task HandleGetIndexers(HttpListenerContext context)
- {
- JToken jsonReply = new JObject();
- try
- {
- jsonReply["result"] = "success";
- jsonReply["api_key"] = ApiKey.CurrentKey;
- jsonReply["app_version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString();
- JArray items = new JArray();
- foreach (var i in indexerManager.Indexers.OrderBy(_ => _.Key))
- {
- var indexer = i.Value;
- var item = new JObject();
- item["id"] = i.Key;
- item["name"] = indexer.DisplayName;
- item["description"] = indexer.DisplayDescription;
- item["configured"] = indexer.IsConfigured;
- item["site_link"] = indexer.SiteLink;
- items.Add(item);
- }
- jsonReply["items"] = items;
- }
- catch (Exception ex)
- {
- jsonReply["result"] = "error";
- jsonReply["error"] = ex.Message;
- }
- return Task.FromResult(jsonReply);
- }
-
- async Task HandleTestIndexer(HttpListenerContext context)
- {
- JToken jsonReply = new JObject();
- try
- {
- var postData = await ReadPostDataJson(context.Request.InputStream);
- string indexerString = (string)postData["indexer"];
- var indexer = indexerManager.GetIndexer(indexerString);
- jsonReply["name"] = indexer.DisplayName;
- await indexerManager.TestIndexer(indexer);
- jsonReply["result"] = "success";
- }
- catch (Exception ex)
- {
- jsonReply["result"] = "error";
- jsonReply["error"] = ex.Message;
- }
- return jsonReply;
- }
-
- async Task HandleDeleteIndexer(HttpListenerContext context)
- {
- JToken jsonReply = new JObject();
- try
- {
- var postData = await ReadPostDataJson(context.Request.InputStream);
- string indexerString = (string)postData["indexer"];
- indexerManager.DeleteIndexer(indexerString);
- }
- catch (Exception ex)
- {
- jsonReply["result"] = "error";
- jsonReply["error"] = ex.Message;
- }
- return jsonReply;
- }
-
-
- //Jacket port functions
- Task 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(jsonReply);
- }
-
- async Task 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 HandleJackettRestart(HttpListenerContext context)
- {
- Program.RestartServer();
- return null;
- }
-
-
- }
-}
diff --git a/src/Jackett/packages.config b/src/Jackett/packages.config
index efab650c9..a4f77e87c 100644
--- a/src/Jackett/packages.config
+++ b/src/Jackett/packages.config
@@ -1,7 +1,22 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file