118 lines
3.5 KiB
JavaScript
118 lines
3.5 KiB
JavaScript
'use strict';
|
|
|
|
const path = require('path');
|
|
const fs = require('fs').promises;
|
|
const { downloadGitHubRepoFile, downloadReleaseAsset } = require('./github');
|
|
|
|
function pad2(n) {
|
|
return String(n).padStart(2, '0');
|
|
}
|
|
function backupSuffix() {
|
|
const d = new Date();
|
|
return `${d.getFullYear()}${pad2(d.getMonth() + 1)}${pad2(d.getDate())}-${pad2(d.getHours())}${pad2(d.getMinutes())}${pad2(d.getSeconds())}`;
|
|
}
|
|
|
|
function wowExePath(cfg) {
|
|
const exe = (cfg.launch && cfg.launch.exe) || 'Wow.exe';
|
|
const parts = exe.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
return path.join(cfg.game_dir, ...parts);
|
|
}
|
|
|
|
function wowInstallValid(cfg) {
|
|
if (!cfg.game_dir) return false;
|
|
return require('fs').existsSync(wowExePath(cfg));
|
|
}
|
|
|
|
async function installFile(cfg, entry) {
|
|
const parts = String(entry.dest).replace(/\\/g, '/').split('/').filter(Boolean);
|
|
const destAbs = path.join(cfg.game_dir, ...parts);
|
|
if (entry.backup) {
|
|
try {
|
|
const st = await fs.stat(destAbs);
|
|
if (st.isFile()) {
|
|
const bak = `${destAbs}.bak-${backupSuffix()}`;
|
|
await fs.rename(destAbs, bak);
|
|
}
|
|
} catch (e) {
|
|
if (e.code !== 'ENOENT') throw e;
|
|
}
|
|
} else {
|
|
try {
|
|
await fs.unlink(destAbs);
|
|
} catch (e) {
|
|
if (e.code !== 'ENOENT') throw e;
|
|
}
|
|
}
|
|
const tmp = destAbs + '.new';
|
|
if (entry.from_release) {
|
|
await downloadReleaseAsset(cfg, entry.source, tmp);
|
|
} else {
|
|
await downloadGitHubRepoFile(cfg, entry.source, tmp);
|
|
}
|
|
await fs.rename(tmp, destAbs);
|
|
}
|
|
|
|
async function applyRealmlist(cfg) {
|
|
if (!cfg.realmlist || !cfg.realmlist.enabled) return;
|
|
let line = String(cfg.realmlist.line || '').trim();
|
|
if (!line) throw new Error('realmlist.line empty');
|
|
if (!line.toLowerCase().startsWith('set realmlist ')) {
|
|
line = `set realmlist ${line}`;
|
|
}
|
|
const content = line + '\n';
|
|
let paths = cfg.realmlist.paths;
|
|
if (!paths || !paths.length) paths = ['Data/enUS/realmlist.wtf'];
|
|
for (const rel of paths) {
|
|
const r = String(rel).trim().replace(/\\/g, '/');
|
|
if (!r) continue;
|
|
const segs = r.split('/').filter(Boolean);
|
|
const abs = path.join(cfg.game_dir, ...segs);
|
|
await fs.mkdir(path.dirname(abs), { recursive: true });
|
|
await fs.writeFile(abs, content, 'utf8');
|
|
}
|
|
}
|
|
|
|
async function applyPatches(cfg, onStatus) {
|
|
for (const f of cfg.files || []) {
|
|
if (onStatus) onStatus(`Updating ${f.dest} …`);
|
|
try {
|
|
await installFile(cfg, f);
|
|
} catch (e) {
|
|
throw new Error(`sync ${f.dest}: ${e.message || e}`);
|
|
}
|
|
}
|
|
if (cfg.realmlist && cfg.realmlist.enabled) {
|
|
if (onStatus) onStatus('Applying realmlist …');
|
|
await applyRealmlist(cfg);
|
|
}
|
|
if (onStatus) onStatus('All patches applied.');
|
|
}
|
|
|
|
async function doAuth(cfg, username, password) {
|
|
if (!cfg.auth || !cfg.auth.enabled) return;
|
|
const u = String(username || '').trim();
|
|
const p = String(password || '');
|
|
if (!u || !p) throw new Error('username and password required');
|
|
const body = {
|
|
[cfg.auth.username_field || 'username']: u,
|
|
[cfg.auth.password_field || 'password']: p,
|
|
};
|
|
const res = await fetch(cfg.auth.url, {
|
|
method: cfg.auth.method || 'POST',
|
|
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
body: JSON.stringify(body),
|
|
});
|
|
const t = await res.text();
|
|
if (res.status < 200 || res.status >= 300) {
|
|
throw new Error(`login failed ${res.status}: ${t.slice(0, 400)}`);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
applyPatches,
|
|
applyRealmlist,
|
|
wowExePath,
|
|
wowInstallValid,
|
|
doAuth,
|
|
};
|