feat: puppeteer robustness improvements

pull/208/head
Travis Fischer 2022-12-28 01:58:29 -06:00
rodzic d7615577bf
commit 533a65db1c
1 zmienionych plików z 30 dodań i 66 usunięć

Wyświetl plik

@ -20,6 +20,7 @@ let hasRecaptchaPlugin = false
let hasNopechaExtension = false let hasNopechaExtension = false
const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
const DEFAULT_TIMEOUT_MS = 3 * 60 * 1000 // 3 minutes
/** /**
* Represents everything that's required to pass into `ChatGPTAPI` in order * Represents everything that's required to pass into `ChatGPTAPI` in order
@ -52,7 +53,7 @@ export async function getOpenAIAuth({
password, password,
browser, browser,
page, page,
timeoutMs = 3 * 60 * 1000, timeoutMs = DEFAULT_TIMEOUT_MS,
isGoogleLogin = false, isGoogleLogin = false,
isMicrosoftLogin = false, isMicrosoftLogin = false,
captchaToken = process.env.CAPTCHA_TOKEN, captchaToken = process.env.CAPTCHA_TOKEN,
@ -83,7 +84,8 @@ export async function getOpenAIAuth({
captchaToken, captchaToken,
nopechaKey, nopechaKey,
executablePath, executablePath,
proxyServer proxyServer,
timeoutMs
}) })
} }
@ -254,6 +256,7 @@ export async function getBrowser(
nopechaKey?: string nopechaKey?: string
proxyServer?: string proxyServer?: string
minimize?: boolean minimize?: boolean
timeoutMs?: number
} = {} } = {}
) { ) {
const { const {
@ -262,6 +265,7 @@ export async function getBrowser(
executablePath = defaultChromeExecutablePath(), executablePath = defaultChromeExecutablePath(),
proxyServer = process.env.PROXY_SERVER, proxyServer = process.env.PROXY_SERVER,
minimize = false, minimize = false,
timeoutMs = DEFAULT_TIMEOUT_MS,
...launchOptions ...launchOptions
} = opts } = opts
@ -324,6 +328,7 @@ export async function getBrowser(
const browser = await puppeteer.launch({ const browser = await puppeteer.launch({
headless: false, headless: false,
// devtools: true,
args: puppeteerArgs, args: puppeteerArgs,
ignoreDefaultArgs: [ ignoreDefaultArgs: [
'--disable-extensions', '--disable-extensions',
@ -367,7 +372,8 @@ export async function getBrowser(
await initializeNopechaExtension(browser, { await initializeNopechaExtension(browser, {
minimize, minimize,
nopechaKey nopechaKey,
timeoutMs
}) })
return browser return browser
@ -378,71 +384,25 @@ export async function initializeNopechaExtension(
opts: { opts: {
minimize?: boolean minimize?: boolean
nopechaKey?: string nopechaKey?: string
timeoutMs?: number
} }
) { ) {
const { minimize = false, nopechaKey } = opts const { minimize = false, nopechaKey } = opts
// TODO: this is a really hackity hack way of setting the API key...
if (hasNopechaExtension) { if (hasNopechaExtension) {
const page = (await browser.pages())[0] || (await browser.newPage()) const page = (await browser.pages())[0] || (await browser.newPage())
if (minimize) { if (minimize) {
await minimizePage(page) await minimizePage(page)
} }
await page.goto(`https://nopecha.com/setup#${nopechaKey}`, { console.log('initializing nopecha extension with key', nopechaKey, '...')
waitUntil: 'networkidle0'
})
await delay(1000)
try {
// find the nopecha extension ID
const targets = browser.targets()
const extensionIds = (
await Promise.all(
targets.map(async (target) => {
// console.log(target.type(), target.url())
if (target.type() !== 'service_worker') { // TODO: setting the nopecha extension key is really, really error prone...
return for (let i = 0; i < 5; ++i) {
} await page.goto(`https://nopecha.com/setup#${nopechaKey}`, {
waitUntil: 'networkidle0'
// const titleL = title?.toLowerCase() })
// if (titleL?.includes('nopecha')) await delay(500)
const url = new URL(target.url())
return url.hostname
})
)
).filter(Boolean)
const extensionId = extensionIds[0]
if (extensionId) {
const extensionUrl = `chrome-extension://${extensionId}/popup.html`
await page.goto(extensionUrl, { waitUntil: 'networkidle0' })
const editKey = await page.waitForSelector('#edit_key .clickable')
await editKey.click()
const settingsInput = await page.waitForSelector('input.settings_text')
const value = await settingsInput.evaluate((el) => el.value)
if (value !== nopechaKey) {
for (let i = 0; i <= 30; i++) {
await settingsInput.press('Backspace')
}
await settingsInput.type(nopechaKey)
await settingsInput.press('Enter')
await delay(500)
await editKey.click()
await delay(2000)
}
console.log('initialized nopecha extension with key', nopechaKey)
} else {
console.error(
"error initializing nopecha extension; couldn't determine extension ID"
)
}
} catch (err) {
console.error('error initializing nopecha extension', err)
} }
} }
} }
@ -624,16 +584,20 @@ async function waitForRecaptcha(
console.log('waiting to solve recaptcha...') console.log('waiting to solve recaptcha...')
do { do {
const captcha = await page.$('textarea#g-recaptcha-response') try {
if (!captcha) { const captcha = await page.$('textarea#g-recaptcha-response')
// the user may have gone past the page manually if (!captcha) {
break // the user may have gone past the page manually
} break
}
const value = (await captcha.evaluate((el) => el.value))?.trim() const value = (await captcha.evaluate((el) => el.value))?.trim()
if (value?.length) { if (value?.length) {
// recaptcha has been solved! // recaptcha has been solved!
break break
}
} catch (err) {
// catch navigation-related page context errors
} }
if (timeoutMs) { if (timeoutMs) {