UNPKG

xinc

Version:

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

487 lines 22 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.App = void 0; const NCWebsocketApi_1 = require("../napcat/NCWebsocketApi"); const Logger_1 = require("./Logger"); const config_1 = require("./config"); const PluginManager_1 = require("./plugin/PluginManager"); const Structs_1 = require("../napcat/Structs"); const path_1 = require("path"); const fs_1 = __importDefault(require("fs")); const packageInfo = require('../../package.json'); class App { constructor(configPath = 'xinc.config.toml') { // 初始化将在 init 方法中完成 } async init(configPath = 'xinc.config.toml') { try { // 加载配置文件 this.config = await (0, config_1.loadConfig)(configPath); // 初始化日志系统 this.logger = new Logger_1.Logger(this.config.logger); this.logger.info('配置加载成功'); // 初始化WebSocket连接 this.ws = new NCWebsocketApi_1.NCWebsocketApi({ host: this.config.host, port: this.config.port, protocol: 'ws' }); this.setupEventHandlers(); this.logger.info('事件处理器设置完成'); // 初始化插件管理器,传入已启用的插件列表 this.pluginManager = new PluginManager_1.PluginManager(this.ws, this.logger, 'plugins', this.config.plugins); this.logger.info('插件管理器初始化完成'); // 注册内置管理插件 this.registerBuiltinAdminPlugin(); this.logger.info('内置管理插件注册完成'); } catch (error) { console.error('初始化失败:', error); process.exit(1); } } // 注册内置管理插件 registerBuiltinAdminPlugin() { // 创建一个内部插件上下文 const ctx = { napcat: this.ws, logger: this.logger, handle: this.pluginManager['createContext']('内置管理插件').handle }; // 处理管理命令 ctx.handle('message', async (e) => { // 检查是否是框架主人或管理员 const isRoot = this.config.root.includes(e.user_id); const isAdmin = this.config.admins.includes(e.user_id) || this.config.root.includes(e.user_id); if (!isRoot && !isAdmin) return; const prefix = this.config.prefix; const message = e.raw_message.trim(); if (!message.startsWith(prefix)) return; const cmd = message.substring(prefix.length).trim(); // 退出命令 if (cmd === `退出` || cmd === `exit`) { // 仅允许主人执行 if (!isRoot) { e.reply('只有框架主人才能执行此命令'); return; } // 发送退出消息 e.reply('正在关闭框架,再见...'); // 延迟一小段时间确保消息能发送出去 setTimeout(async () => { this.logger.info(`收到来自用户 ${e.user_id} 的关闭命令,正在关闭框架...`); await this.stop(); process.exit(0); // 确保完全退出 }, 1000); return; } // 帮助命令 if (cmd === `帮助` || cmd === `help`) { const helpMsg = [ Structs_1.Structs.text(`〓 Xinc 帮助 〓\n`), Structs_1.Structs.text(`命令列表:\n`), Structs_1.Structs.text(`${prefix}状态 - 查看框架状态\n`), Structs_1.Structs.text(`${prefix}插件 列表 - 查看插件列表\n`), Structs_1.Structs.text(`${prefix}插件 重载 <插件名> - 重载指定插件\n`), Structs_1.Structs.text(`${prefix}插件 启用 <插件名> - 启用指定插件\n`), Structs_1.Structs.text(`${prefix}插件 禁用 <插件名> - 禁用指定插件\n`) ]; if (isRoot) { helpMsg.push(Structs_1.Structs.text(`${prefix}设置 加管理 <QQ> - 添加框架管理员\n`)); helpMsg.push(Structs_1.Structs.text(`${prefix}设置 删管理 <QQ> - 删除框架管理员\n`)); helpMsg.push(Structs_1.Structs.text(`${prefix}设置 加主人 <QQ> - 添加框架主人\n`)); helpMsg.push(Structs_1.Structs.text(`${prefix}设置 删主人 <QQ> - 删除框架主人\n`)); helpMsg.push(Structs_1.Structs.text(`${prefix}设置 前缀 <前缀> - 修改命令前缀\n`)); helpMsg.push(Structs_1.Structs.text(`${prefix}设置 日志 <级别> - 修改日志级别\n`)); helpMsg.push(Structs_1.Structs.text(`${prefix}退出 - 退出框架\n`)); } e.reply(helpMsg); return; } // 框架状态 if (cmd === `状态` || cmd === `status`) { // 获取系统信息 const os = require('os'); const uptime = process.uptime(); const uptimeStr = formatUptime(uptime); // 计算内存使用情况 const totalMem = os.totalmem() / 1024 / 1024 / 1024; const freeMem = os.freemem() / 1024 / 1024 / 1024; const usedMem = totalMem - freeMem; const memPercent = (usedMem / totalMem * 100).toFixed(1); // 获取机器人信息 const botInfo = await this.ws.get_login_info(); const groups = await this.ws.get_group_list(); const friends = await this.ws.get_friend_list(); // 获取插件统计 const allPlugins = this.pluginManager.getAllPlugins(); const userPlugins = allPlugins.filter(p => p.type === 'user'); const enabledPlugins = userPlugins.filter(p => p.enabled); // CPU信息 const cpu = os.cpus()[0].model; const statusMsg = [ Structs_1.Structs.text(`〓 Xinc 状态 〓\n`), Structs_1.Structs.text(`昵称: ${botInfo.nickname}\n`), Structs_1.Structs.text(`账号: ${botInfo.user_id}\n`), Structs_1.Structs.text(`社交: ${groups.length} 个群, ${friends.length} 个好友\n`), Structs_1.Structs.text(`插件: ${enabledPlugins.length} 个启用, 共 ${userPlugins.length} 个\n`), Structs_1.Structs.text(`运行时间: ${uptimeStr}\n`), Structs_1.Structs.text(`环境: XincBot.v${packageInfo.version}-Node${process.version.slice(1)}\n`), Structs_1.Structs.text(`处理器: ${cpu}\n`), Structs_1.Structs.text(`内存: ${usedMem.toFixed(1)}GB/${totalMem.toFixed(1)}GB (${memPercent}%)`) ]; e.reply(statusMsg); return; } // 插件管理命令 if (cmd.startsWith('插件 ') || cmd.startsWith('p ')) { const args = cmd.split(' ').slice(1); const subCmd = args[0]; const pluginName = args.slice(1).join(' '); // 插件列表 if (subCmd === '列表' || subCmd === 'ls') { const allPlugins = this.pluginManager.getAllPlugins(); const userPlugins = allPlugins.filter(p => p.type === 'user'); // 使用新的格式显示插件列表 let msg = [Structs_1.Structs.text(`〓 插件列表 〓\n`)]; if (userPlugins.length === 0) { msg.push(Structs_1.Structs.text(`暂无插件\n`)); } else { // 添加用户插件列表 userPlugins.forEach(plugin => { const status = plugin.enabled ? '🟢' : '🔴'; msg.push(Structs_1.Structs.text(`${status} ${plugin.name}\n`)); }); } // 添加统计信息 const enabledCount = userPlugins.filter(p => p.enabled).length; msg.push(Structs_1.Structs.text(`共 ${userPlugins.length} 个,启用 ${enabledCount} 个`)); e.reply(msg); return; } // 重载插件 if (subCmd === '重载' || subCmd === 'reload') { if (!pluginName) { e.reply('请指定要重载的插件名称'); return; } const result = await this.pluginManager.reloadPlugin(pluginName); if (result) { e.reply(`已重载插件 ${pluginName}`); } else { e.reply(`重载插件 ${pluginName} 失败,请检查日志`); } return; } // 启用插件 if (subCmd === '启用' || subCmd === 'on') { if (!pluginName) { e.reply('请指定要启用的插件名称'); return; } // 检查插件是否已经启用 if (this.config.plugins.includes(pluginName)) { e.reply(`插件 ${pluginName} 已经处于启用状态`); return; } const result = await this.pluginManager.enablePlugin(pluginName); if (result) { this.updatePlugins('add', pluginName); e.reply(`已启用插件 ${pluginName}`); } else { e.reply(`启用插件 ${pluginName} 失败,请检查日志`); } return; } // 禁用插件 if (subCmd === '禁用' || subCmd === 'off') { if (!pluginName) { e.reply('请指定要禁用的插件名称'); return; } // 检查插件是否已经禁用 if (!this.config.plugins.includes(pluginName)) { e.reply(`插件 ${pluginName} 已经处于禁用状态`); return; } // 检查是否为内置插件 const allPlugins = this.pluginManager.getAllPlugins(); const targetPlugin = allPlugins.find(p => p.name === pluginName); if (targetPlugin && targetPlugin.type === 'builtin') { e.reply(`无法禁用内置插件 ${pluginName}`); return; } const result = await this.pluginManager.disablePlugin(pluginName); if (result) { this.updatePlugins('remove', pluginName); e.reply(`已禁用插件 ${pluginName}`); } else { e.reply(`禁用插件 ${pluginName} 失败,请检查日志`); } return; } e.reply(`未知的插件命令: ${subCmd},请使用 ${prefix}帮助 查看可用命令`); return; } // 设置命令 if (cmd.startsWith('设置 ') || cmd.startsWith('set ')) { const args = cmd.split(' ').slice(1); const subCmd = args[0]; const value = args.slice(1).join(' '); if (!isRoot) { e.reply('只有框架主人可以修改设置'); return; } // 添加管理员 if (subCmd === '加管理') { const qq = getAtUserID(e); if (!qq) { e.reply('无效的QQ号'); return; } if (this.config.root.includes(qq)) { e.reply('该用户已经是框架主人'); return; } if (this.config.admins.includes(qq)) { e.reply('该用户已经是框架管理员'); return; } // 添加管理员 this.config.admins.push(qq); this.saveConfig(); e.reply(`已将 ${qq} 添加为框架管理员`); return; } // 删除管理员 if (subCmd === '删管理') { const qq = getAtUserID(e); if (!qq) { e.reply('无效的QQ号'); return; } const index = this.config.admins.indexOf(qq); if (index === -1) { e.reply('该用户不是框架管理员'); return; } // 删除管理员 this.config.admins.splice(index, 1); this.saveConfig(); e.reply(`已将 ${qq} 从框架管理员中移除`); return; } // 添加主人 if (subCmd === '加主人') { const qq = getAtUserID(e); if (!qq) { e.reply('无效的QQ号'); return; } if (this.config.root.includes(qq)) { e.reply('该用户已经是框架主人'); return; } // 添加主人 this.config.root.push(qq); this.saveConfig(); e.reply(`已将 ${qq} 添加为框架主人`); return; } // 删除主人 if (subCmd === '删主人') { const qq = getAtUserID(e); if (!qq) { e.reply('无效的QQ号'); return; } if (qq === e.user_id) { e.reply('不能删除自己的主人权限'); return; } const index = this.config.root.indexOf(qq); if (index === -1) { e.reply('该用户不是框架主人'); return; } // 删除主人 this.config.root.splice(index, 1); this.saveConfig(); e.reply(`已将 ${qq} 从框架主人中移除`); return; } // 修改前缀 if (subCmd === '前缀') { if (!value) { e.reply('前缀不能为空'); return; } // 修改前缀 this.config.prefix = value; this.saveConfig(); e.reply(`已将命令前缀修改为 ${value}`); return; } // 修改日志级别 if (subCmd === '日志') { if (!['debug', 'info', 'warn', 'error', 'silent'].includes(value)) { e.reply('无效的日志级别,可选值: debug, info, warn, error, silent'); return; } // 修改日志级别 this.config.logger = value; this.saveConfig(); e.reply(`已将日志级别修改为 ${value}`); return; } e.reply(`未知的设置命令: ${subCmd},请使用 ${prefix}帮助 查看可用命令`); return; } }); } // 保存配置 saveConfig() { try { const configPath = 'xinc.config.toml'; const fullPath = (0, path_1.join)(process.cwd(), configPath); // 创建 TOML 内容,确保插件名称被正确引号包裹 const tomlContent = `host = "${this.config.host}" port = ${this.config.port} prefix = "${this.config.prefix}" root = [${this.config.root.join(', ')}] admins = [${this.config.admins.join(', ')}] plugins = [${this.config.plugins.map(p => `"${p}"`).join(', ')}] logger = "${this.config.logger}" `; fs_1.default.writeFileSync(fullPath, tomlContent); this.logger.info(`配置已保存,已启用插件: ${this.config.plugins.length > 0 ? this.config.plugins.join(', ') : '无'}`); } catch (error) { this.logger.error('保存配置失败:', error); } } setupEventHandlers() { // WebSocket连接事件 this.ws.on('socket.connecting', (data) => { this.logger.info('正在连接WebSocket...'); }); this.ws.on('socket.open', () => { this.logger.info('WebSocket连接成功'); }); this.ws.on('socket.close', (data) => { this.logger.warn(`WebSocket断开连接(代码: ${data.code}),原因: ${data.reason || '未知'},尝试重连...`); }); this.ws.on('socket.error', (error) => { this.logger.error('WebSocket错误:', error); }); // API相关事件 this.ws.on('api.preSend', (data) => { this.logger.debug('发送API请求:', data.action, data.params); }); this.ws.on('api.response.success', (data) => { this.logger.debug('API请求成功:', data.echo, data.data); }); this.ws.on('api.response.failure', (data) => { this.logger.warn('API请求失败:', data.echo, data.message); }); // 消息处理 this.ws.on('message', (message) => { this.logger.debug('收到消息:', message); }); // 群消息 this.ws.on('message.group', (message) => { this.logger.info(`收到群消息 [${message.group_id}] ${message.sender.nickname}: ${JSON.stringify(message.raw_message)}`); }); // 私聊消息 this.ws.on('message.private', (message) => { this.logger.info(`收到私聊消息 [${message.user_id}] ${message.sender.nickname}: ${JSON.stringify(message.raw_message)}`); }); // 通知事件 this.ws.on('notice', (notice) => { this.logger.info('收到通知:', notice.notice_type, notice); }); // 请求事件 this.ws.on('request', (request) => { this.logger.info('收到请求:', request.request_type, request); }); } async start() { try { this.logger.info('启动 Xinc 机器人...'); await this.ws.connect(); this.logger.info(`机器人运行在 ${this.config.host}:${this.config.port}`); // 加载插件 await this.pluginManager.loadAllPlugins(); } catch (error) { this.logger.error('启动机器人失败:', error); process.exit(1); } } async stop() { try { this.logger.info('停止 Xinc 机器人...'); await this.ws.disconnect(); this.logger.info('机器人已成功停止'); // 关闭日志流 await this.logger.close(); } catch (error) { this.logger.error('停止机器人时出错:', error); // 确保日志流关闭 await this.logger.close(); process.exit(1); } } // 更新插件列表 updatePlugins(action, pluginName) { try { if (action === 'add') { if (!this.config.plugins.includes(pluginName)) { this.config.plugins.push(pluginName); this.logger.info(`插件 ${pluginName} 已添加到配置中`); } } else { const index = this.config.plugins.indexOf(pluginName); if (index !== -1) { this.config.plugins.splice(index, 1); this.logger.info(`插件 ${pluginName} 已从配置中移除`); } } this.saveConfig(); } catch (error) { this.logger.error(`更新插件配置失败: ${error}`); } } } exports.App = App; // 添加一个格式化运行时间的辅助函数 function formatUptime(seconds) { const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); const secs = Math.floor(seconds % 60); return `${days}天${hours}小时${minutes}分${secs}秒`; } function 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; } //# sourceMappingURL=App.js.map