diff --git a/.gitignore b/.gitignore
index eb5a9e709..b448ab4bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -196,3 +196,4 @@ FakesAssemblies/
*.opt
/Build.mono
/Build.windows
+/Output
diff --git a/Build.bat b/Build.bat
index c00001a65..d8639c15d 100644
--- a/Build.bat
+++ b/Build.bat
@@ -11,6 +11,8 @@ copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.windows\Jackett
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.windows\JackettService.exe.config
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.windows\JackettTray.exe
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.windows\JackettTray.exe.config
+copy /Y src\Jackett.Updater\bin\Release\JackettUpdater.exe build.windows\JackettUpdater.exe
+copy /Y src\Jackett.Updater\bin\Release\JackettUpdater.exe.config build.windows\JackettUpdater.exe.config
copy /Y LICENSE build.windows\LICENSE
copy /Y README.md build.windows\README.md
@@ -25,6 +27,8 @@ copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.mono\JackettSer
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.mono\JackettService.exe.config
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.mono\JackettTray.exe
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.mono\JackettTray.exe.config
+copy /Y src\Jackett.Updater\bin\Release\JackettUpdater.exe build.mono\JackettUpdater.exe
+copy /Y src\Jackett.Updater\bin\Release\JackettUpdater.exe.config build.mono\JackettUpdater.exe.config
copy /Y LICENSE build.mono\LICENSE
copy /Y README.md build.mono\README.md
copy /Y Upstart.config build.mono\Upstart.config
diff --git a/Installer.iss b/Installer.iss
index 3458be00b..103f09715 100644
--- a/Installer.iss
+++ b/Installer.iss
@@ -24,9 +24,10 @@ DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputBaseFilename=setup
SetupIconFile=src\Jackett.Console\jackett.ico
-UninstallDisplayIcon={app}\JackettConsole.exe
+UninstallDisplayIcon={userappdata}\Jackett\JackettConsole.exe
Compression=lzma
SolidCompression=yes
+DisableDirPage=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -36,26 +37,27 @@ Name: "windowsService"; Description: "Install as a Windows Service"
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
-Source: "build.windows\JackettTray.exe"; DestDir: "{app}"; Flags: ignoreversion
-Source: "build.windows\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "build.windows\JackettTray.exe"; DestDir: "{userappdata}\Jackett"; Flags: ignoreversion
+Source: "build.windows\JackettUpdater.exe"; DestDir: "{userappdata}\Jackett"; Flags: ignoreversion
+Source: "build.windows\*"; DestDir: "{userappdata}\Jackett"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
-Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
+Name: "{group}\{#MyAppName}"; Filename: "{userappdata}\Jackett\{#MyAppExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
-Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
+Name: "{commondesktop}\{#MyAppName}"; Filename: "{userappdata}\Jackett\{#MyAppExeName}"; Tasks: desktopicon
[Run]
-Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
+Filename: "{userappdata}\Jackett\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
[Run]
-Filename: "{app}\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated;
-Filename: "{app}\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated;
-Filename: "{app}\JackettConsole.exe"; Parameters: "--MigrateSettings"; Flags: waituntilterminated;
-Filename: "{app}\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated; Tasks: windowsService
-Filename: "{app}\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated; Tasks: windowsService
+Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated;
+Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated;
+Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--MigrateSettings"; Flags: waituntilterminated;
+Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated; Tasks: windowsService
+Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated; Tasks: windowsService
[UninstallRun]
-Filename: "{app}\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist
+Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist
diff --git a/src/Jackett.Updater/App.config b/src/Jackett.Updater/App.config
new file mode 100644
index 000000000..ac8dbeb66
--- /dev/null
+++ b/src/Jackett.Updater/App.config
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Jackett.Updater/Jackett.Updater.csproj b/src/Jackett.Updater/Jackett.Updater.csproj
new file mode 100644
index 000000000..336b68f84
--- /dev/null
+++ b/src/Jackett.Updater/Jackett.Updater.csproj
@@ -0,0 +1,83 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}
+ Exe
+ Properties
+ Jackett.Updater
+ JackettUpdater
+ v4.5
+ 512
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ jackett.ico
+
+
+
+ ..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll
+ True
+
+
+ ..\packages\NLog.4.2.0\lib\net45\NLog.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {e636d5f8-68b4-4903-b4ed-ccfd9c9e899f}
+ Jackett
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.Updater/Program.cs b/src/Jackett.Updater/Program.cs
new file mode 100644
index 000000000..d65a04040
--- /dev/null
+++ b/src/Jackett.Updater/Program.cs
@@ -0,0 +1,143 @@
+using CommandLine;
+using Jackett.Services;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Jackett.Updater
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ new Program().Run(args);
+ }
+
+ private void Run(string[] args)
+ {
+ Console.WriteLine("Jackett Updater v" + GetCurrentVersion());
+ Console.WriteLine("Waiting for Jackett to close..");
+ Thread.Sleep(2000);
+
+ try {
+ var options = new UpdaterConsoleOptions();
+ if (Parser.Default.ParseArguments(args, options))
+ {
+ ProcessUpdate(options);
+ }
+ else
+ {
+ Console.WriteLine("Failed to process update arguments!: " + string.Join(" ", args));
+ Console.ReadKey();
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Exception applying update: " + e.Message);
+ Console.ReadKey();
+ }
+ }
+
+ private string GetCurrentVersion()
+ {
+ var assembly = System.Reflection.Assembly.GetExecutingAssembly();
+ var fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
+ return fvi.FileVersion;
+ }
+
+ private void ProcessUpdate(UpdaterConsoleOptions options)
+ {
+ var updateLocation = GetUpdateLocation();
+ if(!(updateLocation.EndsWith("\\") || updateLocation.EndsWith("/")))
+ {
+ updateLocation += Path.DirectorySeparatorChar;
+ }
+
+ var isWindows = System.Environment.OSVersion.Platform != PlatformID.Unix;
+ var trayRunning = false;
+ var trayProcesses = Process.GetProcessesByName("JackettTray.exe");
+ if (isWindows)
+ {
+ if (trayProcesses.Count() > 0)
+ {
+ foreach (var proc in trayProcesses)
+ {
+ try
+ {
+ Console.WriteLine("Killing tray process " + proc.Id);
+ proc.Kill();
+ trayRunning = true;
+ }
+ catch { }
+ }
+ }
+ }
+
+ var files = Directory.GetFiles(updateLocation, "*.*", SearchOption.AllDirectories);
+ foreach(var file in files)
+ {
+ var fileName = Path.GetFileName(file).ToLowerInvariant();
+
+ if (fileName.EndsWith(".zip") ||
+ fileName.EndsWith(".tar") ||
+ fileName.EndsWith(".gz"))
+ {
+ continue;
+ }
+
+ Console.WriteLine("Copying " + fileName);
+ var dest = Path.Combine(options.Path, file.Substring(updateLocation.Length));
+ File.Copy(file, dest, true);
+ }
+
+ if (trayRunning)
+ {
+ var startInfo = new ProcessStartInfo()
+ {
+ Arguments = options.Args,
+ FileName = Path.Combine(options.Path, "JackettTray.exe"),
+ UseShellExecute = true
+ };
+
+ Process.Start(startInfo);
+ }
+
+ if(string.Equals(options.Type, "JackettService.exe", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var serviceHelper = new ServiceConfigService(null, null);
+ if (serviceHelper.ServiceExists())
+ {
+ serviceHelper.Start();
+ }
+ } else
+ {
+ var startInfo = new ProcessStartInfo()
+ {
+ Arguments = options.Args,
+ FileName = Path.Combine(options.Path, "JackettConsole.exe"),
+ UseShellExecute = true
+ };
+
+ if (!isWindows)
+ {
+ startInfo.Arguments = startInfo.FileName + " " + startInfo.Arguments;
+ startInfo.FileName = "mono";
+ }
+
+ Process.Start(startInfo);
+ }
+ }
+
+ private string GetUpdateLocation()
+ {
+ var location = new Uri(Assembly.GetEntryAssembly().GetName().CodeBase);
+ return new FileInfo(location.AbsolutePath).DirectoryName;
+ }
+ }
+}
diff --git a/src/Jackett.Updater/Properties/AssemblyInfo.cs b/src/Jackett.Updater/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..a8201c4ad
--- /dev/null
+++ b/src/Jackett.Updater/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.Updater")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Jackett.Updater")]
+[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("a61e311a-6f8b-4497-b5e4-2ea8994c7bd8")]
+
+// 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("0.0.0.0")]
+[assembly: AssemblyFileVersion("0.0.0.0")]
diff --git a/src/Jackett.Updater/UpdaterConsoleOptions.cs b/src/Jackett.Updater/UpdaterConsoleOptions.cs
new file mode 100644
index 000000000..8c9703545
--- /dev/null
+++ b/src/Jackett.Updater/UpdaterConsoleOptions.cs
@@ -0,0 +1,21 @@
+using CommandLine;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Updater
+{
+ public class UpdaterConsoleOptions
+ {
+ [Option('p', "Path", HelpText = "Install location")]
+ public string Path { get; set; }
+
+ [Option('t', "Type", HelpText = "Install type")]
+ public string Type { get; set; }
+
+ [Option('a', "Args", HelpText = "Launch arguments")]
+ public string Args { get; set; }
+ }
+}
diff --git a/src/Jackett.Updater/jackett.ico b/src/Jackett.Updater/jackett.ico
new file mode 100644
index 000000000..6392acc61
Binary files /dev/null and b/src/Jackett.Updater/jackett.ico differ
diff --git a/src/Jackett.Updater/packages.config b/src/Jackett.Updater/packages.config
new file mode 100644
index 000000000..b5bfd259a
--- /dev/null
+++ b/src/Jackett.Updater/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Jackett.sln b/src/Jackett.sln
index 587f30ce4..8f4da4b26 100644
--- a/src/Jackett.sln
+++ b/src/Jackett.sln
@@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett.Distribution", "Jac
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Website", "Website\Website.csproj", "{6B6AB1B0-5ABD-4696-A3D2-70E991174625}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett.Updater", "Jackett.Updater\Jackett.Updater.csproj", "{A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -65,6 +67,10 @@ Global
{6B6AB1B0-5ABD-4696-A3D2-70E991174625}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B6AB1B0-5ABD-4696-A3D2-70E991174625}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B6AB1B0-5ABD-4696-A3D2-70E991174625}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Jackett/Content/custom.css b/src/Jackett/Content/custom.css
index d576a4607..013b4cbd7 100644
--- a/src/Jackett/Content/custom.css
+++ b/src/Jackett/Content/custom.css
@@ -220,7 +220,7 @@ hr {
text-align: center;
}
-#jackett-allowext {
+#jackett-allowext, #jackett-allowupdate {
width: 25px;
}
diff --git a/src/Jackett/Content/custom.js b/src/Jackett/Content/custom.js
index fa026e9c1..aa31c6060 100644
--- a/src/Jackett/Content/custom.js
+++ b/src/Jackett/Content/custom.js
@@ -24,6 +24,7 @@ function loadJackettSettings() {
$("#jackett-port").val(data.config.port);
$("#jackett-savedir").val(data.config.blackholedir);
$("#jackett-allowext").attr('checked', data.config.external);
+ $("#jackett-allowupdate").attr('checked', data.config.updatedisabled);
var password = data.config.password;
$("#jackett-adminpwd").val(password);
if (password != null && password != '') {
@@ -544,9 +545,11 @@ function bindUIButtons() {
$("#change-jackett-port").click(function () {
var jackett_port = $("#jackett-port").val();
var jackett_external = $("#jackett-allowext").is(':checked');
+ var jackett_update = $("#jackett-allowupdate").is(':checked');
var jsonObject = {
port: jackett_port,
external: jackett_external,
+ updatedisabled: jackett_update,
blackholedir: $("#jackett-savedir").val()
};
var jqxhr = $.post("/admin/set_config", JSON.stringify(jsonObject), function (data) {
@@ -570,6 +573,19 @@ function bindUIButtons() {
});
});
+ $("#trigger-updater").click(function () {
+ var jqxhr = $.get("/admin/trigger_update", function (data) {
+ if (data.result == "error") {
+ doNotify("Error: " + data.error, "danger", "glyphicon glyphicon-alert");
+ return;
+ } else {
+ doNotify("Updater triggered see log for details..", "success", "glyphicon glyphicon-ok");
+ }
+ }).fail(function () {
+ doNotify("Request to Jackett server failed", "danger", "glyphicon glyphicon-alert");
+ });
+ });
+
$("#change-jackett-password").click(function () {
var password = $("#jackett-adminpwd").val();
var jsonObject = { password: password };
diff --git a/src/Jackett/Content/index.html b/src/Jackett/Content/index.html
index fdaaf9996..712fc02cf 100644
--- a/src/Jackett/Content/index.html
+++ b/src/Jackett/Content/index.html
@@ -61,7 +61,7 @@
Jackett Configuration
-
+
+
+
+
+
+