UNPKG

cyberbot-next

Version:

cyberbot, 基于napcat-ts, nodejs,轻量qq机器人框架。

322 lines (321 loc) 11.8 kB
import os from 'os'; import * as fs from 'fs'; import * as path from 'path'; import { PluginManager, CybePlugin } from './pluginManager.js'; import { logger } from './logger.js'; import { NCWebsocket, Structs } from './types.js'; import { createEventHandlers } from './event.js'; import { globalJitiLoader, clearModuleCache } from './jitiLoader.js'; import axios from 'axios'; export { CybePlugin, PluginManager, NCWebsocket, Structs }; const loadConfig = (configPath = 'config.json') => { try { if (fs.existsSync(configPath)) { const configData = fs.readFileSync(configPath, 'utf-8'); const config = JSON.parse(configData); logger.debug('配置文件加载成功'); return config; } else { logger.error('配置文件不存在'); throw new Error('配置文件不存在'); } } catch (error) { logger.error(`加载配置文件失败:, ${error}`); return null; } }; const writeConfig = (config, configPath = 'config.json') => { try { const configData = JSON.stringify(config, null, 2); fs.writeFileSync(configPath, configData, 'utf-8'); logger.info('配置文件写入成功'); } catch (error) { logger.error(`写入配置文件失败: ${error}`); } }; export class NapcatConnector extends NCWebsocket { static instance; messageHandlers = new Set(); singleMessageHandler = null; constructor(configPath = 'config.json') { const config = loadConfig(configPath); super({ baseUrl: config.baseUrl, accessToken: config.accessToken, throwPromise: config.throwPromise, reconnection: config.reconnection }); if (!NapcatConnector.instance) { NapcatConnector.instance = this; } } static getInstance(configPath = 'config.json') { if (!NapcatConnector.instance) { NapcatConnector.instance = new NapcatConnector(configPath); } return NapcatConnector.instance; } onMessage(handler) { this.messageHandlers.add(handler); if (!this.singleMessageHandler) { this.singleMessageHandler = (e) => { for (const handlerFn of this.messageHandlers) { try { handlerFn(e); } catch (error) { logger.error('消息处理器执行错误:', error); } } }; this.on('message', this.singleMessageHandler); this.on('notice', this.singleMessageHandler); this.on('request', this.singleMessageHandler); } } removeMessageListener(handler) { return this.messageHandlers.delete(handler); } async connect() { await super.connect(); const logo = ` .oooooo. .o8 oooooooooo. . d8P' \`Y8b "888 \`888' \`Y8b .o8 888 oooo ooo 888oooo. .ooooo. oooo d8b 888 888 .ooooo. .o888oo 888 \`88. .8' d88' \`88b d88' \`88b \`888\"\"8P 888oooo888' d88' \`88b 888 888 \`88..8' 888 888 888ooo888 888 888 \`88b 888 888 888 \`88b ooo \`888' 888 888 888 .o 888 888 .88P 888 888 888 . \`Y8bood8P' .8' \`Y8bod8P' \`Y8bod8P' d888b o888bood8P' \`Y8bod8P' "888" .o..P' \`Y8P' CyberBot 一个基于 node-napcat-ts 的 QQ 机器人 参考: kivibot@viki && Abot@takayama @auther: 星火 `; logger.info(logo); logger.info('NapcatConnector 已连接到服务器'); } disconnect() { super.disconnect(); logger.info('NapcatConnector 已断开连接'); } setConfig(config) { writeConfig(config); } getConfig() { return loadConfig(); } } export class NapcatClient { connector; pluginManager; logger; events; bot_uin; napcat; constructor(connector) { this.connector = connector || NapcatConnector.getInstance(); this.napcat = this.connector; this.logger = logger; this.pluginManager = new PluginManager(this); this.events = createEventHandlers(this.connector, this.connector.getConfig()); this.bot_uin = this.connector.getConfig().bot; } onMessage(handler) { this.connector.onMessage(handler); } removeMessageListener(handler) { return this.connector.removeMessageListener(handler); } async connect() { await this.connector.connect(); try { const now = new Date(); const timeStr = now.toLocaleString('zh-CN', { hour12: false }); const osInfo = `${os.platform()}`; await this.sendPrivateMessage(this.connector.getConfig().master, [ "[Bot🤖]已成功上线!", `📅 ${timeStr}`, `💻 系统信息:${osInfo}`, "✨ 随时等待您的指令~" ].join('\n')); logger.info('已发送上线通知给主人'); } catch (error) { logger.error('发送上线通知失败:', error); } } disconnect() { this.connector.disconnect(); } loadPlugin(plugin) { this.pluginManager.loadPlugin(plugin); } unloadPlugin(pluginName) { return this.pluginManager.unloadPlugin(pluginName); } getLoadedPlugins() { return this.pluginManager.getLoadedPlugins(); } setConfig(config) { this.connector.setConfig(config); } getConfig() { return this.connector.getConfig(); } sendPrivateMessage(userId, content) { return this.events.sendPrivateMessage(userId, content); } sendGroupMessage(groupId, content) { return this.events.sendGroupMessage(groupId, content); } deleteMessage(message_id) { return this.events.delete_msg(message_id); } kickMember(group_id, user_id, reject_add_request = false) { return this.events.kick(group_id, user_id, reject_add_request); } banMember(group_id, user_id, duration) { return this.events.ban(group_id, user_id, duration); } banAllMembers(group_id, enable) { return this.events.banAll(group_id, enable); } setGroupNameEx(group_id, name) { return this.events.setGroupName(group_id, name); } setAdminEx(group_id, user_id, enable) { return this.events.setAdmin(group_id, user_id, enable); } setMemberTitle(group_id, user_id, title) { return this.events.setTitle(group_id, user_id, title); } isMaster(id) { return this.events.isMaster(id); } isAdmin(id) { return this.events.isAdmin(id); } hasRight(user_id) { return this.events.hasRight(user_id); } aprroveGroup(flag) { return this.events.aprroveGroup(flag); } rejectGroup(flag) { return this.events.rejectGroup(flag); } isGroupAdmin(group_id, user_id) { return this.events.isGroupAdmin(group_id, user_id); } isGroupOwner(group_id, user_id) { return this.events.isGroupOwner(group_id, user_id); } md5(text) { return this.events.md5(text); } randomInt(min, max) { return this.events.randomInt(min, max); } randomItem(array) { return this.events.randomItem(array); } getGroupAvatarLink(group_id, size) { return this.events.getGroupAvatarLink(group_id, size); } getQQAvatarLink(user_id, size) { return this.events.getQQAvatarLink(user_id, size); } getImageLink(raw_message) { return this.events.getImageLink(raw_message); } getDirectLink(url) { return this.events.getDirectLink(url); } getMessageId(raw_message) { return this.events.getMessageId(raw_message); } getMessageAt(raw_message) { return this.events.getMessageAt(raw_message); } getText(raw_message) { return this.events.getText(raw_message); } getQuotedText(raw_message) { return this.events.getQuotedText(raw_message); } fakeMessage(target_id, message, isGroup) { return this.events.fakeMessage(target_id, message, isGroup); } } const connector = NapcatConnector.getInstance(); const client = new NapcatClient(connector); client.onMessage((e) => { if ('message' in e) { logger.info(`全局消息处理器: ${JSON.stringify(e.message)}`); } }); async function loadPlugins(client) { const pluginsDir = path.join(process.cwd(), 'plugins'); if (!fs.existsSync(pluginsDir)) { logger.warn('插件目录不存在,将创建插件目录'); fs.mkdirSync(pluginsDir, { recursive: true }); return; } const config = client.getConfig(); const systemPlugins = config.plugins.system || []; const userPlugins = config.plugins.user || []; logger.info(`系统插件: ${JSON.stringify(systemPlugins)}`); logger.info(`用户插件: ${JSON.stringify(userPlugins)}`); const pluginDirs = fs.readdirSync(pluginsDir, { withFileTypes: true }) .filter(dirent => dirent.isDirectory()) .map(dirent => dirent.name); for (const pluginDir of pluginDirs) { try { const isSystemPlugin = systemPlugins.includes(pluginDir); const isEnabledUserPlugin = userPlugins.includes(pluginDir); const shouldBeEnabled = isSystemPlugin || isEnabledUserPlugin; const possibleExtensions = ['.ts', '.js']; let pluginPath = ''; let found = false; for (const ext of possibleExtensions) { const testPath = path.join(pluginsDir, pluginDir, `index${ext}`); if (fs.existsSync(testPath)) { pluginPath = testPath; found = true; break; } } if (!found) { logger.warn(`在插件 ${pluginDir} 中未找到任何可用的入口文件`); continue; } clearModuleCache(pluginPath); logger.debug(`正在使用 jiti 加载插件: ${pluginPath}`); const pluginModule = await globalJitiLoader.import(pluginPath); const pluginClass = Object.values(pluginModule).find((item) => typeof item === 'function' && item.name.endsWith('Plugin')); if (pluginClass) { const plugin = new pluginClass(); plugin.enabled = shouldBeEnabled; plugin.isSystemPlugin = isSystemPlugin; client.pluginManager.loadPlugin(plugin, isSystemPlugin); logger.debug(`成功加载插件: ${pluginDir} (从 ${path.basename(pluginPath)} 加载) ${isSystemPlugin ? '[系统]' : ''} [${shouldBeEnabled ? '启用' : '禁用'}]`); } else { logger.warn(`在 ${pluginDir} 中未找到插件类`); } } catch (error) { logger.error(`加载插件 ${pluginDir} 失败: ${error}`); } } } async function BootStrap() { await client.connect(); await loadPlugins(client); } export { BootStrap, logger, connector, client, axios as http }; //# sourceMappingURL=index.js.map