kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add 2captcha support
rodzic
4d7e518853
commit
658be86e24
|
@ -36,15 +36,16 @@
|
|||
"test:prettier": "prettier '**/*.{js,jsx,ts,tsx}' --check"
|
||||
},
|
||||
"dependencies": {
|
||||
"delay": "^5.0.0",
|
||||
"eventsource-parser": "^0.0.5",
|
||||
"expiry-map": "^2.0.0",
|
||||
"p-timeout": "^6.0.0",
|
||||
"puppeteer-extra": "^3.3.4",
|
||||
"puppeteer-extra-plugin-recaptcha": "^3.6.6",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.1",
|
||||
"remark": "^14.0.2",
|
||||
"strip-markdown": "^5.0.0",
|
||||
"delay": "^5.0.0",
|
||||
"uuid": "^9.0.0",
|
||||
"puppeteer-extra": "^3.3.4",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.0.0",
|
||||
|
|
|
@ -18,6 +18,7 @@ specifiers:
|
|||
prettier: ^2.8.0
|
||||
puppeteer: ^19.4.0
|
||||
puppeteer-extra: ^3.3.4
|
||||
puppeteer-extra-plugin-recaptcha: ^3.6.6
|
||||
puppeteer-extra-plugin-stealth: ^2.11.1
|
||||
remark: ^14.0.2
|
||||
strip-markdown: ^5.0.0
|
||||
|
@ -34,6 +35,7 @@ dependencies:
|
|||
expiry-map: 2.0.0
|
||||
p-timeout: 6.0.0
|
||||
puppeteer-extra: 3.3.4_puppeteer@19.4.0
|
||||
puppeteer-extra-plugin-recaptcha: 3.6.6_puppeteer-extra@3.3.4
|
||||
puppeteer-extra-plugin-stealth: 2.11.1_puppeteer-extra@3.3.4
|
||||
remark: 14.0.2
|
||||
strip-markdown: 5.0.0
|
||||
|
@ -553,6 +555,7 @@ packages:
|
|||
/arr-union/3.1.0:
|
||||
resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/array-find-index/1.0.2:
|
||||
resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==}
|
||||
|
@ -902,6 +905,7 @@ packages:
|
|||
kind-of: 3.2.2
|
||||
lazy-cache: 1.0.4
|
||||
shallow-clone: 0.1.2
|
||||
dev: false
|
||||
|
||||
/clone/1.0.4:
|
||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
||||
|
@ -1570,16 +1574,19 @@ packages:
|
|||
/for-in/0.1.8:
|
||||
resolution: {integrity: sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/for-in/1.0.2:
|
||||
resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/for-own/0.1.5:
|
||||
resolution: {integrity: sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
for-in: 1.0.2
|
||||
dev: false
|
||||
|
||||
/fs-constants/1.0.0:
|
||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||
|
@ -1893,6 +1900,7 @@ packages:
|
|||
|
||||
/is-buffer/1.1.6:
|
||||
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
|
||||
dev: false
|
||||
|
||||
/is-buffer/2.0.5:
|
||||
resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==}
|
||||
|
@ -1924,6 +1932,7 @@ packages:
|
|||
/is-extendable/0.1.1:
|
||||
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/is-extglob/2.1.1:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
|
@ -1994,6 +2003,7 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
isobject: 3.0.1
|
||||
dev: false
|
||||
|
||||
/is-plain-object/5.0.0:
|
||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||
|
@ -2060,6 +2070,7 @@ packages:
|
|||
/isobject/3.0.1:
|
||||
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/javascript-natural-sort/0.7.1:
|
||||
resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==}
|
||||
|
@ -2121,18 +2132,21 @@ packages:
|
|||
universalify: 2.0.0
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.10
|
||||
dev: false
|
||||
|
||||
/kind-of/2.0.1:
|
||||
resolution: {integrity: sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
is-buffer: 1.1.6
|
||||
dev: false
|
||||
|
||||
/kind-of/3.2.2:
|
||||
resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
is-buffer: 1.1.6
|
||||
dev: false
|
||||
|
||||
/kind-of/6.0.3:
|
||||
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||
|
@ -2147,10 +2161,12 @@ packages:
|
|||
/lazy-cache/0.2.7:
|
||||
resolution: {integrity: sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/lazy-cache/1.0.4:
|
||||
resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/lilconfig/2.0.6:
|
||||
resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
|
||||
|
@ -2635,6 +2651,7 @@ packages:
|
|||
dependencies:
|
||||
for-in: 0.1.8
|
||||
is-extendable: 0.1.1
|
||||
dev: false
|
||||
|
||||
/mkdirp-classic/0.5.3:
|
||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
||||
|
@ -3050,6 +3067,26 @@ packages:
|
|||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
/puppeteer-extra-plugin-recaptcha/3.6.6_puppeteer-extra@3.3.4:
|
||||
resolution: {integrity: sha512-SVbmL+igGX8m0Qg9dn85trWDghbfUCTG/QUHYscYx5XgMZVVb0/v0a6MqbPdHoKmBx5BS2kLd6rorMlncMcXdw==}
|
||||
engines: {node: '>=9.11.2'}
|
||||
peerDependencies:
|
||||
playwright-extra: '*'
|
||||
puppeteer-extra: '*'
|
||||
peerDependenciesMeta:
|
||||
playwright-extra:
|
||||
optional: true
|
||||
puppeteer-extra:
|
||||
optional: true
|
||||
dependencies:
|
||||
debug: 4.3.4
|
||||
merge-deep: 3.0.3
|
||||
puppeteer-extra: 3.3.4_puppeteer@19.4.0
|
||||
puppeteer-extra-plugin: 3.2.2_puppeteer-extra@3.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/puppeteer-extra-plugin-stealth/2.11.1_puppeteer-extra@3.3.4:
|
||||
resolution: {integrity: sha512-n0wdC0Ilc9tk5L6FWLyd0P2gT8b2fp+2NuB+KB0oTSw3wXaZ0D6WNakjJsayJ4waGzIJFCUHkmK9zgx5NKMoFw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -3402,6 +3439,7 @@ packages:
|
|||
kind-of: 2.0.1
|
||||
lazy-cache: 0.2.7
|
||||
mixin-object: 2.0.1
|
||||
dev: false
|
||||
|
||||
/shebang-command/1.2.0:
|
||||
resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
|
||||
|
@ -3916,6 +3954,7 @@ packages:
|
|||
/universalify/2.0.0:
|
||||
resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
dev: false
|
||||
|
||||
/update-browserslist-db/1.0.10_browserslist@4.21.4:
|
||||
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
|
||||
|
|
|
@ -3,3 +3,5 @@ export * from './chatgpt-conversation'
|
|||
export * from './types'
|
||||
export * from './utils'
|
||||
export * from './openai-auth'
|
||||
export * from './openai-auth-2captcha'
|
||||
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
import delay from 'delay'
|
||||
import {
|
||||
type Browser,
|
||||
type Page,
|
||||
type Protocol,
|
||||
type PuppeteerLaunchOptions
|
||||
} from 'puppeteer'
|
||||
import puppeteer from 'puppeteer-extra'
|
||||
import RecaptchaPlugin from 'puppeteer-extra-plugin-recaptcha'
|
||||
import StealthPlugin from 'puppeteer-extra-plugin-stealth'
|
||||
|
||||
import { OpenAIAuth, getBrowser } from './openai-auth'
|
||||
|
||||
puppeteer.use(StealthPlugin())
|
||||
|
||||
/**
|
||||
* Bypasses OpenAI's use of Cloudflare to get the cookies required to use
|
||||
* ChatGPT. Uses Puppeteer with a stealth plugin under the hood.
|
||||
*
|
||||
* If you pass `email` and `password`, then it will log into the account and
|
||||
* include a `sessionToken` in the response.
|
||||
*
|
||||
* If you don't pass `email` and `password`, then it will just return a valid
|
||||
* `clearanceToken`.
|
||||
*
|
||||
* This can be useful because `clearanceToken` expires after ~2 hours, whereas
|
||||
* `sessionToken` generally lasts much longer. We recommend renewing your
|
||||
* `clearanceToken` every hour or so and creating a new instance of `ChatGPTAPI`
|
||||
* with your updated credentials.
|
||||
*/
|
||||
export async function getOpenAIAuth2Captcha({
|
||||
email,
|
||||
password,
|
||||
timeoutMs = 2 * 60 * 1000,
|
||||
browser,
|
||||
captchaToken
|
||||
}: {
|
||||
email?: string
|
||||
password?: string
|
||||
timeoutMs?: number
|
||||
browser?: Browser
|
||||
captchaToken?: string
|
||||
}): Promise<OpenAIAuth> {
|
||||
let page: Page
|
||||
let origBrowser = browser
|
||||
puppeteer.use(
|
||||
RecaptchaPlugin({
|
||||
provider: {
|
||||
id: '2captcha',
|
||||
token: captchaToken
|
||||
},
|
||||
visualFeedback: true // colorize reCAPTCHAs (violet = detected, green = solved)
|
||||
})
|
||||
)
|
||||
|
||||
try {
|
||||
if (!browser) {
|
||||
browser = await getBrowser()
|
||||
}
|
||||
|
||||
const userAgent = await browser.userAgent()
|
||||
page = (await browser.pages())[0] || (await browser.newPage())
|
||||
page.setDefaultTimeout(timeoutMs)
|
||||
|
||||
await page.goto('https://chat.openai.com/auth/login')
|
||||
|
||||
// NOTE: this is where you may encounter a CAPTCHA
|
||||
await page.solveRecaptchas()
|
||||
|
||||
await page.waitForSelector('#__next .btn-primary', { timeout: timeoutMs })
|
||||
|
||||
// once we get to this point, the Cloudflare cookies are available
|
||||
await delay(1000)
|
||||
|
||||
// login as well (optional)
|
||||
if (email && password) {
|
||||
await Promise.all([
|
||||
page.click('#__next .btn-primary'),
|
||||
page.waitForNavigation({
|
||||
waitUntil: 'networkidle0'
|
||||
})
|
||||
])
|
||||
await page.type('#username', email, { delay: 10 })
|
||||
await page.solveRecaptchas()
|
||||
await page.click('button[type="submit"]')
|
||||
await page.waitForSelector('#password')
|
||||
await page.type('#password', password, { delay: 10 })
|
||||
await Promise.all([
|
||||
page.click('button[type="submit"]'),
|
||||
page.waitForNavigation({
|
||||
waitUntil: 'networkidle0'
|
||||
})
|
||||
])
|
||||
/*var capacityLimit = await page.$('')
|
||||
if (capacityLimit) {
|
||||
throw `ChatGPT is at capacity right now`
|
||||
}*/
|
||||
}
|
||||
|
||||
const pageCookies = await page.cookies()
|
||||
const cookies = pageCookies.reduce(
|
||||
(map, cookie) => ({ ...map, [cookie.name]: cookie }),
|
||||
{}
|
||||
)
|
||||
|
||||
const authInfo: OpenAIAuth = {
|
||||
userAgent,
|
||||
clearanceToken: cookies['cf_clearance']?.value,
|
||||
sessionToken: cookies['__Secure-next-auth.session-token']?.value,
|
||||
cookies
|
||||
}
|
||||
|
||||
return authInfo
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw err
|
||||
} finally {
|
||||
if (origBrowser) {
|
||||
if (page) {
|
||||
await page.close()
|
||||
}
|
||||
} else if (browser) {
|
||||
await browser.close()
|
||||
}
|
||||
|
||||
page = null
|
||||
browser = null
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue