kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
Merge branch 'feature/improve-robustness' into feature/improve-robustness
commit
b8a3fe0d2a
|
@ -16,7 +16,7 @@ async function main() {
|
|||
const email = process.env.OPENAI_EMAIL
|
||||
const password = process.env.OPENAI_PASSWORD
|
||||
|
||||
const api = new ChatGPTAPIBrowser({ email, password })
|
||||
const api = new ChatGPTAPIBrowser({ email, password, debug: true })
|
||||
const res = await api.init()
|
||||
console.log('init result', res)
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import delay from 'delay'
|
||||
import html2md from 'html-to-md'
|
||||
import { type Browser, type HTTPResponse, type Page } from 'puppeteer'
|
||||
import type { Browser, HTTPRequest, HTTPResponse, Page } from 'puppeteer'
|
||||
|
||||
import * as types from './types'
|
||||
import { getBrowser, getOpenAIAuth } from './openai-auth'
|
||||
import { isRelevantRequest, minimizePage } from './utils'
|
||||
|
||||
export class ChatGPTAPIBrowser {
|
||||
protected _markdown: boolean
|
||||
|
@ -102,25 +103,93 @@ export class ChatGPTAPIBrowser {
|
|||
return false
|
||||
}
|
||||
|
||||
// this._page.on('response', this._onResponse.bind(this))
|
||||
// await minimizePage(this._page)
|
||||
|
||||
this._page.on('request', this._onRequest.bind(this))
|
||||
this._page.on('response', this._onResponse.bind(this))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// _onResponse = (response: HTTPResponse) => {
|
||||
// const request = response.request()
|
||||
_onRequest = (request: HTTPRequest) => {
|
||||
if (!this._debug) return
|
||||
|
||||
// console.log('response', {
|
||||
// url: response.url(),
|
||||
// ok: response.ok(),
|
||||
// status: response.status(),
|
||||
// statusText: response.statusText(),
|
||||
// headers: response.headers(),
|
||||
// request: {
|
||||
// method: request.method(),
|
||||
// headers: request.headers()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
const url = request.url()
|
||||
if (!isRelevantRequest(url)) {
|
||||
return
|
||||
}
|
||||
|
||||
const method = request.method()
|
||||
let body: any
|
||||
|
||||
if (method === 'POST') {
|
||||
body = request.postData()
|
||||
|
||||
try {
|
||||
body = JSON.parse(body)
|
||||
} catch (_) {}
|
||||
|
||||
// if (url.endsWith('/conversation') && typeof body === 'object') {
|
||||
// const conversationBody: types.ConversationJSONBody = body
|
||||
// const conversationId = conversationBody.conversation_id
|
||||
// const parentMessageId = conversationBody.parent_message_id
|
||||
// const messageId = conversationBody.messages?.[0]?.id
|
||||
// const prompt = conversationBody.messages?.[0]?.content?.parts?.[0]
|
||||
|
||||
// // TODO: store this info for the current sendMessage request
|
||||
// }
|
||||
}
|
||||
|
||||
console.log('\nrequest', {
|
||||
url,
|
||||
method,
|
||||
headers: request.headers(),
|
||||
body
|
||||
})
|
||||
}
|
||||
|
||||
_onResponse = async (response: HTTPResponse) => {
|
||||
if (!this._debug) return
|
||||
|
||||
const request = response.request()
|
||||
|
||||
const url = response.url()
|
||||
if (!isRelevantRequest(url)) {
|
||||
return
|
||||
}
|
||||
|
||||
let body: any
|
||||
try {
|
||||
body = await response.json()
|
||||
} catch (_) {}
|
||||
|
||||
if (url.endsWith('/conversation')) {
|
||||
// const parser = createParser((event) => {
|
||||
// if (event.type === 'event') {
|
||||
// onMessage(event.data)
|
||||
// }
|
||||
// })
|
||||
// await response.buffer()
|
||||
// for await (const chunk of streamAsyncIterable(response.body)) {
|
||||
// const str = new TextDecoder().decode(chunk)
|
||||
// parser.feed(str)
|
||||
// }
|
||||
}
|
||||
|
||||
console.log('\nresponse', {
|
||||
url,
|
||||
ok: response.ok(),
|
||||
status: response.status(),
|
||||
statusText: response.statusText(),
|
||||
headers: response.headers(),
|
||||
body,
|
||||
request: {
|
||||
method: request.method(),
|
||||
headers: request.headers(),
|
||||
body: request.postData()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async getIsAuthenticated() {
|
||||
try {
|
||||
|
@ -198,7 +267,7 @@ export class ChatGPTAPIBrowser {
|
|||
|
||||
const lastMessage = await this.getLastMessage()
|
||||
|
||||
await inputBox.click()
|
||||
await inputBox.focus()
|
||||
const paragraphs = message.split('\n')
|
||||
for (let i = 0; i < paragraphs.length; i++) {
|
||||
await inputBox.type(paragraphs[i], { delay: 0 })
|
||||
|
@ -220,6 +289,7 @@ export class ChatGPTAPIBrowser {
|
|||
newLastMessage &&
|
||||
lastMessage?.toLowerCase() !== newLastMessage?.toLowerCase()
|
||||
) {
|
||||
await delay(5000)
|
||||
return newLastMessage
|
||||
}
|
||||
} while (true)
|
||||
|
|
|
@ -2,12 +2,12 @@ import * as fs from 'node:fs'
|
|||
import * as os from 'node:os'
|
||||
|
||||
import delay from 'delay'
|
||||
import {
|
||||
type Browser,
|
||||
type ElementHandle,
|
||||
type Page,
|
||||
type Protocol,
|
||||
type PuppeteerLaunchOptions
|
||||
import type {
|
||||
Browser,
|
||||
ElementHandle,
|
||||
Page,
|
||||
Protocol,
|
||||
PuppeteerLaunchOptions
|
||||
} from 'puppeteer'
|
||||
import puppeteer from 'puppeteer-extra'
|
||||
import RecaptchaPlugin from 'puppeteer-extra-plugin-recaptcha'
|
||||
|
|
47
src/utils.ts
47
src/utils.ts
|
@ -1,3 +1,4 @@
|
|||
import type { Page } from 'puppeteer'
|
||||
import { remark } from 'remark'
|
||||
import stripMarkdown from 'strip-markdown'
|
||||
|
||||
|
@ -7,3 +8,49 @@ export function markdownToText(markdown?: string): string {
|
|||
.processSync(markdown ?? '')
|
||||
.toString()
|
||||
}
|
||||
|
||||
export async function minimizePage(page: Page) {
|
||||
const session = await page.target().createCDPSession()
|
||||
const goods = await session.send('Browser.getWindowForTarget')
|
||||
const { windowId } = goods
|
||||
await session.send('Browser.setWindowBounds', {
|
||||
windowId,
|
||||
bounds: { windowState: 'minimized' }
|
||||
})
|
||||
}
|
||||
|
||||
export async function maximizePage(page: Page) {
|
||||
const session = await page.target().createCDPSession()
|
||||
const goods = await session.send('Browser.getWindowForTarget')
|
||||
const { windowId } = goods
|
||||
await session.send('Browser.setWindowBounds', {
|
||||
windowId,
|
||||
bounds: { windowState: 'normal' }
|
||||
})
|
||||
}
|
||||
|
||||
export function isRelevantRequest(url: string): boolean {
|
||||
let pathname
|
||||
|
||||
try {
|
||||
const parsedUrl = new URL(url)
|
||||
pathname = parsedUrl.pathname
|
||||
url = parsedUrl.toString()
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!url.startsWith('https://chat.openai.com')) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (pathname.startsWith('/_next')) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (pathname.endsWith('backend-api/moderations')) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue