72 lines
3.3 KiB
JavaScript
72 lines
3.3 KiB
JavaScript
// 用 CDP 给页面注入 dm_token 后截图(验证需登录的后台)。
|
|
// 用法:node scripts/cdp-shot.mjs <token> <targetPath> <outPng>
|
|
// 前置:chrome 已带 --remote-debugging-port=9222 启动,并已打开 http://localhost:5173/login
|
|
import WebSocket from 'ws';
|
|
import { writeFileSync } from 'node:fs';
|
|
|
|
const [, , TOKEN, TARGET, OUT] = process.argv;
|
|
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
async function listTargets() {
|
|
const res = await fetch('http://localhost:9222/json/list');
|
|
return res.json();
|
|
}
|
|
|
|
async function main() {
|
|
// 找到 5173 的页面 target。
|
|
let ws = '';
|
|
for (let i = 0; i < 30; i++) {
|
|
const ts = await listTargets();
|
|
const t = ts.find((x) => x.type === 'page' && /localhost:5173/.test(x.url));
|
|
if (t) { ws = t.webSocketDebuggerUrl; break; }
|
|
await wait(300);
|
|
}
|
|
if (!ws) throw new Error('no 5173 page target');
|
|
|
|
const sock = new WebSocket(ws, { perMessageDeflate: false, maxPayload: 64 * 1024 * 1024 });
|
|
let id = 0;
|
|
const pending = new Map();
|
|
const send = (method, params = {}) =>
|
|
new Promise((resolve) => { const mid = ++id; pending.set(mid, resolve); sock.send(JSON.stringify({ id: mid, method, params })); });
|
|
|
|
await new Promise((r) => sock.on('open', r));
|
|
sock.on('message', (buf) => {
|
|
const msg = JSON.parse(buf.toString());
|
|
if (msg.id && pending.has(msg.id)) { pending.get(msg.id)(msg.result); pending.delete(msg.id); return; }
|
|
if (msg.method === 'Network.responseReceived') {
|
|
const u = msg.params?.response?.url || '';
|
|
if (/\/api\//.test(u)) console.log(' NET', msg.params.response.status, u.replace('http://localhost:3701', ''));
|
|
}
|
|
if (msg.method === 'Runtime.exceptionThrown') console.log(' EXC', msg.params?.exceptionDetails?.text, msg.params?.exceptionDetails?.exception?.description?.slice(0, 120));
|
|
});
|
|
|
|
await send('Page.enable');
|
|
await send('Runtime.enable');
|
|
await send('Network.enable');
|
|
// 先到根页把 token 写进 localStorage。
|
|
await send('Page.navigate', { url: 'http://localhost:5173/' });
|
|
await wait(2500);
|
|
const set = await send('Runtime.evaluate', {
|
|
expression: `localStorage.setItem('dm_token', ${JSON.stringify(TOKEN)}); localStorage.getItem('dm_token')?.length || 0`,
|
|
returnByValue: true,
|
|
});
|
|
console.log('token len in storage:', set?.result?.value);
|
|
// 第一次整页跳(预热会话,冷启动可能被守卫弹走)。
|
|
await send('Runtime.evaluate', { expression: `location.href='http://localhost:5173${TARGET}'` });
|
|
await wait(5000);
|
|
// 第二次跳目标(此时 store 已 authed、user 已拉取 → 稳定停在目标页)。
|
|
await send('Page.navigate', { url: `http://localhost:5173${TARGET}` });
|
|
await wait(6000);
|
|
const diag = await send('Runtime.evaluate', {
|
|
expression: `JSON.stringify({path: location.pathname, tok: (localStorage.getItem('dm_token')||'').length, h1: document.querySelector('h1')?.textContent?.slice(0,20), bodyHas: document.body.innerText.includes('大师墙')})`,
|
|
returnByValue: true,
|
|
});
|
|
console.log('after nav:', diag?.result?.value);
|
|
const { data } = await send('Page.captureScreenshot', { format: 'png', captureBeyondViewport: true });
|
|
writeFileSync(OUT, Buffer.from(data, 'base64'));
|
|
console.log('saved', OUT);
|
|
sock.close();
|
|
process.exit(0);
|
|
}
|
|
main().catch((e) => { console.error(e); process.exit(1); });
|