From 6c466a8bb8fe43ff4ca4426c3049972fe4f0826f Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Wed, 3 Jan 2024 13:12:04 +0100 Subject: [PATCH] Implemented automatic updating --- manager/javascripts/popup.js | 6 +- manager/javascripts/preload.js | 144 ++++++++++++++++++++++++++++++++- manager/package.json | 3 + manager/stylesheets/style.css | 2 +- 4 files changed, 150 insertions(+), 5 deletions(-) diff --git a/manager/javascripts/popup.js b/manager/javascripts/popup.js index 7e5bbb65..143adbd4 100644 --- a/manager/javascripts/popup.js +++ b/manager/javascripts/popup.js @@ -13,7 +13,7 @@ function showErrorPopup(message, onCloseCallback) { if (onCloseCallback) onCloseCallback(); } - document.getElementById("popup").querySelector(".content").innerText = message; + document.getElementById("popup").querySelector(".content").innerHTML = message; } function showWaitPopup(message) { @@ -24,7 +24,7 @@ function showWaitPopup(message) { document.getElementById("popup").querySelector(".confirm").classList.add("hide"); document.getElementById("popup").querySelector(".close-popup").classList.add("hide"); document.getElementById("popup").querySelector(".accept-popup").classList.add("hide"); - document.getElementById("popup").querySelector(".content").innerText = message; + document.getElementById("popup").querySelector(".content").innerHTML = message; } function showConfirmPopup(message, onAcceptCallback, onCloseCallback) { @@ -50,7 +50,7 @@ function showConfirmPopup(message, onAcceptCallback, onCloseCallback) { onAcceptCallback(); } - document.getElementById("popup").querySelector(".content").innerText = message; + document.getElementById("popup").querySelector(".content").innerHTML = message; } function hidePopup() { diff --git a/manager/javascripts/preload.js b/manager/javascripts/preload.js index 521c566e..461a0fc2 100644 --- a/manager/javascripts/preload.js +++ b/manager/javascripts/preload.js @@ -2,7 +2,148 @@ const Manager = require('./manager'); const contextBridge = require('electron').contextBridge; const ipcRenderer = require('electron').ipcRenderer; -const { exec } = require("child_process"); +const { exec, spawn } = require("child_process"); +const { showConfirmPopup, showWaitPopup, showErrorPopup } = require('./popup'); +const path = require('path'); +const os = require('os'); +const https = require('follow-redirects').https; +const fs = require('fs'); +const AdmZip = require("adm-zip"); +const { Octokit } = require('octokit'); + +const VERSION = "v2.0.0"; +function checkVersion() { + /* Check if we are running the latest version */ + const request = new Request("https://raw.githubusercontent.com/Pax1601/DCSOlympus/release-candidate/version.json"); + fetch(request).then((response) => { + if (response.status === 200) { + return response.json(); + } else { + throw new Error("Error connecting to Github to retrieve latest version"); + } + }).then((res) => { + if (VERSION.includes("OLYMPUS_VERSION_NUMBER")) { + console.log("Development build detected, skipping version checks...") + } else { + var reg1 = res["version"].match(/\d+/g).map((str) => { return Number(str) }); + var reg2 = VERSION.match(/\d+/g).map((str) => { return Number(str) }); + + if (reg1[0] > reg2[0] || (reg1[0] == reg2[0] && reg1[1] > reg2[1]) || (reg1[0] == reg2[0] && reg1[1] == reg2[1] && reg1[2] > reg2[2])) { + console.log(`New version available: ${res["version"]}`); + showConfirmPopup(`You are currently running DCS Olympus ${VERSION}, but ${res["version"]} is available. Do you want to update DCS Olympus automatically?
Note: DCS and Olympus MUST be stopped before proceeding.
`, + () => { + updateOlympus(res["package"]); + }, () => { + console.log("Update canceled"); + }) + } + else if (reg2[0] > reg1[0] || (reg2[0] == reg1[0] && reg2[1] > reg1[1]) || (reg2[0] == reg1[0] && reg2[1] == reg1[1] && reg2[2] > reg1[2])) { + console.log(`Beta version detected: ${res["version"]}`); + showConfirmPopup(`You are currently running DCS Olympus ${VERSION}, which is newer than the latest release version. Do you want to download the latest beta version?
Note: DCS and Olympus MUST be stopped before proceeding.
`, + () => { + betaUpdateOlympus(); + }, () => { + console.log("Update canceled"); + }) + } + } + }) +} + +async function betaUpdateOlympus() { + const octokit = new Octokit({}); + + const res = await octokit.request('GET /repos/{owner}/{repo}/actions/artifacts', { + owner: 'Pax1601', + repo: 'DCSOlympus', + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + + const artifacts = res.data.artifacts; + var artifact = artifacts.find((artifact) => { return artifact.name = "development_build_not_a_release" }); + + showConfirmPopup(`Latest beta artifact has a timestamp of ${artifact.updated_at}. Do you want to continue?`, () => { + exec(`start https://github.com/Pax1601/DCSOlympus/actions/runs/${artifact.workflow_run.id}/artifacts/${artifact.id}`) + showConfirmPopup('A browser window was opened to download the beta artifact. Please wait for the download to complete, then press "Accept" and select the downloaded beta artifact.', + () => { + var input = document.createElement('input'); + input.type = 'file'; + input.click(); + input.onchange = e => { + console.log(e.target.files[0]); + updateOlympus(e.target.files[0]) + } + }, + () => { + console.log("Update canceled"); + }); + }, + () => { + console.log("Update canceled"); + }) +} + +function updateOlympus(location) { + showWaitPopup("Please wait while Olympus is being updated. The Manager will be closed and reopened automatically when updating is completed.") + if (typeof location === "string") { + console.log(`Updating Olympus with package from ${location}`) + } else { + console.log(`Updating Olympus with package from ${location.path}`) + } + + let tmpDir; + const appPrefix = 'dcs-olympus-'; + try { + const folder = path.join(os.tmpdir(), appPrefix); + tmpDir = fs.mkdtempSync(folder); + + if (typeof location === "string") { + const file = fs.createWriteStream(path.join(tmpDir, "temp.zip")); + console.log(`Downloading update package in ${path.join(tmpDir, "temp.zip")}`) + const request = https.get(location, (response) => { + response.pipe(file); + + // after download completed close filestream + file.on("finish", () => { + file.close(); + console.log("Download completed"); + extractAndCopy(tmpDir); + + }); + file.on("error", (err) => { + file.close(); + console.error(err); + }) + }); + } else { + fs.copyFileSync(location.path, path.join(tmpDir, "temsp.zip")); + extractAndCopy(tmpDir); + } + } + catch (err) { + showErrorPopup("An error has occurred while updating Olympus. Please delete Olympus and update it manually. A browser window will open automatically on the download page.", () => { + exec(`start https://github.com/Pax1601/DCSOlympus/releases`, () => { + ipcRenderer.send('window:close'); + }) + }) + console.error(err) + } +} + +function extractAndCopy(folder) { + const zip = new AdmZip(path.join(folder, "temp.zip")); + zip.extractAllTo(path.join(folder, "temp")); + + fs.writeFileSync(path.join(folder, 'update.bat'), + `timeout /t 5 \nrmdir "${path.join(__dirname, "..", "..")}" /s /q \necho D|xcopy /Y /S /E "${path.join(folder, "temp")}" "${path.join(__dirname, "..", "..")}" \ncd "${path.join(__dirname, "..", "..")}" \ninstall.bat` + ) + + var proc = spawn('cmd.exe', ["/c", path.join(folder, 'update.bat')], { cwd: folder, shell: true, detached: true }); + proc.unref(); + ipcRenderer.send('window:close'); +} /* White-listed channels. */ const ipc = { @@ -69,6 +210,7 @@ window.addEventListener('DOMContentLoaded', async () => { } }) +checkVersion(); window.addEventListener('resize', () => { computePagesHeight(); }) diff --git a/manager/package.json b/manager/package.json index 7d7e524e..1c7a7296 100644 --- a/manager/package.json +++ b/manager/package.json @@ -9,11 +9,14 @@ "author": "", "license": "ISC", "dependencies": { + "adm-zip": "^0.5.10", "create-desktop-shortcuts": "^1.10.1", "dir-compare": "^4.2.0", "ejs": "^3.1.9", "electron": "^28.0.0", "find-process": "^1.4.7", + "follow-redirects": "^1.15.4", + "octokit": "^3.1.2", "portfinder": "^1.0.32", "regedit": "^5.1.2", "sha256": "^0.2.0", diff --git a/manager/stylesheets/style.css b/manager/stylesheets/style.css index 27b01838..a5b139ed 100644 --- a/manager/stylesheets/style.css +++ b/manager/stylesheets/style.css @@ -311,7 +311,7 @@ input { font-weight: 600; width: 100%; text-align: left; - padding: 0px !important; + padding: 15px 0px !important; } #popup .footer {