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

- Admin Password: + Admin password:
+
+ Disable auto update: + + +