From 33c87054c74b5181346aff50d8bfb3275d61a149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=9B=E8=83=A4=E6=B1=A0?= Date: Fri, 16 Dec 2022 19:59:57 +0800 Subject: [PATCH] fix: use full browser mode --- apps/chat.js | 122 ++++++++++++++---------------------------------- apps/help.js | 2 +- config/index.js | 7 ++- 3 files changed, 42 insertions(+), 89 deletions(-) diff --git a/apps/chat.js b/apps/chat.js index 8209e7b..5d670ad 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -1,12 +1,11 @@ import plugin from '../../../lib/plugins/plugin.js' -import { ChatGPTAPI, getOpenAIAuth } from 'chatgpt' +import { ChatGPTAPIBrowser } 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 puppeteer from '../utils/browser.js' // import showdownKatex from 'showdown-katex' -const SESSION_TOKEN = Config.token const blockWords = '屏蔽词1,屏蔽词2,屏蔽词3' const converter = new showdown.Converter({ extensions: [ @@ -175,72 +174,33 @@ export class chatgpt extends plugin { } 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 + let option = { markdown: true } + if (Config['2captchaToken']) { + option.captchaToken = Config['2captchaToken'] } + // option.debug = true + option.email = Config.username + option.password = Config.password + this.chatGPTApi = new ChatGPTAPIBrowser(option) + await redis.set('CHATGPT:API_OPTION', JSON.stringify(option)) } 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, - browser - }) - 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 - } - } + this.chatGPTApi = new ChatGPTAPIBrowser(option) } let question = e.msg.trimStart() await this.reply('我正在思考如何回复你,请稍等', true, { recallMsg: 5 }) - let c logger.info(`chatgpt question: ${question}`) + try { + await this.chatGPTApi.init() + } catch (e) { + await this.reply('chatgpt初始化出错:' + e.msg, true) + } let previousConversation = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`) + let conversation = null if (!previousConversation) { - c = this.chatGPTApi.getConversation() let ctime = new Date() previousConversation = { sender: e.sender, - conversation: c, ctime, utime: ctime, num: 0 @@ -248,25 +208,28 @@ export class chatgpt extends plugin { await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify(previousConversation), { EX: CONVERSATION_PRESERVE_TIME }) } else { previousConversation = JSON.parse(previousConversation) - c = this.chatGPTApi.getConversation({ + conversation = { conversationId: previousConversation.conversation.conversationId, parentMessageId: previousConversation.conversation.parentMessageId - }) + } } try { - // console.log({ c }) - let response = await c.sendMessage(question) - // console.log({c}) - // console.log(response) - // 更新redis中的conversation对象,因为send后c已经被自动更新了 - await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify({ - sender: e.sender, - conversation: c, - ctime: previousConversation.ctime, - utime: new Date(), - num: previousConversation.num + 1 - }), { EX: CONVERSATION_PRESERVE_TIME }) - + let option = { + onConversationResponse: function (c) { + let pc = _.clone(previousConversation) + pc.conversation = { + conversationId: c.conversation_id, + parentMessageId: c.message.id + } + redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify(pc), { EX: CONVERSATION_PRESERVE_TIME }).then(res => { + logger.debug('redis set conversation') + }) + } + } + if (conversation) { + option = Object.assign(option, conversation) + } + let response = await this.chatGPTApi.sendMessage(question, option) // 检索是否有屏蔽词 const blockWord = blockWords.split(',').find(word => response.toLowerCase().includes(word.toLowerCase())) if (blockWord) { @@ -284,12 +247,8 @@ export class chatgpt extends plugin { if (userSetting.usePicture) { let endTokens = ['.', '。', '……', '!', '!', ']', ')', ')', '】', '?', '?', '~', '"', "'"] while (!endTokens.find(token => response.trimEnd().endsWith(token))) { - // while (!response.trimEnd().endsWith('.') && !response.trimEnd().endsWith('。') && !response.trimEnd().endsWith('……') && - // !response.trimEnd().endsWith('!') && !response.trimEnd().endsWith('!') && !response.trimEnd().endsWith(']') && !response.trimEnd().endsWith('】') - // ) { await this.reply('内容有点多,我正在奋笔疾书,请再等一会', true, { recallMsg: 5 }) - const responseAppend = await c.sendMessage('Continue') - // console.log(responseAppend) + const responseAppend = await this.chatGPTApi.sendMessage('Continue') // 检索是否有屏蔽词 const blockWord = blockWords.split(',').find(word => responseAppend.toLowerCase().includes(word.toLowerCase())) if (blockWord) { @@ -300,15 +259,6 @@ export class chatgpt extends plugin { logger.warn('chatgpt might forget what it had said') break } - // 更新redis中的conversation对象,因为send后c已经被自动更新了 - await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify({ - sender: e.sender, - conversation: c, - ctime: previousConversation.ctime, - utime: new Date(), - num: previousConversation.num + 1 - }), { EX: CONVERSATION_PRESERVE_TIME }) - response = response + responseAppend } // logger.info(response) diff --git a/apps/help.js b/apps/help.js index b1986dd..5d76247 100644 --- a/apps/help.js +++ b/apps/help.js @@ -63,7 +63,7 @@ export class help extends plugin { priority: 500, rule: [ { - reg: '^(#|[chatgpt|ChatGPT])*(命令|帮助|菜单|help|说明|功能|指令|使用说明)$', + reg: '#(chatgpt|ChatGPT)(命令|帮助|菜单|help|说明|功能|指令|使用说明)', fnc: 'help' } ] diff --git a/config/index.js b/config/index.js index b0ea2b3..856d11a 100644 --- a/config/index.js +++ b/config/index.js @@ -17,7 +17,10 @@ export const Config = { // 每个人发起的对话保留时长。超过这个时长没有进行对话,再进行对话将开启新的对话。单位:秒 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, + // headless: false, // 为空使用默认puppeteer的chromium,也可以传递自己本机安装的Chrome可执行文件地址,提高通过率 - chromePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' + // 目前库暂时不支持指定chrome + // chromePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', + // 可注册2captcha实现跳过验证码,收费服务但很便宜 + '2captchaToken': '' }