Spaces:
Runtime error
Runtime error
import Puppeteer from "https://deno.land/x/puppeteer@16.2.0/mod.ts"; | |
import EventEmitter from "https://deno.land/x/events@v1.0.0/mod.ts"; | |
import type { Browser, Page } from "https://deno.land/x/puppeteer@16.2.0/mod.ts"; | |
const BROWSER_SIGNALS = [ | |
'disconnected', | |
'targetchanged', | |
'targetcreated', | |
'targetdestroyed' | |
]; | |
const CHROME_ARGS = [ | |
'--no-sandbox', | |
'--disable-setuid-sandbox' | |
]; | |
async function resolve(q: string) { | |
if (q.match(/(\d.?){4}/)) { | |
return q; | |
} | |
return await Deno.resolveDns(q, "A"); | |
} | |
export default class Runner extends EventEmitter { | |
config: { | |
BROWSERLESS_HOST: string; | |
BROWSERLESS_PORT: string; | |
}; | |
target: string; | |
browser: Browser | undefined; | |
connected: Promise<boolean> | undefined; | |
constructor(config = { | |
BROWSERLESS_HOST: Deno.env.get("BROWSERLESS_HOST") || "localhost", | |
BROWSERLESS_PORT: Deno.env.get("BROWSERLESS_PORT") || "3000", | |
}) { | |
super(); | |
this.target = `ws://${config.BROWSERLESS_HOST}:${config.BROWSERLESS_PORT}`; | |
this.config = config; | |
this.connected | |
} | |
public async close() { | |
try { | |
if (this.browser) await this.browser.close(); | |
} catch (err) { | |
console.error(`${err} on close`) | |
} | |
} | |
async connect() { | |
if (!this.connected) | |
this.connected = this._connect() | |
return this.connected | |
} | |
async _connect() { | |
try { | |
const host = await resolve(this.config.BROWSERLESS_HOST); | |
const ver = await fetch(`http://${host}:${this.config.BROWSERLESS_PORT}/json/version`) | |
.then(async res => await res.json()) | |
this.target = ver.webSocketDebuggerUrl; | |
this.browser = this.browser || await Puppeteer.connect({ | |
browserWSEndpoint: this.target | |
}).catch(() => { | |
console.error(` | |
⚠ COULD NOT CONNECT TO BROWSERLESS | |
🦄 will try to spawn a chromedriver instance for you to debug`) | |
return Puppeteer.launch({ | |
args: CHROME_ARGS, | |
headless: false | |
}) | |
}); | |
if (!this.browser) { | |
console.error("couldn't init Browser"); | |
return false; | |
} | |
BROWSER_SIGNALS.map(e => this.browser?.on(e, d => this.emit(`browser:${e}`, d))) | |
this.browser.on('error', e => console.error(`got browser error: ${e}`)) | |
const pages = await this.browser.pages(); | |
for (let p in pages) { | |
await pages[p].close(); | |
} | |
this.emit("ready") | |
} catch (e) { | |
console.error(e); | |
} | |
return true; | |
} | |
public async run(fn: (page: Page) => void) { | |
await this.connect(); | |
if (!this.browser) { | |
return; | |
} | |
try { | |
const page = await this.browser.newPage() | |
if (!page) { | |
return; | |
} | |
const ret = await fn(page) | |
await page.close() | |
return ret | |
} catch (e) { | |
return | |
} | |
} | |
} | |