UNPKG

koishi-plugin-waifu

Version:
472 lines (467 loc) 21.1 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 __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; 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/locales/zh-CN.yml var require_zh_CN = __commonJS({ "src/locales/zh-CN.yml"(exports2, module2) { module2.exports = { avoidNtr: "是否避免用户抽中他人的老婆", onlyActiveUser: "是否只让用户抽中活跃的群友", activeDays: "活跃天数最小值 (onlyActiveUser 判断活跃的标准)", maxTimes: "每日换老婆次数上限 (对换老婆指令生效,0 为不限制)", excludeUsers: { $description: "排除的用户", $value: { uid: "平台名与用户 ID, 格式: platform:userId", note: "备注 (可不填)" } }, commands: { waifu: { description: "娶群友", messages: { marriages: "{quote}你今日的群友老婆是:{name} {avatar}", "times-too-many": "{quote}渣男,你今天没老婆了!", "members-too-few": "潜在的老婆太少啦,快去拐骗(?)点回来吧!或者骗出来聊天!" } }, "force-marry": { description: "强娶群友", messages: { "force-marry": "{quote}好啦好啦,群友「{name}」已经被你强娶回家了 {avatar}", "no-target": "{quote}强娶谁呀~", "already-marriage": "{quote}你已经娶了老婆,今天别再娶啦!", "members-too-few": "能娶的群友没有这位,或许可以先把对方骗出来聊天?!", "target-self": "{quote}娶自己干嘛!" } }, propose: { description: "向群友求婚", messages: { success: "{quote}群友「{name}」答应了你,愿意当你今日的对象!", failure: "{quote}对方拒绝了", "no-target": "{quote}向谁求婚呀~", "already-marriage": "{quote}你已经有对象了,今天别再求婚啦!", "already-marriage2": "{quote} 你已经有对象了,怎么能接受别人求婚呢!", "members-too-few": "能求婚的群友没有这位,或许可以先把对方骗出来聊天?!", "target-self": "{quote}向自己求婚干嘛!", request: "{targetAt} {targetAvatar}<br/>群友「{name}」向你求婚,那么...你愿意嫁给ta吗?在{time}秒内发送【{agree}】或者【{reject}】,回应对方哦!" } }, divorce: { description: "和群友离婚", messages: { "not-married": "{quote}你还是只单身狗,不能离婚!", divorcement: "{quote}你已经离婚,江湖有缘再相见~" } }, "change-waifu": { description: "换老婆", messages: { "not-married": "{quote}你没有老婆,不能换!", "change-success": "{quote}换好了!你今日的老婆是:{name}{avatar}", "last-times": "{quote}再换你就没老婆了!你今日的老婆是:{name}{avatar}", "times-too-many": "{quote}渣男,你今天没老婆了!", "members-too-few": "能换的群友没有了!" } }, "waifu-query": { description: "查询老婆", messages: { "not-married": "{quote}你没有老婆", marriages: "{quote}你今日的群友老婆是:{name} {avatar}" } } } }; } }); // src/index.ts var index_exports = {}; __export(index_exports, { Config: () => Config, apply: () => apply, inject: () => inject, name: () => name }); module.exports = __toCommonJS(index_exports); var import_koishi = require("koishi"); // src/utils.ts function getMaxAge() { const currentTime = Date.now(); const tomorrowMidnight = /* @__PURE__ */ new Date(); tomorrowMidnight.setHours(24, 0, 0, 0); return tomorrowMidnight.getTime() - currentTime; } __name(getMaxAge, "getMaxAge"); // src/index.ts var name = "waifu"; var inject = { required: ["cache"], optional: ["database"] }; var Config = import_koishi.Schema.intersect([ import_koishi.Schema.object({ avoidNtr: import_koishi.Schema.boolean().default(false), onlyActiveUser: import_koishi.Schema.boolean().default(false), activeDays: import_koishi.Schema.natural().default(7), excludeUsers: import_koishi.Schema.array(import_koishi.Schema.object({ uid: import_koishi.Schema.string().required(), note: import_koishi.Schema.string() })).role("table").default([{ uid: "red:2854196310", note: "Q群管家" }]), maxTimes: import_koishi.Schema.natural().default(2) }).i18n({ "zh-CN": require_zh_CN() }), import_koishi.Schema.object({ forceMarry: import_koishi.Schema.boolean().description("是否启用强娶指令").default(false), propose: import_koishi.Schema.boolean().description("是否启用求婚指令").default(false), divorce: import_koishi.Schema.boolean().description("是否启用离婚指令").default(false), changeWaifu: import_koishi.Schema.boolean().description("是否启用换老婆指令").experimental().default(false), waifuQuery: import_koishi.Schema.boolean().description("是否启用查老婆指令").experimental().default(false) }).description("附加指令") ]); function apply(ctx, cfg) { ctx.i18n.define("zh-CN", require_zh_CN()); ctx.guild().on("message-created", async (session) => { if ((0, import_koishi.isNullable)(session.userId) || session.userId === "0") return; const member = { user: session.event.user, ...session.event.member }; await ctx.cache.set(`waifu_members_${session.gid}`, session.userId, member, 4 * import_koishi.Time.day); await ctx.cache.set(`waifu_members_active_${session.gid}`, session.userId, "", cfg.activeDays * import_koishi.Time.day); }); ctx.on("guild-member-removed", (session) => { if ((0, import_koishi.isNullable)(session.userId) || session.userId === "0") return; ctx.cache.delete(`waifu_members_${session.gid}`, session.userId); ctx.cache.delete(`waifu_members_active_${session.gid}`, session.userId); }); async function getMemberList(session, gid) { let result = []; try { const { data, next } = await session.bot.getGuildMemberList(session.guildId); result = data; if (next) { const { data: data2 } = await session.bot.getGuildMemberList(session.guildId, next); result.push(...data2); } } catch { } if (!result.length) { for await (const value of ctx.cache.values(`waifu_members_${gid}`)) { result.push(value); } } return result; } __name(getMemberList, "getMemberList"); async function getMemberInfo(member, id, platform) { let name2 = member?.nick || member?.user?.nick || member?.user?.name; const avatar = member?.avatar || member?.user?.avatar; if (!name2 && ctx.database) { const user = await ctx.database.getUser(platform, id); if (user?.name) { name2 = user.name; } } name2 ||= id; return [name2, avatar]; } __name(getMemberInfo, "getMemberInfo"); ctx.command("waifu").alias("marry", "娶群友", "今日老婆").action(async ({ session }) => { if (!session.guildId) { return session.text(".members-too-few"); } const { gid } = session; const target = await ctx.cache.get(`waifu_marriages_${gid}`, session.userId); let times = await ctx.cache.get(`waifu_times_${gid}`, session.userId); if (cfg.changeWaifu) { if (times > cfg.maxTimes && cfg.maxTimes !== 0 && target === void 0) { return session.text(".times-too-many", { quote: import_koishi.h.quote(session.messageId) }); } } if (target) { let selected2; try { selected2 = await session.bot.getGuildMember(session.guildId, target); } catch { } try { const member = await ctx.cache.get(`waifu_members_${gid}`, target); if (!selected2) { selected2 = member; } else { selected2.nick ??= member.nick; selected2.user ??= member.user; selected2.user.name ??= member.user.name; } } catch { } try { selected2 ??= { user: await session.bot.getUser(target) }; } catch { } const [name3, avatar2] = await getMemberInfo(selected2, target, session.platform); return session.text(".marriages", { quote: import_koishi.h.quote(session.messageId), name: name3, avatar: avatar2 && import_koishi.h.image(avatar2) }); } const excludes = cfg.excludeUsers.map(({ uid }) => uid); excludes.push(session.uid, session.sid); const memberList = await getMemberList(session, gid); let list = memberList.filter((v) => { return v.user && !excludes.includes(`${session.platform}:${v.user.id}`) && !v.user.isBot; }); if (cfg.onlyActiveUser) { let activeList = []; for await (const value of ctx.cache.keys(`waifu_members_active_${gid}`)) { activeList.push(value); } list = list.filter((v) => activeList.find((active) => active === v.user.id)); } if (list.length === 0) return session.text(".members-too-few"); let selected = import_koishi.Random.pick(list); let selectedId = selected.user.id; const selectedTarget = await ctx.cache.get(`waifu_marriages_${gid}`, selectedId); if (selectedTarget) { selected = import_koishi.Random.pick(list); selectedId = selected.user.id; } if (cfg.avoidNtr) { let i = 0; while (true) { const selectedTarget2 = await ctx.cache.get(`waifu_marriages_${gid}`, selectedId); if (selectedTarget2) { selected = import_koishi.Random.pick(list); selectedId = selected.user.id; } else { break; } i++; if (i > list.length) return session.text(".members-too-few"); } } const maxAge = getMaxAge(); await ctx.cache.set(`waifu_marriages_${gid}`, session.userId, selectedId, maxAge); await ctx.cache.set(`waifu_marriages_${gid}`, selectedId, session.userId, maxAge); if (times === void 0) { times = 0; } await ctx.cache.set(`waifu_times_${gid}`, session.userId, times + 1, maxAge); const [name2, avatar] = await getMemberInfo(selected, selectedId, session.platform); return session.text(".marriages", { quote: import_koishi.h.quote(session.messageId), name: name2, avatar: avatar && import_koishi.h.image(avatar) }); }); if (cfg.forceMarry) { ctx.command("force-marry <target:user>").alias("强娶").action(async ({ session }, target) => { if (!session.guildId) { return session.text(".members-too-few"); } if (!target) { return session.text(".no-target", { quote: import_koishi.h.quote(session.messageId) }); } const targetId = target.slice(session.platform.length + 1); if (targetId === session.userId) return session.text(".target-self"); const { gid } = session; const marriage = await ctx.cache.get(`waifu_marriages_${gid}`, session.userId); if (marriage) { return session.text(".already-marriage", { quote: import_koishi.h.quote(session.messageId) }); } const memberList = await getMemberList(session, gid); const selected = memberList.find((u) => u.user.id === targetId); if (!selected) return session.text(".members-too-few"); const selectedId = selected.user.id; const maxAge = getMaxAge(); await ctx.cache.set(`waifu_marriages_${gid}`, session.userId, selectedId, maxAge); await ctx.cache.set(`waifu_marriages_${gid}`, selectedId, session.userId, maxAge); const [name2, avatar] = await getMemberInfo(selected, selectedId, session.platform); return session.text(".force-marry", { quote: import_koishi.h.quote(session.messageId), name: name2, avatar: avatar && import_koishi.h.image(avatar) }); }); } if (cfg.propose) { ctx.command("propose <target:user>").alias("求婚").action(async ({ session }, target) => { if (!session.guildId) { return session.text(".members-too-few"); } if (!target) { return session.text(".no-target", { quote: import_koishi.h.quote(session.messageId) }); } const targetId = target.slice(session.platform.length + 1); if (targetId === session.userId) return session.text(".target-self"); const { gid } = session; const marriage = await ctx.cache.get(`waifu_marriages_${gid}`, session.userId); if (marriage) { return session.text(".already-marriage", { quote: import_koishi.h.quote(session.messageId) }); } const memberList = await getMemberList(session, gid); const selected = memberList.find((u) => u.user.id === targetId); if (!selected) return session.text(".members-too-few"); const selectedId = selected.user.id; const [name2, avatar] = await getMemberInfo(selected, selectedId, session.platform); await session.send( session.text(".request", { targetAt: import_koishi.h.at(selected.user.id), targetAvatar: import_koishi.h.image(avatar), name: session.username, agree: "我愿意", reject: "我拒绝", time: "90" }) ); let timeoutId; const sourceMessageId = session.messageId; const sourceUserId = session.userId; const dispose = ctx.platform(session.platform).user(selected.user.id).guild(session.guildId).on("message-created", async ({ elements, text, send }) => { const reply = import_koishi.h.select(elements, "text").join("").trim(); if (reply === "我愿意") { dispose(); clearTimeout(timeoutId); const isMarriaged = await ctx.cache.get(`waifu_marriages_${gid}`, selectedId); if (isMarriaged) { await send( text("commands.propose.messages.already-marriage2", { quote: import_koishi.h.at(selectedId) }) ); return; } const maxAge = getMaxAge(); await ctx.cache.set(`waifu_marriages_${gid}`, sourceUserId, selectedId, maxAge); await ctx.cache.set(`waifu_marriages_${gid}`, selectedId, sourceUserId, maxAge); await send( text("commands.propose.messages.success", { quote: import_koishi.h.quote(sourceMessageId), name: name2 }) ); } else if (reply === "我拒绝") { dispose(); clearTimeout(timeoutId); await send( text("commands.propose.messages.failure", { quote: import_koishi.h.quote(sourceMessageId) }) ); } }); timeoutId = setTimeout(() => { dispose(); }, 90 * import_koishi.Time.second); }); } if (cfg.divorce) { ctx.command("divorce").alias("离婚").action(async ({ session }) => { const { gid } = session; const marriage = await ctx.cache.get(`waifu_marriages_${gid}`, session.userId); if (!marriage) { return session.text(".not-married", { quote: import_koishi.h.quote(session.messageId) }); } else { ctx.cache.delete(`waifu_marriages_${gid}`, marriage); ctx.cache.delete(`waifu_marriages_${gid}`, session.userId); return session.text(".divorcement", { quote: import_koishi.h.quote(session.messageId) }); } }); } if (cfg.changeWaifu) { ctx.command("change-waifu").alias("换老婆").action(async ({ session }) => { if (!session.guildId) { return session.text(".members-too-few"); } const { gid } = session; const marriage = await ctx.cache.get(`waifu_marriages_${gid}`, session.userId); const maxAge = getMaxAge(); let times = await ctx.cache.get(`waifu_times_${gid}`, session.userId); if (times > cfg.maxTimes && cfg.maxTimes !== 0) { if (marriage) { ctx.cache.delete(`waifu_marriages_${gid}`, marriage); ctx.cache.delete(`waifu_marriages_${gid}`, session.userId); } return session.text(".times-too-many", { quote: import_koishi.h.quote(session.messageId) }); } else if (!marriage || times === 0 || typeof times === "undefined") { if (marriage !== void 0) { await ctx.cache.set(`waifu_times_${gid}`, session.userId, 1, maxAge); times = await ctx.cache.get(`waifu_times_${gid}`, session.userId); } else { return session.text(".not-married", { quote: import_koishi.h.quote(session.messageId) }); } } const excludes = cfg.excludeUsers.map(({ uid }) => uid); excludes.push(session.uid, session.sid); const memberList = await getMemberList(session, gid); let list = memberList.filter((v) => { return v.user && !excludes.includes(`${session.platform}:${v.user.id}`) && !v.user.isBot; }); if (cfg.onlyActiveUser) { let activeList = []; for await (const value of ctx.cache.keys(`waifu_members_active_${gid}`)) { activeList.push(value); } list = list.filter((v) => activeList.find((active) => active === v.user.id)); } if (list.length === 0) return session.text(".members-too-few"); let selected = import_koishi.Random.pick(list); let selectedId = selected.user.id; const selectedTarget = await ctx.cache.get(`waifu_marriages_${gid}`, selectedId); if (selectedTarget) { selected = import_koishi.Random.pick(list); selectedId = selected.user.id; } if (cfg.avoidNtr) { let i = 0; while (true) { const selectedTarget2 = await ctx.cache.get(`waifu_marriages_${gid}`, selectedId); if (selectedTarget2) { selected = import_koishi.Random.pick(list); selectedId = selected.user.id; } else { break; } i++; if (i > list.length) return session.text(".members-too-few"); } } ctx.cache.delete(`waifu_marriages_${gid}`, marriage); ctx.cache.delete(`waifu_marriages_${gid}`, session.userId); await ctx.cache.set(`waifu_marriages_${gid}`, session.userId, selectedId, maxAge); await ctx.cache.set(`waifu_marriages_${gid}`, selectedId, session.userId, maxAge); await ctx.cache.set(`waifu_times_${gid}`, session.userId, times + 1, maxAge); const [name2, avatar] = await getMemberInfo(selected, selectedId, session.platform); if (times === cfg.maxTimes && cfg.maxTimes !== 0) { return session.text(".last-times", { quote: import_koishi.h.quote(session.messageId), name: name2, avatar: avatar && import_koishi.h.image(avatar) }); } else if (times < cfg.maxTimes || cfg.maxTimes === 0) { return session.text(".change-success", { quote: import_koishi.h.quote(session.messageId), name: name2, avatar: avatar && import_koishi.h.image(avatar) }); } else { return session.text("Error"); } }); } if (cfg.waifuQuery) { ctx.command("waifu-query").alias("查老婆").action(async ({ session }) => { if (!session.guildId) { return session.text(".not-married"); } const { gid } = session; const target = await ctx.cache.get(`waifu_marriages_${gid}`, session.userId); if (target) { let selected; try { selected = await session.bot.getGuildMember(session.guildId, target); } catch { } try { const member = await ctx.cache.get(`waifu_members_${gid}`, target); if (!selected) { selected = member; } else { selected.nick ??= member.nick; selected.user ??= member.user; selected.user.name ??= member.user.name; } } catch { } try { selected ??= { user: await session.bot.getUser(target) }; } catch { } const [name2, avatar] = await getMemberInfo(selected, target, session.platform); return session.text(".marriages", { quote: import_koishi.h.quote(session.messageId), name: name2, avatar: avatar && import_koishi.h.image(avatar) }); } else { return session.text(".not-married"); } }); } } __name(apply, "apply"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, apply, inject, name });