ai-chatbot/analysis/qiaodou-extract/extract_tauri_assets.js
Your Name be5b9aef12
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
chore: sync latest workspace changes
2026-04-05 02:08:26 +08:00

117 lines
3.1 KiB
JavaScript

const fs = require("fs");
const path = require("path");
const zlib = require("zlib");
const INPUT =
"/Users/lanmu/Desktop/ai-chatbot-main/analysis/qiaodou-extract/app.arm64";
const OUTPUT_ROOT =
"/Users/lanmu/Desktop/ai-chatbot-main/analysis/qiaodou-extract/extracted";
const MANIFEST =
"/Users/lanmu/Desktop/ai-chatbot-main/analysis/qiaodou-extract/manifest.json";
const ASSET_REGEX =
/\/assets\/[A-Za-z0-9 _.@/-]+\.(?:mjs|wasm|webp|png|svg|css|js|ico)(?=[^A-Za-z0-9_.@/-]|$)/g;
const INDEX_HTML_REGEX = /\/index\.html/g;
function collectOffsets(text, regex) {
const hits = [];
let match;
while ((match = regex.exec(text)) !== null) {
hits.push({
value: match[0],
offset: match.index,
});
}
return hits;
}
function uniqueByOffset(items) {
const seen = new Set();
return items.filter((item) => {
if (seen.has(item.offset)) {
return false;
}
seen.add(item.offset);
return true;
});
}
function ensureDir(filePath) {
fs.mkdirSync(path.dirname(filePath), { recursive: true });
}
function main() {
const buffer = fs.readFileSync(INPUT);
const text = buffer.toString("latin1");
const assets = uniqueByOffset(collectOffsets(text, ASSET_REGEX)).sort(
(a, b) => a.offset - b.offset,
);
const indexHtmlHits = uniqueByOffset(collectOffsets(text, INDEX_HTML_REGEX)).sort(
(a, b) => a.offset - b.offset,
);
if (!assets.length) {
throw new Error("No embedded /assets/* entries were found.");
}
const nextBoundaries = [...assets.map((a) => a.offset), ...indexHtmlHits.map((a) => a.offset)]
.sort((a, b) => a - b);
const manifest = [];
for (const asset of assets) {
const contentStart = asset.offset + Buffer.byteLength(asset.value);
const nextOffset = nextBoundaries.find((offset) => offset > asset.offset);
if (!nextOffset) {
manifest.push({
asset: asset.value,
offset: asset.offset,
status: "skipped_no_boundary",
});
continue;
}
const compressed = buffer.subarray(contentStart, nextOffset);
try {
const decompressed = zlib.brotliDecompressSync(compressed);
const outputPath = path.join(OUTPUT_ROOT, asset.value.replace(/^\//, ""));
ensureDir(outputPath);
fs.writeFileSync(outputPath, decompressed);
manifest.push({
asset: asset.value,
offset: asset.offset,
nextOffset,
compressedBytes: compressed.length,
decompressedBytes: decompressed.length,
outputPath,
status: "ok",
});
} catch (error) {
manifest.push({
asset: asset.value,
offset: asset.offset,
nextOffset,
compressedBytes: compressed.length,
status: "decompress_failed",
error: error instanceof Error ? error.message : String(error),
});
}
}
fs.mkdirSync(OUTPUT_ROOT, { recursive: true });
fs.writeFileSync(MANIFEST, `${JSON.stringify(manifest, null, 2)}\n`);
const ok = manifest.filter((item) => item.status === "ok").length;
const failed = manifest.filter((item) => item.status !== "ok").length;
console.log(`Extracted: ${ok}`);
console.log(`Failed: ${failed}`);
console.log(`Manifest: ${MANIFEST}`);
}
main();