koishi-plugin-toram 4.0.4 → 4.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.
package/lib/index.d.ts CHANGED
@@ -6,6 +6,7 @@ declare module 'koishi' {
6
6
  export interface Config {
7
7
  qq: string;
8
8
  groupId: string;
9
+ adminQQList?: string[];
9
10
  maxLevel: number;
10
11
  levelUP_player_recommend: number;
11
12
  levelUP_player_fixedBossReturn: number;
package/lib/index.js CHANGED
@@ -36,7 +36,7 @@ __export(src_exports, {
36
36
  name: () => name
37
37
  });
38
38
  module.exports = __toCommonJS(src_exports);
39
- var import_koishi2 = require("koishi");
39
+ var import_koishi3 = require("koishi");
40
40
 
41
41
  // src/script/TalkMgr.ts
42
42
  var _TalkMgr = class _TalkMgr {
@@ -178,38 +178,45 @@ var JsonMgr = _JsonMgr;
178
178
 
179
179
  // src/script/botFunction/monthlyCardReminder.ts
180
180
  var import_koishi = require("koishi");
181
- function monthlyCardReminderDailyTask(groupId, hours) {
182
- const scheduleNextRun = /* @__PURE__ */ __name(() => {
183
- const now = /* @__PURE__ */ new Date();
184
- const times = hours.map((hour) => {
185
- const time = new Date(now);
186
- time.setHours(hour, 10, 0, 0);
187
- if (time.getTime() <= now.getTime()) {
188
- time.setDate(time.getDate() + 1);
189
- }
190
- return time;
191
- });
192
- const next = times.reduce(
193
- (earliest, current) => current.getTime() < earliest.getTime() ? current : earliest
181
+ var MONTHLY_CARD_REMINDER_TYPE = "monthly-card-reminder";
182
+ function scheduleMonthlyCardReminders(groupId, hours) {
183
+ const now = /* @__PURE__ */ new Date();
184
+ for (let i = 0; i < hours.length; i++) {
185
+ const hour = hours[i];
186
+ const next = new Date(now);
187
+ next.setHours(hour, 10, 0, 0);
188
+ if (next.getTime() <= now.getTime()) next.setDate(next.getDate() + 1);
189
+ const ts = next.getTime();
190
+ const exists = (BotTodoMgr.Inst().getTodosAt(ts) || []).some(
191
+ (x) => x.type === MONTHLY_CARD_REMINDER_TYPE && x.payload?.groupId === groupId && x.payload?.timeIndex === i
194
192
  );
195
- const nextTimeIndex = hours.indexOf(next.getHours());
196
- const delay = next.getTime() - now.getTime();
197
- setTimeout(() => {
198
- try {
199
- const atUsers = genMonthlyCardReminderUsers(nextTimeIndex);
200
- if (atUsers) {
201
- TalkMgr.Inst().send(groupId, "月卡提醒", { atUsers });
202
- }
203
- } catch (err) {
204
- console.error("每日任务执行报错:", err);
205
- } finally {
206
- scheduleNextRun();
207
- }
208
- }, delay);
209
- }, "scheduleNextRun");
210
- scheduleNextRun();
193
+ if (!exists) {
194
+ BotTodoMgr.Inst().addTodo(ts, MONTHLY_CARD_REMINDER_TYPE, { groupId, timeIndex: i });
195
+ }
196
+ }
197
+ }
198
+ __name(scheduleMonthlyCardReminders, "scheduleMonthlyCardReminders");
199
+ async function executeMonthlyCardReminder(item) {
200
+ const payload = item.payload || {};
201
+ const groupId = payload.groupId;
202
+ const timeIndex = payload.timeIndex;
203
+ if (!groupId || typeof timeIndex !== "number") return;
204
+ const atUsers = genMonthlyCardReminderUsers(timeIndex);
205
+ if (atUsers) {
206
+ TalkMgr.Inst().send(groupId, "月卡提醒", { atUsers });
207
+ }
208
+ const next = new Date(item.ts + 24 * 60 * 60 * 1e3);
209
+ const hour = new Date(item.ts).getHours();
210
+ next.setHours(hour, 10, 0, 0);
211
+ const nextTs = next.getTime();
212
+ const exists = (BotTodoMgr.Inst().getTodosAt(nextTs) || []).some(
213
+ (x) => x.type === MONTHLY_CARD_REMINDER_TYPE && x.payload?.groupId === groupId && x.payload?.timeIndex === timeIndex
214
+ );
215
+ if (!exists) {
216
+ BotTodoMgr.Inst().addTodo(nextTs, MONTHLY_CARD_REMINDER_TYPE, { groupId, timeIndex });
217
+ }
211
218
  }
212
- __name(monthlyCardReminderDailyTask, "monthlyCardReminderDailyTask");
219
+ __name(executeMonthlyCardReminder, "executeMonthlyCardReminder");
213
220
  function genMonthlyCardReminderUsers(timeIndex) {
214
221
  const users = UserMgr.Inst().getUsersWithMonthlyCardRemindTimeIndex(timeIndex);
215
222
  if (users.length === 0) return;
@@ -218,9 +225,146 @@ function genMonthlyCardReminderUsers(timeIndex) {
218
225
  }
219
226
  __name(genMonthlyCardReminderUsers, "genMonthlyCardReminderUsers");
220
227
 
228
+ // src/script/botFunction/allMemberReminder.ts
229
+ var import_koishi2 = require("koishi");
230
+ var ALL_MEMBER_REMINDER_TYPE = "all-member-reminder";
231
+ function genAtAllMessage(content) {
232
+ const atAll = `${(0, import_koishi2.h)("at", { type: "all" })}`;
233
+ return content ? `${atAll} ${content}` : atAll;
234
+ }
235
+ __name(genAtAllMessage, "genAtAllMessage");
236
+ async function executeAllMemberReminder(item) {
237
+ const payload = item.payload || {};
238
+ const groupId = payload.groupId;
239
+ const content = payload.content;
240
+ if (!groupId) return;
241
+ const message = genAtAllMessage(content || "");
242
+ TalkMgr.Inst().send(groupId, "简易回复", { result: message });
243
+ }
244
+ __name(executeAllMemberReminder, "executeAllMemberReminder");
245
+
246
+ // src/script/command/allMemberRemindCommand.ts
247
+ function allMemberRemind(event, args) {
248
+ const qq = event.session.event.user.id;
249
+ const authResult = isAdmin(qq, event);
250
+ if (authResult?.code === 2002 /* 无权限 */) {
251
+ TalkMgr.Inst().reply(event, "无权限");
252
+ return;
253
+ }
254
+ const checkResult = checkArgs(args, event.config);
255
+ switch (checkResult.code) {
256
+ case 2001 /* 参数缺失 */:
257
+ TalkMgr.Inst().reply(event, "简易回复", { result: "参数缺失:需要 时间段 时间点 内容" });
258
+ return;
259
+ case 3002 /* 时间不正确 */:
260
+ TalkMgr.Inst().reply(event, "简易回复", { result: "时间不正确:请输入 (yy.)mm.dd(-yy.mm.dd) 和 hh:mm" });
261
+ return;
262
+ }
263
+ const { timeList, content } = checkResult.result;
264
+ const groupId = event.config.groupId;
265
+ if (!Array.isArray(timeList) || timeList.length === 0) {
266
+ TalkMgr.Inst().reply(event, "简易回复", { result: "没有可用的时间点。" });
267
+ return;
268
+ }
269
+ let created = 0;
270
+ for (const ts of timeList) {
271
+ BotTodoMgr.Inst().addTodo(ts, ALL_MEMBER_REMINDER_TYPE, { groupId, content });
272
+ created++;
273
+ }
274
+ TalkMgr.Inst().reply(event, "简易回复", { result: `咕` });
275
+ }
276
+ __name(allMemberRemind, "allMemberRemind");
277
+ function isAdmin(qq, event) {
278
+ const adminQQList = event.config.adminQQList;
279
+ if (!adminQQList.includes(qq)) {
280
+ return new Result(2002 /* 无权限 */, false);
281
+ }
282
+ }
283
+ __name(isAdmin, "isAdmin");
284
+ function checkArgs(args, config) {
285
+ const timePeriod = args[0];
286
+ const timePointStr = args[1];
287
+ const content = args[2];
288
+ if (timePeriod === void 0 || timePointStr === void 0 || content === void 0) {
289
+ return new Result(2001 /* 参数缺失 */);
290
+ }
291
+ const now = /* @__PURE__ */ new Date();
292
+ const currentYear = now.getFullYear();
293
+ const parseSingleDay = /* @__PURE__ */ __name((str, defaultYear) => {
294
+ if (!str) return null;
295
+ let yearProvided = false;
296
+ let y = defaultYear;
297
+ let mStr = "";
298
+ let dStr = "";
299
+ const parts = str.split(".");
300
+ if (parts.length === 2) {
301
+ mStr = parts[0];
302
+ dStr = parts[1];
303
+ } else if (parts.length === 3) {
304
+ yearProvided = true;
305
+ const yy = parts[0];
306
+ mStr = parts[1];
307
+ dStr = parts[2];
308
+ const yNum = Number(yy);
309
+ if (!Number.isInteger(yNum)) return null;
310
+ if (yy.length <= 2) y = 2e3 + yNum;
311
+ else if (yy.length === 4) y = yNum;
312
+ else return null;
313
+ } else {
314
+ return null;
315
+ }
316
+ const m = Number(mStr);
317
+ const d = Number(dStr);
318
+ if (!Number.isInteger(m) || !Number.isInteger(d)) return null;
319
+ if (m < 1 || m > 12 || d < 1 || d > 31) return null;
320
+ const date = new Date(y, m - 1, d);
321
+ if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) return null;
322
+ return { date, yearProvided };
323
+ }, "parseSingleDay");
324
+ const periodParts = timePeriod.split("-").map((s) => s.trim()).filter((s) => s.length > 0);
325
+ if (periodParts.length < 1 || periodParts.length > 2) {
326
+ return new Result(3002 /* 时间不正确 */);
327
+ }
328
+ const startParsed = parseSingleDay(periodParts[0], currentYear);
329
+ if (!startParsed) return new Result(3002 /* 时间不正确 */);
330
+ let { date: startDate } = startParsed;
331
+ let endDate = startDate;
332
+ if (periodParts.length === 2) {
333
+ const endParsed = parseSingleDay(periodParts[1], startDate.getFullYear());
334
+ if (!endParsed) return new Result(3002 /* 时间不正确 */);
335
+ endDate = endParsed.date;
336
+ if (!endParsed.yearProvided && endDate.getTime() < startDate.getTime()) {
337
+ endDate = new Date(endDate.getFullYear() + 1, endDate.getMonth(), endDate.getDate());
338
+ }
339
+ }
340
+ const timeStr = timePointStr.trim().replace(/:/g, ":");
341
+ const tm = timeStr.match(/^(\d{1,2}):(\d{1,2})$/);
342
+ if (!tm) return new Result(3002 /* 时间不正确 */);
343
+ const hour = Number(tm[1]);
344
+ const minute = Number(tm[2]);
345
+ if (!Number.isInteger(hour) || !Number.isInteger(minute) || hour < 0 || hour > 23 || minute < 0 || minute > 59) {
346
+ return new Result(3002 /* 时间不正确 */);
347
+ }
348
+ if (endDate.getTime() < startDate.getTime()) return new Result(3002 /* 时间不正确 */);
349
+ const timeList = [];
350
+ const cursor = new Date(startDate);
351
+ const maxDays = 366 * 2;
352
+ let guard = 0;
353
+ while (cursor.getTime() <= endDate.getTime()) {
354
+ const dt = new Date(cursor);
355
+ dt.setHours(hour, minute, 0, 0);
356
+ timeList.push(dt.getTime());
357
+ cursor.setDate(cursor.getDate() + 1);
358
+ guard++;
359
+ if (guard > maxDays) return new Result(3002 /* 时间不正确 */);
360
+ }
361
+ return new Result(1001 /* 通过 */, { timeList, content });
362
+ }
363
+ __name(checkArgs, "checkArgs");
364
+
221
365
  // src/script/command/levelUpCommand.ts
222
- async function command_levelUP(event, args) {
223
- const checkResult = checkArgs(args, event.config.maxLevel);
366
+ function command_levelUP(event, args) {
367
+ const checkResult = checkArgs2(args, event.config.maxLevel);
224
368
  switch (checkResult.code) {
225
369
  case 2001 /* 参数缺失 */:
226
370
  TalkMgr.Inst().reply(event, "升级命令_参数缺失");
@@ -284,7 +428,7 @@ ${wildBossResult.join("\n")}`;
284
428
  TalkMgr.Inst().reply(event, "正常回复", { title, result, tips });
285
429
  }
286
430
  __name(command_levelUP, "command_levelUP");
287
- function checkArgs(args, maxLevel) {
431
+ function checkArgs2(args, maxLevel) {
288
432
  let levelCN = args[0];
289
433
  if (levelCN === void 0) return new Result(2001 /* 参数缺失 */);
290
434
  if (/级$/.test(levelCN)) levelCN = levelCN.replace(/级/g, "");
@@ -292,7 +436,7 @@ function checkArgs(args, maxLevel) {
292
436
  if (isNaN(level) || level < 1 || level > maxLevel || Math.floor(level) !== level) return new Result(3001 /* 等级不正确 */);
293
437
  return new Result(1001 /* 通过 */, { level });
294
438
  }
295
- __name(checkArgs, "checkArgs");
439
+ __name(checkArgs2, "checkArgs");
296
440
  function getUpgradeExp(level, maxLevel) {
297
441
  const exp = Math.floor(level ** 4 / 40) + level * 2;
298
442
  return level !== maxLevel ? `${level}级升级所需经验为${exp}` : "";
@@ -300,8 +444,8 @@ function getUpgradeExp(level, maxLevel) {
300
444
  __name(getUpgradeExp, "getUpgradeExp");
301
445
 
302
446
  // src/script/command/monthlyCardRemindCommand.ts
303
- async function command_monthlyCardRemind(event, args) {
304
- const checkResult = checkArgs2(args);
447
+ function command_monthlyCardRemind(event, args) {
448
+ const checkResult = checkArgs3(args);
305
449
  switch (checkResult.code) {
306
450
  case 2001 /* 参数缺失 */:
307
451
  TalkMgr.Inst().reply(event, "月卡提醒_参数缺失");
@@ -329,7 +473,7 @@ async function command_monthlyCardRemind(event, args) {
329
473
  });
330
474
  }
331
475
  __name(command_monthlyCardRemind, "command_monthlyCardRemind");
332
- function checkArgs2(args) {
476
+ function checkArgs3(args) {
333
477
  const time = args[0];
334
478
  if (time === void 0) return new Result(2001 /* 参数缺失 */);
335
479
  const allowTimesCN = ["凌晨", "早上", "中午", "下午", "晚上", "深夜"];
@@ -337,8 +481,8 @@ function checkArgs2(args) {
337
481
  if (index === -1) return new Result(3002 /* 时间不正确 */);
338
482
  return new Result(1001 /* 通过 */, { timeIndex: index });
339
483
  }
340
- __name(checkArgs2, "checkArgs");
341
- async function command_cancelMonthlyCardRemind(event, args) {
484
+ __name(checkArgs3, "checkArgs");
485
+ function command_cancelMonthlyCardRemind(event, args) {
342
486
  const qq = Number(event.session.event.user.id);
343
487
  UserMgr.Inst().setUserMonthlyCardRemindTimeIndex(qq, -1);
344
488
  TalkMgr.Inst().reply(event, "简易回复", {
@@ -482,29 +626,198 @@ __name(_UserMgr, "UserMgr");
482
626
  _UserMgr.instance = null;
483
627
  var UserMgr = _UserMgr;
484
628
 
629
+ // src/script/BotTodoMgr.ts
630
+ var _BotTodoMgr = class _BotTodoMgr {
631
+ constructor() {
632
+ this.jsonName = "botTodos.json";
633
+ this._todos = /* @__PURE__ */ new Map();
634
+ this._handlers = /* @__PURE__ */ new Map();
635
+ this._timer = null;
636
+ this._started = false;
637
+ }
638
+ static Inst() {
639
+ if (!_BotTodoMgr.instance) {
640
+ _BotTodoMgr.instance = new _BotTodoMgr();
641
+ }
642
+ return _BotTodoMgr.instance;
643
+ }
644
+ // 读取 json 到内存
645
+ setTodos() {
646
+ const data = JsonMgr.Inst().getJson(this.jsonName);
647
+ if (!data) return;
648
+ this._todos.clear();
649
+ data.forEach((item) => {
650
+ const list = this._todos.get(item.ts) || [];
651
+ list.push(item);
652
+ this._todos.set(item.ts, list);
653
+ });
654
+ }
655
+ // 持久化内存中的 todo
656
+ saveTodos() {
657
+ const data = [];
658
+ this._todos.forEach((list) => data.push(...list));
659
+ JsonMgr.Inst().saveJson(this.jsonName, data);
660
+ }
661
+ // 新增一条 todo,返回 id
662
+ addTodo(ts, type, payload) {
663
+ const id = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
664
+ const todo = { id, ts, type, payload };
665
+ const list = this._todos.get(ts) || [];
666
+ list.push(todo);
667
+ this._todos.set(ts, list);
668
+ this.saveTodos();
669
+ if (this._started) {
670
+ if (this._nextTs === void 0 || ts < this._nextTs) {
671
+ this.scheduleNext();
672
+ }
673
+ }
674
+ return id;
675
+ }
676
+ // 获取某个时间戳下的 todo 列表(拷贝)
677
+ getTodosAt(ts) {
678
+ const list = this._todos.get(ts) || [];
679
+ return list.map((x) => ({ ...x }));
680
+ }
681
+ // 删除某个时间戳下的指定 todo
682
+ removeTodo(ts, id) {
683
+ const list = this._todos.get(ts);
684
+ if (!list) return;
685
+ const next = list.filter((x) => x.id !== id);
686
+ if (next.length > 0) this._todos.set(ts, next);
687
+ else this._todos.delete(ts);
688
+ this.saveTodos();
689
+ }
690
+ // 删除某个时间戳下的所有 todo
691
+ removeTodosAt(ts) {
692
+ if (!this._todos.has(ts)) return;
693
+ this._todos.delete(ts);
694
+ this.saveTodos();
695
+ }
696
+ // 取出并删除“到期”的 todo 列表(ts <= now)
697
+ popDueTodos(now) {
698
+ const result = [];
699
+ const keys = Array.from(this._todos.keys()).filter((ts) => ts <= now).sort((a, b) => a - b);
700
+ keys.forEach((ts) => {
701
+ const list = this._todos.get(ts);
702
+ if (list && list.length) result.push(...list);
703
+ this._todos.delete(ts);
704
+ });
705
+ if (keys.length > 0) this.saveTodos();
706
+ return result;
707
+ }
708
+ // 下一个最近的时间戳(若不存在返回 undefined)
709
+ getNextTimestamp() {
710
+ const keys = Array.from(this._todos.keys());
711
+ if (keys.length === 0) return void 0;
712
+ return keys.sort((a, b) => a - b)[0];
713
+ }
714
+ // 注册任务处理器
715
+ on(type, handler) {
716
+ this._handlers.set(type, handler);
717
+ }
718
+ // 启动调度(基于 setTimeout)
719
+ start() {
720
+ this._started = true;
721
+ this.scheduleNext();
722
+ }
723
+ // 停止调度
724
+ stop() {
725
+ this._started = false;
726
+ if (this._timer) {
727
+ clearTimeout(this._timer);
728
+ this._timer = null;
729
+ }
730
+ this._nextTs = void 0;
731
+ }
732
+ // 立即重新计算下一个调度点
733
+ scheduleNext() {
734
+ if (!this._started) return;
735
+ try {
736
+ const dropped = this.popDueTodos(Date.now());
737
+ if (dropped.length) {
738
+ console.warn("BotTodoMgr 清理过期任务数量: ", dropped.length);
739
+ }
740
+ } catch (e) {
741
+ console.error("BotTodoMgr 清理过期任务异常: ", e);
742
+ }
743
+ if (this._timer) {
744
+ clearTimeout(this._timer);
745
+ this._timer = null;
746
+ }
747
+ this.internalPlanNext();
748
+ }
749
+ internalPlanNext() {
750
+ if (!this._started) return;
751
+ const now = Date.now();
752
+ const keys = Array.from(this._todos.keys()).filter((ts) => ts > now);
753
+ if (keys.length === 0) {
754
+ this._nextTs = void 0;
755
+ return;
756
+ }
757
+ const next = keys.sort((a, b) => a - b)[0];
758
+ this._nextTs = next;
759
+ const delay = Math.max(0, next - now);
760
+ const scheduledTs = next;
761
+ this._timer = setTimeout(async () => {
762
+ try {
763
+ const list = this._todos.get(scheduledTs) || [];
764
+ if (list.length) {
765
+ this._todos.delete(scheduledTs);
766
+ this.saveTodos();
767
+ await this.executeBatch(list);
768
+ }
769
+ } catch (e) {
770
+ console.error("BotTodoMgr 执行任务异常: ", e);
771
+ } finally {
772
+ this.scheduleNext();
773
+ }
774
+ }, delay);
775
+ }
776
+ async executeBatch(list) {
777
+ for (const item of list) {
778
+ const handler = this._handlers.get(item.type);
779
+ if (!handler) {
780
+ console.warn("BotTodoMgr 未找到处理器:", item.type, item);
781
+ continue;
782
+ }
783
+ try {
784
+ await handler(item);
785
+ } catch (e) {
786
+ console.error("BotTodoMgr 执行单个任务异常:", e, item);
787
+ }
788
+ }
789
+ }
790
+ };
791
+ __name(_BotTodoMgr, "BotTodoMgr");
792
+ _BotTodoMgr.instance = null;
793
+ var BotTodoMgr = _BotTodoMgr;
794
+
485
795
  // src/index.ts
486
796
  var name = "toram";
487
797
  var inject = ["database"];
488
- var Config = import_koishi2.Schema.intersect([
489
- import_koishi2.Schema.object({
490
- qq: import_koishi2.Schema.string().description("机器人QQ号").default("机器人qq号").required(),
491
- groupId: import_koishi2.Schema.string().description("机器人运行的群号").default("机器人运行的群号").required()
798
+ var Config = import_koishi3.Schema.intersect([
799
+ import_koishi3.Schema.object({
800
+ qq: import_koishi3.Schema.string().description("机器人QQ号").default("机器人qq号").required(),
801
+ groupId: import_koishi3.Schema.string().description("机器人运行的群号").default("机器人运行的群号").required()
492
802
  }).description("机器人信息"),
493
- import_koishi2.Schema.object({
494
- maxLevel: import_koishi2.Schema.number().description("当前版本的最大等级").step(5).default(290)
803
+ import_koishi3.Schema.object({
804
+ adminQQList: import_koishi3.Schema.array(String).description("管理员QQ列表").default([])
805
+ }).description("管理员信息"),
806
+ import_koishi3.Schema.object({
807
+ maxLevel: import_koishi3.Schema.number().description("当前版本的最大等级").step(5).default(290)
495
808
  }).description("游戏信息"),
496
- import_koishi2.Schema.object({
497
- levelUP_player_recommend: import_koishi2.Schema.number().description("使用升级指令时推荐系数的影响幅度").min(0).step(5).default(30),
498
- levelUP_player_fixedBossReturn: import_koishi2.Schema.number().description("使用升级指令时返回的定点王数量").min(1).step(1).default(6),
499
- levelUP_player_wildBossReturn: import_koishi2.Schema.number().description("使用升级指令时返回的野王数量").min(1).step(1).default(4)
809
+ import_koishi3.Schema.object({
810
+ levelUP_player_recommend: import_koishi3.Schema.number().description("使用升级指令时推荐系数的影响幅度").min(0).step(5).default(30),
811
+ levelUP_player_fixedBossReturn: import_koishi3.Schema.number().description("使用升级指令时返回的定点王数量").min(1).step(1).default(6),
812
+ levelUP_player_wildBossReturn: import_koishi3.Schema.number().description("使用升级指令时返回的野王数量").min(1).step(1).default(4)
500
813
  }).description("升级指令管理"),
501
- import_koishi2.Schema.object({
502
- monthlyCardReminder_midnightTime: import_koishi2.Schema.number().description("月卡提醒的凌晨时间").default(0),
503
- monthlyCardReminder_morningTime: import_koishi2.Schema.number().description("月卡提醒的早上时间").default(9),
504
- monthlyCardReminder_noonTime: import_koishi2.Schema.number().description("月卡提醒的中午时间").default(12),
505
- monthlyCardReminder_afternoonTime: import_koishi2.Schema.number().description("月卡提醒的下午时间").default(16),
506
- monthlyCardReminder_eveningTime: import_koishi2.Schema.number().description("月卡提醒的晚上时间").default(20),
507
- monthlyCardReminder_latenightTime: import_koishi2.Schema.number().description("月卡提醒的深夜时间").default(23)
814
+ import_koishi3.Schema.object({
815
+ monthlyCardReminder_midnightTime: import_koishi3.Schema.number().description("月卡提醒的凌晨时间").default(0),
816
+ monthlyCardReminder_morningTime: import_koishi3.Schema.number().description("月卡提醒的早上时间").default(9),
817
+ monthlyCardReminder_noonTime: import_koishi3.Schema.number().description("月卡提醒的中午时间").default(12),
818
+ monthlyCardReminder_afternoonTime: import_koishi3.Schema.number().description("月卡提醒的下午时间").default(16),
819
+ monthlyCardReminder_eveningTime: import_koishi3.Schema.number().description("月卡提醒的晚上时间").default(20),
820
+ monthlyCardReminder_latenightTime: import_koishi3.Schema.number().description("月卡提醒的深夜时间").default(23)
508
821
  }).description("月卡提醒管理")
509
822
  ]);
510
823
  async function apply(ctx, config) {
@@ -516,7 +829,10 @@ async function apply(ctx, config) {
516
829
  TalkMgr.Inst().setTalks();
517
830
  UserMgr.Inst().setUsers();
518
831
  MonsterMgr.Inst().setMonsters();
519
- monthlyCardReminderDailyTask(config.groupId, [
832
+ BotTodoMgr.Inst().setTodos();
833
+ registerBotTodoHandlers();
834
+ BotTodoMgr.Inst().start();
835
+ scheduleMonthlyCardReminders(config.groupId, [
520
836
  config.monthlyCardReminder_midnightTime,
521
837
  config.monthlyCardReminder_morningTime,
522
838
  config.monthlyCardReminder_noonTime,
@@ -541,18 +857,27 @@ async function apply(ctx, config) {
541
857
  });
542
858
  ctx.command("升级 <等级数>").action(async ({ session }, ...args) => {
543
859
  const event = newEvent(ctx, session, config, logger);
544
- await command_levelUP(event, args);
860
+ command_levelUP(event, args);
545
861
  });
546
862
  ctx.command("月卡提醒 <时间段>").action(async ({ session }, ...args) => {
547
863
  const event = newEvent(ctx, session, config, logger);
548
- await command_monthlyCardRemind(event, args);
864
+ command_monthlyCardRemind(event, args);
549
865
  });
550
866
  ctx.command("取消月卡提醒").action(async ({ session }, ...args) => {
551
867
  const event = newEvent(ctx, session, config, logger);
552
- await command_cancelMonthlyCardRemind(event, args);
868
+ command_cancelMonthlyCardRemind(event, args);
869
+ });
870
+ ctx.command("魔导书,全员提醒 <时间段> <时间点> <内容>").action(async ({ session }, ...args) => {
871
+ const event = newEvent(ctx, session, config, logger);
872
+ allMemberRemind(event, args);
553
873
  });
554
874
  }
555
875
  __name(apply, "apply");
876
+ function registerBotTodoHandlers() {
877
+ BotTodoMgr.Inst().on(ALL_MEMBER_REMINDER_TYPE, executeAllMemberReminder);
878
+ BotTodoMgr.Inst().on(MONTHLY_CARD_REMINDER_TYPE, executeMonthlyCardReminder);
879
+ }
880
+ __name(registerBotTodoHandlers, "registerBotTodoHandlers");
556
881
  function newEvent(ctx, session, config, logger) {
557
882
  const event = {
558
883
  ctx,
@@ -0,0 +1 @@
1
+ []
@@ -6,7 +6,10 @@
6
6
  "@_result_@"
7
7
  ],
8
8
  "被@":[
9
- "魔导书现在提供这些功能哦:\n1.升级 等级【查询升级头目】\n如:升级 220\n2.月卡提醒 时间段【设置月卡提醒时间】\n时间段可选:午夜(@_MCRMidnight_@点10分) 早晨(@_MCRMorning_@点10分) 中午(@_MCRNoon_@点10分) 下午(@_MCRAfternoon_@点10分) 晚上(@_MCREvening_@点10分) 深夜(@_MCRLatenight_@点10分)\n如:月卡提醒 晚上\n3.取消月卡提醒"
9
+ "魔导书现在提供这些功能哦:\n1.升级 等级【查询升级头目】\n如:升级 220\n2.月卡提醒 时间段【设置月卡提醒时间】\n时间段可选:凌晨(@_MCRMidnight_@点10分) 早上(@_MCRMorning_@点10分) 中午(@_MCRNoon_@点10分) 下午(@_MCRAfternoon_@点10分) 晚上(@_MCREvening_@点10分) 深夜(@_MCRLatenight_@点10分)\n如:月卡提醒 晚上\n3.取消月卡提醒"
10
+ ],
11
+ "无权限": [
12
+ "抱歉,只有青灯同意的人才能这么做哦?"
10
13
  ],
11
14
  "升级命令_参数缺失": [
12
15
  "如果你要查询升级头目,请输入\"升级 等级数\"来进行查询哦?"
@@ -15,10 +18,10 @@
15
18
  "输入的等级有误,请输入1-@_maxLevel_@之间的整数作为等级噢?"
16
19
  ],
17
20
  "月卡提醒_参数缺失": [
18
- "如果你要设置月卡提醒时间,请输入\"月卡提醒 时间段\"来进行设置哦?\n时间段可选:午夜 早晨 中午 下午 傍晚 深夜"
21
+ "如果你要设置月卡提醒时间,请输入\"月卡提醒 时间段\"来进行设置哦?\n时间段可选:凌晨 早上 中午 下午 晚上 深夜"
19
22
  ],
20
23
  "月卡提醒_时间不正确": [
21
- "你输入的时间段不正确哦?\n时间段可选:午夜 早晨 中午 下午 傍晚 深夜"
24
+ "你输入的时间段不正确哦?\n时间段可选:凌晨 早上 中午 下午 晚上 深夜"
22
25
  ],
23
26
  "月卡提醒": [
24
27
  "@_atUsers_@\n魔导书来提醒你去领今天的月卡啦~",
@@ -0,0 +1,35 @@
1
+ export interface BotTodoItem {
2
+ id: string;
3
+ ts: number;
4
+ type: string;
5
+ payload?: any;
6
+ }
7
+ /**
8
+ * BotTodoMgr
9
+ * - 记录“在指定时间戳要执行的任务”
10
+ * - 参考其他 Mgr 的使用方式:单例、set/load/save、增删查
11
+ */
12
+ export declare class BotTodoMgr {
13
+ private static instance;
14
+ static Inst(): BotTodoMgr;
15
+ private readonly jsonName;
16
+ private _todos;
17
+ private _handlers;
18
+ private _timer;
19
+ private _nextTs;
20
+ private _started;
21
+ setTodos(): void;
22
+ private saveTodos;
23
+ addTodo(ts: number, type: string, payload?: any): string;
24
+ getTodosAt(ts: number): BotTodoItem[];
25
+ removeTodo(ts: number, id: string): void;
26
+ removeTodosAt(ts: number): void;
27
+ popDueTodos(now: number): BotTodoItem[];
28
+ getNextTimestamp(): number | undefined;
29
+ on(type: string, handler: (item: BotTodoItem) => any | Promise<any>): void;
30
+ start(): void;
31
+ stop(): void;
32
+ scheduleNext(): void;
33
+ private internalPlanNext;
34
+ private executeBatch;
35
+ }
@@ -1,6 +1,7 @@
1
1
  export declare enum Code {
2
2
  通过 = 1001,
3
3
  参数缺失 = 2001,
4
+ 无权限 = 2002,
4
5
  等级不正确 = 3001,
5
6
  时间不正确 = 3002
6
7
  }
@@ -0,0 +1,16 @@
1
+ export declare enum Ability {
2
+ null = 0,
3
+ 力量 = 1,
4
+ 百分比力量 = 2,
5
+ 智力 = 3,
6
+ 百分比智力 = 4,
7
+ 耐力 = 5,
8
+ 百分比耐力 = 6,
9
+ 灵巧 = 7,
10
+ 百分比灵巧 = 8,
11
+ 敏捷 = 9,
12
+ 百分比敏捷 = 10,
13
+ 体力值上限 = 11,
14
+ 百分比体力值上限 = 12,
15
+ 魔法值上限 = 13
16
+ }
@@ -0,0 +1 @@
1
+ export * from './abilityClass';
@@ -0,0 +1,4 @@
1
+ import { BotTodoItem } from '../BotTodoMgr';
2
+ export declare const ALL_MEMBER_REMINDER_TYPE = "all-member-reminder";
3
+ export declare function genAtAllMessage(content: string): string;
4
+ export declare function executeAllMemberReminder(item: BotTodoItem): Promise<void>;
@@ -1 +1,2 @@
1
1
  export * from './monthlyCardReminder';
2
+ export * from './allMemberReminder';
@@ -1 +1,4 @@
1
- export declare function monthlyCardReminderDailyTask(groupId: string, hours: number[]): void;
1
+ import { BotTodoItem } from "../BotTodoMgr";
2
+ export declare const MONTHLY_CARD_REMINDER_TYPE = "monthly-card-reminder";
3
+ export declare function scheduleMonthlyCardReminders(groupId: string, hours: number[]): void;
4
+ export declare function executeMonthlyCardReminder(item: BotTodoItem): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { SessionEvent } from "../..";
2
+ export declare function allMemberRemind(event: SessionEvent, args: string[]): void;
@@ -1,2 +1,3 @@
1
+ export * from './allMemberRemindCommand';
1
2
  export * from './levelUpCommand';
2
3
  export * from './monthlyCardRemindCommand';
@@ -1,2 +1,2 @@
1
1
  import { SessionEvent } from "../..";
2
- export declare function command_levelUP(event: SessionEvent, args: string[]): Promise<void>;
2
+ export declare function command_levelUP(event: SessionEvent, args: string[]): void;
@@ -1,3 +1,3 @@
1
1
  import { SessionEvent } from "../..";
2
- export declare function command_monthlyCardRemind(event: SessionEvent, args: string[]): Promise<void>;
3
- export declare function command_cancelMonthlyCardRemind(event: SessionEvent, args: string[]): Promise<void>;
2
+ export declare function command_monthlyCardRemind(event: SessionEvent, args: string[]): void;
3
+ export declare function command_cancelMonthlyCardRemind(event: SessionEvent, args: string[]): void;
@@ -1,8 +1,10 @@
1
1
  export * from './TalkMgr';
2
2
  export * from './ResultClass';
3
3
  export * from './JsonMgr';
4
+ export * from './ability';
4
5
  export * from './botFunction';
5
6
  export * from './command';
6
7
  export * from './dish';
7
8
  export * from './monster';
8
9
  export * from './user';
10
+ export * from './BotTodoMgr';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-toram",
3
3
  "description": "托拉姆物语小工具",
4
- "version": "4.0.4",
4
+ "version": "4.1.0",
5
5
  "contributors": [
6
6
  "青灯 <1874053520@qq.com>"
7
7
  ],