UNPKG

@momuhoka/koishi-plugin-jrrp

Version:

自用今日人品插件,AI生成仅供参考:主要负责协助AI大人完成功能完善和BUG修复

398 lines (396 loc) 16 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; 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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Config: () => Config, apply: () => apply, name: () => name, using: () => using }); module.exports = __toCommonJS(src_exports); var import_koishi = require("koishi"); var name = "jrrp"; var using = ["database"]; var Config = import_koishi.Schema.object({ resetHour: import_koishi.Schema.number().min(0).max(23).default(0).description("每天重置人品的时间(0~23点)"), utcOffsetMinutes: import_koishi.Schema.number().default(480).description("时区偏移(分钟),如北京时间为 480"), salt: import_koishi.Schema.string().default("koishi-jrrp").description("盐值,用于随机种子生成,防止可预测"), nameMode: import_koishi.Schema.union(["username", "at"]).default("username").description("人品输出中的{name}字段显示方式(username 或 at)"), style: import_koishi.Schema.string().default("今天 {name} 的人品是:{score}/100 {comment}").description("主输出样式模板"), enableActivities: import_koishi.Schema.boolean().default(true).description("是否显示宜/忌"), enableLuckyNumber: import_koishi.Schema.boolean().default(true).description("是否显示幸运数字"), enableLuckyColor: import_koishi.Schema.boolean().default(true).description("是否显示幸运颜色"), enableYiyan: import_koishi.Schema.boolean().default(true).description("是否使用一言作为额外内容"), scoreMode: import_koishi.Schema.union(["normal", "fathead"]).default("normal").description("分数模式:normal 正常分布,fathead 偏积极"), activitiesCustom: import_koishi.Schema.array(String).role("table").description("自定义活动列表(优先于默认)"), commentsCustom: import_koishi.Schema.array(import_koishi.Schema.object({ min: import_koishi.Schema.number().required(), max: import_koishi.Schema.number().required(), text: import_koishi.Schema.string().required() })).role("table").description("自定义分数评论"), customYiyanApi: import_koishi.Schema.object({ url: import_koishi.Schema.string().required().description("自定义一言API接口地址"), data: import_koishi.Schema.string().required().description("自定义一言API请求数据(如有需要)") }).description("自定义一言API接口地址(填写后启用)").default({ url: "", data: "" }) }); var defaultActivities = [ "整理房间", "喝杯水", "散步", "早睡", "尝试新菜", "备份文件", "阅读", "运动", "联系朋友", "听音乐", "写随笔", "晒太阳", "打扫卫生", "学习新知识", "计划明天", "关注健康", "理性消费", "放松休息", "逛超市", "做家务", "尝试新游戏", "看电影", "写感谢信", "微笑", "冥想", "做饭", "收拾桌面", "整理资料", "浏览新闻", "做理财规划", "尝试新穿搭", "拍照", "逛公园", "看动漫", "做手工", "写日记", "逛论坛", "尝试新APP", "关注天气", "清理手机", "学习外语", "练习书法", "画画", "做运动计划", "尝试新发型", "逛书店", "做健康检查", "尝试新饮品", "关注时事", "做心理调节", "整理邮箱", "清理垃圾文件", "尝试新兴趣", "做自我总结", "关注安全", "尝试新路线", "做预算", "关注环保", "做公益", "关注家人", "逛商场", "尝试新餐厅", "做健康饮食计划", "关注宠物健康", "尝试新运动", "做时间管理", "关注交通安全", "尝试新技能", "做自我提升", "关注心理健康", "逛博物馆", "做志愿服务", "尝试新乐器", "关注网络安全", "做职业规划", "尝试新社交活动", "关注社区动态", "做兴趣小组活动", "尝试新学习方法", "关注节能减排", "做家庭聚会", "尝试新娱乐方式", "关注公共卫生", "做自我反思", "尝试新工作方式", "关注社会新闻", "做团队协作", "尝试新阅读材料", "关注个人隐私", "做年度计划" ]; var defaultComments = [ { min: 0, max: 9, text: ["今天有点挑战,但保持笑容会更好~", "低开高走,别灰心!", "小心运势,积极面对!"] }, { min: 10, max: 29, text: ["可能会遇到小波折,但你能应付~", "有点小坎坷,勇敢一点!", "坚持下去会有转机~"] }, { min: 30, max: 49, text: ["平平淡淡也有好风景~", "今天很普通,享受平静吧", "平稳度过,别忘微笑"] }, { min: 50, max: 69, text: ["小吉,小确幸就在身边~", "运势不错,可以尝试新事物", "有点小幸运,抓住机会"] }, { min: 70, max: 84, text: ["吉,适合开展计划~", "今天很顺利,行动力满满", "适合做重要决定"] }, { min: 85, max: 94, text: ["大吉,今天特别顺利~", "好运连连,事事顺心", "心想事成的一天"] }, { min: 95, max: 100, text: ["欧皇降临,好运爆棚!", "极致好运,快去抽卡!", "幸运爆表,万事如意"] } ]; function fnv1a32(str) { let h = 2166136261 >>> 0; for (let i = 0; i < str.length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619) >>> 0; } return h >>> 0; } __name(fnv1a32, "fnv1a32"); function mulberry32(seed) { let t = seed >>> 0; return function() { t += 1831565813; let r = Math.imul(t ^ t >>> 15, 1 | t); r ^= r + Math.imul(r ^ r >>> 7, 61 | r); return ((r ^ r >>> 14) >>> 0) / 4294967296; }; } __name(mulberry32, "mulberry32"); function fatheadScore(rng) { return Math.floor(Math.pow(rng(), 1 / 5) * 40 + 60); } __name(fatheadScore, "fatheadScore"); function currentDateKey(resetHour, offsetMin, now = /* @__PURE__ */ new Date()) { const utc = now.getTime() + now.getTimezoneOffset() * 6e4; const local = utc + offsetMin * 6e4; const d = new Date(local); const hour = d.getUTCHours(); if (hour < resetHour) d.setUTCDate(d.getUTCDate() - 1); return `${d.getUTCFullYear()}-${(d.getUTCMonth() + 1).toString().padStart(2, "0")}-${d.getUTCDate().toString().padStart(2, "0")}`; } __name(currentDateKey, "currentDateKey"); function pickComment(ctx, score, custom) { const rules = custom && custom.length ? custom : defaultComments; for (const r of rules) { if (score >= r.min && score <= r.max) { if (Array.isArray(r.text)) { const idx = Math.floor(Math.random() * r.text.length); return r.text[idx]; } else { return r.text; } } } return ""; } __name(pickComment, "pickComment"); async function pickYiYan(ctx, config) { const url = config?.customYiyanApi?.url ? config.customYiyanApi.url : "https://v1.hitokoto.cn/"; const data = config?.customYiyanApi?.data; try { const res = await ctx.http.get(url); if (data) { if (res[data]) return `『${res[data]}』`; } else { if (typeof res === "string") return `『${res}』`; if (res?.hitokoto) return `『${res.hitokoto}』`; if (res?.data) return `『${res.data}』`; if (res?.data?.hitokoto) return `『${res.data.hitokoto}』`; } } catch (e) { ctx.logger("jrrp").warn("获取一言失败:\n", e); } return ""; } __name(pickYiYan, "pickYiYan"); function sampleMany(rng, list, n) { const a = list.slice(); for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(rng() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a.slice(0, Math.min(n, a.length)); } __name(sampleMany, "sampleMany"); function formatStyle(style, data) { return style.replace(/\{(\w+)\}/g, (_, k) => String(data[k] ?? "")); } __name(formatStyle, "formatStyle"); function apply(ctx, config) { ctx.on("ready", async () => { ctx.model.extend("jrrp", { userId: "string", date: "string", score: "integer", comment: "string", good: "string", bad: "string", luckyNumber: "integer", luckyColor: "string", yiyan: "string" }, { primary: ["userId", "date"] }); }); const activities = (config.activitiesCustom?.length ? config.activitiesCustom : defaultActivities).slice(); ctx.command("jrrp", "查看今日人品").alias("rp").alias("今日人品").alias("人品").option("detail", "-d, --detail 显示详细签运").action(async ({ session, options }) => { if (!session) return "(无法获取会话信息)"; const dateKey = currentDateKey(config.resetHour, config.utcOffsetMinutes); const id = session.userId; let nameField; if (config.nameMode === "at") { if (session.platform === "qq" || session.platform === "onebot") { nameField = import_koishi.segment.at(id).toString(); } else { nameField = `<at id=${id}/>`; } } else { ctx.logger("jrrp").warn("@用户失败,使用用户昵称代替"); nameField = session.username; } const record = await ctx.database.get("jrrp", { userId: id, date: dateKey }); if (record.length > 0) { const head = formatStyle(config.style, { name: nameField, id, date: dateKey, score: record[0].score, comment: record[0].comment }); let tail = ""; if (options?.detail || config.enableActivities || config.enableLuckyNumber || config.enableLuckyColor || config.enableYiyan) { let good = []; let bad = []; if (config.enableActivities && record[0].good && record[0].bad) { good = record[0].good ? record[0].good.split(",") : []; bad = record[0].bad ? record[0].bad.split(",") : []; tail += ` 宜:${good.join("、") || "暂无"} 忌:${bad.join("、") || "暂无"}`; } if (config.enableLuckyNumber && record[0].luckyNumber) { tail += ` 幸运数字:${record[0].luckyNumber}`; } if (config.enableLuckyColor && record[0].luckyColor) { tail += ` 幸运颜色:${record[0].luckyColor}`; } if (config.enableYiyan && record[0].yiyan) { tail += ` 签语:${record[0].yiyan}`; } } return `${head}${tail}`; } else { const seedBase = `${id}|${dateKey}|${config.salt}`; const seed = fnv1a32(seedBase); const rng = mulberry32(seed); const score = config.scoreMode === "fathead" ? fatheadScore(rng) : Math.floor(rng() * 101); const comment = pickComment(ctx, score, config.commentsCustom); await ctx.database.create("jrrp", { userId: id, date: dateKey, score, comment }); const head = formatStyle(config.style, { name: nameField, id, date: dateKey, score, comment }); let tail = ""; let good = []; let bad = []; good = sampleMany(rng, activities, 2); bad = sampleMany(rng, activities.filter((a) => !good.includes(a)), 2); await ctx.database.set("jrrp", { userId: id, date: dateKey }, { good: good.join(","), bad: bad.join(",") }); tail += options?.detail || config.enableActivities ? ` 宜:${good.join("、") || "暂无"} 忌:${bad.join("、") || "暂无"}` : ""; const luckyNumber = 1 + Math.floor(rng() * 9); await ctx.database.set("jrrp", { userId: id, date: dateKey }, { luckyNumber }); tail += options?.detail || config.enableLuckyNumber ? ` 幸运数字:${luckyNumber}` : ""; const colors = [ "红(热情、好运)", "橙(活力、温暖)", "黄(智慧、财富)", "绿(健康、平安)", "青(清新、成长)", "蓝(冷静、信任)", "紫(高贵、神秘)", "黑(稳重、力量)", "白(纯洁、希望)", "灰(低调、沉稳)", "金(富贵、成功)", "银(高雅、创新)", "粉(温柔、浪漫)", "棕(踏实、可靠)", "青绿(生机、和谐)", "湖蓝(宁静、治愈)", "米色(温和、包容)", "藏青(睿智、深邃)", "珊瑚(活泼、幸福)", "酒红(成熟、魅力)" ]; const luckyColor = colors[Math.floor(rng() * colors.length)]; await ctx.database.set("jrrp", { userId: id, date: dateKey }, { luckyColor }); tail += options?.detail || config.enableLuckyColor ? ` 幸运颜色:${luckyColor}` : ""; const yiyan = await pickYiYan(ctx, config); await ctx.database.set("jrrp", { userId: id, date: dateKey }, { yiyan }); tail += options?.detail || config.enableYiyan ? ` 签语:${yiyan ? yiyan : "暂无"}` : ""; return `${head}${tail}`; } }); ctx.command("jrrp.del [uid] [date]", "删除指定用户与日期的人品记录(管理)", { hidden: true }).userFields(["authority"]).check(async ({ session }) => { if (!session) return "(无法获取会话信息)"; const user = await ctx.database.getUser(session.platform, session.userId, ["authority"]); if (!user || user.authority < 3) return "你没有权限执行此命令。"; }).action(async ({ session }, uid, date) => { const userId = uid || session.userId; const dateKey = date || currentDateKey(config.resetHour, config.utcOffsetMinutes); await ctx.database.remove("jrrp", { userId, date: dateKey }); return `已删除 ${userId} @ ${dateKey} 的人品记录`; }); ctx.command("jrrp.rebuild", "重构数据库表(管理)", { hidden: true }).check(async ({ session }) => { if (!session) return "(无法获取会话信息)"; const user = await ctx.database.getUser(session.platform, session.userId, ["authority"]); if (!user || user.authority < 3) return "你没有权限执行此命令。"; }).action(async () => { await ctx.database.drop("jrrp"); ctx.logger.warn(`已删除数据库表:jrrp`); ctx.model.extend("jrrp", { userId: "string", date: "string", score: "integer", comment: "string", good: "string", bad: "string", luckyNumber: "integer", luckyColor: "string", yiyan: "string" }, { primary: ["userId", "date"] }); return `已重构数据库表:jrrp`; }); ctx.command("jrrp.sim [uid] [date]", "按指定用户与日期模拟 JRRP(管理)").userFields(["authority"]).check(async ({ session }) => { if (!session) return "(无法获取会话信息)"; const user = await ctx.database.getUser(session.platform, session.userId, ["authority"]); if (!user || user.authority < 3) return "你没有权限执行此命令。"; }).option("platform", "-p <platform:string>").action(async ({ session }, uid, date) => { const userId = uid || session.userId; const dateKey = date || currentDateKey(config.resetHour, config.utcOffsetMinutes); const seedBase = `${userId}|${dateKey}|${config.salt}`; const seed = fnv1a32(seedBase); const rng = mulberry32(seed); const score = config.scoreMode === "fathead" ? fatheadScore(rng) : Math.floor(rng() * 101); return `模拟 ${userId} @ ${dateKey} 的人品为 ${score}/100`; }); } __name(apply, "apply"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, apply, name, using });