UNPKG

mm_os

Version:

MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。

1,067 lines (972 loc) 29.9 kB
const Manager = require('mm_machine').Manager; const Drive = require('./drive'); const OpenAI = require('openai'); /** * Cmd指令类 * @augments {Manager} * @class */ class Cmd extends Manager { /** * 配置参数 * @type {object} */ static config = { // 模块名称 name: '', // 模块标题 title: 'Cmd指令管理', // 文件名 filename: 'cmd.json', // 模板目录 tpl_dir: __dirname, // 自定义目录,加载项目自定义资源 dir: './app'.fullname(), /** * 搜索模式 dir按目录搜索 | file按文件名搜索 * @type {string} */ search_way: 'file', // 数据库表名 table: 'wechat_message', // 主键 key: 'message_id', // 缓存前缀 cache_prefix: 'cmd_', // 聊天间隔时长,单位:秒,600秒为10分钟 interval: 600, // 是否启用AI对话, 如果为空则不使用 ai: 'deepseek', // AI API密钥 api_key: 'sk-0521b7b3e9494a5e844b66ec4787f89d', // API端点 base_url: 'https://api.deepseek.com', // 模型名称 model: 'deepseek-chat', // 最大对话轮数 max_turns: 50, // 最大令牌数 max_tokens: 2048, // 温度参数 temperature: 0.8 }; /** * 消息对象 * @type {object} */ static msg = { // 消息ID 'message_id': 0, // 结束状态 0-正常 1-结束 'end': 0, // 阶段 1-9阶段 'stage': 1, // 微信/公众号消息ID 'msgid': '', // 更新时间 'update_time': '', // 创建时间 'create_time': '', // 群组 'group': '', // 消息类型 text-文本 image-图片 voice-语音 video-视频 file-文件 location-位置 link-链接 event-事件 other-其他 'msg_type': 'text', // 媒体ID,图片、语音、视频、文件 'media_id': '', // 发信人姓名 'name': '', // 一般情况下,1永久会话/群、2临时会话/群 'type': 1, // 指令 'cmd': '', // 应用ID 'appid': '', // 发信人 'from_user': '', // 收信人 'to_user': '', // 机器人,是否机器人回复 'robot': 'system', // 会话ID,用于判断是否是同一个会话 'chatid': '', // 发信人头像 'avatar': '', // 除指令外,过滤、抽取后的词,多个词用空格分隔 'keyword': '', // 表单,用于记录用户已填参数,json格式字符串 'form': '', // 聊天内容 'content': '', // 消息传递数据,json格式字符串 'data': '', // 备注信息 'note': '' }; /** * 构造函数 * @param {object} config 配置参数 * @param {object} parent 父级模块 */ constructor(config, parent) { super({ ...Cmd.config, ...config }, parent); this.list_before = []; this.list_check = []; this.list_main = []; this.list_render = []; this.list_after = []; // 智能指令工具函数 this.tools = []; } } /** * Cmd驱动类 */ Cmd.prototype.Drive = Drive; /** * 初始化 * @private */ Cmd.prototype._preset = function () { // 初始化OpenAI客户端 this._initOpenAIClient(); }; /** * 初始化OpenAI客户端 * @private */ Cmd.prototype._initOpenAIClient = function () { var cg = this.config; if (cg.ai && cg.api_key) { try { this.client = new OpenAI({ baseURL: cg.base_url, apiKey: cg.api_key }); } catch (error) { this.log('error', 'AI客户端初始化失败', error.message); this.client = null; } } else { this.client = null; } }; /** * 构建完整指令列表 */ Cmd.prototype._fullList = async function () { this.list_before.clear(); this.list_check.clear(); this.list_main.clear(); this.list_render.clear(); this.list_after.clear(); let infos = this.getInfos(); for (var i = 0; i < infos.length; i++) { var info = infos[i]; if (info.state === 1) { let mod = this.getMod(info.name); if (mod) { switch (mod.config.tense) { case 'before': this.list_before.push(info); break; case 'check': this.list_check.push(info); break; case 'render': this.list_render.push(info); break; case 'after': this.list_after.push(info); break; default: this.list_main.push(info); break; } } } } }; /** * 下达指令 * @param {string} name 名称 * @param {number} state 状态 * @param {...any} params 参数集合 * @returns {object|string} 返回指令执行结果 */ Cmd.prototype.cmd = async function (name, state, ...params) { var obj = this.getMod(name); if (!obj) { return '错误: 指令不存在'; } return await obj.call('cmd', state, ...params); }; /** * 新建消息对象 * @returns {object} 返回新建的消息对象 */ Cmd.prototype.newMsg = function () { return { ...Cmd.msg }; }; /** * 更新后 * @param {string} dir_path 目录路径 */ Cmd.prototype.updateAfter = async function (dir_path) { // 构建完整指令列表 this._fullList(); // 构建指令工具函数 this.tools = this._buildTools(); }; /** * 获取智能指令的工具函数 * @param {number} index 当前阶段ID * @returns {Array} 返回工具函数数组 */ Cmd.prototype._buildTools = function (index = 0) { let tools = []; for (var i = 0; i < this.list_main.length; i++) { var info = this.list_main[i]; if (info.state === 1) { let mod = this.getMod(info.name); if (mod) { let tool = this._buildTool(mod.config, index); if (tool) { tools.push(tool); } } } } return tools; }; /** * 构建智能指令工具函数 * @param {object} o 指令配置项 * @param {number} index 当前阶段ID * @returns {object|null} 返回构建的工具函数对象,若失败则返回null */ Cmd.prototype._buildTool = function (o, index = 0) { try { let description = o.title + "," + o.description; if (o.example) { description += ",例如:" + o.example; } let tool = { // 类型 type: 'function', // 函数定义 function: { // 函数名称 name: o.name, // 函数描述 description }, // 启用结构化输出 strict: true } let pm = this._buildParams(o.stage, index); if (pm) { let { props, required } = pm; tool.function.parameters = { type: 'object', properties: props, required, // 配合 strict 模式 additionalProperties: false } } return tool; } catch (error) { this.log('error', `${o.name} 构建工具函数失败`, error); return null; } }; /** * 构建智能指令的参数 * @param {array} stage 指令阶段对象 * @param {number} index 当前阶段索引 * @returns {object} 返回当前阶段的参数对象 * @private */ Cmd.prototype._buildParams = function (stage, index) { if (!stage || index < 0 || !stage.length || index >= stage.length) { return null } let props = {}; let required = []; var list = stage[index].param; for (let i = 0; i < list.length; i++) { let o = list[i]; let description = o.title + "," + o.desc; if (o.example) { description += ",例如:" + o.example; } if (o.name) { props[o.name] = { type: o.type || 'string', description }; if (o.required) { required.push(o.name); } } } return { props, required }; }; /** * 调用AI模型(公开通用) * @param {array} messages 消息对象数组 * @param {array} tools 工具函数数组 * @param {string} model 模型名称 * @returns {object|string} 返回AI模型的响应消息对象,若失败则返回错误信息字符串 */ Cmd.prototype.postToAI = async function (messages, tools = [], model = '') { if (!this.client) { return '错误: AI模型未初始化'; } try { let cg = this.config; let body = { model: model || cg.model, messages, temperature: cg.temperature, max_tokens: cg.max_tokens || 2048, stream: false }; if (tools && tools.length > 0) { body.tools = tools; body.tool_choice = 'auto'; } return res = await this.client.chat.completions.create(body); } catch (error) { this.log('error', 'AI API调用失败', error.message); // 根据错误类型提供更具体的提示 if (error.code === 'insufficient_quota' || error.status === 402) { return '抱歉,API配额不足,请检查账户余额'; } else if (error.code === 'invalid_api_key' || error.status === 401) { return 'API密钥无效,请检查配置'; } else if (error.status === 429) { return '请求过于频繁,请稍后重试'; } else { return '抱歉,AI服务暂时不可用,请稍后再试'; } } }; /** * 发布消息到AI模型 * @param {object} msg 消息对象 * @param {object} db 数据库对象 * @returns {object|string} 返回AI模型的响应消息对象,若失败则返回错误信息字符串 * @private */ Cmd.prototype.callAI = async function (msg, db) { if (!msg || !msg.content) { return '错误: 消息内容不能为空'; } msg.robot = this.config.ai; let content = ''; var messages = await this._buildMessages(msg, db); if (!messages || messages.length === 0) { throw new Error('消息数组不能为空'); } // 最大迭代次数限制,防止无限循环 const max_iterations = 10; let iteration_count = 0; let has_tool_calls = false; do { has_tool_calls = false; iteration_count++; // 调用AI模型,始终包含工具函数以确保AI返回标准格式 let res = await this.postToAI(messages, this.tools); if (!res || !res.choices || res.choices.length === 0) { throw new Error('AI模型响应为空'); } let message = res.choices[0].message; messages.push(message); // 检查是否有工具调用 if (message.tool_calls && message.tool_calls.length > 0) { has_tool_calls = true; // 处理工具调用,返回工具调用信息 let rets = await this._handleToolCalls(msg, db, message.tool_calls); if (!rets || rets.length === 0) { this.log('warn', '处理工具调用失败', rets); // 如果工具调用失败,移除工具调用相关的消息,然后让AI直接回复 // 保留系统消息和用户消息,移除AI的工具调用响应 messages = messages.filter(msg => msg.role !== 'assistant' || !msg.tool_calls); // 重新调用AI,这次不包含工具函数,让AI直接回复 let direct_res = await this.postToAI(messages, []); if (direct_res && direct_res.choices && direct_res.choices.length > 0) { let direct_message = direct_res.choices[0].message; content = direct_message.content || '抱歉,我无法处理这个请求'; // 添加直接回复到消息上下文 messages.push(direct_message); has_tool_calls = false; // 结束循环 } else { content = '抱歉,AI服务暂时不可用,请稍后再试'; has_tool_calls = false; // 结束循环 } } else { // 将工具调用结果添加到消息上下文 messages = messages.concat(rets); } } else { // 没有工具调用,获取最终响应内容 content = message.content || '错误:AI未提供有效响应'; } // 防止无限循环 if (iteration_count >= max_iterations) { this.log('warn', '达到最大迭代次数限制', iteration_count); if (!content) { content = '错误:达到最大处理次数限制,请简化您的请求'; } break; } } while (has_tool_calls && msg.robot); // 保存指令执行日志 await this.saveHistory(msg, db, messages); return content; }; /** * 构建消息数组 * @param {object} msg 消息对象 * @param {object} db 数据库对象 * @returns {array} 返回构建的消息数组 * @private */ Cmd.prototype._buildMessages = async function (msg, db) { if (!msg || !msg.content) { return []; } var messages = await this.getHistory(msg, db); if (!messages || messages.length === 0) { messages = []; let system_prompt = this._getSystemPrompt(); messages.push({ role: 'system', content: system_prompt }); } messages.push({ role: 'user', content: msg.content }); return messages; }; /** * 获取系统提示 * @returns {string} 返回系统提示字符串 * @private */ Cmd.prototype._getSystemPrompt = function () { // 获取个性提示词 let personality_prompt = this._getPersonalityPrompt(); // 获取规范提示词 let standard_prompt = this._getStandardPrompt(); // 合并个性提示和规范提示 let system_prompt = `${personality_prompt}\n${standard_prompt}`; return system_prompt; }; /** * 获取个性提示词 * @returns {string} 返回个性提示字符串 * @private */ Cmd.prototype._getPersonalityPrompt = function () { let prompt = this.config.personality_prompt; if (!prompt) { prompt = `你是一个专业的智能指令转换专家,具备以下核心能力: ## 角色定位 - 智能指令解析专家,擅长将自然语言转换为结构化指令 - 上下文理解大师,能够基于会话历史和状态进行智能判断 - 多模态消息处理专家,支持文本、图片、语音、文件等多种消息类型 ## 核心能力 1. **自然语言理解**:准确理解用户意图,识别关键指令和参数 2. **上下文感知**:利用消息历史、会话状态、表单数据等上下文信息 3. **指令映射**:将用户请求映射到合适的系统指令和工具函数 4. **参数提取**:自动提取和补全指令执行所需的参数 5. **多步骤规划**:处理复杂的多步骤指令执行场景 ## 专业特性 - 响应速度快,判断准确,能够处理复杂的指令转换场景 - 具备良好的容错能力,能够处理模糊或不完整的用户输入 - 支持个性化定制,能够根据不同的用户和场景调整响应策略 ## 工具调用失败处理策略 - 当系统工具调用失败时,基于自己的知识库直接回答用户问题 - 回复时要自然流畅,不要提及工具调用失败或技术细节 - 对于天气查询:直接提供一般性天气信息、季节特点或穿衣建议,就像自己知道这些信息一样 - 对于时间查询:直接提供当前时间或相关时间信息 - 对于计算问题:直接计算结果并给出答案 - 对于其他问题:基于常识和经验提供有用的回答 - 避免提及任何技术限制,保持回复的自然性和实用性`; } return prompt; }; /** * 获取规范提示词 * @returns {string} 返回规范提示字符串 * @private */ Cmd.prototype._getStandardPrompt = function () { let prompt = this.config.standard_prompt; if (!prompt) { prompt = ` ## 消息上下文信息 你可以利用以下消息上下文信息来更好地理解用户意图: ### 基础消息属性 - **消息类型**: 文本、图片、语音、视频、文件、位置、链接、事件等 - **消息内容**: 原始消息文本、媒体文件URL、文件信息等 - **时间信息**: 消息发送时间、创建时间、更新时间 ### 会话上下文 - **会话类型**: 群组、私聊、临时会话、公众号会话 - **参与者信息**: 发信人ID、收信人ID、机器人标识、群组成员 - **会话状态**: 会话ID、会话阶段、结束状态、活跃状态 ### 历史状态 - **关键词历史**: 用户历史关键词、常用指令模式 - **表单数据**: 已填写的表单字段、待补充的参数 - **备注信息**: 用户备注、会话标签、自定义属性 ## 智能指令映射规则 ### 1. 消息类型映射规则 - **文本消息**: - 优先匹配文本处理指令(搜索、翻译、计算等) - 识别指令关键词(如"搜索""查询""计算"等) - 支持自然语言指令(如"帮我找一下资料") - **媒体消息**(图片/语音/视频): - 优先匹配媒体处理指令(识别、分析、转换等) - 结合文本内容进行多模态理解 - 支持媒体文件的分析和提取 - **文件消息**: - 优先匹配文件处理指令(上传、下载、解析等) - 根据文件类型选择合适工具(文档、表格、图片等) - 支持文件内容的智能提取 - **位置消息**: - 优先匹配位置相关指令(导航、周边搜索、地理信息) - 结合位置坐标和描述信息 ### 2. 会话上下文映射规则 - **群组消息**: - 考虑群组特定的指令和权限 - 支持群组管理功能(成员管理、公告等) - 适应群组交流场景 - **私聊消息**: - 考虑个人化指令和偏好设置 - 支持个性化服务和定制功能 - 保护用户隐私信息 - **临时会话**: - 考虑临时性指令和一次性服务 - 快速响应,简化流程 - 支持会话状态的快速清理 ### 3. 历史状态映射规则 - **阶段信息**: - 根据当前阶段选择合适的指令流程 - 支持多步骤指令的连续执行 - 维护阶段间的上下文连贯性 - **表单数据**: - 利用已有的表单数据自动补全参数 - 减少用户重复输入 - 支持表单数据的智能验证 - **关键词历史**: - 基于历史关键词理解用户意图 - 识别用户的使用习惯和偏好 - 支持个性化推荐和智能补全 ## 指令处理流程 ### 1. 意图识别阶段 - 分析用户输入的自然语言 - 识别关键指令词和参数 - 结合上下文信息理解真实意图 ### 2. 指令映射阶段 - 将用户意图映射到系统指令 - 选择合适的工具函数 - 确定指令执行优先级 ### 3. 参数处理阶段 - 提取和验证指令参数 - 补全缺失的参数信息 - 处理参数格式转换 ### 4. 执行规划阶段 - 规划指令执行步骤 - 处理多步骤指令场景 - 考虑异常情况和回退策略 ## 特别注意 ### 智能判断原则 - 充分利用所有可用上下文信息 - 优先考虑最相关的指令映射 - 支持模糊匹配和容错处理 ### 用户体验优化 - 减少用户输入,智能补全参数 - 提供清晰的指令反馈 - 支持指令的撤销和重做 ### 错误处理机制 - 识别和处理无效指令 - 提供友好的错误提示 - 支持指令的重新解释和修正 ### 工具调用失败处理 - 当工具调用失败时,基于自己的知识直接回答用户问题 - 回复时要自然流畅,不要提及工具调用失败或技术细节 - 对于常见问题(如天气、时间、计算等),直接提供一般性信息或建议,就像自己知道这些信息一样 - 避免重复工具调用过程,直接给出有用的回答 - 如果无法提供准确信息,可以给出替代方案或建议,但不要暴露技术限制 ### 性能考虑 - 快速响应,减少等待时间 - 优化指令映射算法 - 支持并发指令处理`; } return prompt; }; /** * 执行指令 * @param {string} cmd 指令字符串 * @param {string} method 方法名 * @param {...*} args 指令参数 * @returns {string} 返回指令执行结果 * @private */ Cmd.prototype._exec = async function (tense, cmd, method, ...args) { var list = this['list_' + tense]; if (!list) { throw new Error(` 不存在时态: ${tense}`); } // 查找指令 for (var i = 0; i < list.length; i++) { var info = list[i]; if (info.name === cmd) { let mod = this.getMod(info.name); if (mod) { return await mod.call(method, ...args); } } } }; /** * 推送工具调用消息 * @param {*} ret 工具调用执行结果 * @param {string} tool_call_id 工具调用ID * @returns {object} 返回工具调用消息对象 * @private */ Cmd.prototype.getMessage = function (ret, tool_call_id) { if (typeof ret === 'object') { if (ret.error) { return { role: 'tool', tool_call_id, content: JSON.stringify({ error: ret.error.message }), } } ret = JSON.stringify(ret); } else if (typeof ret === 'string') { if (this._isError(ret)) { // 记录工具调用信息 return { role: 'tool', tool_call_id, content: JSON.stringify({ error: ret }) } } } // 记录工具调用信息 return { role: 'tool', tool_call_id, content: ret } }; /** * 判断是否为错误信息 * @param {string} content 内容字符串 * @returns {boolean} 返回是否为错误信息 * @private */ Cmd.prototype._isError = function (content) { return content.startsWith('错误') || content.startsWith('不能为'); }; /** * 处理工具调用 * @description 处理消息中的工具调用,执行对应的指令并返回结果 * @param {object} msg 消息对象,包含工具调用信息 * @param {object} db 数据管理器,用于存储和检索数据 * @param {Array} tool_calls 工具调用数组,每个元素包含工具调用的信息 * @returns {string} 返回工具调用处理结果,格式为JSON字符串 * @private */ Cmd.prototype._handleToolCalls = async function (msg, db, tool_calls) { var messages = []; for (var i = 0; i < tool_calls.length; i++) { var tool = tool_calls[i]; var cmd = tool.function.name; var form = {}; try { // 解析函数参数 var args = tool.function.arguments; if (args) { if (typeof args === 'string') { form = JSON.parse(args); } else { form = args; } } msg.form = form; var ret = await this._exec('main', cmd, 'main', msg, db); if (ret) { messages.push(this.getMessage(ret, tool.id)); } } catch (error) { this.log('error', `解析工具调用参数失败: ${cmd} `, error.message); messages.push({ role: 'tool', tool_call_id: tool.id, content: JSON.stringify({ error: `工具调用参数解析失败: ${error.message} ` }) }); } } return messages; }; /** * 获取指令执行日志 * @param {object} msg 消息对象,包含指令信息 * @param {object} db 数据管理器,用于存储和检索数据 * @returns {Array} 返回指令执行日志数组 */ Cmd.prototype.getHistory = async function (msg, db) { var key = this._getKey(msg); var logs = await $.cache.get(key); if (!logs) { logs = []; } else if (typeof logs === 'string') { logs = JSON.parse(logs); } return logs; }; /** * 保存指令执行日志 * @param {object} msg 消息对象,包含指令信息 * @param {object} db 数据管理器,用于存储和检索数据 * @param {Array} logs 指令执行日志数组 * @private */ Cmd.prototype.saveHistory = async function (msg, db, logs) { var key = this._getKey(msg); await $.cache.set(key, logs, this.config.interval); }; /** * 获取指令执行日志缓存键 * @param {object} msg 消息内容 * @returns {string} 返回指令执行日志缓存键 */ Cmd.prototype._getKey = function (msg) { return this.config.cache_prefix + msg.form + "_" + msg.to_user + "_" + msg.group; }; /** * 执行指令 * @param {object} msg 消息对象,包含指令信息 * @param {object} db 数据管理器,用于存储和检索数据 * @returns {string} 返回指令执行结果,格式为JSON字符串 * @private */ Cmd.prototype.run = async function (msg, db) { // 判断是否含有消息和消息正文 if (!msg || !msg.content) { return; } // 初始化数据库配置 db.table = this.config.table; db.key = this.config.key; // 统一的指令处理流程 var ret = await this._run(msg, db); // 记录执行结果 db.ret = ret; return ret; }; /** * 指令行为主函数 * @param {object} msg 消息 * @param {object} db 数据管理器,如: { next: async function{}, ret: {} } * @returns {object} 执行结果 * @private */ Cmd.prototype._run = async function (msg, db) { return null; var cg = this.config; if (cg.ai) { msg.robot = cg.ai; let ret = await this.callAI(msg, db); return ret; } else { let ret = await this._exec('main', msg.content, 'main', msg, db); return ret; } }; /** * 执行指令前处理 * @param {object} msg 消息对象 * @param {object} db 数据库对象 * @returns {object|string} 返回指令执行结果 */ Cmd.prototype._runBefore = async function (msg, db) { db.logs = await this._getLogs(msg, db); await this._fullMsg(msg, db); return await this.runSub(msg, db, 'before'); }; /** * 执行主指令 * @param {object} msg 消息 * @param {object} db 数据管理器 * @returns {object} 返回执行结果 * @private */ Cmd.prototype._runMain = async function (msg, db) { // 先判断本次内容是否为指令 var ret_main = await this.runSub(msg, db, 'main'); if (ret_main) { return ret_main; } // 获取历史未完成的指令,拼接本次内容并执行 var log = await this.getContext(msg, db); if (!log) { return null; } return await this.runSub(m, db, 'main'); }; /** * 执行后时态指令 * @param {object} msg 消息 * @param {object} db 数据管理器 * @returns {object|string} 返回指令执行结果 */ Cmd.prototype._runAfter = async function (msg, db) { var ret = await this.runSub(msg, db, 'after'); return ret; }; /** * 补全消息 * @param {object} msg 消息对象 * @param {object} db 数据管理器 * @returns {object} 返回合并后的消息对象 */ Cmd.prototype._fullMsg = function (msg, db) { }; /** * 执行指令 * @param {object} msg 消息对象 * @param {object} db 数据库对象 * @param {string} tense 时态 * @returns {object|string} 返回指令执行结果 */ Cmd.prototype.runSub = async function (msg, db, tense = 'main') { var list = this['list_' + tense]; if (!list) { return; } var ret; for (var i = 0, info; info = list[i++];) { if (info.state === 1) { let mod = this.getMod(info.name); if (mod) { ret = await mod.run(msg, db); if (ret) { db.ret = ret; // 如果匹配指令则将该消息定义为使用该指令 msg.cmd = info.name; if (mod.config.end) { break; } } } } } return ret; }; /** * 获取对话历史 * @param {object} msg 当前消息 * @param {object} db 数据库对象 * @returns {Array} 返回历史消息数组 */ Cmd.prototype._getLogs = async function (msg, db) { // 先尝试从缓存中获取对话历史 var logs = await this._getLogsFromCache(msg); if (logs.length > 0) { return logs; } // 如果缓存中没有,从数据库查询 logs = await this._getLogsFromDB(msg, db); if (logs.length > 0) { // 缓存查询结果 await this._setLogsToCache(msg, logs); } return logs; }; /** * 从数据库中获取对话历史 * @param {object} msg 当前消息 * @param {object} db 数据库对象 * @returns {Array} 返回历史消息数组 * @private */ Cmd.prototype._getLogsFromDB = async function (msg, db) { var cg = this.config; var max_turns = cg.max_turns; // 基于实际数据库字段查询对话记录 var query = { from_user: msg.from_user, to_user: msg.to_user, group: msg.group, type: msg.type }; // 如果当前消息有chatid,优先基于chatid查询同一个对话会话 if (msg.chatid) { query.chatid = msg.chatid; } var db1 = db.new(cg.table, cg.key); var logs = await db1.getList(query, '`time_create` desc', max_turns * 2); return logs; }; /** * 从缓存中获取对话历史 * @param {object} msg 当前消息 * @returns {Array} 返回历史消息数组 * @private */ Cmd.prototype._getLogsFromCache = async function (msg) { var logs = await $.cache.get(msg.chatid || this._getKey(msg)); if (!logs) { logs = []; } else if (typeof logs === 'string') { logs = JSON.parse(logs); } return logs; }; /* 导出指令 */ exports.Cmd = Cmd; /** * Cmd事件池 */ if (!$.pool.cmd) { $.pool.cmd = {}; } /** * Cmd管理器,用于创建缓存 * @param {string} scope 作用域 * @param {string} title 标题 * @returns {object} 返回一个缓存类 */ function cmdAdmin(scope, title) { var sc = scope || $.val.scope + ''; var obj = $.pool.cmd[sc]; if (!obj) { $.pool.cmd[sc] = new Cmd({ name: sc, title: title || sc }); obj = $.pool.cmd[sc]; } return obj; } /** * @module 导出Cmd管理器 */ if ($.admin) { $.admin.cmd = cmdAdmin; }