Files
blog/blog-admin/tools/check-artalk-human.mjs
T
zqlit a74b3c7127
Deploy to Production / pre-check (push) Successful in 58s
Deploy to Production / build (push) Successful in 4m3s
Deploy to Production / deploy-edgeone (push) Successful in 3m48s
Deploy to Production / finalize (push) Successful in 26s
Deploy to Production / notify-failure (push) Skipped
归档 artalk-cf 评论后端 + rss-robot 到 blog-admin(含技术选型/模块分布 README)
2026-10-04 08:45:40 +08:00

69 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 在「真实 Artalk 评论区」里逐状态截图:包装页 iframe 里是 /comment.html
import { spawn } from 'node:child_process';
import { mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const CHROME = 'C:/Users/QunLIn/.agent-browser/browsers/chrome-154.0.8037.92/chrome.exe';
const PORT = 9385;
const URL_ = process.argv[2] || 'http://127.0.0.1:1313/human-demo.html';
const OUT = process.argv[3] || 'C:/Users/QunLIn/WorkBuddy/2026-10-02-15-13-24/.workbuddy/artalk-human.png';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const userDir = mkdtempSync(join(tmpdir(), 'cdp-atk-human-'));
const chrome = spawn(CHROME, ['--headless=new', `--remote-debugging-port=${PORT}`, `--user-data-dir=${userDir}`,
'--no-first-run', '--disable-gpu', '--window-size=1280,1100', 'about:blank'], { stdio: 'ignore' });
const PROBE = "JSON.stringify((()=>{const f=document.getElementById('fr');const d=f&&f.contentDocument;if(!d)return 'no-iframe-doc';const w=d.querySelector('.atk-human-box');const ed=d.querySelector('.atk-main-editor');const r=(e)=>{if(!e)return null;const b=e.getBoundingClientRect();return {x:Math.round(b.x),y:Math.round(b.y),w:Math.round(b.width),h:Math.round(b.height)};};const im=w?w.querySelector('.atk-human-img'):null;return {box:w?{cls:w.className,text:w.textContent.trim(),rect:r(w),imgW:im?im.naturalWidth:0}:null,editor:r(ed),hasHook:typeof f.contentWindow.__humanCheck};})())";
try {
for (let i = 0; i < 40; i++) { try { const r = await fetch(`http://127.0.0.1:${PORT}/json/version`); if (r.ok) break; } catch {} await sleep(300); }
const tab = await (await fetch(`http://127.0.0.1:${PORT}/json/new?` + encodeURIComponent(URL_), { method: 'PUT' })).json();
const ws = new WebSocket(tab.webSocketDebuggerUrl);
let id = 0; const pending = new Map();
ws.addEventListener('message', (e) => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { pending.get(m.id)(m); pending.delete(m.id); } });
await new Promise((res) => ws.addEventListener('open', res));
const send = (m, p = {}) => new Promise((res) => { const mid = ++id; pending.set(mid, res); ws.send(JSON.stringify({ id: mid, method: m, params: p })); });
const ev = async (expr) => {
const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true });
return r.result?.result?.value ?? r.result?.value ?? null;
};
await send('Runtime.enable');
await send('Page.enable');
// 等 iframe 里的评论页 + Artalk 编辑器渲染出来
for (let i = 0; i < 30; i++) {
const p = await ev(PROBE);
if (p && p.indexOf('"editor":{') >= 0) { console.log('— 评论区已就绪(' + (i * 0.5).toFixed(1) + 's)'); break; }
if (i === 29) console.log('— 评论区未就绪,最后探测:', p);
await sleep(500);
}
await sleep(4500); // 等页面自己的静默验证跑完,避免它的 drop 把我的控件带走
console.log('— 初始(正常读者):', await ev(PROBE));
let s = await send('Page.captureScreenshot', { format: 'png' });
writeFileSync(OUT.replace(/\.png$/, '-none.png'), Buffer.from(s.result.data, 'base64'));
await ev("call('click')");
await sleep(700);
console.log('— 点一下状态:', await ev(PROBE));
s = await send('Page.captureScreenshot', { format: 'png' });
writeFileSync(OUT.replace(/\.png$/, '-click.png'), Buffer.from(s.result.data, 'base64'));
await ev("call('captcha')");
await sleep(2200);
console.log('— 图形验证码状态:', await ev(PROBE));
s = await send('Page.captureScreenshot', { format: 'png' });
writeFileSync(OUT, Buffer.from(s.result.data, 'base64'));
await ev("call('run')");
await sleep(5000);
console.log('— 真实验证后:', await ev(PROBE));
s = await send('Page.captureScreenshot', { format: 'png' });
writeFileSync(OUT.replace(/\.png$/, '-run.png'), Buffer.from(s.result.data, 'base64'));
ws.close();
} catch (e) {
console.error('ERROR', e.message);
} finally {
chrome.kill();
}