hotcat-bot-qq 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,53 +1,55 @@
1
- # HotCat Bot
2
-
3
- 基于 [node-napcat-ts](https://github.com/HkTeamX/node-napcat-ts) 的 TypeScript QQ 机器人框架。
4
-
5
- <p align="center">
6
- <img src="logo.png" width="120" alt="HotCat Bot Logo">
7
- </p>
8
-
9
- ## 安装
10
-
11
- ```bash
12
- npm add hotcat-bot-qq
13
- # or
14
- pnpm add hotcat-bot-qq
15
- # or
16
- bun add hotcat-bot-qq
17
- ```
18
-
19
- ## 快速开始
20
-
21
- ```ts
22
- import { BotClient } from './botClient'
23
- import { Message } from './message'
24
-
25
- const bot = new BotClient({
26
- baseUrl: 'ws://localhost:8082/onebot/v11/ws/',
27
- accessToken: 'your-access-token',
28
- })
29
- await bot.start()
30
-
31
- bot.event.message.onGroupMessage(async (bot, event) => {
32
- await bot.api.sendGroupMessage(event.group_id,
33
- Message.reply(event.message_id),
34
- Message.text('pong!')
35
- )
36
- })
37
- ```
38
-
39
- ## 特性
40
-
41
- - **类型安全** — 完整的 TypeScript 类型推导,封装 napcat 全部 API
42
- - **消息段构建** — `Message` 类支持文本、图片、表情、文件等所有消息类型
43
- - **事件系统** — `BotEvent` 按类别分组暴露 message/messageSent/request/notice 事件
44
- - **定时任务** — `BotScheduler` 支持 cron 表达式、固定间隔、指定时间
45
- - **插件系统** — 继承 `PluginBase` 即可开发插件,支持热重载、目录监听自动加载,`scan` + `watch` 零配置接入
46
-
47
- ## 文档
48
-
49
- 完整文档 → [框架开发文档](https://hotcat-bot-qq.docs.chcat1320.top)
50
-
51
- ## 协议
52
-
53
- MIT © CHCAT1320
1
+ # HotCat Bot
2
+
3
+ 基于 [node-napcat-ts](https://github.com/HkTeamX/node-napcat-ts) 的 TypeScript QQ 机器人框架。
4
+
5
+ <p align="center">
6
+ <img src="logo.png" width="120" alt="HotCat Bot Logo">
7
+ </p>
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ npm add hotcat-bot-qq
13
+ # or
14
+ pnpm add hotcat-bot-qq
15
+ # or
16
+ bun add hotcat-bot-qq
17
+ ```
18
+
19
+ ## 快速开始
20
+
21
+ ```ts
22
+ import { BotClient } from './botClient'
23
+ import { Message } from './message'
24
+
25
+ const bot = new BotClient({
26
+ baseUrl: 'ws://localhost:8082/onebot/v11/ws/',
27
+ accessToken: 'your-access-token',
28
+ owner: 123456789, // 必填:bot 主人(管理员)QQ 号
29
+ })
30
+ await bot.start()
31
+
32
+ bot.event.message.onGroupMessage(async (bot, event) => {
33
+ await bot.api.sendGroupMessage(event.group_id,
34
+ Message.reply(event.message_id),
35
+ Message.text('pong!')
36
+ )
37
+ })
38
+ ```
39
+
40
+ ## 特性
41
+
42
+ - **类型安全** — 完整的 TypeScript 类型推导,封装 napcat 全部 API
43
+ - **消息段构建** — `Message` 类支持文本、图片、表情、文件等所有消息类型
44
+ - **事件系统** — `BotEvent` 按类别分组暴露 message/messageSent/request/notice 事件
45
+ - **定时任务** — `BotScheduler` 支持 cron 表达式、固定间隔、指定时间
46
+ - **插件系统** — 继承 `PluginBase` 即可开发插件,支持热重载、目录监听自动加载,`scan` + `watch` 零配置接入
47
+
48
+ ## 文档
49
+
50
+ 完整文档 → [框架开发文档](https://hotcat-bot-qq.docs.chcat1320.top)
51
+
52
+ 交流群638144340
53
+ ## 协议
54
+
55
+ MIT © CHCAT1320
package/dist/botApi.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { NCWebsocket } from 'node-napcat-ts';
2
- import { BotConsole } from './botConsole';
2
+ import { BotConsole } from './botConsole.js';
3
3
  export class BotApi {
4
4
  get client() { return this._client; }
5
5
  set client(c) { this._client = c; }
@@ -5,6 +5,8 @@ import { BotScheduler } from './botScheduler';
5
5
  export interface BotConfig {
6
6
  baseUrl: string;
7
7
  accessToken?: string;
8
+ /** Bot 主人(管理员)QQ 号,必填,未配置将拒绝启动 */
9
+ owner: number;
8
10
  reconnection?: {
9
11
  enable?: boolean;
10
12
  attempts?: number;
@@ -19,6 +21,7 @@ export interface BotConfig {
19
21
  * const bot = new BotClient({
20
22
  * baseUrl: 'ws://localhost:8082/onebot/v11/ws/',
21
23
  * accessToken: 'yourAccessToken',
24
+ * owner: 123456789,
22
25
  * })
23
26
  * await bot.start()
24
27
  */
@@ -29,7 +32,14 @@ export declare class BotClient {
29
32
  plugin: import('./botPlugin').BotPluginSystem;
30
33
  nickname: string | null;
31
34
  id: number | null;
35
+ /** Bot 主人(管理员)QQ 号,来自配置项 `owner` */
36
+ owner: number;
32
37
  constructor(config: BotConfig);
38
+ /**
39
+ * 判断指定 QQ 号是否为 bot 主人
40
+ * @param qq - 待判断的 QQ 号
41
+ */
42
+ isOwner(qq: number | string): boolean;
33
43
  /**
34
44
  * 连接 napcat 并初始化事件监听,启动成功后自动填充 {@link nickname} 和 {@link id}。
35
45
  */
package/dist/botClient.js CHANGED
@@ -1,7 +1,7 @@
1
- import { BotApi } from './botApi';
2
- import { BotConsole } from './botConsole';
3
- import { BotEvent } from './botEvent';
4
- import { BotScheduler } from './botScheduler';
1
+ import { BotApi } from './botApi.js';
2
+ import { BotConsole } from './botConsole.js';
3
+ import { BotEvent } from './botEvent.js';
4
+ import { BotScheduler } from './botScheduler.js';
5
5
  import { existsSync, mkdirSync, cpSync, readdirSync, readFileSync, statSync, lstatSync } from 'fs';
6
6
  import { join, dirname, relative } from 'path';
7
7
  import { fileURLToPath } from 'url';
@@ -12,6 +12,7 @@ import { fileURLToPath } from 'url';
12
12
  * const bot = new BotClient({
13
13
  * baseUrl: 'ws://localhost:8082/onebot/v11/ws/',
14
14
  * accessToken: 'yourAccessToken',
15
+ * owner: 123456789,
15
16
  * })
16
17
  * await bot.start()
17
18
  */
@@ -53,19 +54,45 @@ export class BotClient {
53
54
  writable: true,
54
55
  value: void 0
55
56
  });
56
- this.api = new BotApi(config);
57
+ /** Bot 主人(管理员)QQ 号,来自配置项 `owner` */
58
+ Object.defineProperty(this, "owner", {
59
+ enumerable: true,
60
+ configurable: true,
61
+ writable: true,
62
+ value: void 0
63
+ });
64
+ const owner = Number(config?.owner);
65
+ if (!Number.isInteger(owner) || owner <= 0) {
66
+ throw new Error('未配置 bot 主人 QQ 号:请在 BotClient 配置中填写 owner 字段,例如 owner: 123456789,未配置前无法启动');
67
+ }
68
+ const baseUrl = typeof config?.baseUrl === 'string' ? config.baseUrl.trim() : '';
69
+ if (!baseUrl) {
70
+ throw new Error('未配置 NapCat WebSocket 地址:请在 BotClient 配置中填写 baseUrl 字段,例如 baseUrl: "ws://localhost:8082/onebot/v11/ws/",未配置前无法启动');
71
+ }
72
+ if (!/^wss?:\/\/\S+$/i.test(baseUrl)) {
73
+ throw new Error('baseUrl 格式错误:必须以 ws:// 或 wss:// 开头,例如 ws://localhost:8082/onebot/v11/ws/');
74
+ }
75
+ this.owner = owner;
76
+ this.api = new BotApi({ ...config, baseUrl });
57
77
  this.api.client = this;
58
78
  this.event = new BotEvent(this.api, this);
59
79
  this.scheduler = new BotScheduler();
60
80
  this.nickname = null;
61
81
  this.id = null;
62
82
  }
83
+ /**
84
+ * 判断指定 QQ 号是否为 bot 主人
85
+ * @param qq - 待判断的 QQ 号
86
+ */
87
+ isOwner(qq) {
88
+ return Number(qq) === this.owner;
89
+ }
63
90
  /**
64
91
  * 连接 napcat 并初始化事件监听,启动成功后自动填充 {@link nickname} 和 {@link id}。
65
92
  */
66
93
  async start() {
67
94
  await this.api.connect();
68
- const { BotPluginSystem } = await import('./botPlugin');
95
+ const { BotPluginSystem } = await import('./botPlugin.js');
69
96
  this.plugin = new BotPluginSystem(this.api, this);
70
97
  this.api.napcat.on('meta_event.lifecycle.connect', () => {
71
98
  new BotConsole('system', 'napcat服务器连接成功').log();
package/dist/botEvent.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BotConsole } from './botConsole';
1
+ import { BotConsole } from './botConsole.js';
2
2
  /**
3
3
  * 接收到的事件处理(别人发的消息)。
4
4
  */
package/dist/botPlugin.js CHANGED
@@ -1,6 +1,7 @@
1
- import { BotConsole } from './botConsole';
1
+ import { BotConsole } from './botConsole.js';
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
+ import { pathToFileURL } from 'url';
4
5
  /**
5
6
  * 插件管理器,通过 `bot.plugin.xxx()` 访问。
6
7
  *
@@ -150,7 +151,9 @@ export class BotPluginSystem {
150
151
  if (!indexPath)
151
152
  continue;
152
153
  try {
153
- const mod = await import(path.resolve(indexPath));
154
+ // Node 的 ESM 加载器不接受裸 Windows 绝对路径(ERR_UNSUPPORTED_ESM_URL_SCHEME),
155
+ // 必须转成 file:// URL;Bun 两者都接受。
156
+ const mod = await import(pathToFileURL(path.resolve(indexPath)).href);
154
157
  const ctor = mod[name.charAt(0).toUpperCase() + name.slice(1) + 'Plugin'] || mod.default || Object.values(mod).find((v) => typeof v === 'function' && v.create);
155
158
  if (!ctor || typeof ctor.create !== 'function') {
156
159
  new BotConsole('error', `插件目录 "${name}" 未导出符合规范的插件类`).log();
@@ -236,7 +239,7 @@ export class BotPluginSystem {
236
239
  if (!indexPath)
237
240
  return;
238
241
  try {
239
- const mod = await import(indexPath);
242
+ const mod = await import(pathToFileURL(path.resolve(indexPath)).href);
240
243
  const ctor = mod[name.charAt(0).toUpperCase() + name.slice(1) + 'Plugin'] || mod.default || Object.values(mod).find((v) => typeof v === 'function' && v.create);
241
244
  if (!ctor || typeof ctor.create !== 'function')
242
245
  return;
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- export { BotClient } from './botClient';
2
- export { BotApi } from './botApi';
3
- export { BotEvent, MessageEvent, MessageSent, RequestEvent, NoticeEvent } from './botEvent';
4
- export { BotScheduler } from './botScheduler';
5
- export { BotPluginSystem } from './botPlugin';
6
- export { BotConsole, colors, parseCQ, formatMessage } from './botConsole';
7
- export { Message } from './message';
8
- export { PluginBase } from './plugin';
1
+ export { BotClient } from './botClient.js';
2
+ export { BotApi } from './botApi.js';
3
+ export { BotEvent, MessageEvent, MessageSent, RequestEvent, NoticeEvent } from './botEvent.js';
4
+ export { BotScheduler } from './botScheduler.js';
5
+ export { BotPluginSystem } from './botPlugin.js';
6
+ export { BotConsole, colors, parseCQ, formatMessage } from './botConsole.js';
7
+ export { Message } from './message.js';
8
+ export { PluginBase } from './plugin.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hotcat-bot-qq",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "基于 node-napcat-ts 的 TypeScript QQ 机器人框架",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -51,9 +51,9 @@
51
51
  "logo.png"
52
52
  ],
53
53
  "scripts": {
54
- "build": "tsc -p tsconfig.build.json",
55
- "build:plugin": "tsc --outDir plugins/hotCatPlugin --rootDir plugins/hotCatPlugin --module ESNext --target ES2020 --moduleResolution bundler --declaration --skipLibCheck plugins/hotCatPlugin/index.ts",
56
- "prepublishOnly": "bun run build && bun run build:plugin",
54
+ "build": "tsc -p tsconfig.build.json && node scripts/fix-dist-extensions.mjs",
55
+ "build:plugin": "bun run build && tsc --outDir plugins/hotCatPlugin --rootDir plugins/hotCatPlugin --module ESNext --target ES2020 --moduleResolution bundler --declaration --skipLibCheck plugins/hotCatPlugin/index.ts",
56
+ "prepublishOnly": "bun run build:plugin",
57
57
  "docs:dev": "vitepress dev docs",
58
58
  "docs:build": "vitepress build docs",
59
59
  "docs:preview": "vitepress preview docs"
@@ -12,6 +12,9 @@ export declare class HotCatPlugin extends PluginBase {
12
12
  static create(api: BotApi, bot: BotClient): HotCatPlugin;
13
13
  load(): Promise<void>;
14
14
  unload(): Promise<void>;
15
+ private isInfoCommand;
16
+ private buildInfo;
15
17
  private onGroupMsg;
18
+ private onPrivateMsg;
16
19
  private formatUptime;
17
20
  }
@@ -7,20 +7,15 @@ export class HotCatPlugin extends PluginBase {
7
7
  this.startTime = 0;
8
8
  this.onGroupMsg = async (_bot, event) => {
9
9
  const msg = event.raw_message.trim();
10
- if (msg === '#hotCat' || msg === '#hotcat') {
11
- const uptime = this.formatUptime(Date.now() - this.startTime);
12
- const platform = os.platform();
13
- const arch = os.arch();
14
- await this.api.sendGroupMessage(event.group_id, Message.reply(event.message_id), Message.text(`HotCat 信息\n` +
15
- `版本:${this.meta.version}\n` +
16
- `平台:${platform} ${arch}\n` +
17
- `运行时间:${uptime}\n` +
18
- `Github: https://github.com/CHCAT1320/hotCat-bot-qq\n` +
19
- `开发文档: https://hotcat-bot-qq.docs.chcat1320.top\n` +
20
- `交流群: 638144340\n` +
21
- `管理员QQ: 1095216448\n` +
22
- `基于 MIT 许可发布 版权所有 © 2026 CHCAT1320`));
23
- }
10
+ if (!this.isInfoCommand(msg))
11
+ return;
12
+ await this.api.sendGroupMessage(event.group_id, Message.reply(event.message_id), Message.text(this.buildInfo()));
13
+ };
14
+ this.onPrivateMsg = async (_bot, event) => {
15
+ const msg = event.raw_message.trim();
16
+ if (!this.isInfoCommand(msg))
17
+ return;
18
+ await this.api.sendPrivateMessage(event.user_id, Message.text(this.buildInfo()));
24
19
  };
25
20
  }
26
21
  static create(api, bot) {
@@ -29,9 +24,28 @@ export class HotCatPlugin extends PluginBase {
29
24
  async load() {
30
25
  this.startTime = Date.now();
31
26
  this.bot.event.message.onGroupMessage(this.onGroupMsg);
27
+ this.bot.event.message.onPrivateMessage(this.onPrivateMsg);
32
28
  }
33
29
  async unload() {
34
30
  this.bot.event.message.offGroupMessage(this.onGroupMsg);
31
+ this.bot.event.message.offPrivateMessage(this.onPrivateMsg);
32
+ }
33
+ isInfoCommand(msg) {
34
+ return msg === '#hotCat' || msg === '#hotcat';
35
+ }
36
+ buildInfo() {
37
+ const uptime = this.formatUptime(Date.now() - this.startTime);
38
+ const platform = os.platform();
39
+ const arch = os.arch();
40
+ return `HotCat 信息\n` +
41
+ `版本:${this.meta.version}\n` +
42
+ `平台:${platform} ${arch}\n` +
43
+ `运行时间:${uptime}\n` +
44
+ `管理员QQ: ${this.bot.owner}\n` +
45
+ `Github: https://github.com/CHCAT1320/hotCat-bot-qq\n` +
46
+ `开发文档: https://hotcat-bot-qq.docs.chcat1320.top\n` +
47
+ `交流群: 638144340\n` +
48
+ `基于 MIT 许可发布 版权所有 © 2026 CHCAT1320`;
35
49
  }
36
50
  formatUptime(ms) {
37
51
  const s = Math.floor(ms / 1000);
@@ -50,7 +64,7 @@ export class HotCatPlugin extends PluginBase {
50
64
  }
51
65
  HotCatPlugin.meta = {
52
66
  name: 'hotCatPlugin',
53
- version: '0.1.9',
54
- description: 'HotCat 默认插件(#hotCat 指令查询 bot 状态)',
67
+ version: '0.1.11',
68
+ description: 'HotCat 默认插件(群聊/私聊 #hotCat 指令查询 bot 状态)',
55
69
  author: 'CHCAT1320',
56
70
  };
@@ -7,8 +7,8 @@ import * as os from 'os'
7
7
  export class HotCatPlugin extends PluginBase {
8
8
  static meta = {
9
9
  name: 'hotCatPlugin',
10
- version: '0.1.9',
11
- description: 'HotCat 默认插件(#hotCat 指令查询 bot 状态)',
10
+ version: '0.1.11',
11
+ description: 'HotCat 默认插件(群聊/私聊 #hotCat 指令查询 bot 状态)',
12
12
  author: 'CHCAT1320',
13
13
  }
14
14
 
@@ -21,35 +21,51 @@ export class HotCatPlugin extends PluginBase {
21
21
  async load() {
22
22
  this.startTime = Date.now()
23
23
  this.bot.event.message.onGroupMessage(this.onGroupMsg)
24
+ this.bot.event.message.onPrivateMessage(this.onPrivateMsg)
24
25
  }
25
26
 
26
27
  async unload() {
27
28
  this.bot.event.message.offGroupMessage(this.onGroupMsg)
29
+ this.bot.event.message.offPrivateMessage(this.onPrivateMsg)
30
+ }
31
+
32
+ private isInfoCommand(msg: string): boolean {
33
+ return msg === '#hotCat' || msg === '#hotcat'
34
+ }
35
+
36
+ private buildInfo(): string {
37
+ const uptime = this.formatUptime(Date.now() - this.startTime)
38
+ const platform = os.platform()
39
+ const arch = os.arch()
40
+
41
+ return `HotCat 信息\n` +
42
+ `版本:${this.meta.version}\n` +
43
+ `平台:${platform} ${arch}\n` +
44
+ `运行时间:${uptime}\n` +
45
+ `管理员QQ: ${this.bot.owner}\n` +
46
+ `Github: https://github.com/CHCAT1320/hotCat-bot-qq\n` +
47
+ `开发文档: https://hotcat-bot-qq.docs.chcat1320.top\n` +
48
+ `交流群: 638144340\n` +
49
+ `基于 MIT 许可发布 版权所有 © 2026 CHCAT1320`
28
50
  }
29
51
 
30
52
  private onGroupMsg = async (_bot: BotClient, event: any) => {
31
53
  const msg = event.raw_message.trim()
54
+ if (!this.isInfoCommand(msg)) return
55
+
56
+ await this.api.sendGroupMessage(event.group_id,
57
+ Message.reply(event.message_id),
58
+ Message.text(this.buildInfo())
59
+ )
60
+ }
32
61
 
33
- if (msg === '#hotCat' || msg === '#hotcat') {
34
- const uptime = this.formatUptime(Date.now() - this.startTime)
35
- const platform = os.platform()
36
- const arch = os.arch()
62
+ private onPrivateMsg = async (_bot: BotClient, event: any) => {
63
+ const msg = event.raw_message.trim()
64
+ if (!this.isInfoCommand(msg)) return
37
65
 
38
- await this.api.sendGroupMessage(event.group_id,
39
- Message.reply(event.message_id),
40
- Message.text(
41
- `HotCat 信息\n` +
42
- `版本:${this.meta.version}\n` +
43
- `平台:${platform} ${arch}\n` +
44
- `运行时间:${uptime}\n` +
45
- `Github: https://github.com/CHCAT1320/hotCat-bot-qq\n` +
46
- `开发文档: https://hotcat-bot-qq.docs.chcat1320.top\n` +
47
- `交流群: 638144340\n` +
48
- `管理员QQ: 1095216448\n` +
49
- `基于 MIT 许可发布 版权所有 © 2026 CHCAT1320`
50
- )
51
- )
52
- }
66
+ await this.api.sendPrivateMessage(event.user_id,
67
+ Message.text(this.buildInfo())
68
+ )
53
69
  }
54
70
 
55
71
  private formatUptime(ms: number): string {