feat: add auth support by puppeteer.

Still maybe 403
This commit is contained in:
葛胤池 2022-12-13 15:43:17 +08:00
parent f88eb792ee
commit bc09525187
3 changed files with 166 additions and 18 deletions

View file

@ -1,9 +1,10 @@
import plugin from '../../../lib/plugins/plugin.js'
import { ChatGPTAPI } from 'chatgpt'
import { ChatGPTAPI, getOpenAIAuth } from 'chatgpt'
import _ from 'lodash'
import { Config } from '../config/index.js'
import showdown from 'showdown'
import mjAPI from 'mathjax-node'
import puppeteer from '../utils/browser.js'
// import showdownKatex from 'showdown-katex'
const SESSION_TOKEN = Config.token
const blockWords = '屏蔽词1,屏蔽词2,屏蔽词3'
@ -74,12 +75,6 @@ export class chatgpt extends plugin {
}
]
})
this.chatGPTApi = new ChatGPTAPI({
sessionToken: SESSION_TOKEN,
markdown: true,
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'
})
logger.info('chatgpt插件已加载')
}
/**
@ -178,17 +173,64 @@ export class chatgpt extends plugin {
if (e.isGroup && !e.atme) {
return
}
// let question = _.trimStart(e.msg, '#chatgpt')
let question = e.msg.trimStart()
// await e.runtime.render('chatgpt-plugin', 'content/index', { content: "", question })
// return
try {
await this.chatGPTApi.ensureAuth()
} catch (e) {
logger.error(e)
await this.reply(`OpenAI认证失败请检查Token${e}`, true)
return
let api = await redis.get('CHATGPT:API_OPTION')
if (!api) {
let browser = await puppeteer.getBrowser()
const openAIAuth = await getOpenAIAuth((Config.username && Config.password)
? {
email: Config.username,
password: Config.password,
browser
}
: {
browser
})
const userAgent = await browser.userAgent()
let config = { markdown: true, userAgent }
let option
if (Config.username && Config.password) {
option = { ...Object.assign(config, openAIAuth) }
this.chatGPTApi = new ChatGPTAPI(option)
} else {
config.sessionToken = Config.token
option = { ...Object.assign(config, openAIAuth) }
this.chatGPTApi = new ChatGPTAPI(option)
}
try {
await this.chatGPTApi.ensureAuth()
await redis.set('CHATGPT:API_OPTION', JSON.stringify(option))
} catch (e) {
logger.error(e)
await this.reply(`OpenAI认证失败请检查Token${e}`, true)
return
}
} else {
let option = JSON.parse(api)
this.chatGPTApi = new ChatGPTAPI(option)
try {
await this.chatGPTApi.ensureAuth()
} catch (e) {
let browser = await puppeteer.getBrowser()
const openAIAuth = await getOpenAIAuth({
email: Config.username,
password: Config.password,
browserW
})
const userAgent = await browser.userAgent()
let config = { markdown: true, userAgent }
let option = { ...Object.assign(config, openAIAuth) }
this.chatGPTApi = new ChatGPTAPI(option)
try {
await this.chatGPTApi.ensureAuth()
await redis.set('CHATGPT:API_OPTION', JSON.stringify(option))
} catch (e) {
logger.error(e)
await this.reply(`OpenAI认证失败请检查Token${e}`, true)
return
}
}
}
let question = e.msg.trimStart()
await this.reply('我正在思考如何回复你,请稍等', true, { recallMsg: 5 })
let c
logger.info(`chatgpt question: ${question}`)

View file

@ -1,5 +1,23 @@
// Token如不需要手动配置不填
const SESSION_TOKEN = ''
// CFtoken每小时刷新一般不用填
const CF_CLEARANCE = ''
const PROXY = ''
export const Config = {
token: SESSION_TOKEN
token: SESSION_TOKEN,
cfClearance: CF_CLEARANCE,
proxy: PROXY,
username: '',
password: '',
// 改为true后全局默认以图片形式回复并自动发出Continue命令补全回答
defaultUsePicture: true,
// 每个人发起的对话保留时长。超过这个时长没有进行对话,再进行对话将开启新的对话。单位:秒
conversationPreserveTime: 600,
// UA: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
headless: false,
// 为空使用默认puppeteer的chromium也可以传递自己本机安装的Chrome可执行文件地址提高通过率
chromePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'
}

88
utils/browser.js Normal file
View file

@ -0,0 +1,88 @@
import lodash from 'lodash'
import cfg from '../../../lib/config/config.js'
import { Config } from '../config/index.js'
import StealthPlugin from 'puppeteer-extra-plugin-stealth'
let puppeteer = {}
class Puppeteer {
constructor () {
let args = [
'--exclude-switches',
'--no-sandbox',
'enable-automation',
// '--shm-size=1gb'
]
if (Config.proxy) {
args.push(`--proxy-server=${Config.proxy}`)
}
this.browser = false
this.lock = false
this.config = {
headless: Config.headless,
args
}
if (Config.chromePath) {
this.config.executablePath = Config.chromePath
}
this.html = {}
}
async initPupp () {
if (!lodash.isEmpty(puppeteer)) return puppeteer
puppeteer = (await import('puppeteer-extra')).default
const pluginStealth = StealthPlugin()
puppeteer.use(pluginStealth)
return puppeteer
}
/**
* 初始化chromium
*/
async browserInit () {
await this.initPupp()
if (this.browser) return this.browser
if (this.lock) return false
this.lock = true
logger.mark('puppeteer Chromium 启动中...')
/** 初始化puppeteer */
this.browser = await puppeteer.launch(this.config).catch((err) => {
logger.error(err.toString())
if (String(err).includes('correct Chromium')) {
logger.error('没有正确安装Chromium可以尝试执行安装命令node ./node_modules/puppeteer/install.js')
}
})
this.lock = false
if (!this.browser) {
logger.error('puppeteer Chromium 启动失败')
return false
}
logger.mark('puppeteer Chromium 启动成功')
/** 监听Chromium实例是否断开 */
this.browser.on('disconnected', (e) => {
logger.error('Chromium实例关闭或崩溃')
this.browser = false
})
return this.browser
}
}
class ChatGPTPuppeteer extends Puppeteer {
async getBrowser () {
if (this.browser) {
return this.browser
} else {
return await this.browserInit()
}
}
}
export default new ChatGPTPuppeteer()