38 lines
2.3 KiB
JavaScript
38 lines
2.3 KiB
JavaScript
const BASE = process.env.CDP_BASE || 'http://127.0.0.1:9223';
|
|
export const SAN = s => (s||'').replace(/data:[a-z+/-]+;base64,[A-Za-z0-9+/=\s]{40,}/gi,'<IMG>').replace(/[A-Za-z0-9+/]{100,}={0,2}/g,'<B64>').replace(/\s+/g,' ').trim();
|
|
export async function newTarget(url='about:blank'){
|
|
const r=await fetch(`${BASE}/json/new?${encodeURIComponent(url)}`,{method:'PUT'});
|
|
return r.ok? r.json() : (await fetch(`${BASE}/json/new?${encodeURIComponent(url)}`)).json();
|
|
}
|
|
export async function attach(match){
|
|
const list=await (await fetch(`${BASE}/json/list`)).json();
|
|
const ps=list.filter(t=>t.type==='page'&&(!match||t.url.includes(match)));
|
|
if(!ps.length) return null;
|
|
const c=await CDP.connect(ps[ps.length-1].webSocketDebuggerUrl);
|
|
await c.send('Page.enable'); await c.send('Runtime.enable'); return c;
|
|
}
|
|
export async function closeAllTabs(){
|
|
const list=await (await fetch(`${BASE}/json/list`)).json();
|
|
for(const t of list.filter(x=>x.type==='page')) await fetch(`${BASE}/json/close/${t.id}`).catch(()=>{});
|
|
}
|
|
export class CDP{
|
|
constructor(ws){this.ws=ws;this.id=0;this.pending=new Map();this.handlers=[];}
|
|
static async connect(u){const ws=new WebSocket(u);await new Promise((s,j)=>{ws.onopen=s;ws.onerror=j;});
|
|
const c=new CDP(ws);
|
|
ws.onmessage=ev=>{const m=JSON.parse(ev.data);
|
|
if(m.id&&c.pending.has(m.id)){const{res,rej}=c.pending.get(m.id);c.pending.delete(m.id);
|
|
m.error?rej(new Error(JSON.stringify(m.error))):res(m.result);}
|
|
else if(m.method){for(const h of c.handlers)h(m);}};
|
|
return c;}
|
|
send(method,params={}){const id=++this.id;
|
|
return new Promise((res,rej)=>{this.pending.set(id,{res,rej});
|
|
this.ws.send(JSON.stringify({id,method,params}));
|
|
setTimeout(()=>{if(this.pending.has(id)){this.pending.delete(id);rej(new Error('timeout '+method));}},60000);});}
|
|
on(f){this.handlers.push(f);}
|
|
async evalJS(e,aw=true){const r=await this.send('Runtime.evaluate',{expression:e,returnByValue:true,awaitPromise:aw});
|
|
if(r.exceptionDetails)throw new Error(JSON.stringify(r.exceptionDetails).slice(0,220));return r.result?.value;}
|
|
async shot(p){const r=await this.send('Page.captureScreenshot',{format:'jpeg',quality:80});
|
|
const fs=await import('fs'); fs.writeFileSync(p,Buffer.from(r.data,'base64')); return p;}
|
|
close(){try{this.ws.close();}catch{}}
|
|
}
|