Auto update #8

This commit is contained in:
WhatFox 2015-11-09 21:59:16 +00:00
parent 35580224c7
commit a9e14cc4af
21 changed files with 610 additions and 18 deletions

1
.gitignore vendored
View File

@ -196,3 +196,4 @@ FakesAssemblies/
*.opt *.opt
/Build.mono /Build.mono
/Build.windows /Build.windows
/Output

View File

@ -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.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 build.windows\JackettTray.exe
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.windows\JackettTray.exe.config 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 LICENSE build.windows\LICENSE
copy /Y README.md build.windows\README.md 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.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 build.mono\JackettTray.exe
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.mono\JackettTray.exe.config 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 LICENSE build.mono\LICENSE
copy /Y README.md build.mono\README.md copy /Y README.md build.mono\README.md
copy /Y Upstart.config build.mono\Upstart.config copy /Y Upstart.config build.mono\Upstart.config

View File

@ -24,9 +24,10 @@ DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes DisableProgramGroupPage=yes
OutputBaseFilename=setup OutputBaseFilename=setup
SetupIconFile=src\Jackett.Console\jackett.ico SetupIconFile=src\Jackett.Console\jackett.ico
UninstallDisplayIcon={app}\JackettConsole.exe UninstallDisplayIcon={userappdata}\Jackett\JackettConsole.exe
Compression=lzma Compression=lzma
SolidCompression=yes SolidCompression=yes
DisableDirPage=yes
[Languages] [Languages]
Name: "english"; MessagesFile: "compiler:Default.isl" 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 Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files] [Files]
Source: "build.windows\JackettTray.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "build.windows\JackettTray.exe"; DestDir: "{userappdata}\Jackett"; Flags: ignoreversion
Source: "build.windows\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 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 ; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons] [Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" Name: "{group}\{#MyAppName}"; Filename: "{userappdata}\Jackett\{#MyAppExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" 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] [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] [Run]
Filename: "{app}\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated; Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated;
Filename: "{app}\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated; Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated;
Filename: "{app}\JackettConsole.exe"; Parameters: "--MigrateSettings"; Flags: waituntilterminated; Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--MigrateSettings"; Flags: waituntilterminated;
Filename: "{app}\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated; Tasks: windowsService Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated; Tasks: windowsService
Filename: "{app}\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated; Tasks: windowsService Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated; Tasks: windowsService
[UninstallRun] [UninstallRun]
Filename: "{app}\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist Filename: "{userappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Jackett.Updater</RootNamespace>
<AssemblyName>JackettUpdater</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>jackett.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="CommandLine, Version=1.9.71.2, Culture=neutral, PublicKeyToken=de6f01bd326f8c32, processorArchitecture=MSIL">
<HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.0\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UpdaterConsoleOptions.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Jackett\Jackett.csproj">
<Project>{e636d5f8-68b4-4903-b4ed-ccfd9c9e899f}</Project>
<Name>Jackett</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="jackett.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -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;
}
}
}

View File

@ -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")]

View File

@ -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; }
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommandLineParser" version="1.9.71" targetFramework="net45" />
<package id="NLog" version="4.2.0" targetFramework="net45" />
</packages>

View File

@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett.Distribution", "Jac
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Website", "Website\Website.csproj", "{6B6AB1B0-5ABD-4696-A3D2-70E991174625}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Website", "Website\Website.csproj", "{6B6AB1B0-5ABD-4696-A3D2-70E991174625}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett.Updater", "Jackett.Updater\Jackett.Updater.csproj", "{A61E311A-6F8B-4497-B5E4-2EA8994C7BD8}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{6B6AB1B0-5ABD-4696-A3D2-70E991174625}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -220,7 +220,7 @@ hr {
text-align: center; text-align: center;
} }
#jackett-allowext { #jackett-allowext, #jackett-allowupdate {
width: 25px; width: 25px;
} }

View File

@ -24,6 +24,7 @@ function loadJackettSettings() {
$("#jackett-port").val(data.config.port); $("#jackett-port").val(data.config.port);
$("#jackett-savedir").val(data.config.blackholedir); $("#jackett-savedir").val(data.config.blackholedir);
$("#jackett-allowext").attr('checked', data.config.external); $("#jackett-allowext").attr('checked', data.config.external);
$("#jackett-allowupdate").attr('checked', data.config.updatedisabled);
var password = data.config.password; var password = data.config.password;
$("#jackett-adminpwd").val(password); $("#jackett-adminpwd").val(password);
if (password != null && password != '') { if (password != null && password != '') {
@ -544,9 +545,11 @@ function bindUIButtons() {
$("#change-jackett-port").click(function () { $("#change-jackett-port").click(function () {
var jackett_port = $("#jackett-port").val(); var jackett_port = $("#jackett-port").val();
var jackett_external = $("#jackett-allowext").is(':checked'); var jackett_external = $("#jackett-allowext").is(':checked');
var jackett_update = $("#jackett-allowupdate").is(':checked');
var jsonObject = { var jsonObject = {
port: jackett_port, port: jackett_port,
external: jackett_external, external: jackett_external,
updatedisabled: jackett_update,
blackholedir: $("#jackett-savedir").val() blackholedir: $("#jackett-savedir").val()
}; };
var jqxhr = $.post("/admin/set_config", JSON.stringify(jsonObject), function (data) { 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 () { $("#change-jackett-password").click(function () {
var password = $("#jackett-adminpwd").val(); var password = $("#jackett-adminpwd").val();
var jsonObject = { password: password }; var jsonObject = { password: password };

View File

@ -61,7 +61,7 @@
<hr /> <hr />
<h3>Jackett Configuration</h3> <h3>Jackett Configuration</h3>
<div class="input-area"> <div class="input-area">
<span class="input-header">Admin Password: </span> <span class="input-header">Admin password: </span>
<input id="jackett-adminpwd" class="form-control input-right" type="password" value="" placeholder="Blank to disable" /> <input id="jackett-adminpwd" class="form-control input-right" type="password" value="" placeholder="Blank to disable" />
<button id="change-jackett-password" class="btn btn-primary btn-sm"> <button id="change-jackett-password" class="btn btn-primary btn-sm">
<i class="fa fa-user-secret"></i> Set Password <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span> <i class="fa fa-user-secret"></i> Set Password <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
@ -88,6 +88,13 @@
<span class="input-header">External access: </span> <span class="input-header">External access: </span>
<input id="jackett-allowext" class="form-control input-right" type="checkbox" /> <input id="jackett-allowext" class="form-control input-right" type="checkbox" />
</div> </div>
<div class="input-area">
<span class="input-header">Disable auto update: </span>
<input id="jackett-allowupdate" class="form-control input-right" type="checkbox" />
<button id="trigger-updater" class="btn btn-warning btn-sm">
<i class="fa fa-wrench"></i> Check for updates <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
</button>
</div>
<hr /> <hr />
<div id="footer"> <div id="footer">
Jackett Version <span id="app-version"></span> Jackett Version <span id="app-version"></span>

View File

@ -39,8 +39,9 @@ namespace Jackett.Controllers
private ICacheService cacheService; private ICacheService cacheService;
private Logger logger; private Logger logger;
private ILogCacheService logCache; private ILogCacheService logCache;
private IUpdateService updater;
public AdminController(IConfigurationService config, IIndexerManagerService i, IServerService ss, ISecuityService s, IProcessService p, ICacheService c, Logger l, ILogCacheService lc) public AdminController(IConfigurationService config, IIndexerManagerService i, IServerService ss, ISecuityService s, IProcessService p, ICacheService c, Logger l, ILogCacheService lc, IUpdateService u)
{ {
this.config = config; this.config = config;
indexerService = i; indexerService = i;
@ -50,6 +51,7 @@ namespace Jackett.Controllers
cacheService = c; cacheService = c;
logger = l; logger = l;
logCache = lc; logCache = lc;
updater = u;
} }
private async Task<JToken> ReadPostDataJson() private async Task<JToken> ReadPostDataJson()
@ -291,6 +293,15 @@ namespace Jackett.Controllers
return Json(jsonReply); return Json(jsonReply);
} }
[Route("trigger_update")]
[HttpGet]
public IHttpActionResult TriggerUpdates()
{
var jsonReply = new JObject();
updater.CheckForUpdatesNow();
return Json(jsonReply);
}
[Route("get_jackett_config")] [Route("get_jackett_config")]
[HttpGet] [HttpGet]
public IHttpActionResult GetConfig() public IHttpActionResult GetConfig()
@ -303,6 +314,7 @@ namespace Jackett.Controllers
cfg["external"] = serverService.Config.AllowExternal; cfg["external"] = serverService.Config.AllowExternal;
cfg["api_key"] = serverService.Config.APIKey; cfg["api_key"] = serverService.Config.APIKey;
cfg["blackholedir"] = serverService.Config.BlackholeDir; cfg["blackholedir"] = serverService.Config.BlackholeDir;
cfg["updatedisabled"] = serverService.Config.UpdateDisabled;
cfg["password"] = string.IsNullOrEmpty(serverService.Config.AdminPassword) ? string.Empty : serverService.Config.AdminPassword.Substring(0, 10); cfg["password"] = string.IsNullOrEmpty(serverService.Config.AdminPassword) ? string.Empty : serverService.Config.AdminPassword.Substring(0, 10);
jsonReply["config"] = cfg; jsonReply["config"] = cfg;
@ -331,8 +343,9 @@ namespace Jackett.Controllers
int port = (int)postData["port"]; int port = (int)postData["port"];
bool external = (bool)postData["external"]; bool external = (bool)postData["external"];
string saveDir = (string)postData["blackholedir"]; string saveDir = (string)postData["blackholedir"];
bool updateDisabled = (bool)postData["updatedisabled"];
if (port != Engine.Server.Config.Port || external != Engine.Server.Config.AllowExternal) if (port != Engine.Server.Config.Port || external != Engine.Server.Config.AllowExternal || Engine.Server.Config.UpdateDisabled != updateDisabled)
{ {
if (ServerUtil.RestrictedPorts.Contains(port)) if (ServerUtil.RestrictedPorts.Contains(port))
{ {
@ -344,6 +357,7 @@ namespace Jackett.Controllers
// Save port to the config so it can be picked up by the if needed when running as admin below. // Save port to the config so it can be picked up by the if needed when running as admin below.
Engine.Server.Config.AllowExternal = external; Engine.Server.Config.AllowExternal = external;
Engine.Server.Config.Port = port; Engine.Server.Config.Port = port;
Engine.Server.Config.UpdateDisabled = updateDisabled;
Engine.Server.SaveConfig(); Engine.Server.SaveConfig();
// On Windows change the url reservations // On Windows change the url reservations

View File

@ -82,6 +82,10 @@
<HintPath>..\packages\CsQuery.1.3.4\lib\net40\CsQuery.dll</HintPath> <HintPath>..\packages\CsQuery.1.3.4\lib\net40\CsQuery.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath> <HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -126,6 +130,10 @@
<HintPath>..\packages\NLog.Windows.Forms.4.0\lib\net35\NLog.Windows.Forms.dll</HintPath> <HintPath>..\packages\NLog.Windows.Forms.4.0\lib\net35\NLog.Windows.Forms.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Octokit, Version=0.16.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Octokit.0.16.0\lib\net45\Octokit.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL"> <Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath> <HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -262,6 +270,7 @@
<Compile Include="Services\CacheService.cs" /> <Compile Include="Services\CacheService.cs" />
<Compile Include="Services\LogCacheService.cs" /> <Compile Include="Services\LogCacheService.cs" />
<Compile Include="Services\ProtectionService.cs" /> <Compile Include="Services\ProtectionService.cs" />
<Compile Include="Services\UpdateService.cs" />
<Compile Include="Utils\Clients\BaseWebResult.cs" /> <Compile Include="Utils\Clients\BaseWebResult.cs" />
<Compile Include="Utils\Clients\UnixLibCurlWebClient.cs" /> <Compile Include="Utils\Clients\UnixLibCurlWebClient.cs" />
<Compile Include="Utils\Clients\WebByteResult.cs" /> <Compile Include="Utils\Clients\WebByteResult.cs" />

View File

@ -21,6 +21,9 @@ namespace Jackett.Models.Config
public string AdminPassword { get; set; } public string AdminPassword { get; set; }
public string InstanceId { get; set; } public string InstanceId { get; set; }
public string BlackholeDir { get; set; } public string BlackholeDir { get; set; }
public string GitHubUsername { get; set; }
public string GitHubPassword { get; set; }
public bool UpdateDisabled { get; set; }
public string[] GetListenAddresses(bool? external = null) public string[] GetListenAddresses(bool? external = null)
{ {

View File

@ -47,8 +47,9 @@ namespace Jackett.Services
private IConfigurationService configService; private IConfigurationService configService;
private Logger logger; private Logger logger;
private IWebClient client; private IWebClient client;
private IUpdateService updater;
public ServerService(IIndexerManagerService i, IProcessService p, ISerializeService s, IConfigurationService c, Logger l, IWebClient w) public ServerService(IIndexerManagerService i, IProcessService p, ISerializeService s, IConfigurationService c, Logger l, IWebClient w, IUpdateService u)
{ {
indexerService = i; indexerService = i;
processService = p; processService = p;
@ -56,6 +57,7 @@ namespace Jackett.Services
configService = c; configService = c;
logger = l; logger = l;
client = w; client = w;
updater = u;
LoadConfig(); LoadConfig();
} }
@ -139,6 +141,7 @@ namespace Jackett.Services
config.GetListenAddresses().ToList().ForEach(u => startOptions.Urls.Add(u)); config.GetListenAddresses().ToList().ForEach(u => startOptions.Urls.Add(u));
_server = WebApp.Start<Startup>(startOptions); _server = WebApp.Start<Startup>(startOptions);
logger.Debug("Web server started"); logger.Debug("Web server started");
updater.StartUpdateChecker();
} }
public void ReserveUrls(bool doInstall = true) public void ReserveUrls(bool doInstall = true)

View File

@ -22,7 +22,7 @@ namespace Jackett.Services
void Stop(); void Stop();
} }
class ServiceConfigService : IServiceConfigService public class ServiceConfigService : IServiceConfigService
{ {
private const string NAME = "Jackett"; private const string NAME = "Jackett";
private const string DESCRIPTION = "Additional indexers for Sonarr"; private const string DESCRIPTION = "Additional indexers for Sonarr";

View File

@ -0,0 +1,207 @@
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;
using Jackett.Models.Config;
using Jackett.Utils.Clients;
using NLog;
using Octokit;
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.Services
{
public interface IUpdateService
{
void StartUpdateChecker();
void CheckForUpdatesNow();
}
public class UpdateService: IUpdateService
{
Logger logger;
IWebClient client;
IConfigurationService configService;
ManualResetEvent locker = new ManualResetEvent(false);
public UpdateService(Logger l, IWebClient c, IConfigurationService cfg)
{
logger = l;
client = c;
configService = cfg;
}
private string ExePath()
{
var location = new Uri(Assembly.GetEntryAssembly().GetName().CodeBase);
return new FileInfo(location.AbsolutePath).FullName;
}
public void StartUpdateChecker()
{
Task.Factory.StartNew(UpdateWorkerThread);
}
public void CheckForUpdatesNow()
{
locker.Set();
}
private async void UpdateWorkerThread()
{
while (true)
{
locker.WaitOne((int)new TimeSpan(24, 0, 0).TotalMilliseconds);
locker.Reset();
await CheckForUpdates();
}
}
private async Task CheckForUpdates()
{
var config = configService.GetConfig<ServerConfig>();
if (config.UpdateDisabled)
{
logger.Info($"Skipping update check as it is disabled.");
return;
}
var isWindows = System.Environment.OSVersion.Platform != PlatformID.Unix;
if (Debugger.IsAttached)
{
logger.Info($"Skipping checking for new releases as the debugger is attached.");
return;
}
try
{
var github = new GitHubClient(new ProductHeaderValue("Jackett"));
if(config!=null && !string.IsNullOrWhiteSpace(config.GitHubUsername))
{
github.Credentials = new Credentials(config.GitHubUsername, config.GitHubPassword);
}
var releases = await github.Release.GetAll("Jackett", "Jackett");
if (releases.Count > 0)
{
var latestRelease = releases.OrderByDescending(o => o.CreatedAt).First();
var currentVersion = $"v{GetCurrentVersion()}";
if (latestRelease.Name != currentVersion && currentVersion != "v0.0.0.0")
{
logger.Info($"New release found. Current: {currentVersion} New: {latestRelease.Name}");
try
{
var tempDir = await DownloadRelease(latestRelease.Name, isWindows);
// Copy updater
var installDir = Path.GetDirectoryName(ExePath());
var updaterPath = Path.Combine(tempDir, "Jackett", "JackettUpdater.exe");
StartUpdate(updaterPath, installDir, isWindows);
}
catch (Exception e)
{
logger.Error(e, "Error performing update.");
}
}
else
{
logger.Info($"Checked for a updated release but none was found.");
}
}
}
catch (Exception e)
{
logger.Error(e, "Error checking for updates.");
}
}
private string GetCurrentVersion()
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
return fvi.FileVersion;
}
private async Task<string> DownloadRelease(string version, bool isWindows)
{
var downloadUrl = $"https://github.com/Jackett/Jackett/releases/download/{version}/";
if (isWindows)
{
downloadUrl += "Jackett.Binaries.Windows.zip";
}
else
{
downloadUrl += "Jackett.Binaries.Mono.tar.gz";
}
var data = await client.GetBytes(new WebRequest() { Url = downloadUrl, EmulateBrowser = true, Type = RequestType.GET });
while (data.IsRedirect)
{
data = await client.GetBytes(new WebRequest() { Url = data.RedirectingTo, EmulateBrowser = true, Type = RequestType.GET });
}
var tempDir = Path.Combine(Path.GetTempPath(), "JackettUpdate-" + version + "-" + DateTime.Now.Ticks);
if (Directory.Exists(tempDir))
{
Directory.Delete(tempDir, true);
}
Directory.CreateDirectory(tempDir);
if (isWindows)
{
var zipPath = Path.Combine(tempDir, "Update.zip");
File.WriteAllBytes(zipPath, data.Content);
var fastZip = new FastZip();
fastZip.ExtractZip(zipPath, tempDir, null);
}
else
{
var gzPath = Path.Combine(tempDir, "Update.tar.gz");
File.WriteAllBytes(gzPath, data.Content);
Stream inStream = File.OpenRead(gzPath);
Stream gzipStream = new GZipInputStream(inStream);
TarArchive tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
tarArchive.ExtractContents(tempDir);
tarArchive.Close();
gzipStream.Close();
inStream.Close();
}
return tempDir;
}
private void StartUpdate(string updaterExePath, string installLocation, bool isWindows)
{
var exe = Path.GetFileName(ExePath()).ToLowerInvariant();
var args = string.Join(" ", Environment.GetCommandLineArgs().Skip(1));
if (!isWindows)
{
// Wrap mono
args = exe + " " + args;
exe = "mono";
}
var startInfo = new ProcessStartInfo()
{
Arguments = $"--Path \"{installLocation}\" --Type \"{exe}\" --Args \"{args}\"",
FileName = Path.Combine(updaterExePath)
};
var procInfo = Process.Start(startInfo);
logger.Info($"Updater started process id: {procInfo.Id}");
Environment.Exit(0);
}
}
}

View File

@ -26,5 +26,7 @@
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="NLog" version="4.2.0" targetFramework="net45" /> <package id="NLog" version="4.2.0" targetFramework="net45" />
<package id="NLog.Windows.Forms" version="4.0" targetFramework="net45" /> <package id="NLog.Windows.Forms" version="4.0" targetFramework="net45" />
<package id="Octokit" version="0.16.0" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" /> <package id="Owin" version="1.0" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
</packages> </packages>