koishi-plugin-onebot-verifier 1.0.9 → 1.0.10
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 +6 -0
- package/lib/index.js +65 -3
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -21,6 +21,12 @@ export interface Config {
|
|
|
21
21
|
minLevel?: number;
|
|
22
22
|
action?: 'accept' | 'reject';
|
|
23
23
|
}[];
|
|
24
|
+
voteRatio?: string;
|
|
25
|
+
syncNotify?: boolean;
|
|
26
|
+
specialRules?: {
|
|
27
|
+
guildId: string;
|
|
28
|
+
mode: 'vote';
|
|
29
|
+
}[];
|
|
24
30
|
}
|
|
25
31
|
export declare const Config: Schema<Config>;
|
|
26
32
|
export declare function apply(ctx: Context, config?: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -74,7 +74,17 @@ var Config = import_koishi.Schema.intersect([
|
|
|
74
74
|
import_koishi.Schema.const("reject").description("拒绝")
|
|
75
75
|
]).description("操作")
|
|
76
76
|
})).description("加群验证配置").role("table")
|
|
77
|
-
}).description("加群请求配置")
|
|
77
|
+
}).description("加群请求配置"),
|
|
78
|
+
import_koishi.Schema.object({
|
|
79
|
+
syncNotify: import_koishi.Schema.boolean().description("同步通知目标").default(true),
|
|
80
|
+
specialRules: import_koishi.Schema.array(import_koishi.Schema.object({
|
|
81
|
+
guildId: import_koishi.Schema.string().description("群号").required(),
|
|
82
|
+
mode: import_koishi.Schema.union([
|
|
83
|
+
import_koishi.Schema.const("vote").description("投票")
|
|
84
|
+
]).description("模式").default("vote")
|
|
85
|
+
})).description("群组特殊配置").role("table"),
|
|
86
|
+
voteRatio: import_koishi.Schema.string().description("投票比例").default("3:2")
|
|
87
|
+
}).description("特殊验证配置")
|
|
78
88
|
]);
|
|
79
89
|
function apply(ctx, config = {}) {
|
|
80
90
|
const logger = new import_koishi.Logger("onebot-verifier");
|
|
@@ -130,6 +140,7 @@ function apply(ctx, config = {}) {
|
|
|
130
140
|
if (adminId) infoLines.push(`管理:${adminInfo?.name ? `${adminInfo.name}(${adminId})` : adminId}`);
|
|
131
141
|
if (session.guildId) infoLines.push(`群组:${groupInfo?.name ? `${groupInfo.name}(${session.guildId})` : session.guildId}`);
|
|
132
142
|
if (eventData.comment) infoLines.push(`验证信息:${eventData.comment}`);
|
|
143
|
+
if (status === "waiting") infoLines.push(`使用"y/n"回复本消息,以同意/拒绝该请求`);
|
|
133
144
|
const content = infoLines.join("\n");
|
|
134
145
|
const msgIds = await (targetType === "private" ? session.bot.sendPrivateMessage(targetId, content) : session.bot.sendMessage(targetId, content)) || [];
|
|
135
146
|
return msgIds;
|
|
@@ -138,6 +149,24 @@ function apply(ctx, config = {}) {
|
|
|
138
149
|
return [];
|
|
139
150
|
}
|
|
140
151
|
}, "sendNotice");
|
|
152
|
+
const handleSpecialRule = /* @__PURE__ */ __name(async (session, kind) => {
|
|
153
|
+
if (kind !== "member" || !config.specialRules || config.specialRules.length === 0) return false;
|
|
154
|
+
const rule = config.specialRules.find((r) => String(r.guildId) === String(session.guildId));
|
|
155
|
+
if (!rule) return false;
|
|
156
|
+
if (rule.mode === "vote") {
|
|
157
|
+
const [yesStr, noStr] = config.voteRatio.split(":");
|
|
158
|
+
const targetYes = parseInt(yesStr) || 0;
|
|
159
|
+
const targetNo = parseInt(noStr) || 0;
|
|
160
|
+
let msgIds = [];
|
|
161
|
+
if (config.syncNotify !== false) msgIds = await sendNotice(session, kind, "waiting");
|
|
162
|
+
if (msgIds.length > 0) {
|
|
163
|
+
const task = { session, kind, messages: msgIds, specialMode: "vote", voteTarget: { yes: targetYes, no: targetNo }, votes: { yes: /* @__PURE__ */ new Set(), no: /* @__PURE__ */ new Set() } };
|
|
164
|
+
msgIds.forEach((id) => activeTasks.set(id, task));
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}, "handleSpecialRule");
|
|
141
170
|
const setupManual = /* @__PURE__ */ __name(async (session, kind) => {
|
|
142
171
|
const waitMinutes = config.timeout ?? 0;
|
|
143
172
|
const action = kind === "member" ? config.verifyMode : config.timeoutAction;
|
|
@@ -177,6 +206,7 @@ function apply(ctx, config = {}) {
|
|
|
177
206
|
if (config.debugMode) logger.info(`[收到请求] 类型: ${kind} 数据: ${JSON.stringify(session.event?._data || {})}`);
|
|
178
207
|
const verifyText = getComment(session.event?._data?.comment);
|
|
179
208
|
if (kind === "member") {
|
|
209
|
+
if (await handleSpecialRule(session, kind)) return;
|
|
180
210
|
const rules = config.verifyRules?.filter((r) => String(r.guildId) === String(session.guildId)) || [];
|
|
181
211
|
for (const rule of rules) {
|
|
182
212
|
const minL = rule.minLevel ?? 0;
|
|
@@ -255,6 +285,34 @@ function apply(ctx, config = {}) {
|
|
|
255
285
|
logger.error(`处理失败: ${error}`);
|
|
256
286
|
}
|
|
257
287
|
}, "hookEvent");
|
|
288
|
+
const handleSpecialVote = /* @__PURE__ */ __name(async (session, task, isApprove, extraInfo, targetType, targetId) => {
|
|
289
|
+
if (!task.voteTarget || !task.votes) return;
|
|
290
|
+
const voterId = session.userId;
|
|
291
|
+
if (!voterId) return;
|
|
292
|
+
task.votes.yes.delete(voterId);
|
|
293
|
+
task.votes.no.delete(voterId);
|
|
294
|
+
if (isApprove) {
|
|
295
|
+
task.votes.yes.add(voterId);
|
|
296
|
+
} else {
|
|
297
|
+
task.votes.no.add(voterId);
|
|
298
|
+
}
|
|
299
|
+
if (config.debugMode) logger.info(`[投票] 赞成: ${task.votes.yes.size}/${task.voteTarget.yes} | 反对: ${task.votes.no.size}/${task.voteTarget.no}`);
|
|
300
|
+
let thresholdMet = false;
|
|
301
|
+
let finalVerdict = false;
|
|
302
|
+
if (task.voteTarget.yes > 0 && task.votes.yes.size >= task.voteTarget.yes) {
|
|
303
|
+
thresholdMet = true;
|
|
304
|
+
finalVerdict = true;
|
|
305
|
+
} else if (task.voteTarget.no > 0 && task.votes.no.size >= task.voteTarget.no) {
|
|
306
|
+
thresholdMet = true;
|
|
307
|
+
finalVerdict = false;
|
|
308
|
+
}
|
|
309
|
+
if (!thresholdMet) return;
|
|
310
|
+
task.messages.forEach((msg) => activeTasks.delete(msg));
|
|
311
|
+
const isSuccess = await executeAction(task.session, task.kind, finalVerdict, finalVerdict ? "" : extraInfo);
|
|
312
|
+
const replyText = isSuccess ? `已${finalVerdict ? "通过" : "拒绝"}该投票` : `处理投票失败`;
|
|
313
|
+
if (session.bot) await (targetType === "private" ? session.bot.sendPrivateMessage(targetId, replyText) : session.bot.sendMessage(targetId, replyText)).catch(() => {
|
|
314
|
+
});
|
|
315
|
+
}, "handleSpecialVote");
|
|
258
316
|
ctx.on("friend-request", hookEvent("friend"));
|
|
259
317
|
ctx.on("guild-request", hookEvent("guild"));
|
|
260
318
|
ctx.on("guild-member-request", hookEvent("member"));
|
|
@@ -286,11 +344,15 @@ function apply(ctx, config = {}) {
|
|
|
286
344
|
const input = session.content.replace(/<(quote|at)\s+[^>]*\/>/gi, "").trim();
|
|
287
345
|
const cmdMatch = input.match(/^(y|n|通过|拒绝)(?:\s+(.*))?$/i);
|
|
288
346
|
if (!cmdMatch) return next();
|
|
289
|
-
if (task.timer) clearTimeout(task.timer);
|
|
290
|
-
task.messages.forEach((msg) => activeTasks.delete(msg));
|
|
291
347
|
const isApprove = ["y", "通过"].includes(cmdMatch[1].toLowerCase());
|
|
292
348
|
const extraInfo = cmdMatch[2]?.trim() || "";
|
|
293
349
|
if (config.debugMode) logger.info(`[操作] 收到指令: ${isApprove ? "同意" : "拒绝"}`);
|
|
350
|
+
if (task.specialMode === "vote") {
|
|
351
|
+
await handleSpecialVote(session, task, isApprove, extraInfo, targetType, targetId);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (task.timer) clearTimeout(task.timer);
|
|
355
|
+
task.messages.forEach((msg) => activeTasks.delete(msg));
|
|
294
356
|
const isSuccess = await executeAction(task.session, task.kind, isApprove, isApprove ? "" : extraInfo, isApprove && task.kind === "friend" ? extraInfo : "");
|
|
295
357
|
const replyText = isSuccess ? `已${isApprove ? "通过" : "拒绝"}该请求` : `处理请求失败`;
|
|
296
358
|
if (session.bot) await (targetType === "private" ? session.bot.sendPrivateMessage(targetId, replyText) : session.bot.sendMessage(targetId, replyText)).catch(() => {
|