diff --git a/apps/ai.js b/apps/ai.js index 00397e1..99a8ecf 100644 --- a/apps/ai.js +++ b/apps/ai.js @@ -10,7 +10,7 @@ import Group from '../lib/yunzai/group.js'; import Message from '../lib/yunzai/message.js'; import YunzaiUtils from '../lib/yunzai/utils.js'; import { segment } from 'oicq'; -import tools from "../components/tool.js"; +import tools from '../components/tool.js'; const nickname = await ConfigControl.get('profile')?.nickName; export class crystelfAI extends plugin { @@ -28,7 +28,7 @@ export class crystelfAI extends plugin { { reg: '^(#|/)?重置(对话|会话)$', fnc: 'clearChatHistory', - } + }, ], }); this.isInitialized = false; @@ -48,31 +48,31 @@ export class crystelfAI extends plugin { } } - async in(e){ + async in(e) { return await index(e); } - async clearChatHistory(e){ - let session = SessionManager.createOrGetSession(e.group_id,e.user_id,e); - if(!session) return e.reply(`当前有群友正在和${nickname}聊天噢,请等待会话结束..`,true); - SessionManager.updateChatHistory(e.group_id,[]); - SessionManager.deactivateSession(e.group_id,e.user_id); - return e.reply('成功重置聊天,聊天记录已经清除了..',true); + async clearChatHistory(e) { + let session = SessionManager.createOrGetSession(e.group_id, e.user_id, e); + if (!session) return e.reply(`当前有群友正在和${nickname}聊天噢,请等待会话结束..`, true); + SessionManager.updateChatHistory(e.group_id, []); + SessionManager.deactivateSession(e.group_id, e.user_id); + return e.reply('成功重置聊天,聊天记录已经清除了..', true); } } -Bot.on("message.group",async(e)=>{ +Bot.on('message.group', async (e) => { let flag = false; - if(e.message){ - e.message.forEach(message=>{ - if(message.type === 'at' && message.qq == e.bot.uin){ + if (e.message) { + e.message.forEach((message) => { + if (message.type === 'at' && message.qq == e.bot.uin) { flag = true; } - }) + }); } - if(!flag) return; + if (!flag) return; return await index(e); -}) +}); async function index(e) { try { @@ -91,12 +91,12 @@ async function index(e) { if (e.user_id === e.bot.uin) { return; } - const userMessage = await extractUserMessage(e.msg, nickname,e); + const userMessage = await extractUserMessage(e.msg, nickname, e); if (!userMessage) { return; } const adapter = await YunzaiUtils.getAdapter(e); - await Message.emojiLike(e,e.message_id,128064,e.group_id,adapter);//👀 + await Message.emojiLike(e, e.message_id, 128064, e.group_id, adapter); //👀 const result = await processMessage(userMessage, e, aiConfig); if (result && result.length > 0) { // TODO 优化流式输出 @@ -104,9 +104,10 @@ async function index(e) { } } catch (error) { logger.error(`[crystelf-ai] 处理消息失败: ${error.message}`); + await Message.emojiLike(e, e.message_id, 10060, e.group_id, adapter); const config = await ConfigControl.get(); const aiConfig = config?.ai; - return e.reply(segment.image(await Meme.getMeme(aiConfig.character, 'default'))); + //return e.reply(segment.image(await Meme.getMeme(aiConfig.character, 'default'))); } } @@ -114,32 +115,31 @@ async function extractUserMessage(msg, nickname, e) { if (e.message) { let text = []; let at = []; - e.message.forEach(message => { + e.message.forEach((message) => { logger.info(message); if (message.type === 'text') { text.push(message.text); } else if (message.type === 'at') { at.push(message.qq); } - }) + }); let returnMessage = ''; if (text.length > 0) { - text.forEach(message => { + text.forEach((message) => { returnMessage += `[${e.sender?.nickname},id:${e.user_id}]说:${message}\n`; - }) + }); } if (at.length > 0) { at.forEach((at) => { - if(at === e.bot.uin){ + if (at === e.bot.uin) { returnMessage += `[${e.sender?.nickname},id:${e.user_id}]@(at)了你,你的id是${at}\n`; - } - else{ - returnMessage += `[${e.sender?.nickname},id:${e.user_id}]@(at)了一个人,id是${at}\n`; + } else { + returnMessage += `[${e.sender?.nickname},id:${e.user_id}]@(at)了一个人,id是${at}\n`; } }); } const imgUrls = await YunzaiUtils.getImages(e, 1, true); - if(imgUrls){ + if (imgUrls) { returnMessage += `[${e.sender?.nickname},id:${e.user_id}]发送了一张图片(你可能暂时无法查看)\n`; } return returnMessage; @@ -157,7 +157,7 @@ async function extractUserMessage(msg, nickname, e) { */ async function processMessage(userMessage, e, aiConfig) { const mode = aiConfig?.mode || 'mix'; - logger.info(`[crystelf-ai] 群${e.group_id} 用户${e.user_id}使用${mode}进行回复..`) + logger.info(`[crystelf-ai] 群${e.group_id} 用户${e.user_id}使用${mode}进行回复..`); switch (mode) { case 'keyword': return await handleKeywordMode(userMessage, e); @@ -209,14 +209,14 @@ async function handleMixMode(userMessage, e, aiConfig) { if (isTooLong) { //消息太长,使用AI回复 - logger.info('[crystelf-ai] 消息过长,使用ai回复') + logger.info('[crystelf-ai] 消息过长,使用ai回复'); return await callAiForResponse(userMessage, e, aiConfig); } else { const matchResult = await KeywordMatcher.matchKeywords(userMessage, 'ai'); if (matchResult && matchResult.matched) { - const session = SessionManager.createOrGetSession(e.group_id, e.user_id,e); + const session = SessionManager.createOrGetSession(e.group_id, e.user_id, e); const historyLen = aiConfig.chatHistory; - const chatHistory = session.chatHistory.slice(-historyLen|-10); + const chatHistory = session.chatHistory.slice(-historyLen | -10); const res = [ { type: 'message', @@ -239,11 +239,11 @@ async function handleMixMode(userMessage, e, aiConfig) { { role: 'assistant', content: JSON.stringify(resMessage) }, ]; SessionManager.updateChatHistory(e.group_id, newChatHistory); - SessionManager.deactivateSession(e.group_id,e.user_id); + SessionManager.deactivateSession(e.group_id, e.user_id); return res; } else { - logger.info('[crystelf-ai] 关键词匹配失败,使用ai回复') + logger.info('[crystelf-ai] 关键词匹配失败,使用ai回复'); //关键词匹配失败,使用AI回复 return await callAiForResponse(userMessage, e, aiConfig); } @@ -253,20 +253,21 @@ async function handleMixMode(userMessage, e, aiConfig) { async function callAiForResponse(userMessage, e, aiConfig) { try { //创建session - const session = SessionManager.createOrGetSession(e.group_id, e.user_id,e); + const session = SessionManager.createOrGetSession(e.group_id, e.user_id, e); if (!session) { logger.info( `[crystelf-ai] 群${e.group_id} , 用户${e.user_id}无法创建session,请检查是否聊天频繁` ); + await Message.emojiLike(e, e.message_id, 128166, e.group_id, adapter); return null; } //搜索相关记忆 - const memories = await MemorySystem.searchMemories(e.user_id,e.msg||'',5); - logger.info(`[crystelf-ai] ${memories}`) + const memories = await MemorySystem.searchMemories(e.user_id, e.msg || '', 5); + logger.info(`[crystelf-ai] ${memories}`); //构建聊天历史 const historyLen = aiConfig.chatHistory; - const chatHistory = session.chatHistory.slice(-historyLen|-10); - const aiResult = await AiCaller.callAi(userMessage, chatHistory, memories,e); + const chatHistory = session.chatHistory.slice(-historyLen | -10); + const aiResult = await AiCaller.callAi(userMessage, chatHistory, memories, e); if (!aiResult.success) { logger.error(`[crystelf-ai] AI调用失败: ${aiResult.error}`); return [ @@ -290,17 +291,13 @@ async function callAiForResponse(userMessage, e, aiConfig) { { role: 'assistant', content: aiResult.response }, ]; SessionManager.updateChatHistory(e.group_id, newChatHistory); - SessionManager.deactivateSession(e.group_id,e.user_id); + SessionManager.deactivateSession(e.group_id, e.user_id); return processedResponse; } catch (error) { + await Message.emojiLike(e, e.message_id, 10060, e.group_id, adapter); logger.error(`[crystelf-ai] AI调用失败: ${error.message}`); - SessionManager.deactivateSession(e.group_id,e.user_id); - return [ - { - type: 'meme', - data: 'default', - }, - ]; + SessionManager.deactivateSession(e.group_id, e.user_id); + return []; } } @@ -361,6 +358,8 @@ async function sendResponse(e, messages) { await tools.sleep(40); } } catch (error) { + const adapter = await YunzaiUtils.getAdapter(e); + await Message.emojiLike(e, e.message_id, 10060, e.group_id, adapter); logger.error(`[crystelf-ai] 发送回复失败: ${error.message}`); } } @@ -369,16 +368,18 @@ async function handleCodeMessage(e, message) { try { //渲染代码为图片 logger.info(message); - logger.info(message.language) + logger.info(message.language); const imagePath = await Renderer.renderCode(message.data, message.language); if (imagePath) { await e.reply(segment.image(imagePath)); } else { - await e.reply('渲染代码失败了,待会儿再试试吧..',true); + await e.reply('渲染代码失败了,待会儿再试试吧..', true); } } catch (error) { logger.error(`[crystelf-ai] 处理代码消息失败: ${error.message}`); - await e.reply('渲染代码失败了,待会儿再试试吧..',true); + const adapter = await YunzaiUtils.getAdapter(e); + await Message.emojiLike(e, e.message_id, 10060, e.group_id, adapter); + await e.reply('渲染代码失败了,待会儿再试试吧..', true); } } @@ -390,11 +391,13 @@ async function handleMarkdownMessage(e, message) { await e.reply(segment.image(imagePath)); } else { //渲染失败 TODO 构造转发消息发送,避免刷屏 - await e.reply('渲染markdown失败了,待会儿再试试吧..',true); + await e.reply('渲染markdown失败了,待会儿再试试吧..', true); } } catch (error) { + const adapter = await YunzaiUtils.getAdapter(e); + await Message.emojiLike(e, e.message_id, 10060, e.group_id, adapter); logger.error(`[crystelf-ai] 处理Markdown消息失败: ${error.message}`); - await e.reply('渲染markdown失败了,待会儿再试试吧..',true); + await e.reply('渲染markdown失败了,待会儿再试试吧..', true); } } @@ -402,12 +405,7 @@ async function handleMemeMessage(e, message) { try { const config = await ConfigControl.get('ai'); const memeConfig = config?.memeConfig || {}; - const availableEmotions = memeConfig.availableEmotions || [ - 'happy', - 'sad', - 'angry', - 'confused', - ]; + const availableEmotions = memeConfig.availableEmotions || ['happy', 'sad', 'angry', 'confused']; //情绪是否有效 const emotion = availableEmotions.includes(message.data) ? message.data : 'default'; const character = memeConfig.character || 'default'; @@ -415,7 +413,9 @@ async function handleMemeMessage(e, message) { await e.reply(segment.image(memeUrl)); } catch (error) { logger.error(`[crystelf-ai] 处理表情消息失败: ${error.message}`); - e.reply(segment.image(await Meme.getMeme(aiConfig.character, 'default'))); + const adapter = await YunzaiUtils.getAdapter(e); + await Message.emojiLike(e, e.message_id, 10060, e.group_id, adapter); + //e.reply(segment.image(await Meme.getMeme(aiConfig.character, 'default'))); } } diff --git a/config/ai.json b/config/ai.json index b6a233d..257e7e6 100644 --- a/config/ai.json +++ b/config/ai.json @@ -58,6 +58,19 @@ "?memeConfig": "表情配置", "memeConfig": { "character": "zhenxun", - "availableEmotions": ["angry", "bye", "confused", "default", "good", "goodmorning", "goodnight", "happy", "sad", "shy", "sorry", "surprise"] + "availableEmotions": [ + "angry", + "bye", + "confused", + "default", + "good", + "goodmorning", + "goodnight", + "happy", + "sad", + "shy", + "sorry", + "surprise" + ] } }