'use strict'; const { dialog } = require('electron'); const { autoUpdater } = require('electron-updater'); /** * @param {import('electron').App} app * @param {() => import('electron').BrowserWindow | null} getMainWindow * @param {{ updateFeedUrl?: string, githubOwner?: string, githubRepo?: string, token?: string }} opts */ function setupAutoUpdater(app, getMainWindow, opts = {}) { if (!app.isPackaged) { return { checkNow: async () => ({ skipped: true, reason: 'development build' }), }; } autoUpdater.autoDownload = true; autoUpdater.autoInstallOnAppQuit = true; const token = String(opts.token || '').trim(); const envGeneric = String(process.env.LAUNCHER_UPDATE_URL || '').trim(); const configGeneric = String(opts.updateFeedUrl || '').trim(); const genericUrl = envGeneric || configGeneric; const owner = String(opts.githubOwner || 'Dawnforger').trim(); const repo = String(opts.githubRepo || 'Fractured').trim(); if (genericUrl) { const base = genericUrl.replace(/\/?$/, '/'); autoUpdater.setFeedURL({ provider: 'generic', url: base, }); if (token) { autoUpdater.requestHeaders = { ...autoUpdater.requestHeaders, Authorization: `Bearer ${token}`, }; } } else if (token && owner && repo) { autoUpdater.setFeedURL({ provider: 'github', owner, repo, private: true, token, }); } const send = (msg) => { const w = getMainWindow(); if (w && !w.isDestroyed()) { w.webContents.send('launcher:progress', msg); } }; autoUpdater.on('checking-for-update', () => send('Checking for launcher updates…')); autoUpdater.on('update-available', (info) => { send(`Launcher update available: ${info.version}`); }); autoUpdater.on('update-not-available', () => {}); autoUpdater.on('error', (err) => { const m = (err && (err.message || String(err))) || ''; if (/404|releases\.atom|HttpError:\s*404/i.test(m)) { send( 'Launcher update: could not read GitHub releases (404). ' + 'If the repo is private, set GITHUB_TOKEN (or your token_env) so the launcher can authenticate, ' + 'or set update_feed_url in launcher.json to a public HTTPS folder that contains latest.yml.' ); return; } if (m && !/net::ERR|ENOTFOUND|ETIMEDOUT/i.test(m)) { send(`Launcher update: ${m.slice(0, 400)}`); } }); autoUpdater.on('download-progress', (p) => { const pct = Math.round(p.percent || 0); send(`Launcher update download: ${pct}%`); }); autoUpdater.on('update-downloaded', async (info) => { const win = getMainWindow(); const r = await dialog.showMessageBox(win || undefined, { type: 'info', title: 'Launcher update', message: `Version ${info.version} is ready to install.`, detail: 'Restart the launcher now to finish. You can finish patching WoW after restart.', buttons: ['Restart now', 'Later'], defaultId: 0, cancelId: 1, noLink: true, }); if (r.response === 0) { autoUpdater.quitAndInstall(false, true); } }); const checkNow = async () => { const r = await autoUpdater.checkForUpdates(); return { ok: true, updateInfo: r && r.updateInfo }; }; const tick = () => { checkNow().catch(() => {}); }; setTimeout(tick, 5000); setInterval(tick, 6 * 60 * 60 * 1000); return { checkNow }; } module.exports = { setupAutoUpdater };