LCE-Emerald-Launcher/scripts/download-android-assets.mjs
2026-08-11 03:00:19 +03:00

110 lines
2.9 KiB
JavaScript

#!/usr/bin/env node
import {
createWriteStream,
createReadStream,
existsSync,
unlinkSync,
} from "node:fs";
import { mkdir, rename } from "node:fs/promises";
import { createHash } from "node:crypto";
import { Readable } from "node:stream";
import { fileURLToPath } from "node:url";
import path from "node:path";
const RELEASE_TAG = "android-assets-v1";
const REPO = "LCE-Hub/LCE-Emerald-Launcher";
const ASSET_DIR = fileURLToPath(
new URL("../src-tauri/gen/android/app/src/main/assets/", import.meta.url),
);
const ASSETS = [
{
file: "imagefs.tar.zst",
sha256: "7838756e6a05c91afff68f4bf12aa2780f815877753f8dd354e203e99b9caf8a",
},
{
file: "proton-11.0-arm64ec.tar.zst",
sha256: "ceb768396c2d44256518f94ae236f0c1f40738cf050a52e990e2fef67ff161df",
},
];
function sha256File(file) {
return new Promise((resolve, reject) => {
const hash = createHash("sha256");
const stream = createReadStream(file);
stream.on("data", (chunk) => hash.update(chunk));
stream.on("end", () => resolve(hash.digest("hex")));
stream.on("error", reject);
});
}
async function download(url, dest) {
const res = await fetch(url, { redirect: "follow" });
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${res.statusText} for ${url}`);
}
if (!res.body) {
throw new Error(`no response body for ${url}`);
}
const fileStream = createWriteStream(dest);
await new Promise((resolve, reject) => {
const body = Readable.fromWeb(res.body);
body.pipe(fileStream);
body.on("error", reject);
fileStream.on("finish", resolve);
fileStream.on("error", reject);
});
}
let failed = false;
for (const asset of ASSETS) {
const target = path.join(ASSET_DIR, asset.file);
if (existsSync(target)) {
const actual = await sha256File(target);
if (actual === asset.sha256) {
console.log(`okay ${asset.file} (up to date)`);
continue;
}
console.error(
`error ${asset.file}: sha256 mismatch (expected ${asset.sha256}, got ${actual}); delete it and rerun`,
);
failed = true;
continue;
}
const url = `https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${asset.file}`;
console.log(`get ${asset.file} <- ${url}`);
await mkdir(path.dirname(target), { recursive: true });
const tmp = target + ".part";
try {
await download(url, tmp);
const actual = await sha256File(tmp);
if (actual !== asset.sha256) {
console.error(
`error ${asset.file}: downloaded sha256 mismatch (expected ${asset.sha256}, got ${actual})`,
);
failed = true;
if (existsSync(tmp)) {
unlinkSync(tmp);
}
continue;
}
await rename(tmp, target);
console.log(`okay ${asset.file} (downloaded)`);
} catch (error) {
console.error(`error ${asset.file}: ${error.message}`);
failed = true;
if (existsSync(tmp)) {
unlinkSync(tmp);
}
}
}
process.exit(failed ? 1 : 0);