9cb3c79dbe
- Gate electron-updater GitHub provider on launcher_updates_from_github (default false) so GITHUB_TOKEN no longer targets the source repo without latest.yml. - Improve GitHub releases 404 hint when assets are on Gitea. - Document in README and default-launcher.json. Co-authored-by: Cursor <cursoragent@cursor.com>
149 lines
4.5 KiB
JavaScript
149 lines
4.5 KiB
JavaScript
'use strict';
|
|
|
|
const { dialog } = require('electron');
|
|
const { autoUpdater } = require('electron-updater');
|
|
const { useGiteaReleases, getGiteaUpdaterFeedBase } = require('./gitea-release');
|
|
|
|
/**
|
|
* @param {import('electron').App} app
|
|
* @param {() => import('electron').BrowserWindow | null} getMainWindow
|
|
* @param {{
|
|
* updateFeedUrl?: string,
|
|
* githubOwner?: string,
|
|
* githubRepo?: string,
|
|
* githubToken?: string,
|
|
* giteaToken?: string,
|
|
* allowGithubLauncherUpdates?: boolean,
|
|
* config?: object,
|
|
* }} opts
|
|
*/
|
|
async function setupAutoUpdater(app, getMainWindow, opts = {}) {
|
|
if (!app.isPackaged) {
|
|
return {
|
|
checkNow: async () => ({ skipped: true, reason: 'development build' }),
|
|
};
|
|
}
|
|
|
|
const ghToken = String(opts.githubToken || '').trim();
|
|
const giteaTok = String(opts.giteaToken || '').trim();
|
|
const envGeneric = String(process.env.LAUNCHER_UPDATE_URL || '').trim();
|
|
const configGeneric = String(opts.updateFeedUrl || '').trim();
|
|
let genericUrl = envGeneric || configGeneric;
|
|
let genericAuthHeader = '';
|
|
|
|
if (!genericUrl && opts.config && useGiteaReleases(opts.config)) {
|
|
const gfb = await getGiteaUpdaterFeedBase(opts.config);
|
|
if (gfb && gfb.url) {
|
|
genericUrl = gfb.url;
|
|
const t = String(gfb.token || giteaTok || '').trim();
|
|
if (t) genericAuthHeader = `token ${t}`;
|
|
}
|
|
} else if (genericUrl) {
|
|
if (giteaTok) genericAuthHeader = `token ${giteaTok}`;
|
|
else if (ghToken) genericAuthHeader = `Bearer ${ghToken}`;
|
|
}
|
|
|
|
const owner = String(opts.githubOwner || '').trim();
|
|
const repo = String(opts.githubRepo || '').trim();
|
|
|
|
let feedConfigured = false;
|
|
|
|
if (genericUrl) {
|
|
const base = genericUrl.replace(/\/?$/, '/');
|
|
autoUpdater.setFeedURL({
|
|
provider: 'generic',
|
|
url: base,
|
|
});
|
|
if (genericAuthHeader) {
|
|
autoUpdater.requestHeaders = {
|
|
...autoUpdater.requestHeaders,
|
|
Authorization: genericAuthHeader,
|
|
};
|
|
}
|
|
feedConfigured = true;
|
|
} else if (opts.allowGithubLauncherUpdates && ghToken && owner && repo) {
|
|
autoUpdater.setFeedURL({
|
|
provider: 'github',
|
|
owner,
|
|
repo,
|
|
private: true,
|
|
token: ghToken,
|
|
});
|
|
feedConfigured = true;
|
|
}
|
|
|
|
if (!feedConfigured) {
|
|
const reason =
|
|
'No update channel configured. Set launcher.json → update_feed_url (HTTPS folder with latest.yml), ' +
|
|
'or fill gitea.base_url/owner/repo (+ GITEA_TOKEN for private), ' +
|
|
'or set launcher_updates_from_github to true with GITHUB_TOKEN for private GitHub release feeds.';
|
|
return {
|
|
checkNow: async () => ({ skipped: true, reason }),
|
|
};
|
|
}
|
|
|
|
autoUpdater.autoDownload = true;
|
|
autoUpdater.autoInstallOnAppQuit = true;
|
|
|
|
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: 404 (no latest.yml or wrong URL). For Gitea use gitea.* + token, or set update_feed_url. ' +
|
|
'For private GitHub set GITHUB_TOKEN.'
|
|
);
|
|
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 };
|