UNPKG

xincbot

Version:

A flexible QQ bot framework based on NapCat and node-napcat-ts

300 lines (284 loc) 9.83 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const prompts_1 = __importDefault(require("prompts")); const config_1 = require("./core/config"); const bot_1 = require("./core/bot"); // 版本信息从 package.json 获取 const packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../package.json'), 'utf8')); commander_1.program .name('xinc') .description('xincBot - A flexible QQ bot framework') .version(packageJson.version); // 初始化命令 commander_1.program .command('init') .description('Initialize xincBot configuration') .action(async () => { console.log('欢迎使用 xincBot 配置向导!'); console.log('这将帮助你创建一个基本的配置文件。'); const configManager = new config_1.ConfigManager(); const configPath = path_1.default.join(process.cwd(), 'xinc.config.toml'); // 检查配置文件是否已存在 const configExists = fs_1.default.existsSync(configPath); // 如果配置文件已存在,询问是否覆盖 if (configExists) { const { overwrite } = await (0, prompts_1.default)({ type: 'confirm', name: 'overwrite', message: '配置文件已存在,是否覆盖?', initial: false }); if (!overwrite) { console.log('配置向导已取消。'); process.exit(0); } } // 收集配置信息 const responses = await (0, prompts_1.default)([ { type: 'text', name: 'host', message: '请输入 NapCat 服务器地址:', initial: '127.0.0.1' }, { type: 'number', name: 'port', message: '请输入 NapCat 服务器端口:', initial: 4001 }, { type: 'text', name: 'prefix', message: '请输入命令前缀:', initial: '#' }, { type: 'text', name: 'root', message: '请输入主人QQ号(多个用逗号分隔):', validate: value => value.trim() !== '' ? true : '至少需要一个主人QQ号' } ]); // 处理用户输入 const config = { host: responses.host, port: responses.port, prefix: responses.prefix, root: responses.root.split(',').map((id) => id.trim()), admin: [], plugins: [] // 不再包含 cmd 插件 }; // 创建插件目录 const pluginsDir = path_1.default.join(process.cwd(), 'plugins'); if (!fs_1.default.existsSync(pluginsDir)) { fs_1.default.mkdirSync(pluginsDir, { recursive: true }); } // 创建示例插件 createTemplatePlugin(pluginsDir); // 创建或更新 package.json const packageJsonPath = path_1.default.join(process.cwd(), 'package.json'); let packageJson = {}; // 检查 package.json 是否存在 if (fs_1.default.existsSync(packageJsonPath)) { try { packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8')); } catch (error) { console.error('无法解析现有的 package.json 文件,将创建新文件'); packageJson = {}; } } // 确保有 scripts 部分 packageJson.scripts = packageJson.scripts || {}; // 添加启动脚本 packageJson.scripts.start = "npx xinc start"; packageJson.scripts.dev = "npx xinc start"; // 写入 package.json fs_1.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); // 保存配置 - 移到这里,确保在创建示例插件后才写入配置文件 fs_1.default.writeFileSync(configPath, configManager.convertToToml(config)); // 在 createTemplatePlugin 函数后添加 function createIndexFile(dir) { const indexPath = path_1.default.join(dir, 'index.js'); // 如果文件已存在,不覆盖 if (fs_1.default.existsSync(indexPath)) { return; } const content = `#!/usr/bin/env node // xincBot 启动文件 const { spawn } = require('child_process'); // 启动 xincBot const bot = spawn('npx', ['xinc', 'start'], { stdio: 'inherit', shell: true }); // 处理进程退出 bot.on('close', (code) => { console.log(\`xincBot 进程已退出,退出码: \${code}\`); process.exit(code); }); // 处理信号 process.on('SIGINT', () => { bot.kill('SIGINT'); }); process.on('SIGTERM', () => { bot.kill('SIGTERM'); }); `; fs_1.default.writeFileSync(indexPath, content); console.log('已创建启动文件: index.js'); } // 然后在 init 命令中调用 // 在创建示例插件后添加 createIndexFile(process.cwd()); console.log('配置文件已创建: xinc.config.toml'); console.log('已创建示例插件: plugins/example'); console.log('已创建启动文件: index.js'); console.log('\n启动方式:'); console.log('1. npm start - 直接启动'); console.log('2. node index.js - 使用 Node 启动'); console.log('3. pm2 start index.js - 使用 PM2 后台运行'); process.exit(0); }); // 启动命令 commander_1.program .command('start', { isDefault: true }) .description('Start xincBot') .action(() => { console.log('正在启动 xincBot...'); const bot = new bot_1.Bot(); bot.start().catch((error) => { console.error('启动失败:', error); process.exit(1); }); }); // 在 program 定义部分添加新命令 commander_1.program .command('new <plugin-name>') .description('Create a new plugin template') .action((pluginName) => { console.log(`正在创建插件: ${pluginName}`); // 创建插件目录 const pluginsDir = path_1.default.join(process.cwd(), 'plugins'); if (!fs_1.default.existsSync(pluginsDir)) { fs_1.default.mkdirSync(pluginsDir, { recursive: true }); } const pluginDir = path_1.default.join(pluginsDir, pluginName); // 检查插件是否已存在 if (fs_1.default.existsSync(pluginDir)) { console.error(`错误: 插件 "${pluginName}" 已存在`); process.exit(1); } // 创建插件目录 fs_1.default.mkdirSync(pluginDir, { recursive: true }); // 创建插件文件 const pluginContent = `import { definePlugin } from 'xincbot'; export default definePlugin({ name: '${pluginName}', version: '1.0.0', desc: '${pluginName} 插件', setup(ctx) { // 在这里编写你的插件逻辑 ctx.handle('message', async e => { // 示例: 响应特定消息 const text = ctx.getText(e); if (text === '${pluginName}') { await ctx.respond(e, ['你好,这是 ${pluginName} 插件!']); } }); // 你可以处理更多事件 ctx.handle('notice', async e => { // 处理通知事件 }); // 返回清理函数(可选) return () => { console.log('${pluginName} 插件已卸载'); }; } }); `; fs_1.default.writeFileSync(path_1.default.join(pluginDir, 'index.ts'), pluginContent); // 创建 README.md const readmeContent = `# ${pluginName} ## 描述 ${pluginName} 插件 ## 功能 - 功能1 - 功能2 ## 使用方法 - 命令1: 描述 - 命令2: 描述 ## 配置 \`\`\`toml # 在 xinc.config.toml 中添加: [plugins.${pluginName}] # 在这里添加插件配置 \`\`\` `; fs_1.default.writeFileSync(path_1.default.join(pluginDir, 'README.md'), readmeContent); console.log(`插件 "${pluginName}" 创建成功!`); console.log(`插件目录: ${pluginDir}`); console.log('要启用此插件,请编辑 xinc.config.toml 文件,在 plugins 数组中添加 "${pluginName}"'); }); commander_1.program.parse(); // 在 cli.ts 中添加创建模板插件的函数 function createTemplatePlugin(pluginsDir) { const examplePluginDir = path_1.default.join(pluginsDir, 'example'); // 创建插件目录 if (!fs_1.default.existsSync(examplePluginDir)) { fs_1.default.mkdirSync(examplePluginDir, { recursive: true }); } // 创建插件文件 const pluginContent = `import { definePlugin } from 'xincbot'; export default definePlugin({ name: 'example', version: '1.0.0', desc: '示例插件 - 回复"你好"', setup(ctx) { ctx.handle('message', async e => { // 获取消息文本 const text = ctx.getText(e); // 如果消息是"你好",回复"你好!我是 xincBot" if (text === '你好') { await ctx.respond(e, ['你好!我是 xincBot']); } }); } }); `; fs_1.default.writeFileSync(path_1.default.join(examplePluginDir, 'index.ts'), pluginContent); console.log('已创建示例插件: plugins/example'); } function createPM2Config(dir) { const configPath = path_1.default.join(dir, 'ecosystem.config.js'); // 如果文件已存在,不覆盖 if (fs_1.default.existsSync(configPath)) { return; } const content = `module.exports = { apps: [{ name: 'xincBot', script: 'index.js', watch: false, autorestart: true, max_memory_restart: '1G', env: { NODE_ENV: 'production' } }] }; `; fs_1.default.writeFileSync(configPath, content); console.log('已创建 PM2 配置文件: ecosystem.config.js'); } // 然后在 init 命令中调用 createPM2Config(process.cwd()); //# sourceMappingURL=cli.js.map