Skip to content

Commit

Permalink
feat: improve support for proxy auth
Browse files Browse the repository at this point in the history
  • Loading branch information
transitive-bullshit committed Jan 15, 2023
1 parent 1d78476 commit 0c11a4d
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 37 deletions.
44 changes: 16 additions & 28 deletions src/chatgpt-api-browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -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')
}

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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()
Expand Down
52 changes: 43 additions & 9 deletions src/openai-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export type OpenAIAuth = {
userAgent: string
clearanceToken: string
sessionToken: string
cookies?: Record<string, Protocol.Network.Cookie>
}

/**
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
}
Expand All @@ -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) {
Expand All @@ -392,7 +424,8 @@ export async function getBrowser(
nopechaKey,
minimize,
debug,
timeoutMs
timeoutMs,
proxyServer
})

return browser
Expand All @@ -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)
}
Expand Down

0 comments on commit 0c11a4d

Please sign in to comment.