feat: improve support for proxy auth

pull/273/head
Travis Fischer 2023-01-15 03:53:31 -06:00
rodzic 1d784766c5
commit 0c11a4d766
2 zmienionych plików z 59 dodań i 37 usunięć

Wyświetl plik

@ -4,7 +4,7 @@ import { v4 as uuidv4 } from 'uuid'
import * as types from './types'
import { AChatGPTAPI } from './abstract-chatgpt-api'
import { getBrowser, getOpenAIAuth } from './openai-auth'
import { getBrowser, getOpenAIAuth, getPage } from './openai-auth'
import {
browserPostEventStream,
isRelevantRequest,
@ -129,25 +129,10 @@ export class ChatGPTAPIBrowser extends AChatGPTAPI {
proxyServer: this._proxyServer,
minimize: this._minimize
})
this._page =
(await this._browser.pages())[0] || (await this._browser.newPage())
if (this._proxyServer && this._proxyServer.includes('@')) {
try {
const proxyUsername = this._proxyServer.split('@')[0].split(':')[0]
const proxyPassword = this._proxyServer.split('@')[0].split(':')[1]
await this._page.authenticate({
username: proxyUsername,
password: proxyPassword
})
} catch (err) {
console.error(
`Proxy "${this._proxyServer}" throws an error at authenticating`,
err.toString()
)
}
}
this._page = await getPage(this._browser, {
proxyServer: this._proxyServer
})
// bypass annoying popup modals
this._page.evaluateOnNewDocument(() => {
@ -238,6 +223,12 @@ export class ChatGPTAPIBrowser extends AChatGPTAPI {
} while (true)
if (!(await this.getIsAuthenticated())) {
if (!this._accessToken) {
console.warn('no access token')
} else {
console.warn('failed to find prompt textarea')
}
throw new types.ChatGPTError('Failed to authenticate session')
}
@ -313,22 +304,19 @@ export class ChatGPTAPIBrowser extends AChatGPTAPI {
}
})
}
const detail = body?.detail || ''
if (url.endsWith('/conversation')) {
if (status === 403) {
console.log(`ChatGPT "${this._email}" error 403...`)
if (status >= 400) {
console.warn(`ChatGPT "${this._email}" error ${status};`, detail)
// this will be handled in the sendMessage error handler
// await this.refreshSession()
}
} else if (url.endsWith('api/auth/session')) {
if (status === 401) {
console.log(`ChatGPT "${this._email}" error 401...`)
if (status >= 400) {
console.warn(`ChatGPT "${this._email}" error ${status};`, detail)
// this will be handled in the sendMessage error handler
// await this.resetSession()
} else if (status === 403) {
console.log(`ChatGPT "${this._email}" error 403...`)
// this will be handled in the sendMessage error handler
// await this.refreshSession()
} else {
const session: types.SessionResult = body
@ -581,7 +569,7 @@ export class ChatGPTAPIBrowser extends AChatGPTAPI {
// response handler or if the user has closed the page manually.
if (++numTries >= 2) {
const error = new types.ChatGPTError(err.toString())
const error = new types.ChatGPTError(err.toString(), { cause: err })
error.statusCode = err.response?.statusCode
error.statusText = err.response?.statusText
cleanup()

Wyświetl plik

@ -30,7 +30,6 @@ export type OpenAIAuth = {
userAgent: string
clearanceToken: string
sessionToken: string
cookies?: Record<string, Protocol.Network.Cookie>
}
/**
@ -91,7 +90,7 @@ export async function getOpenAIAuth({
const userAgent = await browser.userAgent()
if (!page) {
page = (await browser.pages())[0] || (await browser.newPage())
page = await getPage(browser, { proxyServer })
page.setDefaultTimeout(timeoutMs)
if (minimize) {
@ -240,8 +239,7 @@ export async function getOpenAIAuth({
const authInfo: OpenAIAuth = {
userAgent,
clearanceToken: cookies['cf_clearance']?.value,
sessionToken: cookies['__Secure-next-auth.session-token']?.value,
cookies
sessionToken: cookies['__Secure-next-auth.session-token']?.value
}
return authInfo
@ -261,6 +259,38 @@ export async function getOpenAIAuth({
}
}
export async function getPage(
browser: Browser,
opts: {
proxyServer?: string
}
) {
const { proxyServer = process.env.PROXY_SERVER } = opts
const page = (await browser.pages())[0] || (await browser.newPage())
if (proxyServer && proxyServer.includes('@')) {
const proxyAuth = proxyServer.split('@')[0].split(':')
const proxyUsername = proxyAuth[0]
const proxyPassword = proxyAuth[1]
try {
await page.authenticate({
username: proxyUsername,
password: proxyPassword
})
} catch (err) {
console.error(
`ChatGPT "${this._email}" error authenticating proxy "${this._proxyServer}"`,
err.toString()
)
throw err
}
}
return page
}
/**
* Launches a non-puppeteer instance of Chrome. Note that in my testing, I wasn't
* able to use the built-in `puppeteer` version of Chromium because Cloudflare
@ -359,7 +389,7 @@ export async function getBrowser(
})
if (process.env.PROXY_VALIDATE_IP) {
const page = (await browser.pages())[0] || (await browser.newPage())
const page = await getPage(browser, { proxyServer })
if (minimize) {
await minimizePage(page)
}
@ -378,7 +408,9 @@ export async function getBrowser(
ip = res?.ip
} catch (err) {
throw new Error(`Proxy IP validation failed: ${err.toString()}`)
throw new Error(`Proxy IP validation failed: ${err.toString()}`, {
cause: err
})
}
if (!ip || ip !== process.env.PROXY_VALIDATE_IP) {
@ -392,7 +424,8 @@ export async function getBrowser(
nopechaKey,
minimize,
debug,
timeoutMs
timeoutMs,
proxyServer
})
return browser
@ -401,16 +434,17 @@ export async function getBrowser(
export async function initializeNopechaExtension(
browser: Browser,
opts: {
proxyServer?: string
nopechaKey?: string
minimize?: boolean
debug?: boolean
timeoutMs?: number
}
) {
const { minimize = false, debug = false, nopechaKey } = opts
const { minimize = false, debug = false, nopechaKey, proxyServer } = opts
if (hasNopechaExtension) {
const page = (await browser.pages())[0] || (await browser.newPage())
const page = await getPage(browser, { proxyServer })
if (minimize) {
await minimizePage(page)
}