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 +1 -0
- package/lib/index.js +386 -61
- package/lib/json/botTodos.json +1 -0
- package/lib/json/talks.json +6 -3
- package/lib/script/BotTodoMgr.d.ts +35 -0
- package/lib/script/ResultClass.d.ts +1 -0
- package/lib/script/ability/abilityClass.d.ts +16 -0
- package/lib/script/ability/index.d.ts +1 -0
- package/lib/script/botFunction/allMemberReminder.d.ts +4 -0
- package/lib/script/botFunction/index.d.ts +1 -0
- package/lib/script/botFunction/monthlyCardReminder.d.ts +4 -1
- package/lib/script/command/allMemberRemindCommand.d.ts +2 -0
- package/lib/script/command/index.d.ts +1 -0
- package/lib/script/command/levelUpCommand.d.ts +1 -1
- package/lib/script/command/monthlyCardRemindCommand.d.ts +2 -2
- package/lib/script/index.d.ts +2 -0
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
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
|
|
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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
|
|
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(
|
|
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
|
-
|
|
223
|
-
const checkResult =
|
|
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
|
|
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(
|
|
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
|
-
|
|
304
|
-
const checkResult =
|
|
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
|
|
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(
|
|
341
|
-
|
|
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 =
|
|
489
|
-
|
|
490
|
-
qq:
|
|
491
|
-
groupId:
|
|
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
|
-
|
|
494
|
-
|
|
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
|
-
|
|
497
|
-
levelUP_player_recommend:
|
|
498
|
-
levelUP_player_fixedBossReturn:
|
|
499
|
-
levelUP_player_wildBossReturn:
|
|
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
|
-
|
|
502
|
-
monthlyCardReminder_midnightTime:
|
|
503
|
-
monthlyCardReminder_morningTime:
|
|
504
|
-
monthlyCardReminder_noonTime:
|
|
505
|
-
monthlyCardReminder_afternoonTime:
|
|
506
|
-
monthlyCardReminder_eveningTime:
|
|
507
|
-
monthlyCardReminder_latenightTime:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
[]
|
package/lib/json/talks.json
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
"@_result_@"
|
|
7
7
|
],
|
|
8
8
|
"被@":[
|
|
9
|
-
"魔导书现在提供这些功能哦:\n1.升级 等级【查询升级头目】\n如:升级 220\n2.月卡提醒 时间段【设置月卡提醒时间】\n
|
|
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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './abilityClass';
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
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>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { SessionEvent } from "../..";
|
|
2
|
-
export declare function command_levelUP(event: SessionEvent, args: string[]):
|
|
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[]):
|
|
3
|
-
export declare function command_cancelMonthlyCardRemind(event: SessionEvent, args: string[]):
|
|
2
|
+
export declare function command_monthlyCardRemind(event: SessionEvent, args: string[]): void;
|
|
3
|
+
export declare function command_cancelMonthlyCardRemind(event: SessionEvent, args: string[]): void;
|
package/lib/script/index.d.ts
CHANGED
|
@@ -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';
|