UNPKG

xinc

Version:

基于napcat,node-napcat-ts的bot框架

786 lines 32.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PluginManager = void 0; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const Structs_1 = require("../../napcat/Structs"); const config_1 = require("../config"); class PluginManager { constructor(api, logger, pluginsDir = 'plugins', enabledPlugins = []) { this.plugins = new Map(); this.builtinPlugins = new Map(); // 内置插件单独存储 this.handlers = new Map(); this.handlersByPlugin = new Map(); // 跟踪每个插件的处理器 this.enabledPlugins = []; // 已启用的插件列表 this.api = api; this.logger = logger; this.pluginsDir = path_1.default.join(process.cwd(), pluginsDir); this.enabledPlugins = enabledPlugins; // 确保插件目录存在 if (!fs_1.default.existsSync(this.pluginsDir)) { fs_1.default.mkdirSync(this.pluginsDir, { recursive: true }); } // 设置事件处理 this.setupEventHandlers(); } // 设置事件处理 setupEventHandlers() { // 处理私聊消息 this.api.on('message.private', (event) => { // 增强事件对象 const enhancedEvent = this.enhanceMessageEvent(event); this.triggerHandlers('message.private', enhancedEvent); this.triggerHandlers('message', enhancedEvent); }); // 处理群聊消息 this.api.on('message.group', (event) => { // 增强事件对象 const enhancedEvent = this.enhanceMessageEvent(event); this.triggerHandlers('message.group', enhancedEvent); this.triggerHandlers('message', enhancedEvent); }); // 其他事件直接转发 const events = [ 'notice', 'request', 'meta_event', 'notice.notify.poke', 'notice.notify.lucky_king', 'notice.group.increase', 'notice.group.decrease', 'notice.group.admin', 'notice.group.ban', 'notice.friend.add', 'request.friend', 'request.group' ]; for (const event of events) { this.api.on(event, (data) => { this.triggerHandlers(event, data); }); } } // 增强消息事件对象 enhanceMessageEvent(event) { return { ...event, // 回复消息 reply: async (message, quote = false) => { // 处理消息格式 let msgArray = []; // 如果是字符串,转换为文本消息数组 if (typeof message === 'string') { msgArray = [Structs_1.Structs.text(message)]; } // 如果是数组,处理数组中的每个元素 else if (Array.isArray(message)) { msgArray = message.map(item => { if (typeof item === 'string') { return Structs_1.Structs.text(item); } return item; }); } // 如果需要引用回复,添加回复消息 if (quote && event.message_id) { msgArray.unshift(Structs_1.Structs.reply(event.message_id)); } // 根据消息类型发送消息 let result; if (event.message_type === 'private') { result = await this.api.send_private_msg({ user_id: event.user_id, message: msgArray }); // 使用 raw_message 记录日志 const rawContent = typeof message === 'string' ? message : this.extractRawMessage(msgArray); this.logger.info(`发送私聊消息 [${event.user_id}] : ${rawContent}`); } else if (event.message_type === 'group') { result = await this.api.send_group_msg({ group_id: event.group_id, message: msgArray }); // 使用 raw_message 记录日志 const rawContent = typeof message === 'string' ? message : this.extractRawMessage(msgArray); this.logger.info(`发送群消息 [${event.group_id}] : ${rawContent}`); } return result; } }; } // 添加一个辅助方法来提取消息数组中的原始文本 extractRawMessage(msgArray) { return msgArray.map(item => { if (item.type === 'text') { return item.data.text; } else if (item.type === 'image') { return '[图片]'; } else if (item.type === 'face') { return '[表情]'; } else if (item.type === 'at') { return `@${item.data.qq}`; } else if (item.type === 'reply') { return '[回复]'; } else { return `[${item.type}]`; } }).join(''); } // 触发事件处理器 triggerHandlers(event, data) { const handlers = this.handlers.get(event); if (handlers) { for (const handler of handlers) { try { handler(data); } catch (error) { this.logger.error(`插件事件处理错误 [${event}]:`, error); } } } } // 创建插件上下文 createContext(pluginName) { return { napcat: this.api, logger: this.logger, handle: (event, handler) => { if (!this.handlers.has(event)) { this.handlers.set(event, new Set()); } const handlers = this.handlers.get(event); handlers.add(handler); // 跟踪这个插件的处理器 if (!this.handlersByPlugin.has(pluginName)) { this.handlersByPlugin.set(pluginName, new Set()); } const pluginHandlers = this.handlersByPlugin.get(pluginName); pluginHandlers.add(handler); this.logger.debug(`插件 [${pluginName}] 注册事件处理器: ${event}`); // 返回取消注册的函数 return () => { handlers.delete(handler); if (pluginHandlers) { pluginHandlers.delete(handler); } this.logger.debug(`插件 [${pluginName}] 取消注册事件处理器: ${event}`); }; }, // 新增: 获取QQ头像URL getAvatarURL: (qq) => { return `https://q1.qlogo.cn/g?b=qq&nk=${qq}&s=640`; }, // 新增: 获取群头像URL getGroupAvatarURL: (group_id) => { return `https://p.qlogo.cn/gh/${group_id}/${group_id}/640/`; }, // 获取被引用的消息详细 getQuoteMessage: async (e) => { if (!e || !e.message) return null; try { const reply = e.message.find((msg) => msg.type === 'reply'); if (!reply) return null; const msg = await this.api.get_msg({ message_id: reply.data.id }); return msg; } catch (error) { return null; } }, // 新增: 获取消息文本内容 getText: (e) => { // 处理消息数组 if (Array.isArray(e.message)) { const text = e.message .filter((msg) => msg.type === 'text') .map((msg) => msg.data.text) .join(''); return text.trim(); } return ''; }, // 新增: 获取消息中的图片URL getImageURL: (e) => { if (!e || !e.message) return null; for (const segment of e.message) { if (segment.type === 'image' && segment.data && segment.data.url) { return segment.data.url; } } return null; }, // 新增: 获取消息中提及到的图片URL(消息或被引用消息中的图片) getQuoteImageURL: async (e) => { if (!e || !e.message) return null; try { const reply = e.message.find((msg) => msg.type === 'reply'); if (!reply) return null; const msg = await this.api.get_msg({ message_id: reply.data.id }); for (const segment of msg.message) { if (segment.type === 'image' && segment.data && segment.data.url) { return segment.data.url; } } } catch { for (const segment of e.message) { if (segment.type === 'image' && segment.data && segment.data.url) { return segment.data.url; } } } return null; }, // 新增: 获取消息中@的用户QQ号 getAtUserID: (e) => { if (!e || !e.message) return null; for (const segment of e.message) { if (segment.type === 'at' && segment.data && segment.data.qq) { return parseInt(segment.data.qq); } } return null; }, // 新增: 判断是否是主人 isRoot: async (e) => { const config = await (0, config_1.loadConfig)(); return config.root.includes(e.user_id); }, // 新增: 判断是否是管理员 isAdmin: async (e) => { const config = await (0, config_1.loadConfig)(); return config.admins.includes(e.user_id) || config.root.includes(e.user_id); }, // 新增: 判断是否是群主或管理员 isGroupAdmin: (e) => { if (!e || !e.sender || !e.sender.role) return false; return e.sender.role === 'owner' || e.sender.role === 'admin'; }, // 新增: 发送私聊消息 sendPrivateMsg: async (user_id, message) => { let msgArray = Array.isArray(message) ? message : [{ type: 'text', data: { text: message } }]; // 如果传入的是字符串数组,转换成文本消息数组 msgArray = msgArray.map(item => { if (typeof item === 'string') { return { type: 'text', data: { text: item } }; } return item; }); const result = await this.api.send_private_msg({ user_id: user_id, message: msgArray }); const rawContent = typeof message === 'string' ? message : this.extractRawMessage(msgArray); this.logger.info(`发送私聊消息 [${user_id}] : ${rawContent}`); return result; }, // 新增: 发送群聊消息 sendGroupMsg: async (group_id, message) => { let msgArray = Array.isArray(message) ? message : [{ type: 'text', data: { text: message } }]; // 如果传入的是字符串数组,转换成文本消息数组 msgArray = msgArray.map(item => { if (typeof item === 'string') { return { type: 'text', data: { text: item } }; } return item; }); const result = await this.api.send_group_msg({ group_id: group_id, message: msgArray }); const rawContent = typeof message === 'string' ? message : this.extractRawMessage(msgArray); this.logger.info(`发送群消息 [${group_id}] : ${rawContent}`); return result; }, // 新增: 撤回消息 deleteMsg: async (message_id) => { await this.api.delete_msg({ message_id: message_id }); }, // 新增: 获取群信息 getGroupInfo: async (group_id) => { const result = await this.api.get_group_info({ group_id: group_id }); return result; }, // 新增: 获取群成员信息 getGroupMemberInfo: async (group_id, user_id, no_cache = false) => { const result = await this.api.get_group_member_info({ group_id: group_id, user_id: user_id, no_cache: no_cache }); return result; }, // 新增: 获取群成员列表 getGroupMemberList: async (group_id) => { const result = await this.api.get_group_member_list({ "group_id": group_id }); // 将API返回的数据转换为正确的GroupMemberInfo类型 return result.map((member) => ({ group_id: member.group_id, user_id: member.user_id, nickname: member.nickname, card: member.card, role: member.role, title: member.title, join_time: member.join_time, last_sent_time: member.last_sent_time })); }, // 新增: 获取群列表 getGroupList: async () => { const result = await this.api.get_group_list(); return result; }, // 新增: 设置群名片 setGroupCard: async (group_id, user_id, card) => { await this.api.set_group_card({ group_id: group_id, user_id: user_id, card: card }); }, // 新增: 设置群管理员 setGroupAdmin: async (group_id, user_id, enable = true) => { await this.api.set_group_admin({ group_id: group_id, user_id: user_id, enable: enable }); }, // 新增: 群禁言 setGroupBan: async (group_id, user_id, duration = 1800) => { await this.api.set_group_ban({ group_id: group_id, user_id: user_id, duration: duration }); }, // 新增: 全员禁言 setGroupWholeBan: async (group_id, enable = true) => { await this.api.set_group_whole_ban({ group_id: group_id, enable: enable }); }, // 新增: 踢出群成员 setGroupKick: async (group_id, user_id, reject_add_request = false) => { await this.api.set_group_kick({ group_id: group_id, user_id: user_id, reject_add_request: reject_add_request }); }, // 新增: 退出群组 setGroupLeave: async (group_id, is_dismiss = false) => { await this.api.set_group_leave({ group_id: group_id, is_dismiss: is_dismiss }); }, // 新增: 设置群名 setGroupName: async (group_id, group_name) => { await this.api.set_group_name({ group_id: group_id, group_name: group_name }); }, // 新增: 设置专属头衔 setTitle: async (group_id, user_id, special_title) => { await this.api.set_group_special_title({ group_id: group_id, user_id: user_id, special_title: special_title, }); }, // 新增: 发送好友赞 sendLike: async (user_id, times = 20) => { // 使用call方法获取完整响应 const result = await this.api.send_like({ user_id: user_id, times: times }); return result; // 返回完整响应 }, // 新增: 获取版本信息 getVersionInfo: async () => { const result = await this.api.get_version_info(); return result; }, // 新增: 设置qq个性签名 setSignature: async (signature) => { await this.api.set_self_longnick({ longNick: signature }); }, // 新增: 设置QQ性别 setSex: async (sex) => { const botInfo = await this.api.get_login_info(); await this.api.set_qq_profile({ nickname: botInfo.nickname, sex: sex }); }, // 新增: 判断bot是否是群主 botIsGroupOwner: async (e) => { const botId = (await this.api.get_login_info()).user_id; const result = await this.api.get_group_member_info({ group_id: e.group_id, user_id: botId, no_cache: false }); return result.role === 'owner'; }, // 新增: 判断bot是否是群管理员 botIsGroupAdmin: async (e) => { const botId = (await this.api.get_login_info()).user_id; const result = await this.api.get_group_member_info({ group_id: e.group_id, user_id: botId, no_cache: false }); return result.role === 'admin' || result.role === 'owner'; }, }; } // 加载单个插件 async loadPlugin(pluginPath, isBuiltin = false) { try { // 清除缓存以支持热重载 const fullPath = require.resolve(pluginPath); delete require.cache[fullPath]; // 导入插件 const module = await Promise.resolve(`${fullPath}`).then(s => __importStar(require(s))); const plugin = module.default; if (!plugin || !plugin.name || !plugin.setup) { this.logger.error(`无效的插件: ${pluginPath}`); return false; } // 如果不是内置插件,且不在已启用列表中,则跳过加载 if (!isBuiltin && !this.enabledPlugins.includes(plugin.name)) { this.logger.debug(`跳过禁用的插件: ${plugin.name}`); return false; } // 如果插件已加载,先卸载 if (this.plugins.has(plugin.name) || this.builtinPlugins.has(plugin.name)) { await this.unloadPlugin(plugin.name); } // 创建插件上下文并设置插件 const context = this.createContext(plugin.name); await Promise.resolve(plugin.setup(context)); // 保存插件 if (isBuiltin) { this.builtinPlugins.set(plugin.name, plugin); this.logger.info(`内置插件加载成功: ${plugin.name} v${plugin.version}`); } else { this.plugins.set(plugin.name, plugin); this.logger.info(`插件加载成功: ${plugin.name} v${plugin.version}`); } return true; } catch (error) { this.logger.error(`加载插件失败: ${pluginPath}`, error); return false; } } // 注册内置插件 async registerBuiltinPlugin(plugin) { try { // 如果插件已加载,先卸载 if (this.builtinPlugins.has(plugin.name)) { await this.unloadPlugin(plugin.name, true); } // 创建插件上下文并设置插件 const context = this.createContext(plugin.name); await Promise.resolve(plugin.setup(context)); // 保存插件 this.builtinPlugins.set(plugin.name, plugin); this.logger.debug(`内置插件注册成功: ${plugin.name} v${plugin.version}`); return true; } catch (error) { this.logger.error(`注册内置插件失败: ${plugin.name}`, error); return false; } } // 卸载插件 async unloadPlugin(pluginName, isBuiltin = false) { // 根据是否为内置插件选择相应的Map const pluginMap = isBuiltin ? this.builtinPlugins : this.plugins; const plugin = pluginMap.get(pluginName); if (!plugin) { this.logger.warn(`插件未加载: ${pluginName}`); return false; } // 移除该插件的所有事件处理器 const pluginHandlers = this.handlersByPlugin.get(pluginName); if (pluginHandlers) { for (const [event, handlers] of this.handlers.entries()) { for (const handler of pluginHandlers) { handlers.delete(handler); } } this.handlersByPlugin.delete(pluginName); } // 移除插件 pluginMap.delete(pluginName); this.logger.info(`${isBuiltin ? '内置' : ''}插件卸载成功: ${pluginName}`); return true; } // 加载目录中的所有启用的插件 async loadAllPlugins() { try { const pluginFolders = fs_1.default.readdirSync(this.pluginsDir); for (const folder of pluginFolders) { const pluginDir = path_1.default.join(this.pluginsDir, folder); const stat = fs_1.default.statSync(pluginDir); if (stat.isDirectory()) { const indexFile = path_1.default.join(pluginDir, 'index.ts'); const indexJsFile = path_1.default.join(pluginDir, 'index.js'); if (fs_1.default.existsSync(indexFile)) { await this.loadPlugin(indexFile); } else if (fs_1.default.existsSync(indexJsFile)) { await this.loadPlugin(indexJsFile); } else { this.logger.warn(`插件目录缺少入口文件: ${folder}`); } } } this.logger.info(`已加载 ${this.plugins.size} 个插件`); } catch (error) { this.logger.error('加载插件失败:', error); } } // 重新加载所有插件 async reloadAllPlugins() { // 保存当前加载的插件名称 const pluginNames = [...this.plugins.keys()]; // 卸载所有插件 for (const name of pluginNames) { await this.unloadPlugin(name); } // 重新加载所有插件 await this.loadAllPlugins(); } // 重新加载单个插件 async reloadPlugin(pluginName) { // 首先检查插件是否存在 const plugin = this.plugins.get(pluginName); if (!plugin) { this.logger.warn(`无法重载未加载的插件: ${pluginName}`); return false; } // 查找插件路径 let pluginPath = null; const pluginFolders = fs_1.default.readdirSync(this.pluginsDir); for (const folder of pluginFolders) { // 假设插件文件夹名称与插件名一致,或者包含插件名 if (folder === pluginName || folder.toLowerCase() === pluginName.toLowerCase()) { const indexFile = path_1.default.join(this.pluginsDir, folder, 'index.ts'); const indexJsFile = path_1.default.join(this.pluginsDir, folder, 'index.js'); if (fs_1.default.existsSync(indexFile)) { pluginPath = indexFile; break; } else if (fs_1.default.existsSync(indexJsFile)) { pluginPath = indexJsFile; break; } } } if (!pluginPath) { this.logger.error(`找不到插件文件: ${pluginName}`); return false; } // 卸载插件 await this.unloadPlugin(pluginName); // 重新加载插件 return await this.loadPlugin(pluginPath); } // 启用插件 async enablePlugin(pluginName) { // 检查插件是否已启用 if (this.enabledPlugins.includes(pluginName)) { this.logger.debug(`插件已启用: ${pluginName}`); return true; } // 将插件添加到启用列表 this.enabledPlugins.push(pluginName); // 如果插件尚未加载,尝试加载它 if (!this.plugins.has(pluginName)) { let pluginPath = null; const pluginFolders = fs_1.default.readdirSync(this.pluginsDir); for (const folder of pluginFolders) { if (folder === pluginName || folder.toLowerCase() === pluginName.toLowerCase()) { const indexFile = path_1.default.join(this.pluginsDir, folder, 'index.ts'); const indexJsFile = path_1.default.join(this.pluginsDir, folder, 'index.js'); if (fs_1.default.existsSync(indexFile)) { pluginPath = indexFile; break; } else if (fs_1.default.existsSync(indexJsFile)) { pluginPath = indexJsFile; break; } } } if (!pluginPath) { this.logger.error(`找不到插件文件: ${pluginName}`); return false; } return await this.loadPlugin(pluginPath); } return true; } // 禁用插件 async disablePlugin(pluginName) { // 检查是否为内置插件 if (this.builtinPlugins.has(pluginName)) { this.logger.warn(`无法禁用内置插件: ${pluginName}`); return false; } // 检查插件是否已禁用 const index = this.enabledPlugins.indexOf(pluginName); if (index === -1) { this.logger.debug(`插件已禁用: ${pluginName}`); // 确保插件被卸载 if (this.plugins.has(pluginName)) { await this.unloadPlugin(pluginName); } return true; } // 从启用列表中移除 this.enabledPlugins.splice(index, 1); // 卸载插件 return await this.unloadPlugin(pluginName); } // 获取已加载的插件列表 getLoadedPlugins() { return [...this.plugins.values()]; } // 获取所有插件列表(包括内置插件) getAllPlugins() { const pluginList = []; // 扫描插件目录获取所有可用插件 try { const pluginFolders = fs_1.default.readdirSync(this.pluginsDir); // 处理所有插件目录 for (const folder of pluginFolders) { const pluginDir = path_1.default.join(this.pluginsDir, folder); const stat = fs_1.default.statSync(pluginDir); if (stat.isDirectory()) { const indexFile = path_1.default.join(pluginDir, 'index.ts'); const indexJsFile = path_1.default.join(pluginDir, 'index.js'); let pluginInfo = null; // 首先检查已加载的插件 if (this.plugins.has(folder)) { const plugin = this.plugins.get(folder); pluginInfo = { name: plugin.name, version: plugin.version, desc: plugin.desc, type: 'user', enabled: true }; } // 如果没有加载但存在索引文件,尝试提取信息 else if (fs_1.default.existsSync(indexFile) || fs_1.default.existsSync(indexJsFile)) { try { // 检查插件是否已启用 const enabled = this.enabledPlugins.includes(folder); // 由于未加载,我们不读取版本和描述,只展示名称和状态 pluginInfo = { name: folder, version: '未加载', desc: '在目录中但未加载', type: 'user', enabled: enabled }; } catch (error) { this.logger.debug(`读取插件信息失败: ${folder}`, error); } } if (pluginInfo) { pluginList.push(pluginInfo); } } } } catch (error) { this.logger.error('获取插件列表失败:', error); } // 添加内置插件 for (const [name, plugin] of this.builtinPlugins.entries()) { pluginList.push({ name: plugin.name, version: plugin.version, desc: plugin.desc, type: 'builtin', enabled: true }); } return pluginList; } // 获取启用的插件列表 getEnabledPlugins() { return [...this.enabledPlugins]; } // 设置启用的插件列表 setEnabledPlugins(plugins) { this.enabledPlugins = [...plugins]; } } exports.PluginManager = PluginManager; //# sourceMappingURL=PluginManager.js.map