From e445cb3c7f7258d346457b078d6299741d9fd931 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Fri, 28 Jul 2023 23:58:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BF=85=E5=BA=94=E9=AA=8C=E8=AF=81=E7=A0=81?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88=20(#528)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 必应验证码另一个解决方案 * fix: add log * fix: try try * fix: 优化报错信息 --- apps/chat.js | 81 +++++++++++++++++++++----------------------- guoba.support.js | 6 ++++ utils/bingCaptcha.js | 32 +++++++++++++++-- utils/config.js | 1 + 4 files changed, 75 insertions(+), 45 deletions(-) diff --git a/apps/chat.js b/apps/chat.js index 8985f379..06123d7f 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -66,7 +66,7 @@ import { SendDiceTool } from '../utils/tools/SendDiceTool.js' import { SendAvatarTool } from '../utils/tools/SendAvatarTool.js' import { SendMessageToSpecificGroupOrUserTool } from '../utils/tools/SendMessageToSpecificGroupOrUserTool.js' import { SetTitleTool } from '../utils/tools/SetTitleTool.js' -import { createCaptcha, solveCaptcha } from '../utils/bingCaptcha.js' +import { createCaptcha, solveCaptcha, solveCaptchaOneShot } from '../utils/bingCaptcha.js' try { await import('emoji-strip') @@ -233,7 +233,7 @@ export class chatgpt extends plugin { reg: '^#chatgpt删除对话', fnc: 'deleteConversation', permission: 'master' - }, + } // { // reg: '^#chatgpt必应验证码', // fnc: 'bingCaptcha' @@ -1678,42 +1678,37 @@ export class chatgpt extends plugin { } catch (error) { logger.error(error) const message = error?.message || error?.data?.message || error || '出错了' - // if (message && typeof message === 'string' && message.indexOf('CaptchaChallenge') > -1) { - // if (bingToken) { - // // let { id, regionId, image } = await createCaptcha(e, bingToken) - // // e.bingCaptchaId = id - // // e.token = bingToken - // // e.regionId = regionId - // // const { - // // conversationSignature, - // // conversationId, - // // clientId - // // } = error?.conversation - // // e.bingConversation = { - // // conversationSignature, - // // conversationId, - // // clientId - // // } - // return { - // text: '请在60秒内输入下面图片以通过必应人机验证', - // image, - // error: true, - // token: bingToken - // } - // } - // } else - if (message && typeof message === 'string' && message.indexOf('限流') > -1) { - throttledTokens.push(bingToken) - let bingTokens = JSON.parse(await redis.get('CHATGPT:BING_TOKENS')) - const badBingToken = bingTokens.findIndex(element => element.Token === bingToken) - const now = new Date() - const hours = now.getHours() - now.setHours(hours + 6) - bingTokens[badBingToken].State = '受限' - bingTokens[badBingToken].DisactivationTime = now - await redis.set('CHATGPT:BING_TOKENS', JSON.stringify(bingTokens)) + if (message && typeof message === 'string' && message.indexOf('CaptchaChallenge') > -1) { + if (bingToken) { + await e.reply('出现必应验证码,尝试解决中') + try { + let captchaResolveResult = await solveCaptchaOneShot(bingToken) + if (captchaResolveResult?.success) { + await e.reply('验证码已解决') + } else { + logger.error(captchaResolveResult) + await e.reply('验证码解决失败: ' + captchaResolveResult.error) + retry = 0 + } + } catch (err) { + logger.error(err) + await e.reply('验证码解决失败: ' + err) + retry = 0 + } + } + } else + if (message && typeof message === 'string' && message.indexOf('限流') > -1) { + throttledTokens.push(bingToken) + let bingTokens = JSON.parse(await redis.get('CHATGPT:BING_TOKENS')) + const badBingToken = bingTokens.findIndex(element => element.Token === bingToken) + const now = new Date() + const hours = now.getHours() + now.setHours(hours + 6) + bingTokens[badBingToken].State = '受限' + bingTokens[badBingToken].DisactivationTime = now + await redis.set('CHATGPT:BING_TOKENS', JSON.stringify(bingTokens)) // 不减次数 - } else if (message && typeof message === 'string' && message.indexOf('UnauthorizedRequest') > -1) { + } else if (message && typeof message === 'string' && message.indexOf('UnauthorizedRequest') > -1) { // token过期了 // let bingTokens = JSON.parse(await redis.get('CHATGPT:BING_TOKENS')) // const badBingToken = bingTokens.findIndex(element => element.Token === bingToken) @@ -1729,12 +1724,12 @@ export class chatgpt extends plugin { // bingTokens[badBingToken].exception = 1 // } // await redis.set('CHATGPT:BING_TOKENS', JSON.stringify(bingTokens)) - logger.warn(`token${bingToken}疑似不存在或已过期,再试试`) - retry = retry - 0.1 - } else { - retry-- - errorMessage = message === 'Timed out waiting for response. Try enabling debug mode to see more information.' ? (reply ? `${reply}\n不行了,我的大脑过载了,处理不过来了!` : '必应的小脑瓜不好使了,不知道怎么回答!') : message - } + logger.warn(`token${bingToken}疑似不存在或已过期,再试试`) + retry = retry - 0.1 + } else { + retry-- + errorMessage = message === 'Timed out waiting for response. Try enabling debug mode to see more information.' ? (reply ? `${reply}\n不行了,我的大脑过载了,处理不过来了!` : '必应的小脑瓜不好使了,不知道怎么回答!') : message + } } } while (retry > 0) if (errorMessage) { diff --git a/guoba.support.js b/guoba.support.js index 0d10068f..9153cf50 100644 --- a/guoba.support.js +++ b/guoba.support.js @@ -465,6 +465,12 @@ export function supportGuoba () { bottomHelpMessage: '【一般情况无需也不建议开启】默认情况下仅创建对话走反代,对话时仍然直连微软。开启本选项将使对话过程也走反,需反代支持', component: 'Switch' }, + { + field: 'bingCaptchaOneShotUrl', + label: '必应验证码pass服务', + bottomHelpMessage: '必应出验证码会自动用该服务绕过', + component: 'Input' + }, { field: 'sydneyMood', label: '情感显示', diff --git a/utils/bingCaptcha.js b/utils/bingCaptcha.js index 3a6fe23e..d0ebf112 100644 --- a/utils/bingCaptcha.js +++ b/utils/bingCaptcha.js @@ -1,9 +1,9 @@ import fetch from 'node-fetch' // this file is deprecated - -import { Config } from './config.js' +import {Config} from './config.js' import HttpsProxyAgent from 'https-proxy-agent' + const newFetch = (url, options = {}) => { const defaultOptions = Config.proxy ? { @@ -60,3 +60,31 @@ export async function solveCaptcha (id, regionId, text, token) { } } } + +export async function solveCaptchaOneShot (token) { + if (!token) { + throw new Error('no token') + } + let solveUrl = Config.bingCaptchaOneShotUrl + if (!solveUrl) { + throw new Error('no captcha source') + } + logger.info(`尝试解决token${token}的验证码`) + let result = await fetch(solveUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + _U: token + }) + }) + if (result.status === 200) { + return await result.json() + } else { + return { + success: false, + error: result.statusText + } + } +} diff --git a/utils/config.js b/utils/config.js index 808d3664..36510bc3 100644 --- a/utils/config.js +++ b/utils/config.js @@ -131,6 +131,7 @@ const defaultConfig = { serpSource: 'ikechan8370', extraUrl: 'https://cpe.ikechan8370.com', smartMode: false, + bingCaptchaOneShotUrl: 'http://bingcaptcha.ikechan8370.com/bing', version: 'v2.7.3' } const _path = process.cwd()