UNPKG

koishi-plugin-toram

Version:
1,024 lines (1,005 loc) 37.7 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name2 in all) __defProp(target, name2, { get: all[name2], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Config: () => Config, apply: () => apply, inject: () => inject, name: () => name }); module.exports = __toCommonJS(src_exports); var import_koishi = require("koishi"); // src/script/TalkMgr.ts var _TalkMgr = class _TalkMgr { constructor() { this.bot = null; this._talks = /* @__PURE__ */ new Map(); } static Inst() { if (!_TalkMgr.instance) { _TalkMgr.instance = new _TalkMgr(); } return _TalkMgr.instance; } setBot(bot) { this.bot = bot; } setTalks() { const data = JsonMgr.Inst().getJson("talks.json"); Object.keys(data).forEach((key) => { this._talks.set(key, data[key]); }); } genTalk(talkType, args) { const talkList = this._talks.get(talkType); let talk = talkList[Math.floor(Math.random() * talkList.length)]; if (args) Object.keys(args).forEach((key) => talk = talk.replace(`@_${key}_@`, args[key])); return talk; } reply(event, talkType, args) { const talk = this.genTalk(talkType, args); event.session.send(talk); } send(targetId, talkType, args) { const talk = this.genTalk(talkType, args); this.bot?.sendMessage(targetId, talk); } }; __name(_TalkMgr, "TalkMgr"); _TalkMgr.instance = null; var TalkMgr = _TalkMgr; // src/script/ResultClass.ts var _Result = class _Result { constructor(code, result) { this.code = 1001 /* 通过 */; this.code = code; if (result !== void 0) this.result = result; } }; __name(_Result, "Result"); var Result = _Result; // src/script/JsonMgr.ts var import_promises = __toESM(require("fs/promises")); var import_path = __toESM(require("path")); var _JsonMgr = class _JsonMgr { constructor() { this._json = /* @__PURE__ */ new Map(); this._logger = null; } static Inst() { if (!_JsonMgr.instance) { _JsonMgr.instance = new _JsonMgr(); } return _JsonMgr.instance; } /** * 异步获取 ./external/toram/src/json 目录下的所有JSON文件,并将其内容解析后存储到内部的Map对象中。 * 该方法会遍历指定目录下的所有文件,筛选出扩展名为.json的文件,然后读取每个文件的内容, * 将其解析为JavaScript对象,并以文件名作为键,解析后的对象作为值存储在内部的Map对象中。 * 如果在读取文件或解析JSON时发生错误,将在控制台输出错误信息。 */ async loadJson() { const arr = __dirname.split("\\"); if (arr[arr.length - 1] !== "lib") arr.pop(); arr.push("json"); const pathWay = arr.join("\\"); this._logger.info(pathWay); try { const files = await import_promises.default.readdir(pathWay); const jsonFiles = files.filter((file) => import_path.default.extname(file).toLowerCase() === ".json"); for (const file of jsonFiles) { const filePath = import_path.default.join(pathWay, file); try { const data = await import_promises.default.readFile(filePath, "utf-8"); this._json.set(file, JSON.parse(data)); } catch (readErr) { console.error(`Error reading file ${filePath}:`, readErr); } } } catch (err) { console.error(`Error reading directory ${pathWay}:`, err); } } /** * 根据指定的名称从内部的Map对象中获取对应的JSON数据。 * 该方法会在内部的Map对象中查找与给定名称匹配的键,并返回对应的值。 * 如果找不到匹配的键,则返回undefined。 * @param name - 要获取的JSON数据的名称,通常是文件名(不包括扩展名)。 * @returns 返回与指定名称对应的JSON数据,如果找不到则打印log并返回null。 */ getJson(name2) { const result = this._json.get(name2); if (result) { return result; } else { this._logger.error(`未找到${name2}`); return null; } } /** * 设置日志记录器实例,用于记录JsonMgr类的操作日志。 * 该方法允许外部传入一个Logger实例,以便在JsonMgr类的各个方法中使用该实例进行日志记录。 * @param logger - 一个Logger实例,用于记录日志。 */ setLogger(logger) { this._logger = logger; } /** 保存json */ async saveJson(name2, data) { if (!data) data = this._json.get(name2); const arr = __dirname.split("\\"); if (arr[arr.length - 1] !== "lib") arr.pop(); arr.push("json"); const pathWay = arr.join("\\"); const filePath = import_path.default.join(pathWay, "", name2); const jsonString = JSON.stringify(data, null, 2); try { await import_promises.default.writeFile(filePath, jsonString, "utf8"); this._logger.info("JSON 文件已保存!"); } catch (err) { this._logger.error("保存文件时出错:", err); } } }; __name(_JsonMgr, "JsonMgr"); _JsonMgr.instance = null; var JsonMgr = _JsonMgr; // src/script/botFunction/monthlyCardReminder.ts var MONTHLY_CARD_REMINDER_TYPE = "monthly-card-reminder"; async function scheduleMonthlyCardReminders(groupId, hours) { const now = /* @__PURE__ */ new Date(); for (let i = 0; i < hours.length; i++) { const hour = hours[i]; const next = new Date(now); next.setHours(hour, 10, 0, 0); if (next.getTime() <= now.getTime()) next.setDate(next.getDate() + 1); const ts = next.getTime(); const exists = (BotTodoMgr.Inst().getTodosAt(ts) || []).some( (x) => x.type === MONTHLY_CARD_REMINDER_TYPE && x.payload?.groupId === groupId && x.payload?.timeIndex === i ); if (!exists) { await BotTodoMgr.Inst().addTodo(ts, MONTHLY_CARD_REMINDER_TYPE, { groupId, timeIndex: i }); } } } __name(scheduleMonthlyCardReminders, "scheduleMonthlyCardReminders"); function executeMonthlyCardReminder(item) { const payload = item.payload || {}; const groupId = payload.groupId; const timeIndex = payload.timeIndex; if (!groupId || typeof timeIndex !== "number") return; const atUsers = genMonthlyCardReminderUsers(timeIndex); if (atUsers) { TalkMgr.Inst().send(groupId, "月卡提醒", { atUsers }); } const next = new Date(item.ts + 24 * 60 * 60 * 1e3); const hour = new Date(item.ts).getHours(); next.setHours(hour, 10, 0, 0); const nextTs = next.getTime(); const exists = (BotTodoMgr.Inst().getTodosAt(nextTs) || []).some( (x) => x.type === MONTHLY_CARD_REMINDER_TYPE && x.payload?.groupId === groupId && x.payload?.timeIndex === timeIndex ); if (!exists) { BotTodoMgr.Inst().addTodo(nextTs, MONTHLY_CARD_REMINDER_TYPE, { groupId, timeIndex }); } } __name(executeMonthlyCardReminder, "executeMonthlyCardReminder"); function genMonthlyCardReminderUsers(timeIndex) { const users = UserMgr.Inst().getUsersWithMonthlyCardRemindTimeIndex(timeIndex); if (users.length === 0) return; const atUsers = users.map((user) => `<at id="${user.qq}"/>`).join(" "); return atUsers; } __name(genMonthlyCardReminderUsers, "genMonthlyCardReminderUsers"); // src/script/botFunction/allMemberReminder.ts var ALL_MEMBER_REMINDER_TYPE = "all-member-reminder"; function genAtAllMessage(content) { const atAll = `<at id="all"/>`; return content ? `${atAll} ${content}` : atAll; } __name(genAtAllMessage, "genAtAllMessage"); function executeAllMemberReminder(item) { const payload = item.payload || {}; const groupId = payload.groupId; const content = payload.content; if (!groupId) return; const message = genAtAllMessage(content || ""); TalkMgr.Inst().send(groupId, "简易回复", { result: message }); } __name(executeAllMemberReminder, "executeAllMemberReminder"); // src/script/botFunction/monthlyCardFinalReminder.ts var MONTHLY_CARD_FINAL_REMINDER_TYPE = "monthly-card-final-reminder"; async function scheduleMonthlyCardFinalReminder(groupId) { const now = /* @__PURE__ */ new Date(); const next = new Date(now); next.setHours(23, 30, 0, 0); if (next.getTime() <= now.getTime()) next.setDate(next.getDate() + 1); const ts = next.getTime(); const exists = (BotTodoMgr.Inst().getTodosAt(ts) || []).some( (x) => x.type === MONTHLY_CARD_FINAL_REMINDER_TYPE && x.payload?.groupId === groupId ); if (!exists) { await BotTodoMgr.Inst().addTodo(ts, MONTHLY_CARD_FINAL_REMINDER_TYPE, { groupId }); } } __name(scheduleMonthlyCardFinalReminder, "scheduleMonthlyCardFinalReminder"); function executeMonthlyCardFinalReminder(item) { const payload = item.payload || {}; const groupId = payload.groupId; if (!groupId) return; const atUsers = genMonthlyCardFinalReminderUsers(); if (atUsers) { TalkMgr.Inst().send(groupId, "月卡最后提醒", { atUsers }); } const next = new Date(item.ts + 24 * 60 * 60 * 1e3); next.setHours(23, 30, 0, 0); const nextTs = next.getTime(); const exists = (BotTodoMgr.Inst().getTodosAt(nextTs) || []).some( (x) => x.type === MONTHLY_CARD_FINAL_REMINDER_TYPE && x.payload?.groupId === groupId ); if (!exists) { BotTodoMgr.Inst().addTodo(nextTs, MONTHLY_CARD_FINAL_REMINDER_TYPE, { groupId }); } } __name(executeMonthlyCardFinalReminder, "executeMonthlyCardFinalReminder"); function genMonthlyCardFinalReminderUsers() { const users = UserMgr.Inst().getAllMonthlyCardRemindUsers(); if (users.length === 0) return; const now = /* @__PURE__ */ new Date(); const todayStr = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`; const notConfirmed = users.filter((user) => user.lastGetMonthlyCardDate !== todayStr); if (notConfirmed.length === 0) return; const atUsers = notConfirmed.map((user) => `<at id="${user.qq}"/>`).join(" "); return atUsers; } __name(genMonthlyCardFinalReminderUsers, "genMonthlyCardFinalReminderUsers"); // src/script/command/allMemberRemindCommand.ts function allMemberRemind(event, args) { const qq = event.session.event.user.id; const authResult = isAdmin(qq, event); if (authResult?.code === 2002 /* 无权限 */) { TalkMgr.Inst().reply(event, "无权限"); return; } const checkResult = checkArgs(args, event.config); switch (checkResult.code) { case 2001 /* 参数缺失 */: TalkMgr.Inst().reply(event, "简易回复", { result: "参数缺失:需要 时间段 时间点 内容" }); return; case 3002 /* 时间不正确 */: TalkMgr.Inst().reply(event, "简易回复", { result: "时间不正确:请输入 (yy.)mm.dd(-yy.mm.dd) 和 hh:mm" }); return; } const { timeList, content } = checkResult.result; const groupId = event.config.groupId; if (!Array.isArray(timeList) || timeList.length === 0) { TalkMgr.Inst().reply(event, "简易回复", { result: "没有可用的时间点。" }); return; } let created = 0; for (const ts of timeList) { BotTodoMgr.Inst().addTodo(ts, ALL_MEMBER_REMINDER_TYPE, { groupId, content }); created++; } TalkMgr.Inst().reply(event, "简易回复", { result: `咕` }); } __name(allMemberRemind, "allMemberRemind"); function isAdmin(qq, event) { const adminQQList = event.config.adminQQList; if (!adminQQList.includes(qq)) { return new Result(2002 /* 无权限 */, false); } } __name(isAdmin, "isAdmin"); function checkArgs(args, config) { const timePeriod = args[0]; const timePointStr = args[1]; const content = args[2]; if (timePeriod === void 0 || timePointStr === void 0 || content === void 0) { return new Result(2001 /* 参数缺失 */); } const now = /* @__PURE__ */ new Date(); const currentYear = now.getFullYear(); const parseSingleDay = /* @__PURE__ */ __name((str, defaultYear) => { if (!str) return null; let yearProvided = false; let y = defaultYear; let mStr = ""; let dStr = ""; const parts = str.split("."); if (parts.length === 2) { mStr = parts[0]; dStr = parts[1]; } else if (parts.length === 3) { yearProvided = true; const yy = parts[0]; mStr = parts[1]; dStr = parts[2]; const yNum = Number(yy); if (!Number.isInteger(yNum)) return null; if (yy.length <= 2) y = 2e3 + yNum; else if (yy.length === 4) y = yNum; else return null; } else { return null; } const m = Number(mStr); const d = Number(dStr); if (!Number.isInteger(m) || !Number.isInteger(d)) return null; if (m < 1 || m > 12 || d < 1 || d > 31) return null; const date = new Date(y, m - 1, d); if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) return null; return { date, yearProvided }; }, "parseSingleDay"); const timeStr = timePointStr.trim().replace(/:/g, ":"); const tm = timeStr.match(/^(\d{1,2}):(\d{1,2})$/); if (!tm) return new Result(3002 /* 时间不正确 */); const hour = Number(tm[1]); const minute = Number(tm[2]); if (!Number.isInteger(hour) || !Number.isInteger(minute) || hour < 0 || hour > 23 || minute < 0 || minute > 59) { return new Result(3002 /* 时间不正确 */); } const periodParts = timePeriod.split("-").map((s) => s.trim()).filter((s) => s.length > 0); if (periodParts.length < 1 || periodParts.length > 2) { return new Result(3002 /* 时间不正确 */); } const startParsed = parseSingleDay(periodParts[0], currentYear); if (!startParsed) return new Result(3002 /* 时间不正确 */); let { date: startDate } = startParsed; let endDate = startDate; if (periodParts.length === 2) { const endParsed = parseSingleDay(periodParts[1], startDate.getFullYear()); if (!endParsed) return new Result(3002 /* 时间不正确 */); endDate = endParsed.date; if (!endParsed.yearProvided && endDate.getTime() < startDate.getTime()) { endDate = new Date(endDate.getFullYear() + 1, endDate.getMonth(), endDate.getDate()); } } if (periodParts.length === 1 && !startParsed.yearProvided) { const firstDt = new Date(startDate); firstDt.setHours(hour, minute, 0, 0); if (firstDt.getTime() <= now.getTime()) { startDate = new Date(startDate.getFullYear() + 1, startDate.getMonth(), startDate.getDate()); endDate = startDate; } } if (endDate.getTime() < startDate.getTime()) return new Result(3002 /* 时间不正确 */); const timeList = []; const cursor = new Date(startDate); const maxDays = 366 * 2; let guard = 0; while (cursor.getTime() <= endDate.getTime()) { const dt = new Date(cursor); dt.setHours(hour, minute, 0, 0); if (dt.getTime() > now.getTime()) { timeList.push(dt.getTime()); } cursor.setDate(cursor.getDate() + 1); guard++; if (guard > maxDays) return new Result(3002 /* 时间不正确 */); } return new Result(1001 /* 通过 */, { timeList, content }); } __name(checkArgs, "checkArgs"); // src/script/command/levelUpCommand.ts function command_levelUP(event, args) { const checkResult = checkArgs2(args, event.config.maxLevel); switch (checkResult.code) { case 2001 /* 参数缺失 */: TalkMgr.Inst().reply(event, "升级命令_参数缺失"); return; case 3001 /* 等级不正确 */: TalkMgr.Inst().reply(event, `升级命令_等级不正确`, { maxLevel: event.config.maxLevel.toString() }); return; } let title = ""; let result = ""; let tips = ""; const { level } = checkResult.result; title = getUpgradeExp(level, event.config.maxLevel); switch (true) { case level < 38: result = "\n亲亲,建议去尼塞尔山刷布兰达哦?"; break; case level < 55: result = "\n去上古女帝陵墓打机骨龙吧~"; break; case level < event.config.maxLevel: let fixBossList = []; const fixBossDataList = MonsterMgr.Inst().getMonsters().filter((data) => data.type === 2 /* 定点王 */ && data.baseLevel >= level - 50 && data.baseLevel <= level + 20); fixBossDataList.forEach((data) => { for (let i = 0; i <= 4; i++) { fixBossList.push(new Monster(data, i)); } }); fixBossList = fixBossList.sort((a, b) => b.getPlayerExp(level) * (100 + b.recommend * 30) - a.getPlayerExp(level) * (100 + a.recommend * 30)).slice(0, event.config.levelUP_player_fixedBossReturn); let wildBossList = []; const wildBossDataList = MonsterMgr.Inst().getMonsters().filter((data) => data.type === 1 /* 野王 */ && data.baseLevel >= level - 10 && data.baseLevel <= level + 10); wildBossDataList.forEach((data) => { wildBossList.push(new Monster(data)); }); wildBossList = wildBossList.sort((a, b) => b.getPlayerExp(level) * (100 + b.recommend * 30) - a.getPlayerExp(level) * (100 + a.recommend * 30)).slice(0, event.config.levelUP_player_wildBossReturn); const fixBossResult = fixBossList.map((monster, i) => { return `${i + 1}.${monster.cmdPlayerLevelUP(level)}`; }); result += ` 定点王: ${fixBossResult.join("\n")}`; const wildBossResult = wildBossList.map((monster, i) => { return `${i + 1}.${monster.cmdPlayerLevelUP(level)}`; }); result += ` 野王: ${wildBossResult.join("\n")}`; const rand = Math.floor(Math.random() * (fixBossList.length + wildBossList.length)); let suggestion = rand < fixBossList.length ? fixBossList[rand] : wildBossList[rand - fixBossList.length]; tips = ` 去打${suggestion.name}怎么样?`; break; case level === event.config.maxLevel: result = ` 你已经升到满级啦!`; break; } TalkMgr.Inst().reply(event, "正常回复", { title, result, tips }); } __name(command_levelUP, "command_levelUP"); function checkArgs2(args, maxLevel) { let levelCN = args[0]; if (levelCN === void 0) return new Result(2001 /* 参数缺失 */); if (/级$/.test(levelCN)) levelCN = levelCN.replace(/级/g, ""); const level = Number(levelCN); if (isNaN(level) || level < 1 || level > maxLevel || Math.floor(level) !== level) return new Result(3001 /* 等级不正确 */); return new Result(1001 /* 通过 */, { level }); } __name(checkArgs2, "checkArgs"); function getUpgradeExp(level, maxLevel) { const exp = Math.floor(level ** 4 / 40) + level * 2; return level !== maxLevel ? `${level}级升级所需经验为${exp}` : ""; } __name(getUpgradeExp, "getUpgradeExp"); // src/script/command/monthlyCardRemindCommand.ts function command_monthlyCardRemind(event, args) { const checkResult = checkArgs3(args); switch (checkResult.code) { case 2001 /* 参数缺失 */: TalkMgr.Inst().reply(event, "月卡提醒_参数缺失"); return; case 3002 /* 时间不正确 */: TalkMgr.Inst().reply(event, `月卡提醒_时间不正确`); return; } const { timeIndex } = checkResult.result; const qq = event.session.event.user.id; UserMgr.Inst().setUserMonthlyCardRemindTimeIndex(qq, timeIndex); const hours = [ event.config.monthlyCardReminder_midnightTime, event.config.monthlyCardReminder_morningTime, event.config.monthlyCardReminder_noonTime, event.config.monthlyCardReminder_afternoonTime, event.config.monthlyCardReminder_eveningTime, event.config.monthlyCardReminder_latenightTime ]; TalkMgr.Inst().reply(event, "正常回复", { title: "月卡提醒设置成功!\n", result: `你已将月卡提醒时间设置为${args[0]}(${hours[timeIndex]}点10分) `, tips: "魔导书会在每天对应的时间点提醒你领取月卡哦~" }); } __name(command_monthlyCardRemind, "command_monthlyCardRemind"); function checkArgs3(args) { const time = args[0]; if (time === void 0) return new Result(2001 /* 参数缺失 */); const allowTimesCN = ["凌晨", "早上", "中午", "下午", "晚上", "深夜"]; const index = allowTimesCN.indexOf(time); if (index === -1) return new Result(3002 /* 时间不正确 */); return new Result(1001 /* 通过 */, { timeIndex: index }); } __name(checkArgs3, "checkArgs"); function command_cancelMonthlyCardRemind(event, args) { const qq = event.session.event.user.id; UserMgr.Inst().setUserMonthlyCardRemindTimeIndex(qq, -1); TalkMgr.Inst().reply(event, "简易回复", { result: "月卡提醒取消成功!" }); } __name(command_cancelMonthlyCardRemind, "command_cancelMonthlyCardRemind"); function confirmMonthlyCardGet(event) { const qq = event.session.event.user.id; const user = UserMgr.Inst().getAllMonthlyCardRemindUsers().find((u) => u.qq === qq); let result; if (user) { result = UserMgr.Inst().updateUserLastGetMonthlyCardDate(qq); } else { result = new Result(1002 /* 无需处理 */); } return result; } __name(confirmMonthlyCardGet, "confirmMonthlyCardGet"); // src/script/monster/monsterClass.ts var ElementType = /* @__PURE__ */ ((ElementType2) => { ElementType2[ElementType2["无"] = 0] = "无"; ElementType2[ElementType2["风"] = 1] = "风"; ElementType2[ElementType2["地"] = 2] = "地"; ElementType2[ElementType2["水"] = 3] = "水"; ElementType2[ElementType2["火"] = 4] = "火"; ElementType2[ElementType2["光"] = 5] = "光"; ElementType2[ElementType2["暗"] = 6] = "暗"; return ElementType2; })(ElementType || {}); var _Monster = class _Monster { // 推荐系数 constructor(monsterData, star) { this.type = monsterData.type; this.name = monsterData.name; this.level = monsterData.baseLevel; this.baseExp = monsterData.baseExp; this.map = monsterData.map; this.element = monsterData.element; const starLevel = [-10, 0, 10, 20, 40]; const starExp = [0.1, 1, 2, 5, 10]; if (star !== void 0) { this.name = `${star}星${this.name}`; this.star = star; this.level = Math.max(1, this.level + starLevel[star]); this.baseExp *= starExp[star]; } if (monsterData.recommend) this.recommend = monsterData.recommend; } getPlayerExp(level) { const playerExpRate = [11, 11, 11, 11, 11, 11, 10, 9, 7, 3, 1]; return this.baseExp * playerExpRate[Math.abs(level - this.level)] || 0; } cmdPlayerLevelUP(level) { return `${this.name} 等级${this.level} 经验值${this.getPlayerExp(level)} ${this.map} ${ElementType[this.element]}属性`; } }; __name(_Monster, "Monster"); var Monster = _Monster; // src/script/monster/MonsterMgr.ts var _MonsterMgr = class _MonsterMgr { constructor() { this._monsters = /* @__PURE__ */ new Map(); } static Inst() { if (!_MonsterMgr.instance) { _MonsterMgr.instance = new _MonsterMgr(); } return _MonsterMgr.instance; } setMonsters() { const data = JsonMgr.Inst().getJson("monsters.json"); data.forEach((monster) => { this._monsters.set(monster.id, monster); }); } getMonsters() { return Array.from(this._monsters.values()); } }; __name(_MonsterMgr, "MonsterMgr"); _MonsterMgr.instance = null; var MonsterMgr = _MonsterMgr; // src/script/user/UserMgr.ts var _UserMgr = class _UserMgr { constructor() { this._users = /* @__PURE__ */ new Map(); } static Inst() { if (!_UserMgr.instance) { _UserMgr.instance = new _UserMgr(); } return _UserMgr.instance; } async setUsers(ctx) { this.ctx = ctx; const data = await ctx.database.get("toram_user", {}); if (!data) return; data.forEach((user) => { this._users.set(user.qq, user); }); } saveUser(user) { this.ctx.database.upsert("toram_user", () => [user]); } addUser(qq, saveNow = true) { const user = { qq, nickname: "", otherNames: [], monthlyCardRemindTimeIndex: -1, lastGetMonthlyCardDate: "" }; this._users.set(user.qq, user); if (saveNow) { this.saveUser(user); } } setUserMonthlyCardRemindTimeIndex(qq, timeIndex) { let user = this._users.get(qq); if (!user) { this.addUser(qq, false); user = this._users.get(qq); } user.monthlyCardRemindTimeIndex = timeIndex; this.saveUser(user); } getUsersWithMonthlyCardRemindTimeIndex(timeIndex) { const result = []; const now = /* @__PURE__ */ new Date(); this._users.forEach((user) => { if (user.monthlyCardRemindTimeIndex !== timeIndex) return; if (user.lastGetMonthlyCardDate === `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`) return; result.push(user); }); return result; } getAllMonthlyCardRemindUsers() { const result = []; this._users.forEach((user) => { if (user.monthlyCardRemindTimeIndex === -1) return; result.push(user); }); return result; } updateUserLastGetMonthlyCardDate(qq) { let user = this._users.get(qq); if (!user) { this.addUser(qq, false); user = this._users.get(qq); } const now = /* @__PURE__ */ new Date(); const dateStr = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`; if (user.lastGetMonthlyCardDate === dateStr) { return new Result(1002 /* 无需处理 */); } user.lastGetMonthlyCardDate = dateStr; this.saveUser(user); return new Result(1001 /* 通过 */); } }; __name(_UserMgr, "UserMgr"); _UserMgr.instance = null; var UserMgr = _UserMgr; // src/script/BotTodoMgr.ts var _BotTodoMgr = class _BotTodoMgr { constructor() { this.ctx = null; this._todos = /* @__PURE__ */ new Map(); this._handlers = /* @__PURE__ */ new Map(); this._timer = null; this._started = false; } static Inst() { if (!_BotTodoMgr.instance) { _BotTodoMgr.instance = new _BotTodoMgr(); } return _BotTodoMgr.instance; } // 读取 json 到内存 async setTodos(ctx) { this.ctx = ctx; const data = await ctx.database.get("toram_todo", {}); if (!data) return; this._todos.clear(); data.forEach((item) => { const list = this._todos.get(item.ts) || []; list.push(item); this._todos.set(item.ts, list); }); } // 持久化内存中的 todo async saveTodos() { const data = Array.from(this._todos.values()).flat(); await this.ctx.database.upsert("toram_todo", data); } // 新增一条 todo,返回 id async addTodo(ts, type, payload) { const id = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`; const todo = { id, ts, type, payload }; const list = this._todos.get(ts) || []; list.push(todo); this._todos.set(ts, list); await this.saveTodos(); if (this._started) { if (this._nextTs === void 0 || ts < this._nextTs) { this.scheduleNext(); } } return id; } // 获取某个时间戳下的 todo 列表(拷贝) getTodosAt(ts) { const list = this._todos.get(ts) || []; return list.map((x) => ({ ...x })); } // 删除某个时间戳下的指定 todo async removeTodo(ts, id) { const list = this._todos.get(ts); if (!list) return; const next = list.filter((x) => x.id !== id); if (next.length > 0) this._todos.set(ts, next); else this._todos.delete(ts); await this.saveTodos(); } // 删除某个时间戳下的所有 todo async removeTodosAt(ts) { if (!this._todos.has(ts)) return; this._todos.delete(ts); await this.saveTodos(); } // 取出并删除“到期”的 todo 列表(ts <= now) async popDueTodos(now) { const result = []; const keys = Array.from(this._todos.keys()).filter((ts) => ts <= now).sort((a, b) => a - b); keys.forEach((ts) => { const list = this._todos.get(ts); if (list && list.length) result.push(...list); this._todos.delete(ts); }); if (keys.length > 0) await this.saveTodos(); return result; } // 下一个最近的时间戳(若不存在返回 undefined) getNextTimestamp() { const keys = Array.from(this._todos.keys()); if (keys.length === 0) return void 0; return keys.sort((a, b) => a - b)[0]; } // 注册任务处理器 on(type, handler) { this._handlers.set(type, handler); } // 启动调度(基于 setTimeout) start() { this._started = true; this.scheduleNext(); } // 停止调度 stop() { this._started = false; if (this._timer) { clearTimeout(this._timer); this._timer = null; } this._nextTs = void 0; } // 立即重新计算下一个调度点 async scheduleNext() { if (!this._started) return; try { const dropped = await this.popDueTodos(Date.now()); if (dropped.length) { console.warn("BotTodoMgr 清理过期任务数量: ", dropped.length); } } catch (e) { console.error("BotTodoMgr 清理过期任务异常: ", e); } if (this._timer) { clearTimeout(this._timer); this._timer = null; } this.internalPlanNext(); } internalPlanNext() { if (!this._started) return; const now = Date.now(); const keys = Array.from(this._todos.keys()).filter((ts) => ts > now); if (keys.length === 0) { this._nextTs = void 0; return; } const next = keys.sort((a, b) => a - b)[0]; this._nextTs = next; const delay = Math.max(0, next - now); const scheduledTs = next; this._timer = setTimeout(async () => { try { const list = this._todos.get(scheduledTs) || []; if (list.length) { this._todos.delete(scheduledTs); await this.saveTodos(); await this.executeBatch(list); } } catch (e) { console.error("BotTodoMgr 执行任务异常: ", e); } finally { this.scheduleNext(); } }, delay); } async executeBatch(list) { for (const item of list) { const handler = this._handlers.get(item.type); if (!handler) { console.warn("BotTodoMgr 未找到处理器:", item.type, item); continue; } try { await handler(item); } catch (e) { console.error("BotTodoMgr 执行单个任务异常:", e, item); } } } }; __name(_BotTodoMgr, "BotTodoMgr"); _BotTodoMgr.instance = null; var BotTodoMgr = _BotTodoMgr; // src/index.ts var name = "toram"; var inject = ["database"]; var Config = import_koishi.Schema.intersect([ import_koishi.Schema.object({ qq: import_koishi.Schema.string().description("机器人QQ号").default("机器人qq号").required(), groupId: import_koishi.Schema.string().description("机器人运行的群号").default("机器人运行的群号").required() }).description("机器人信息"), import_koishi.Schema.object({ adminQQList: import_koishi.Schema.array(String).description("管理员QQ列表").default([]) }).description("管理员信息"), import_koishi.Schema.object({ maxLevel: import_koishi.Schema.number().description("当前版本的最大等级").step(5).default(290) }).description("游戏信息"), import_koishi.Schema.object({ levelUP_player_recommend: import_koishi.Schema.number().description("使用升级指令时推荐系数的影响幅度").min(0).step(5).default(30), levelUP_player_fixedBossReturn: import_koishi.Schema.number().description("使用升级指令时返回的定点王数量").min(1).step(1).default(6), levelUP_player_wildBossReturn: import_koishi.Schema.number().description("使用升级指令时返回的野王数量").min(1).step(1).default(4) }).description("升级指令管理"), import_koishi.Schema.object({ monthlyCardReminder_midnightTime: import_koishi.Schema.number().description("月卡提醒的凌晨时间").default(0), monthlyCardReminder_morningTime: import_koishi.Schema.number().description("月卡提醒的早上时间").default(9), monthlyCardReminder_noonTime: import_koishi.Schema.number().description("月卡提醒的中午时间").default(12), monthlyCardReminder_afternoonTime: import_koishi.Schema.number().description("月卡提醒的下午时间").default(16), monthlyCardReminder_eveningTime: import_koishi.Schema.number().description("月卡提醒的晚上时间").default(20), monthlyCardReminder_latenightTime: import_koishi.Schema.number().description("月卡提醒的深夜时间").default(23) }).description("月卡提醒管理"), import_koishi.Schema.object({ sendDialog: import_koishi.Schema.boolean().description("是否发送日志以调试").default(false) }).description("调试相关") ]); async function apply(ctx, config) { const logger = ctx.logger("toram"); ctx.model.extend( "toram_user", { // 各字段的类型声明 qq: "string", nickname: "string", otherNames: "list", monthlyCardRemindTimeIndex: "integer", lastGetMonthlyCardDate: "string" }, { primary: "qq" } ); ctx.model.extend("toram_todo", { // 各字段的类型声明 id: "string", ts: "double", type: "string", payload: "json" }, { primary: "id" }); JsonMgr.Inst().setLogger(logger); await JsonMgr.Inst().loadJson(); const bot = ctx.bots.find((bot2) => bot2.selfId === config.qq); TalkMgr.Inst().setBot(bot); TalkMgr.Inst().setTalks(); await UserMgr.Inst().setUsers(ctx); MonsterMgr.Inst().setMonsters(); await BotTodoMgr.Inst().setTodos(ctx); registerBotTodoHandlers(); BotTodoMgr.Inst().start(); scheduleMonthlyCardReminders(config.groupId, [ config.monthlyCardReminder_midnightTime, config.monthlyCardReminder_morningTime, config.monthlyCardReminder_noonTime, config.monthlyCardReminder_afternoonTime, config.monthlyCardReminder_eveningTime, config.monthlyCardReminder_latenightTime ]); scheduleMonthlyCardFinalReminder(config.groupId); ctx.on("notice", (session) => { if (config.sendDialog) logger.info(session); if (session.event._data.target_id != config.qq) return; const event = newEvent(ctx, session, config, logger); const result = confirmMonthlyCardGet(event); if (result.code === 1001 /* 通过 */) { TalkMgr.Inst().reply(event, "月卡确认领取"); } else { TalkMgr.Inst().reply(event, "戳一戳"); } }); ctx.middleware(async (session, next) => { if (config.sendDialog) logger.info(session); if (session.event.message.elements.some((e) => e.type === "at" && e.attrs.id === config.qq)) { const event = newEvent(ctx, session, config, logger); TalkMgr.Inst().reply(event, "被@", { MCRMidnight: config.monthlyCardReminder_midnightTime.toString(), MCRMorning: config.monthlyCardReminder_morningTime.toString(), MCRNoon: config.monthlyCardReminder_noonTime.toString(), MCRAfternoon: config.monthlyCardReminder_afternoonTime.toString(), MCREvening: config.monthlyCardReminder_eveningTime.toString(), MCRLatenight: config.monthlyCardReminder_latenightTime.toString() }); } return next(); }); ctx.command("升级 <等级数>").action(async ({ session }, ...args) => { const event = newEvent(ctx, session, config, logger); command_levelUP(event, args); }); ctx.command("月卡提醒 <时间段>").action(async ({ session }, ...args) => { const event = newEvent(ctx, session, config, logger); command_monthlyCardRemind(event, args); }); ctx.command("取消月卡提醒").action(async ({ session }, ...args) => { const event = newEvent(ctx, session, config, logger); command_cancelMonthlyCardRemind(event, args); }); ctx.command("魔导书,全员提醒 <时间段> <时间点> <内容>").action(async ({ session }, ...args) => { const event = newEvent(ctx, session, config, logger); allMemberRemind(event, args); }); ctx.command("我领月卡啦").action(async ({ session }, ...args) => { const event = newEvent(ctx, session, config, logger); const result = confirmMonthlyCardGet(event); if (result.code === 1001 /* 通过 */) { TalkMgr.Inst().reply(event, "月卡确认领取"); } }); } __name(apply, "apply"); function registerBotTodoHandlers() { BotTodoMgr.Inst().on(ALL_MEMBER_REMINDER_TYPE, executeAllMemberReminder); BotTodoMgr.Inst().on(MONTHLY_CARD_REMINDER_TYPE, executeMonthlyCardReminder); BotTodoMgr.Inst().on(MONTHLY_CARD_FINAL_REMINDER_TYPE, executeMonthlyCardFinalReminder); } __name(registerBotTodoHandlers, "registerBotTodoHandlers"); function newEvent(ctx, session, config, logger) { const event = { ctx, session, config, logger }; return event; } __name(newEvent, "newEvent"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, apply, inject, name });