koishi-plugin-waifu
Version:
Marry with your groupmate
472 lines (467 loc) • 21.1 kB
JavaScript
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
});