diff --git a/apps/button.js b/apps/button.js new file mode 100644 index 0000000..290ee6d --- /dev/null +++ b/apps/button.js @@ -0,0 +1,352 @@ +import plugin from '../../../lib/plugins/plugin.js' +import {Config} from "../utils/config.js"; + +const PLUGIN_CHAT = 'ChatGpt 对话' +const PLUGIN_MANAGEMENT = 'ChatGPT-Plugin 管理' +const PLUGIN_ENTERTAINMENT = 'ChatGPT-Plugin 娱乐小功能' +const FUNCTION_CHAT = 'chatgpt' +const FUNCTION_CHAT3 = 'chatgpt3' +const FUNCTION_CHAT1 = 'chatgpt1' +const FUNCTION_BING = 'bing' +const FUNCTION_GEMINI = 'gemini' +const FUNCTION_XH = 'xh' +const FUNCTION_QWEN = 'qwen' +const FUNCTION_GLM4 = 'glm4' +const FUNCTION_CLAUDE2 = 'claude2' + +const FUNCTION_END = 'destroyConversations' +const FUNCTION_END_ALL = 'endAllConversations' + +const FUNCTION_PIC = 'switch2Picture' +const FUNCTION_TEXT = 'switch2Text' +const FUNCTION_AUDIO = 'switch2Audio' + +const FUNCTION_CONFIRM_ON = 'turnOnConfirm' +const FUNCTION_CONFIRM_OFF = 'turnOffConfirm' +const FUNCTION_VERSION = 'versionChatGPTPlugin' +const FUNCTION_SHUTUP = 'shutUp' +const FUNCTION_OPEN_MOUTH = 'openMouth' +const FUNCTION_QUERY_CONFIG = 'queryConfig' +const FUNCTION_ENABLE_CONTEXT = 'enableGroupContext' +const FUNCTION_MODELS = 'viewAPIModel' + +const FUNCTION_SWITCH_BING = 'useBingSolution' + +const FUNCTION_WORDCLOUD = 'wordcloud' +const FUNCTION_WORDCLOUD_LATEST = 'wordcloud_latest' +const FUNCTION_WORDCLOUD_NEW = 'wordcloud_new' +const FUNCTION_TRANSLATE = 'translate' +const FUNCTION_TRANSLATE_SOURCE = 'translateSource' +const FUNCTION_TRANSLATE_OCR = 'ocr' +const FUNCTION_TRANSLATE_SCREENSHOT = 'screenshotUrl' +export class ChatGPTButtonHandler extends plugin { + constructor () { + super({ + name: 'chatgpt按钮处理器', + priority: -100, + namespace: 'chatgpt-plugin', + handler: [{ + key: 'chatgpt.button.post', + fn: 'btnHandler' + }] + }) + } + + async btnHandler (e, options, reject) { + // logger.mark('[chatgpt按钮处理器]') + if (!Config.enableMd || (e.adapter !== 'shamrock' && (!segment.button || segment.button(1)?.content !== 1))) { + return null + } + const fnc = e.logFnc + switch (fnc) { + case `[${PLUGIN_CHAT}][${FUNCTION_CHAT3}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_CHAT1}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_BING}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_GEMINI}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_XH}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_QWEN}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_CLAUDE2}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_GLM4}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_CHAT}]`: { + return this.makeButtonChat(options?.btnData) + } + case `[${PLUGIN_CHAT}][${FUNCTION_END}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_END_ALL}]`: { + return this.makeButtonEnd(options?.btnData) + } + case `[${PLUGIN_CHAT}][${FUNCTION_PIC}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_AUDIO}]`: + case `[${PLUGIN_CHAT}][${FUNCTION_TEXT}]`: { + return this.makeButtonMode(options?.btnData) + } + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_VERSION}]`: + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_SHUTUP}]`: + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_OPEN_MOUTH}]`: + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_MODELS}]`: + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_QUERY_CONFIG}]`: + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_ENABLE_CONTEXT}]`: + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_CONFIRM_OFF}]`: + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_CONFIRM_ON}]`: { + return this.makeButtonConfirm(options?.btnData) + } + case `[${PLUGIN_MANAGEMENT}][${FUNCTION_SWITCH_BING}]`: { + return this.makeButtonBingMode(options?.btnData) + } + case `[${PLUGIN_ENTERTAINMENT}][${FUNCTION_WORDCLOUD}]`: + case `[${PLUGIN_ENTERTAINMENT}][${FUNCTION_WORDCLOUD_LATEST}]`: + case `[${PLUGIN_ENTERTAINMENT}][${FUNCTION_WORDCLOUD_NEW}]`: + case `[${PLUGIN_ENTERTAINMENT}][${FUNCTION_TRANSLATE}]`: + case `[${PLUGIN_ENTERTAINMENT}][${FUNCTION_TRANSLATE_SOURCE}]`: + case `[${PLUGIN_ENTERTAINMENT}][${FUNCTION_TRANSLATE_OCR}]`: + case `[${PLUGIN_ENTERTAINMENT}][${FUNCTION_TRANSLATE_SCREENSHOT}]`: { + return this.makeButtonEntertainment(options?.btnData) + } + default: + } + return null + } + + /** + * + * @param {{suggested: string?, use: string}?} options + */ + async makeButtonChat (options) { + let endCommand = '#摧毁对话' + switch (options?.use) { + case 'api': { + endCommand = '#api结束对话' + break + } + case 'api3': { + endCommand = '#api3结束对话' + break + } + case 'bing': { + endCommand = '#必应结束对话' + break + } + case 'claude2': { + endCommand = '#克劳德结束对话' + break + } + case 'gemini': { + endCommand = '#双子星结束对话' + break + } + case 'xh': { + endCommand = '#星火结束对话' + break + } + case 'qwen': { + endCommand = '#通义千问结束对话' + break + } + case 'chatglm4': { + endCommand = '#智谱结束对话' + break + } + } + let rows = [ + { + buttons: [ + createButtonBase('结束对话', '#毁灭对话'), + createButtonBase('结束当前对话', endCommand), + createButtonBase('at我对话', '', false) + ] + } + ] + let buttons = [[], []] + if (Config.apiKey) { + buttons[0].push(createButtonBase('OpenAPI', '#chat1', false)) + } + if (await redis.get('CHATGPT:TOKEN')) { + buttons[0].push(createButtonBase('ChatGPT', '#chat3', false)) + } + if (await redis.get('CHATGPT:BING_TOKENS')) { + buttons[0].push(createButtonBase('Copilot', '#bing', false)) + } + if (Config.geminiKey) { + buttons[0].push(createButtonBase('Gemini', '#gemini', false)) + } + if (Config.xhAPIKey) { + buttons[buttons[0].length >= 4 ? 1 : 0].push(createButtonBase('讯飞星火', '#xh', false)) + } + if (Config.qwenApiKey) { + buttons[buttons[0].length >= 4 ? 1 : 0].push(createButtonBase('通义千问', '#qwen', false)) + } + if (Config.chatglmRefreshToken) { + buttons[buttons[0].length >= 4 ? 1 : 0].push(createButtonBase('ChatGLM4', '#glm4', false)) + } + if (Config.claudeAISessionKey) { + buttons[buttons[0].length >= 4 ? 1 : 0].push(createButtonBase('Claude', '#claude.ai', false)) + } + rows.push({ + buttons: buttons[0] + }) + if (buttons[1].length > 0) { + rows.push({ + buttons: buttons[1] + }) + } + if (options?.suggested) { + rows.unshift({ + buttons: options.suggested.split('\n').map(s => { + return createButtonBase(s, s) + }) + }) + } + return { + appid: 1, + rows + } + } + + makeButtonEnd (options) { + return { + appid: 1, + rows: [ + { + buttons: [ + createButtonBase('重新开始', '#摧毁对话'), + createButtonBase('全部结束', '#摧毁全部对话'), + createButtonBase('切换模式', '#chatgpt切换', false) + ] + } + ] + } + } + + makeButtonMode (options) { + return { + appid: 1, + rows: [ + { + buttons: [ + createButtonBase('以文字回复', '#chatgpt文本模式'), + createButtonBase('以图片回复', '#chatgpt图片模式'), + createButtonBase('以语音回复', '#chatgpt语音模式') + ] + } + ] + } + } + + makeButtonConfirm (options) { + return { + appid: 1, + rows: [ + { + buttons: [ + createButtonBase('开启确认', '#chatgpt开启确认'), + createButtonBase('关闭确认', '#chatgpt关闭确认'), + createButtonBase('暂停本群回复', '#chatgpt本群闭嘴', false) + + ] + }, + { + buttons: [ + createButtonBase('恢复本群回复', '#chatgpt本群张嘴', false), + createButtonBase('开启上下文', '#打开群聊上下文'), + createButtonBase('关闭上下文 ', '#关闭群聊上下文') + + ] + }, + { + buttons: [ + createButtonBase('查看指令表', '#chatgpt指令表', false), + createButtonBase('查看帮助', '#chatgpt帮助'), + createButtonBase('查看配置', '#chatgpt查看当前配置') + + ] + }, + { + buttons: [ + createButtonBase('查看配置', '#chatgpt查看当前配置'), + createButtonBase('查看模型列表', '#chatgpt模型列表'), + createButtonBase('版本信息', '#chatgpt版本信息') + ] + } + ] + } + } + + makeButtonBingMode (options) { + return { + appid: 1, + rows: [ + { + buttons: [ + createButtonBase('创意模式', '#chatgpt必应切换创意'), + createButtonBase('精准模式', '#chatgpt必应切换精准'), + createButtonBase('使用设定', '#chatgpt使用设定', false) + ] + }, + { + buttons: [ + createButtonBase('禁用搜索', '#chatgpt必应禁用搜索'), + createButtonBase('开启搜索', '#chatgpt必应开启搜索'), + createButtonBase('设定列表', '#chatgpt浏览设定', false) + ] + }, + { + buttons: [ + createButtonBase('切换到API', '#chatgpt切换API'), + createButtonBase('切换到Gemini', '#chatgpt切换gemini'), + createButtonBase('切换到星火', '#chatgpt切换xh') + ] + } + ] + } + } + + makeButtonEntertainment (options) { + return { + appid: 1, + rows: [ + { + buttons: [ + createButtonBase('今日词云', '#今日词云'), + createButtonBase('最新词云', '#最新词云', false), + createButtonBase('我的词云', '#我的今日词云') + + ] + }, + { + buttons: [ + createButtonBase('翻译', '#翻译', false), + createButtonBase('OCR', '#ocr', false), + createButtonBase('截图', '#url', false) + ] + }, + { + buttons: [ + createButtonBase('设置OPENAI翻译源', '#chatgpt设置翻译来源openai'), + createButtonBase('设置gemini翻译源', '#chatgpt设置翻译来源gemini'), + createButtonBase('设置星火翻译源', '#chatgpt设置翻译来源xh'), + createButtonBase('设置通义千问翻译源', '#chatgpt设置翻译来源qwen') + ] + } + ] + } + } +} + +function createButtonBase (label, data, enter = true, style = 1) { + return { + id: '', + render_data: { + label, + style, + visited_label: label + }, + action: { + type: 2, + permission: { + type: 2 + }, + data, + enter, + unsupport_tips: '' + } + } +} diff --git a/apps/chat.js b/apps/chat.js index f01f02c..75fc56d 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -132,9 +132,8 @@ const newFetch = (url, options = {}) => { return fetch(url, mergedOptions) } export class chatgpt extends plugin { - constructor () { + constructor (e) { let toggleMode = Config.toggleMode - let apiStream = Config.apiStream super({ /** 功能名称 */ name: 'ChatGpt 对话', @@ -174,7 +173,7 @@ export class chatgpt extends plugin { }, { /** 命令正则匹配 */ - reg: '^#claude2[sS]*', + reg: '^#claude(2|3|.ai)[sS]*', /** 执行方法 */ fnc: 'claude2' }, @@ -292,7 +291,23 @@ export class chatgpt extends plugin { ] }) this.toggleMode = toggleMode - this.apiStream = apiStream + this.reply = async (msg, quote, data) => { + if (!Config.enableMd) { + return e.reply(msg, quote, data) + } + let handler = e.runtime?.handler || {} + const btns = await handler.call('chatgpt.button.post', this.e, data) + const btnElement = { + type: 'button', + content: btns + } + if (Array.isArray(msg)) { + msg.push(btnElement) + } else { + msg = [msg, btnElement] + } + return e.reply(msg, quote, data) + } } /** @@ -342,22 +357,22 @@ export class chatgpt extends plugin { // }) // await client.endConversation() await redis.del(`CHATGPT:SLACK_CONVERSATION:${(e.isGroup && Config.groupMerge) ? e.group_id.toString() : e.sender.user_id}`) - await e.reply('claude对话已结束') + await this.reply('claude对话已结束') return } if (use === 'claude2') { await redis.del(`CHATGPT:CLAUDE2_CONVERSATION:${e.sender.user_id}`) - await e.reply('claude2对话已结束') + await this.reply('claude2对话已结束') return } if (use === 'xh') { await redis.del(`CHATGPT:CONVERSATIONS_XH:${(e.isGroup && Config.groupMerge) ? e.group_id.toString() : e.sender.user_id}`) - await e.reply('星火对话已结束') + await this.reply('星火对话已结束') return } if (use === 'bard') { await redis.del(`CHATGPT:CONVERSATIONS_BARD:${(e.isGroup && Config.groupMerge) ? e.group_id.toString() : e.sender.user_id}`) - await e.reply('Bard对话已结束') + await this.reply('Bard对话已结束') return } let ats = e.message.filter(m => m.type === 'at') @@ -803,11 +818,11 @@ export class chatgpt extends plugin { break } default: { - await e.reply('请使用#chatgpt语音换源+数字进行换源。1为vits-uma-genshin-honkai,2为微软Azure,3为voicevox') + await this.reply('请使用#chatgpt语音换源+数字进行换源。1为vits-uma-genshin-honkai,2为微软Azure,3为voicevox') return } } - await e.reply('语音转换源已切换为' + Config.ttsMode) + await this.reply('语音转换源已切换为' + Config.ttsMode) } async setDefaultRole (e) { @@ -895,7 +910,7 @@ export class chatgpt extends plugin { * #chatgpt */ async chatgpt (e) { - let msg = (Version.isTrss || e.adapter === 'shamrock') ? e.msg : e.raw_message + let msg = e.msg let prompt if (this.toggleMode === 'at') { if (!msg || e.msg?.startsWith('#')) { @@ -947,7 +962,7 @@ export class chatgpt extends plugin { } return false } - prompt = _.replace(e.raw_message.trimStart(), '#chat', '').trim() + prompt = _.replace(e.msg.trimStart(), '#chat', '').trim() if (prompt.length === 0) { return false } @@ -1187,7 +1202,7 @@ export class chatgpt extends plugin { bingToken: previousConversation.bingToken } } - + let handler = this.e.runtime?.handler || {} try { if (Config.debug) { logger.mark({ conversation }) @@ -1199,7 +1214,7 @@ export class chatgpt extends plugin { // 处理星火和bard图片 if ((use === 'bard' || use === 'xh') && chatMessage?.images) { chatMessage.images.forEach(async element => { - await e.reply([element.tag, segment.image(element.url)]) + await this.reply([element.tag, segment.image(element.url)]) }) } // chatglm4图片,调整至sendMessage中处理 @@ -1244,7 +1259,7 @@ export class chatgpt extends plugin { if (use === 'claude') response = response.replace(/:[a-zA-Z_]+:/g, '') let mood = 'blandness' if (!response) { - await e.reply('没有任何回复', true) + await this.reply('没有任何回复', true) return } let emotion, emotionDegree @@ -1382,7 +1397,15 @@ export class chatgpt extends plugin { if (Config.ttsMode === 'vits-uma-genshin-honkai' && ttsResponse.length > parseInt(Config.ttsAutoFallbackThreshold)) { await this.reply('回复的内容过长,已转为文本模式') } - await this.reply(await convertFaces(response, Config.enableRobotAt, e), e.isGroup) + let responseText = await convertFaces(response, Config.enableRobotAt, e) + if (handler.has('chatgpt.markdown.convert')) { + responseText = await handler.call('chatgpt.markdown.convert', this.e, { + content: responseText, + use, + prompt + }) + } + await this.reply(finalResponse, e.isGroup) if (quotemessage.length > 0) { this.reply(await makeForwardMsg(this.e, quotemessage.map(msg => `${msg.text} - ${msg.url}`))) } @@ -1422,10 +1445,25 @@ export class chatgpt extends plugin { this.reply('今日对话已达上限') return false } - await this.reply(await convertFaces(response, Config.enableRobotAt, e), e.isGroup) + let responseText = await convertFaces(response, Config.enableRobotAt, e) + if (handler.has('chatgpt.markdown.convert')) { + responseText = await handler.call('chatgpt.markdown.convert', this.e, { + content: responseText, + use, + prompt + }) + } + // await this.reply(responseText, e.isGroup) if (quotemessage.length > 0) { this.reply(await makeForwardMsg(this.e, quotemessage.map(msg => `${msg.text} - ${msg.url}`))) } + + this.reply(responseText, e.isGroup, { + btnData: { + use, + suggested: chatMessage.suggestedResponses + } + }) if (Config.enableSuggestedResponses && chatMessage.suggestedResponses) { this.reply(`建议的回复:\n${chatMessage.suggestedResponses}`) } @@ -1471,7 +1509,7 @@ export class chatgpt extends plugin { } async claude2 (e) { - return await this.otherMode(e, 'claude2') + return await this.otherMode(e, 'claude2', /^#claude(2|3|.ai)/) } async claude (e) { @@ -1537,7 +1575,7 @@ export class chatgpt extends plugin { async renderImage (e, use, content, prompt, quote = [], mood = '', suggest = '', imgUrls = []) { let cacheData = await this.cacheContent(e, use, content, prompt, quote, mood, suggest, imgUrls) const template = use !== 'bing' ? 'content/ChatGPT/index' : 'content/Bing/index' - if (cacheData.error || cacheData.status != 200) { await this.reply(`出现错误:${cacheData.error || 'server error ' + cacheData.status}`, true) } else { await e.reply(await renderUrl(e, (Config.viewHost ? `${Config.viewHost}/` : `http://127.0.0.1:${Config.serverPort || 3321}/`) + `page/${cacheData.file}?qr=${Config.showQRCode ? 'true' : 'false'}`, { retType: Config.quoteReply ? 'base64' : '', Viewport: { width: parseInt(Config.chatViewWidth), height: parseInt(parseInt(Config.chatViewWidth) * 0.56) }, func: (parseFloat(Config.live2d) && !Config.viewHost) ? 'window.Live2d == true' : '', deviceScaleFactor: parseFloat(Config.cloudDPR) }), e.isGroup && Config.quoteReply) } + if (cacheData.error || cacheData.status != 200) { await this.reply(`出现错误:${cacheData.error || 'server error ' + cacheData.status}`, true) } else { await this.reply(await renderUrl(e, (Config.viewHost ? `${Config.viewHost}/` : `http://127.0.0.1:${Config.serverPort || 3321}/`) + `page/${cacheData.file}?qr=${Config.showQRCode ? 'true' : 'false'}`, { retType: Config.quoteReply ? 'base64' : '', Viewport: { width: parseInt(Config.chatViewWidth), height: parseInt(parseInt(Config.chatViewWidth) * 0.56) }, func: (parseFloat(Config.live2d) && !Config.viewHost) ? 'window.Live2d == true' : '', deviceScaleFactor: parseFloat(Config.cloudDPR) }), e.isGroup && Config.quoteReply) } } async sendMessage (prompt, conversation = {}, use, e) { @@ -1667,7 +1705,7 @@ export class chatgpt extends plugin { client.getImages(prompt, e) } catch (err) { redis.del(`CHATGPT:DRAW:${e.sender.user_id}`) - e.reply('绘图失败:' + err) + this.reply('绘图失败:' + err) } }) } @@ -1715,20 +1753,20 @@ export class chatgpt extends plugin { if (bingToken) { if (maxConv >= 20 && Config.bingCaptchaOneShotUrl) { // maxConv为30说明token有效,可以通过解验证码码服务过码 - await e.reply('出现必应验证码,尝试解决中') + await this.reply('出现必应验证码,尝试解决中') try { let captchaResolveResult = await solveCaptchaOneShot(bingToken) if (captchaResolveResult?.success) { - await e.reply('验证码已解决') + await this.reply('验证码已解决') } else { logger.error(captchaResolveResult) errorMessage = message - await e.reply('验证码解决失败: ' + captchaResolveResult.error) + await this.reply('验证码解决失败: ' + captchaResolveResult.error) retry = 0 } } catch (err) { logger.error(err) - await e.reply('验证码解决失败: ' + err) + await this.reply('验证码解决失败: ' + err) retry = 0 } } else { @@ -2192,7 +2230,7 @@ export class chatgpt extends plugin { }) let resp = await client.sendMessage(prompt, conversation) if (resp.image) { - e.reply(segment.image(resp.image), true) + this.reply(segment.image(resp.image), true) } return resp } else { @@ -2275,7 +2313,7 @@ export class chatgpt extends plugin { let option = { timeoutMs: 600000, completionParams, - stream: this.apiStream, + stream: Config.apiStream, onProgress: (data) => { if (Config.debug) { logger.info(data?.text || data.functionCall || data) @@ -2416,7 +2454,7 @@ export class chatgpt extends plugin { logger.info(msg) while (msg.functionCall) { if (msg.text) { - await e.reply(msg.text.replace('\n\n\n', '\n')) + await this.reply(msg.text.replace('\n\n\n', '\n')) } let { name, @@ -2449,7 +2487,7 @@ export class chatgpt extends plugin { logger.warn(err) await redis.del(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`) await redis.del(`CHATGPT:WRONG_EMOTION:${e.sender.user_id}`) - await e.reply('字数超限啦,将为您自动结束本次对话。') + await this.reply('字数超限啦,将为您自动结束本次对话。') return null } else { logger.error(err) @@ -2466,7 +2504,7 @@ export class chatgpt extends plugin { logger.warn(err) await redis.del(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`) await redis.del(`CHATGPT:WRONG_EMOTION:${e.sender.user_id}`) - await e.reply('字数超限啦,将为您自动结束本次对话。') + await this.reply('字数超限啦,将为您自动结束本次对话。') return null } else { logger.error(err) @@ -2494,11 +2532,11 @@ export class chatgpt extends plugin { await redis.del(`CHATGPT:WRONG_EMOTION:${e.sender.user_id}`) } response = await client.sendMessage('', e) - await e.reply(response, true) + await this.reply(response, true) } else { let preset = getPromptByName(presetName) if (!preset) { - await e.reply('没有这个设定', true) + await this.reply('没有这个设定', true) } else { let conversationId = await redis.get(`CHATGPT:SLACK_CONVERSATION:${e.sender.user_id}`) if (conversationId) { @@ -2510,7 +2548,7 @@ export class chatgpt extends plugin { logger.info('send preset: ' + preset.content) response = await client.sendMessage(preset.content, e) + await client.sendMessage(await AzureTTS.getEmotionPrompt(e), e) - await e.reply(response, true) + await this.reply(response, true) } } return true @@ -2519,15 +2557,15 @@ export class chatgpt extends plugin { async newxhBotConversation (e) { let botId = e.msg.replace(/^#星火助手/, '').trim() if (Config.xhmode != 'web') { - await e.reply('星火助手仅支持体验版使用', true) + await this.reply('星火助手仅支持体验版使用', true) return true } if (!botId) { - await e.reply('无效助手id', true) + await this.reply('无效助手id', true) } else { const ssoSessionId = Config.xinghuoToken if (!ssoSessionId) { - await e.reply('未绑定星火token,请使用#chatgpt设置星火token命令绑定token', true) + await this.reply('未绑定星火token,请使用#chatgpt设置星火token命令绑定token', true) return true } let client = new XinghuoClient({ @@ -2564,15 +2602,15 @@ export class chatgpt extends plugin { }), Config.conversationPreserveTime > 0 ? { EX: Config.conversationPreserveTime } : {} ) - await e.reply(`成功创建助手对话\n助手名称:${botInfo.data.bot_name}\n助手描述:${botInfo.data.bot_desc}`, true) + await this.reply(`成功创建助手对话\n助手名称:${botInfo.data.bot_name}\n助手描述:${botInfo.data.bot_desc}`, true) } else { - await e.reply(`创建助手对话失败,${botInfo.desc}`, true) + await this.reply(`创建助手对话失败,${botInfo.desc}`, true) } } else { - await e.reply('创建助手对话失败,服务器异常', true) + await this.reply('创建助手对话失败,服务器异常', true) } } catch (error) { - await e.reply(`创建助手对话失败 ${error}`, true) + await this.reply(`创建助手对话失败 ${error}`, true) } } return true @@ -2582,7 +2620,7 @@ export class chatgpt extends plugin { let searchBot = e.msg.replace(/^#星火(搜索|查找)助手/, '').trim() const ssoSessionId = Config.xinghuoToken if (!ssoSessionId) { - await e.reply('未绑定星火token,请使用#chatgpt设置星火token命令绑定token', true) + await this.reply('未绑定星火token,请使用#chatgpt设置星火token命令绑定token', true) return true } const cacheresOption = { @@ -2608,10 +2646,10 @@ export class chatgpt extends plugin { if (bots.data.pageList.length > 0) { this.reply(await makeForwardMsg(this.e, bots.data.pageList.map(msg => `${msg.e.bot.botId} - ${msg.e.bot.botName}`))) } else { - await e.reply('未查到相关助手', true) + await this.reply('未查到相关助手', true) } } else { - await e.reply('搜索助手失败', true) + await this.reply('搜索助手失败', true) } } @@ -2763,6 +2801,13 @@ export class chatgpt extends plugin { return await this.chatGPTApi.sendMessage(prompt, sendMessageOption) } + /** + * 其他模式 + * @param e + * @param mode + * @param {string|RegExp} pattern + * @returns {Promise} + */ async otherMode (e, mode, pattern = `#${mode}`) { if (!Config.allowOtherMode) { return false @@ -2774,7 +2819,7 @@ export class chatgpt extends plugin { } return false } - let prompt = _.replace(e.raw_message.trimStart(), pattern, '').trim() + let prompt = _.replace(e.msg.trimStart(), pattern, '').trim() if (prompt.length === 0) { return false } diff --git a/apps/entertainment.js b/apps/entertainment.js index 1de8d70..b977a5a 100644 --- a/apps/entertainment.js +++ b/apps/entertainment.js @@ -82,6 +82,23 @@ export class Entertainment extends plugin { fnc: this.sendRandomMessage.bind(this) } ] + this.reply = async (msg, quote, data) => { + if (!Config.enableMd) { + return e.reply(msg, quote, data) + } + let handler = e.runtime?.handler || {} + const btns = await handler.call('chatgpt.button.post', this.e) + const btnElement = { + type: 'button', + content: btns + } + if (Array.isArray(msg)) { + msg.push(btnElement) + } else { + msg = [msg, btnElement] + } + return e.reply(msg, quote, data) + } } async ocr (e) { @@ -116,7 +133,7 @@ ${translateLangLabels} let result = [] let multiText = false if (languageCode !== 'auto' && !translateLangLabelAbbrS.includes(languageCode)) { - e.reply(`输入格式有误或暂不支持该语言,\n当前支持${translateLangLabels}`, e.isGroup) + this.reply(`输入格式有误或暂不支持该语言,\n当前支持${translateLangLabels}`, e.isGroup) return false } // 引用回复 @@ -206,9 +223,9 @@ ${translateLangLabels} } else if (command.includes('qwen')) { Config.translateSource = 'qwen' } else { - e.reply('暂不支持该翻译源') + this.reply('暂不支持该翻译源') } - e.reply('√成功设置翻译源为' + Config.translateSource) + this.reply('√成功设置翻译源为' + Config.translateSource) } async wordcloud (e) { @@ -216,20 +233,21 @@ ${translateLangLabels} let groupId = e.group_id let lock = await redis.get(`CHATGPT:WORDCLOUD:${groupId}`) if (lock) { - await e.reply('别着急,上次统计还没完呢') + await this.reply('别着急,上次统计还没完呢') return true } - await e.reply('在统计啦,请稍等...') + await this.reply('在统计啦,请稍等...') await redis.set(`CHATGPT:WORDCLOUD:${groupId}`, '1', { EX: 600 }) try { - await makeWordcloud(e, e.group_id) + let img = await makeWordcloud(e, e.group_id) + this.reply(img, true) } catch (err) { logger.error(err) - await e.reply(err) + await this.reply(err) } await redis.del(`CHATGPT:WORDCLOUD:${groupId}`) } else { - await e.reply('请在群里发送此命令') + await this.reply('请在群里发送此命令') } } @@ -238,7 +256,7 @@ ${translateLangLabels} let groupId = e.group_id let lock = await redis.get(`CHATGPT:WORDCLOUD:${groupId}`) if (lock) { - await e.reply('别着急,上次统计还没完呢') + await this.reply('别着急,上次统计还没完呢') return true } @@ -247,21 +265,21 @@ ${translateLangLabels} const duration = !match[1] ? 12 : parseInt(match[1]) // default 12h if (duration > 24) { - await e.reply('最多只能统计24小时内的记录哦,你可以使用#本周词云和#本月词云获取更长时间的统计~') + await this.reply('最多只能统计24小时内的记录哦,你可以使用#本周词云和#本月词云获取更长时间的统计~') return false } - await e.reply('在统计啦,请稍等...') + await this.reply('在统计啦,请稍等...') await redis.set(`CHATGPT:WORDCLOUD:${groupId}`, '1', { EX: 600 }) try { await makeWordcloud(e, e.group_id, duration) } catch (err) { logger.error(err) - await e.reply(err) + await this.reply(err) } await redis.del(`CHATGPT:WORDCLOUD:${groupId}`) } else { - await e.reply('请在群里发送此命令') + await this.reply('请在群里发送此命令') } } @@ -278,10 +296,10 @@ ${translateLangLabels} } let lock = await redis.get(`CHATGPT:WORDCLOUD_NEW:${groupId}_${userId}`) if (lock) { - await e.reply('别着急,上次统计还没完呢') + await this.reply('别着急,上次统计还没完呢') return true } - await e.reply('在统计啦,请稍等...') + await this.reply('在统计啦,请稍等...') let duration = 24 if (e.msg.includes('本周')) { const now = new Date() // Get the current date and time @@ -307,11 +325,11 @@ ${translateLangLabels} await makeWordcloud(e, e.group_id, duration, userId) } catch (err) { logger.error(err) - await e.reply(err) + await this.reply(err) } await redis.del(`CHATGPT:WORDCLOUD_NEW:${groupId}_${userId}`) } else { - await e.reply('请在群里发送此命令') + await this.reply('请在群里发送此命令') } } @@ -327,7 +345,7 @@ ${translateLangLabels} if (fs.existsSync(resultFileLoc)) { let image = segment.image(fs.createReadStream(resultFileLoc)) image.asface = true - await e.reply(image, true) + await this.reply(image, true) return true } const _path = process.cwd() @@ -349,7 +367,7 @@ ${translateLangLabels} } } if (!url) { - await e.reply('不支持合成', true) + await this.reply('不支持合成', true) return false } let response = await fetch(url) @@ -359,7 +377,7 @@ ${translateLangLabels} await fs.writeFileSync(resultFileLoc, resultBuffer) let image = segment.image(fs.createReadStream(resultFileLoc)) image.asface = true - await e.reply(image, true) + await this.reply(image, true) return true } @@ -376,7 +394,7 @@ ${translateLangLabels} logger.info(groupId) groupId = parseInt(groupId) if (groupId && !e.bot.gl.get(groupId)) { - await e.reply('机器人不在这个群里!') + await this.reply('机器人不在这个群里!') return } let message = await generateHello() @@ -387,10 +405,10 @@ ${translateLangLabels} sendable = segment.record(audio) } if (!groupId) { - await e.reply(sendable) + await this.reply(sendable) } else { await e.bot.sendGroupMsg(groupId, sendable) - await e.reply('发送成功!') + await this.reply('发送成功!') } } @@ -563,7 +581,7 @@ ${translateLangLabels} url = 'http://' + url } let urlLink = new URL(url) - await e.reply( + await this.reply( await renderUrl( e, urlLink.href, { diff --git a/apps/management.js b/apps/management.js index 0145bcc..5b6d7eb 100644 --- a/apps/management.js +++ b/apps/management.js @@ -93,7 +93,7 @@ export class ChatgptManagement extends plugin { permission: 'master' }, { - reg: '^#chatgpt切换(必应|Bing)$', + reg: '^#chatgpt切换(必应|Bing|Copilot|copilot)$', fnc: 'useBingSolution', permission: 'master' }, @@ -333,6 +333,25 @@ export class ChatgptManagement extends plugin { } ] }) + this.reply = async (msg, quote, data) => { + if (!Config.enableMd) { + return e.reply(msg, quote, data) + } + let handler = e.runtime?.handler || {} + const btns = await handler.call('chatgpt.button.post', this.e) + if (btns) { + const btnElement = { + type: 'button', + content: btns + } + if (Array.isArray(msg)) { + msg.push(btnElement) + } else { + msg = [msg, btnElement] + } + } + return e.reply(msg, quote, data) + } } async viewUserSetting (e) { @@ -1001,9 +1020,9 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, logger.error(error) logger.error(stderr) logger.info(stdout) - this.e.reply('失败,请查看日志手动操作') + this.reply('失败,请查看日志手动操作') } else { - this.e.reply('修补完成,请手动重启') + this.reply('修补完成,请手动重启') } }) } @@ -1047,20 +1066,20 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, } if (map[tongStyle]) { Config.toneStyle = map[tongStyle] - await e.reply('切换成功') + await this.reply('切换成功') } else { - await e.reply('没有这种风格。支持的风格:`精准`和`创意`,均支持设定') + await this.reply('没有这种风格。支持的风格:`精准`和`创意`,均支持设定') } } async bingOpenSuggestedResponses (e) { Config.enableSuggestedResponses = e.msg.indexOf('开启') > -1 - await e.reply('操作成功') + await this.reply('操作成功') } async checkAuth (e) { if (!e.isMaster) { - e.reply(`只有主人才能命令ChatGPT哦~ + this.reply(`只有主人才能命令ChatGPT哦~ (*/ω\*)`) return false } @@ -1068,7 +1087,8 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, } async versionChatGPTPlugin (e) { - await renderUrl(e, `http://127.0.0.1:${Config.serverPort || 3321}/version`, { Viewport: { width: 800, height: 600 } }) + let img = await renderUrl(e, `http://127.0.0.1:${Config.serverPort || 3321}/version`, { Viewport: { width: 800, height: 600 }, retType: 'base64' }) + this.reply(img) } async modeHelp () { @@ -1107,13 +1127,13 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, if (await redis.get(`CHATGPT:SHUT_UP:${scope}`)) { await redis.del(`CHATGPT:SHUT_UP:${scope}`) await redis.set(`CHATGPT:SHUT_UP:${scope}`, '1', { EX: time }) - await e.reply(`好的,已切换休眠状态:倒计时${formatDuration(time)}`) + await this.reply(`好的,已切换休眠状态:倒计时${formatDuration(time)}`) } else { await redis.set(`CHATGPT:SHUT_UP:${scope}`, '1', { EX: time }) - await e.reply(`好的,已切换休眠状态:倒计时${formatDuration(time)}`) + await this.reply(`好的,已切换休眠状态:倒计时${formatDuration(time)}`) } } else { - await e.reply('主人,这里好像不是群哦') + await this.reply('主人,这里好像不是群哦') return false } } else if (match) { @@ -1122,23 +1142,23 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, if (await redis.get(`CHATGPT:SHUT_UP:${groupId}`)) { await redis.del(`CHATGPT:SHUT_UP:${groupId}`) await redis.set(`CHATGPT:SHUT_UP:${groupId}`, '1', { EX: time }) - await e.reply(`好的,即将在群${groupId}中休眠${formatDuration(time)}`) + await this.reply(`好的,即将在群${groupId}中休眠${formatDuration(time)}`) } else { await redis.set(`CHATGPT:SHUT_UP:${groupId}`, '1', { EX: time }) - await e.reply(`好的,即将在群${groupId}中休眠${formatDuration(time)}`) + await this.reply(`好的,即将在群${groupId}中休眠${formatDuration(time)}`) } } else { - await e.reply('主人还没告诉我群号呢') + await this.reply('主人还没告诉我群号呢') return false } } else { if (await redis.get('CHATGPT:SHUT_UP:ALL')) { await redis.del('CHATGPT:SHUT_UP:ALL') await redis.set('CHATGPT:SHUT_UP:ALL', '1', { EX: time }) - await e.reply(`好的,我会延长休眠时间${formatDuration(time)}`) + await this.reply(`好的,我会延长休眠时间${formatDuration(time)}`) } else { await redis.set('CHATGPT:SHUT_UP:ALL', '1', { EX: time }) - await e.reply(`好的,我会延长休眠时间${formatDuration(time)}`) + await this.reply(`好的,我会延长休眠时间${formatDuration(time)}`) } } } @@ -1147,36 +1167,36 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, const match = e.msg.match(/^#chatgpt群(\d+)/) if (e.msg.indexOf('本群') > -1) { if (await redis.get('CHATGPT:SHUT_UP:ALL')) { - await e.reply('当前为休眠模式,没办法做出回应呢') + await this.reply('当前为休眠模式,没办法做出回应呢') return false } if (e.isGroup) { let scope = e.group.group_id if (await redis.get(`CHATGPT:SHUT_UP:${scope}`)) { await redis.del(`CHATGPT:SHUT_UP:${scope}`) - await e.reply('好的主人,我又可以和大家聊天啦') + await this.reply('好的主人,我又可以和大家聊天啦') } else { - await e.reply('主人,我已经启动过了哦') + await this.reply('主人,我已经启动过了哦') } } else { - await e.reply('主人,这里好像不是群哦') + await this.reply('主人,这里好像不是群哦') return false } } else if (match) { if (await redis.get('CHATGPT:SHUT_UP:ALL')) { - await e.reply('当前为休眠模式,没办法做出回应呢') + await this.reply('当前为休眠模式,没办法做出回应呢') return false } const groupId = parseInt(match[1], 10) if (e.bot.getGroupList().get(groupId)) { if (await redis.get(`CHATGPT:SHUT_UP:${groupId}`)) { await redis.del(`CHATGPT:SHUT_UP:${groupId}`) - await e.reply(`好的主人,我终于又可以在群${groupId}和大家聊天了`) + await this.reply(`好的主人,我终于又可以在群${groupId}和大家聊天了`) } else { - await e.reply(`主人,我在群${groupId}中已经是启动状态了哦`) + await this.reply(`主人,我在群${groupId}中已经是启动状态了哦`) } } else { - await e.reply('主人还没告诉我群号呢') + await this.reply('主人还没告诉我群号呢') return false } } else { @@ -1186,14 +1206,14 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, for (let i = 0; i < keys.length; i++) { await redis.del(keys[i]) } - await e.reply('好的,我会开启所有群聊响应') + await this.reply('好的,我会开启所有群聊响应') } else if (keys || keys.length > 0) { for (let i = 0; i < keys.length; i++) { await redis.del(keys[i]) } - await e.reply('已经开启过全群响应啦') + await this.reply('已经开启过全群响应啦') } else { - await e.reply('我没有在任何群休眠哦') + await this.reply('我没有在任何群休眠哦') } } } @@ -1427,7 +1447,7 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, async setOpenAIPlatformToken (e) { this.setContext('doSetOpenAIPlatformToken') - await e.reply('请发送refreshToken\n你可以在已登录的platform.openai.com后台界面打开调试窗口,在终端中执行\nJSON.parse(localStorage.getItem(Object.keys(localStorage).filter(k => k.includes(\'auth0\'))[0])).body.refresh_token\n如果仍不能查看余额,请退出登录重新获取刷新令牌.设置后可以发送#chatgpt设置sessKey来将sessKey作为API Key使用') + await this.reply('请发送refreshToken\n你可以在已登录的platform.openai.com后台界面打开调试窗口,在终端中执行\nJSON.parse(localStorage.getItem(Object.keys(localStorage).filter(k => k.includes(\'auth0\'))[0])).body.refresh_token\n如果仍不能查看余额,请退出登录重新获取刷新令牌.设置后可以发送#chatgpt设置sessKey来将sessKey作为API Key使用') } async getSessKey (e) { @@ -1455,9 +1475,9 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, let errMsg = await refreshRes.json() logger.error(JSON.stringify(errMsg)) if (errMsg.error === 'access_denied') { - await e.reply('刷新令牌失效,请重新发送【#chatgpt设置后台刷新token】进行配置。建议退出platform.openai.com重新登录后再获取和配置') + await this.reply('刷新令牌失效,请重新发送【#chatgpt设置后台刷新token】进行配置。建议退出platform.openai.com重新登录后再获取和配置') } else { - await e.reply('获取失败') + await this.reply('获取失败') } return false } @@ -1480,9 +1500,9 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, let sess = authRes.user.session.sensitive_id if (sess) { Config.apiKey = sess - await e.reply('已成功将sessKey设置为apiKey,您可以发送#openai余额来查看该账号余额') + await this.reply('已成功将sessKey设置为apiKey,您可以发送#openai余额来查看该账号余额') } else { - await e.reply('设置失败!') + await this.reply('设置失败!') } } } @@ -1493,7 +1513,7 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, return false } Config.OpenAiPlatformRefreshToken = token.replaceAll('\'', '') - await this.e.reply('设置成功') + await this.reply('设置成功') this.finish('doSetOpenAIPlatformToken') } @@ -1535,7 +1555,7 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, return true } this.setContext('doImportConfig') - await e.reply('请发送配置文件') + await this.reply('请发送配置文件') } async doImportConfig (e) { @@ -1591,7 +1611,7 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, await this.reply(await makeForwardMsg(this.e, changeConfig.map(msg => `修改项:${msg.item}\n旧数据\n\n${msg.old}\n\n新数据\n ${msg.value}`))) } catch (error) { console.error(error) - await e.reply('配置文件错误') + await this.reply('配置文件错误') } } } else { @@ -1605,18 +1625,18 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, async switchSmartMode (e) { if (e.msg.includes('开启')) { if (Config.smartMode) { - await e.reply('已经开启了') + await this.reply('已经开启了') return } Config.smartMode = true - await e.reply('好的,已经打开智能模式,注意API额度哦。配合开启读取群聊上下文效果更佳!') + await this.reply('好的,已经打开智能模式,注意API额度哦。配合开启读取群聊上下文效果更佳!') } else { if (!Config.smartMode) { - await e.reply('已经是关闭得了') + await this.reply('已经是关闭得了') return } Config.smartMode = false - await e.reply('好的,已经关闭智能模式') + await this.reply('好的,已经关闭智能模式') } } @@ -1638,7 +1658,7 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, // console.log(value) modelList.push(value) }) - await this.e.reply(makeForwardMsg(e, modelList, '模型列表')) + await this.reply(makeForwardMsg(e, modelList, '模型列表')) } async setAPIModel (e) { @@ -1717,10 +1737,10 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, async switchBingSearch (e) { if (e.msg.includes('启用') || e.msg.includes('开启')) { Config.sydneyEnableSearch = true - await e.reply('已开启必应搜索') + await this.reply('已开启必应搜索') } else { Config.sydneyEnableSearch = false - await e.reply('已禁用必应搜索') + await this.reply('已禁用必应搜索') } } @@ -1735,24 +1755,24 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务, config.push(`\n当前必应反代:${Config.sydneyReverseProxy}`) } config.push(`\n当前星火模型:${Config.xhmode}`) - e.reply(config) + this.reply(config) } async switchStream (e) { if (e.msg.includes('开启')) { if (Config.apiStream) { - await e.reply('已经开启了') + await this.reply('已经开启了') return } Config.apiStream = true - await e.reply('好的,已经打开API流式输出') + await this.reply('好的,已经打开API流式输出') } else { if (!Config.apiStream) { - await e.reply('已经是关闭得了') + await this.reply('已经是关闭得了') return } Config.apiStream = false - await e.reply('好的,已经关闭API流式输出') + await this.reply('好的,已经关闭API流式输出') } } } diff --git a/apps/md.js b/apps/md.js new file mode 100644 index 0000000..4409a88 --- /dev/null +++ b/apps/md.js @@ -0,0 +1,40 @@ +import plugin from '../../../lib/plugins/plugin.js' +import {Config} from '../utils/config.js' + +export class ChatGPTMarkdownHandler extends plugin { + constructor () { + super({ + name: 'chatgptmd处理器', + priority: -100, + namespace: 'chatgpt-plugin', + handler: [{ + key: 'chatgpt.markdown.convert', + fn: 'mdHandler' + }] + }) + } + + async mdHandler (e, options, reject) { + const { content, prompt, use } = options + if (Config.enableMd) { + let mode = transUse(use) + return `> ${prompt}\n\n---\n${content}\n\n---\n*当前模式:${mode}*` + } else { + return content + } + } +} + +function transUse (use) { + let useMap = { + api: Config.model, + bing: '必应(Copilot)' + Config.toneStyle, + gemini: Config.geminiModel, + xh: '讯飞星火 ' + Config.xhmode, + qwen: '通义千问 ' + Config.qwenModel, + claude2: 'Claude 3 Sonnet', + glm4: 'ChatGLM4', + chat3: 'ChatGPT官网' + } + return useMap[use] || use +} diff --git a/apps/vocal.js b/apps/vocal.js index d6adcb8..74ce9d8 100644 --- a/apps/vocal.js +++ b/apps/vocal.js @@ -20,15 +20,15 @@ export class Vocal extends plugin { } ] }) - this.task = [ - { - // 设置十分钟左右的浮动 - cron: '0/1 * * * ?', - // cron: '*/2 * * * *', - name: '保持suno心跳', - fnc: this.heartbeat.bind(this) - } - ] + // this.task = [ + // { + // // 设置十分钟左右的浮动 + // cron: '0/1 * * * ?', + // // cron: '*/2 * * * *', + // name: '保持suno心跳', + // fnc: this.heartbeat.bind(this) + // } + // ] } async heartbeat (e) { diff --git a/guoba.support.js b/guoba.support.js index 9115d88..683c636 100644 --- a/guoba.support.js +++ b/guoba.support.js @@ -57,6 +57,12 @@ export function supportGuoba () { bottomHelpMessage: '将输出更多调试信息,如果不希望控制台刷屏的话,可以关闭', component: 'Switch' }, + { + field: 'enableMd', + label: 'QQ开启markdown', + bottomHelpMessage: 'qq的第三方md,非QQBot。需要适配器实现segment.markdown和segment.button方可使用,否则不建议开启,会造成各种错误。默认关闭', + component: 'Switch' + }, { field: 'translateSource', label: '翻译来源', diff --git a/utils/claude.ai/index.js b/utils/claude.ai/index.js index 4eeb663..a397aba 100644 --- a/utils/claude.ai/index.js +++ b/utils/claude.ai/index.js @@ -132,7 +132,8 @@ export class ClaudeAIClient { let body = { attachments, files: [], - model: 'claude-2.1', + // 官方更新后这里没有传值了 + // model: 'claude-2.1', prompt: text, timezone: 'Asia/Hong_Kong' } diff --git a/utils/config.js b/utils/config.js index 5e9dd77..fce6809 100644 --- a/utils/config.js +++ b/utils/config.js @@ -27,6 +27,7 @@ const defaultConfig = { openAiBaseUrl: defaultOpenAIReverseProxy, OpenAiPlatformRefreshToken: '', openAiForceUseReverse: false, + apiStream: false, drawCD: 30, model: '', temperature: 0.8, @@ -178,6 +179,7 @@ const defaultConfig = { sunoSessToken: '', sunoClientToken: '', translateSource: 'openai', + enableMd: false, // 第三方md,非QQBot。需要适配器实现segment.markdown和segment.button方可使用,否则不建议开启,会造成各种错误 version: 'v2.7.10' } const _path = process.cwd() diff --git a/utils/face.js b/utils/face.js index 52d4456..c4dc87e 100644 --- a/utils/face.js +++ b/utils/face.js @@ -479,7 +479,7 @@ export async function convertFaces (msg, handleAt = false, e) { groupCardQQMap[groupMembers.get(key).card || groupMembers.get(key).nickname] = groupMembers.get(key).user_id } } -} + } let tmpMsg = '' let tmpFace = '' let tmpAt = '' diff --git a/utils/wordcloud/wordcloud.js b/utils/wordcloud/wordcloud.js index 09d7614..1bcb816 100644 --- a/utils/wordcloud/wordcloud.js +++ b/utils/wordcloud/wordcloud.js @@ -7,7 +7,7 @@ export async function makeWordcloud (e, groupId, duration = 0, userId) { let list = JSON.stringify(topK) logger.info(list) let img = await render(e, 'chatgpt-plugin', 'wordcloud/index', { list }, { retType: 'base64' }) - await e.reply(img, true) + return img } function getTokenizer (e) {