hotcat-bot-qq 0.0.1 → 0.1.0

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.
@@ -1,6 +1,7 @@
1
1
  import { NCWebsocketOptions } from 'node-napcat-ts';
2
2
  import { BotApi } from './botApi';
3
3
  import { BotEvent } from './botEvent';
4
+ import { BotScheduler } from './botScheduler';
4
5
  /**
5
6
  * Bot 客户端,封装连接、启动流程及 bot 自身信息。
6
7
  *
@@ -23,6 +24,8 @@ export declare class BotClient {
23
24
  api: BotApi;
24
25
  /** 事件监听入口 */
25
26
  event: BotEvent;
27
+ /** 定时任务入口 */
28
+ scheduler: BotScheduler;
26
29
  /** 登录后 bot 自身昵称 */
27
30
  nickname: string | null;
28
31
  /** 登录后 bot 自身 QQ 号 */
package/dist/botClient.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { BotApi } from './botApi';
2
2
  import { BotConsole } from './botConsole';
3
3
  import { BotEvent } from './botEvent';
4
+ import { BotScheduler } from './botScheduler';
4
5
  /**
5
6
  * Bot 客户端,封装连接、启动流程及 bot 自身信息。
6
7
  *
@@ -34,6 +35,13 @@ export class BotClient {
34
35
  writable: true,
35
36
  value: void 0
36
37
  });
38
+ /** 定时任务入口 */
39
+ Object.defineProperty(this, "scheduler", {
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true,
43
+ value: void 0
44
+ });
37
45
  /** 登录后 bot 自身昵称 */
38
46
  Object.defineProperty(this, "nickname", {
39
47
  enumerable: true,
@@ -51,6 +59,7 @@ export class BotClient {
51
59
  this.api = new BotApi(config);
52
60
  this.api.client = this;
53
61
  this.event = new BotEvent(this.api, this);
62
+ this.scheduler = new BotScheduler();
54
63
  this.nickname = null;
55
64
  this.id = null;
56
65
  }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * 定时任务调度器,支持 cron、间隔、指定时间三种模式。
3
+ *
4
+ * cron('0 8 * * *', fn) 每天 8:00
5
+ * every('5m', fn) 每5分钟
6
+ * at('08:00', fn) 每天 8:00
7
+ */
8
+ export declare class BotScheduler {
9
+ private jobs;
10
+ private idCounter;
11
+ /**
12
+ * cron 表达式定时
13
+ * @param expr - cron 表达式,如 `'0 8 * * *'`(每天 8:00)
14
+ * @param fn - 回调函数
15
+ * @returns job id,可用于 cancel
16
+ */
17
+ cron(expr: string, fn: () => void): number;
18
+ /**
19
+ * 间隔重复执行
20
+ * @param time - 间隔,支持数字(ms)或字符串 `'5s'` `'10m'` `'1h'` `'2d'`
21
+ * @param fn - 回调函数
22
+ * @returns job id
23
+ */
24
+ every(time: number | string, fn: () => void): number;
25
+ /**
26
+ * 指定时间执行(一次性或每日重复)
27
+ * @param time - 字符串 `'08:00'`(每日)/ `'2026-08-01 12:00'`(一次性),或 Date
28
+ * @param fn - 回调函数
29
+ * @returns job id
30
+ */
31
+ at(time: string | Date, fn: () => void): number;
32
+ /**
33
+ * 取消指定任务
34
+ * @param id - cron/every/at 返回的 id
35
+ */
36
+ cancel(id: number): void;
37
+ /** 取消全部任务 */
38
+ cancelAll(): void;
39
+ private parseTime;
40
+ private timeToCron;
41
+ }
@@ -0,0 +1,146 @@
1
+ import * as schedule from 'node-schedule';
2
+ /**
3
+ * 定时任务调度器,支持 cron、间隔、指定时间三种模式。
4
+ *
5
+ * cron('0 8 * * *', fn) 每天 8:00
6
+ * every('5m', fn) 每5分钟
7
+ * at('08:00', fn) 每天 8:00
8
+ */
9
+ export class BotScheduler {
10
+ constructor() {
11
+ Object.defineProperty(this, "jobs", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: new Map()
16
+ });
17
+ Object.defineProperty(this, "idCounter", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: 0
22
+ });
23
+ }
24
+ /**
25
+ * cron 表达式定时
26
+ * @param expr - cron 表达式,如 `'0 8 * * *'`(每天 8:00)
27
+ * @param fn - 回调函数
28
+ * @returns job id,可用于 cancel
29
+ */
30
+ cron(expr, fn) {
31
+ const id = ++this.idCounter;
32
+ const job = schedule.scheduleJob(expr, () => {
33
+ try {
34
+ fn();
35
+ }
36
+ catch { }
37
+ });
38
+ if (job)
39
+ this.jobs.set(id, job);
40
+ return id;
41
+ }
42
+ /**
43
+ * 间隔重复执行
44
+ * @param time - 间隔,支持数字(ms)或字符串 `'5s'` `'10m'` `'1h'` `'2d'`
45
+ * @param fn - 回调函数
46
+ * @returns job id
47
+ */
48
+ every(time, fn) {
49
+ const ms = typeof time === 'number' ? time : this.parseTime(time);
50
+ const id = ++this.idCounter;
51
+ const timer = setInterval(() => {
52
+ try {
53
+ fn();
54
+ }
55
+ catch { }
56
+ }, ms);
57
+ this.jobs.set(id, timer);
58
+ return id;
59
+ }
60
+ /**
61
+ * 指定时间执行(一次性或每日重复)
62
+ * @param time - 字符串 `'08:00'`(每日)/ `'2026-08-01 12:00'`(一次性),或 Date
63
+ * @param fn - 回调函数
64
+ * @returns job id
65
+ */
66
+ at(time, fn) {
67
+ const id = ++this.idCounter;
68
+ if (typeof time === 'string' && time.includes('-')) {
69
+ const target = new Date(time);
70
+ if (isNaN(target.getTime()))
71
+ return id;
72
+ const ms = target.getTime() - Date.now();
73
+ if (ms <= 0) {
74
+ try {
75
+ fn();
76
+ }
77
+ catch { }
78
+ return id;
79
+ }
80
+ const timer = setTimeout(() => { try {
81
+ fn();
82
+ }
83
+ catch { } }, ms);
84
+ this.jobs.set(id, timer);
85
+ return id;
86
+ }
87
+ if (typeof time === 'string') {
88
+ return this.cron(this.timeToCron(time), fn);
89
+ }
90
+ const ms = time.getTime() - Date.now();
91
+ if (ms <= 0) {
92
+ try {
93
+ fn();
94
+ }
95
+ catch { }
96
+ return id;
97
+ }
98
+ const timer = setTimeout(() => { try {
99
+ fn();
100
+ }
101
+ catch { } }, ms);
102
+ this.jobs.set(id, timer);
103
+ return id;
104
+ }
105
+ /**
106
+ * 取消指定任务
107
+ * @param id - cron/every/at 返回的 id
108
+ */
109
+ cancel(id) {
110
+ const job = this.jobs.get(id);
111
+ if (!job)
112
+ return;
113
+ if ('cancel' in job) {
114
+ job.cancel();
115
+ }
116
+ else {
117
+ clearInterval(job);
118
+ }
119
+ this.jobs.delete(id);
120
+ }
121
+ /** 取消全部任务 */
122
+ cancelAll() {
123
+ for (const id of Array.from(this.jobs.keys())) {
124
+ this.cancel(id);
125
+ }
126
+ }
127
+ parseTime(t) {
128
+ const m = t.match(/^(\d+)\s*(s|sec|secs|second|seconds|m|min|mins|minute|minutes|h|hr|hrs|hour|hours|d|day|days)$/i);
129
+ if (!m)
130
+ return 0;
131
+ const v = parseInt(m[1]);
132
+ switch (m[2][0].toLowerCase()) {
133
+ case 's': return v * 1000;
134
+ case 'm': return v * 60000;
135
+ case 'h': return v * 3600000;
136
+ case 'd': return v * 86400000;
137
+ default: return 0;
138
+ }
139
+ }
140
+ timeToCron(t) {
141
+ const m = t.match(/^(\d{1,2}):(\d{2})$/);
142
+ if (!m)
143
+ return '';
144
+ return `${m[2]} ${m[1]} * * *`;
145
+ }
146
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { BotClient } from './botClient';
2
2
  export { BotApi } from './botApi';
3
3
  export { BotEvent, MessageEvent, MessageSent, RequestEvent, NoticeEvent } from './botEvent';
4
+ export { BotScheduler } from './botScheduler';
4
5
  export { BotConsole, colors, parseCQ, formatMessage } from './botConsole';
5
6
  export type { BotConsoleType, PrivateMessage, PrivateMessageSelf, RequestGroup, NoticeEvent as NoticeEventType } from './botConsole';
6
7
  export { Message } from './message';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { BotClient } from './botClient';
2
2
  export { BotApi } from './botApi';
3
3
  export { BotEvent, MessageEvent, MessageSent, RequestEvent, NoticeEvent } from './botEvent';
4
+ export { BotScheduler } from './botScheduler';
4
5
  export { BotConsole, colors, parseCQ, formatMessage } from './botConsole';
5
6
  export { Message } from './message';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hotcat-bot-qq",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "基于 node-napcat-ts 的 TypeScript QQ 机器人框架",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -61,6 +61,7 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "node-napcat-ts": "^0.4.25",
64
+ "node-schedule": "^2.1.1",
64
65
  "@types/node": "^26.1.2"
65
66
  },
66
67
  "devDependencies": {