cyberbot-next
Version:
cyberbot, 基于napcat-ts, nodejs,轻量qq机器人框架。
322 lines (321 loc) • 11.8 kB
JavaScript
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