aboutsummaryrefslogtreecommitdiff
path: root/src/modules/update.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/update.js')
-rw-r--r--src/modules/update.js239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/modules/update.js b/src/modules/update.js
new file mode 100644
index 0000000..cfdb42b
--- /dev/null
+++ b/src/modules/update.js
@@ -0,0 +1,239 @@
+const path = require("path");
+const fs = require("fs-extra");
+const { ipcMain, Notification } = require("electron");
+
+const cli = require("../cli");
+const lang = require("../lang");
+
+const win = require("./window");
+const version = require("./version");
+const settings = require("./settings");
+const requests = require("./requests");
+const gamepath = require("./gamepath");
+const is_running = require("./is_running");
+
+const unzip = require("unzipper");
+const { https } = require("follow-redirects");
+
+let update = {};
+
+// renames excluded files to their original name
+function restore_excluded_files() {
+ if (! gamepath.exists()) {return}
+
+ for (let i = 0; i < settings.excludes.length; i++) {
+ let exclude = path.join(settings.gamepath + "/" + settings.excludes[i]);
+ if (fs.existsSync(exclude + ".excluded")) {
+ fs.renameSync(exclude + ".excluded", exclude);
+ }
+ }
+}; restore_excluded_files();
+
+// renames excluded files to <file>.excluded, the list of files to be
+// exluded is set in the settings (settings.excludes)
+function exclude_files() {
+ for (let i = 0; i < settings.excludes.length; i++) {
+ let exclude = path.join(settings.gamepath + "/" + settings.excludes[i]);
+ if (fs.existsSync(exclude)) {
+ fs.renameSync(exclude, exclude + ".excluded");
+ }
+ }
+}
+
+// whether update.northstar_auto_update() has already been run before
+let is_auto_updating = false;
+
+// Handles auto updating Northstar.
+//
+// It uses isGameRunning() to ensure it doesn't run while the game is
+// running, as that may have all kinds of issues.
+update.northstar_autoupdate = () => {
+ if (! settings.nsupdate || ! fs.existsSync("viper.json") || settings.gamepath.length === 0) {
+ return;
+ }
+
+ if (is_auto_updating) {return}
+
+ async function _checkForUpdates() {
+ is_auto_updating = true;
+
+ console.log(lang("cli.autoupdates.checking"));
+
+ // Checks if NS is outdated
+ if (await northstar_update_available()) {
+ console.log(lang("cli.autoupdates.available"));
+ if (await is_running.game()) {
+ console.log(lang("cli.autoupdates.gamerunning"));
+ new Notification({
+ title: lang("gui.nsupdate.gaming.title"),
+ body: lang("gui.nsupdate.gaming.body")
+ }).show();
+ } else {
+ console.log(lang("cli.autoupdates.updatingns"));
+ update.northstar();
+ }
+ } else {
+ console.log(lang("cli.autoupdates.noupdate"));
+ }
+
+ setTimeout(
+ _checkForUpdates,
+ 15 * 60 * 1000
+ // interval in between each update check
+ // by default 15 minutes.
+ );
+ }
+
+ _checkForUpdates();
+}
+
+// returns whether an update is available for Northstar
+async function northstar_update_available() {
+ let local = version.northstar();
+ let distant = await requests.getLatestNsVersion();
+
+ if (distant == false) {
+ return false;
+ }
+
+ // checks if NS is outdated
+ if (local !== distant) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// Updates Viper itself
+//
+// This uses electron updater to easily update and publish releases, it
+// simply fetches it from GitHub and updates if it's outdated, very
+// useful. Not much we have to do on our side.
+update.viper = (autoinstall) => {
+ const { autoUpdater } = require("electron-updater");
+
+ if (! autoUpdater.isUpdaterActive()) {
+ if (settings.nsupdate) {
+ update.northstar_autoupdate();
+ }
+
+ return cli.exit();
+ }
+
+ if (autoinstall) {
+ autoUpdater.on("update-downloaded", (info) => {
+ autoUpdater.quitAndInstall();
+ });
+ }
+
+ autoUpdater.on("error", (info) => {cli.exit(1)});
+ autoUpdater.on("update-not-available", (info) => {
+ // only check for NS updates if Viper itself has no updates and
+ // if NS auto updates is enabled.
+ if (settings.nsupdate || cli.hasArgs()) {
+ update.northstar_autoupdate();
+ }
+ cli.exit();
+ });
+
+ autoUpdater.checkForUpdatesAndNotify();
+}
+
+// Installs/Updates Northstar
+//
+// If Northstar is already installed it'll be an update, otherwise it'll
+// install it. It simply downloads the Northstar archive from GitHub, if
+// it's outdated, then extracts it into the game path.
+//
+// As to handle not overwriting files we rename certain files to
+// <file>.excluded, then rename them back after the extraction. The
+// unzip module does not support excluding files directly.
+update.northstar = async () => {
+ if (await is_running.game()) {
+ console.log(lang("cli.autoupdates.gamerunning"));
+ return false;
+ }
+
+ if (! gamepath.exists()) {return}
+
+ ipcMain.emit("ns-update-event", "cli.update.checking");
+ console.log(lang("cli.update.checking"));
+ let ns_version = version.northstar();
+
+ const latest_version = await requests.getLatestNsVersion();
+ console.log(latest_version)
+ if (latest_version == false) {
+ ipcMain.emit("ns-update-event", "cli.update.noInternet");
+ return;
+ }
+
+ // Makes sure it is not already the latest version
+ if (! await northstar_update_available()) {
+ ipcMain.emit("ns-update-event", "cli.update.uptodate.short");
+ console.log(lang("cli.update.uptodate"), ns_version);
+
+ win.log(lang("gui.update.uptodate"));
+ cli.exit();
+ return;
+ } else {
+ if (ns_version != "unknown") {
+ console.log(lang("cli.update.current"), ns_version);
+ };
+
+ console.log(lang("cli.update.downloading") + ":", latest_version);
+ ipcMain.emit("ns-update-event", "cli.update.downloading");
+ }
+
+ exclude_files();
+
+ // Start the download of the zip
+ https.get(requests.getLatestNsVersionLink(), (res) => {
+ let stream = fs.createWriteStream(settings.zip);
+ res.pipe(stream);
+
+ let received = 0;
+ // Progress messages, we should probably switch this to
+ // percentage instead of how much is downloaded.
+ res.on("data", (chunk) => {
+ received += chunk.length;
+ ipcMain.emit("ns-update-event", lang("gui.update.downloading") + " " + (received / 1024 / 1024).toFixed(1) + "mb");
+ })
+
+ stream.on("finish", () => {
+ stream.close();
+ let extract = fs.createReadStream(settings.zip);
+
+ win.log(lang("gui.update.extracting"));
+ ipcMain.emit("ns-update-event", "gui.update.extracting");
+ console.log(lang("cli.update.downloaddone"));
+ // Extracts the zip, this is the part where we're actually
+ // installing Northstar.
+ extract.pipe(unzip.Extract({path: settings.gamepath}))
+
+ let max = received;
+ received = 0;
+
+ extract.on("data", (chunk) => {
+ received += chunk.length;
+ let percent = Math.floor(received / max * 100);
+ ipcMain.emit("ns-update-event", lang("gui.update.extracting") + " " + percent + "%");
+ })
+
+ extract.on("end", () => {
+ extract.close();
+ ipcMain.emit("getversion");
+
+ restore_excluded_files();
+
+ ipcMain.emit("gui-getmods");
+ ipcMain.emit("get-version");
+ ipcMain.emit("ns-update-event", "cli.update.uptodate.short");
+ win.log(lang("gui.update.finished"));
+ console.log(lang("cli.update.finished"));
+ cli.exit();
+ })
+ })
+ })
+}
+
+module.exports = update;