koishi-plugin-onebot-verifier 1.2.10 → 1.2.11
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.js +64 -70
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -109,36 +109,47 @@ function apply(ctx, config) {
|
|
|
109
109
|
const answers = lines.filter((s) => /^(回答|答案)[::]/i.test(s)).map((s) => s.replace(/^(回答|答案)[::]\s*/i, ""));
|
|
110
110
|
return answers.length > 0 ? answers.join("\n") : comment;
|
|
111
111
|
}, "getComment");
|
|
112
|
+
const getQQLevel = /* @__PURE__ */ __name((stats) => +(stats?.qqLevel ?? stats?.qq_level ?? stats?.level ?? 0), "getQQLevel");
|
|
113
|
+
const pushText = /* @__PURE__ */ __name(async (session, target, content) => {
|
|
114
|
+
const [type, id] = (target || "").split(":");
|
|
115
|
+
if (!id || !session.bot) return;
|
|
116
|
+
await (type === "private" ? session.bot.sendPrivateMessage(id, content) : session.bot.sendMessage(id, content)).catch(() => {
|
|
117
|
+
});
|
|
118
|
+
}, "pushText");
|
|
112
119
|
const executeAction = /* @__PURE__ */ __name(async (session, kind, pass, reason = "", remark = "") => {
|
|
113
120
|
try {
|
|
114
121
|
const eventData = session.event?._data || {};
|
|
115
122
|
if (config.debugMode) logger.info(`[操作] 类型: ${kind} 结果: ${pass ? "同意" : "拒绝"} 原因: ${reason || "无"}`);
|
|
116
|
-
if (pass && kind === "guild" && session.guildId && session.userId) inviterMap.set(session.guildId, session.userId);
|
|
117
|
-
if (!pass && kind === "guild"
|
|
118
|
-
const targetId = eventData.operator_id || session.
|
|
119
|
-
if (targetId) {
|
|
120
|
-
const rejectMsg = `已拒绝该群组邀请${reason ? `,原因:${reason}` : ""}`;
|
|
121
|
-
await session.bot.sendPrivateMessage(targetId, rejectMsg).catch(() => {
|
|
122
|
-
});
|
|
123
|
-
}
|
|
123
|
+
if (pass && kind === "guild" && session.guildId && session.userId && session.userId !== session.selfId) inviterMap.set(session.guildId, session.userId);
|
|
124
|
+
if (!pass && kind === "guild") {
|
|
125
|
+
const targetId = eventData.operator_id || session.userId;
|
|
126
|
+
if (targetId) await pushText(session, `private:${targetId}`, `已拒绝该群组邀请${reason ? `,原因:${reason}` : ""}`);
|
|
124
127
|
}
|
|
125
|
-
if (!pass && kind === "guild" && session.guildId &&
|
|
126
|
-
if (reason) await
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return true;
|
|
128
|
+
if (!pass && kind === "guild" && session.guildId && eventData.notice_type === "group_increase") {
|
|
129
|
+
if (reason) await pushText(session, `guild:${session.guildId}`, `${reason},将退出该群`);
|
|
130
|
+
const left = await session.onebot?.setGroupLeave(session.guildId, false).then(() => true, () => false);
|
|
131
|
+
if (config.debugMode) logger.info(`[操作] ${left ? "退出群组" : "退出群组失败"}: ${session.guildId}`);
|
|
132
|
+
return !!left;
|
|
131
133
|
}
|
|
132
134
|
const flag = eventData.flag;
|
|
133
135
|
if (!flag || !session.onebot) return false;
|
|
134
136
|
if (kind === "friend") {
|
|
135
137
|
await session.onebot.setFriendAddRequest(flag, pass, remark);
|
|
138
|
+
if (pass && remark) setTimeout(async () => {
|
|
139
|
+
const onebot = session.onebot;
|
|
140
|
+
try {
|
|
141
|
+
if (onebot.setFriendRemark) await onebot.setFriendRemark(session.userId, remark);
|
|
142
|
+
else await onebot._get("set_friend_remark", { user_id: session.userId, remark });
|
|
143
|
+
} catch (error) {
|
|
144
|
+
logger.warn(`设置好友备注失败: ${error}`);
|
|
145
|
+
}
|
|
146
|
+
}, 1e3);
|
|
136
147
|
} else {
|
|
137
148
|
await session.onebot.setGroupAddRequest(flag, eventData.sub_type ?? "add", pass, pass ? "" : reason);
|
|
138
149
|
}
|
|
139
150
|
return true;
|
|
140
151
|
} catch (error) {
|
|
141
|
-
logger.error(
|
|
152
|
+
logger.error(`操作失败(${kind}${session.guildId ? ` 群 ${session.guildId}` : ""}${session.userId ? ` 用户 ${session.userId}` : ""}): ${error}`);
|
|
142
153
|
return false;
|
|
143
154
|
}
|
|
144
155
|
}, "executeAction");
|
|
@@ -150,7 +161,7 @@ function apply(ctx, config) {
|
|
|
150
161
|
const eventData = session.event?._data || {};
|
|
151
162
|
const userInfo = session.userId ? await session.bot.getUser?.(session.userId).catch(() => null) : null;
|
|
152
163
|
const groupInfo = kind !== "friend" && session.guildId ? await session.bot.getGuild?.(session.guildId).catch(() => null) : null;
|
|
153
|
-
const adminId = String(eventData.operator_id ||
|
|
164
|
+
const adminId = String(eventData.operator_id || "");
|
|
154
165
|
const adminInfo = adminId && adminId !== session.userId ? await session.bot.getUser?.(adminId).catch(() => null) : null;
|
|
155
166
|
const typeMap = { friend: "好友申请", member: "加群请求", guild: eventData.post_type === "notice" ? "群组邀请 (审核)" : "群组邀请 (请求)", removed: eventData.sub_type === "kick_me" ? "移出群组" : "退出群组" };
|
|
156
167
|
const statusMap = { auto_pass: " [自动通过]", auto_reject: " [自动拒绝]", waiting: " [等待处理]" };
|
|
@@ -160,7 +171,7 @@ function apply(ctx, config) {
|
|
|
160
171
|
if (kind !== "guild" && kind !== "removed" || session.userId && session.userId !== session.selfId) infoLines.push(`用户:${userInfo?.name || session.userId}${session.userId ? `(${session.userId})` : ""}`);
|
|
161
172
|
if (adminId) infoLines.push(`管理:${adminInfo?.name ? `${adminInfo.name}(${adminId})` : adminId}`);
|
|
162
173
|
if (session.guildId) infoLines.push(`群组:${groupInfo?.name ? `${groupInfo.name}(${session.guildId})` : session.guildId}`);
|
|
163
|
-
if (eventData.
|
|
174
|
+
if (eventData.inviter_id && String(eventData.inviter_id) !== "0") infoLines.push(`邀请者:${eventData.invitor_id}`);
|
|
164
175
|
if (eventData.comment) infoLines.push(`验证信息:${eventData.comment}`);
|
|
165
176
|
if (eventData.via) infoLines.push(`来源:${eventData.via}`);
|
|
166
177
|
if (status === "waiting" && kind !== "removed") {
|
|
@@ -175,6 +186,17 @@ function apply(ctx, config) {
|
|
|
175
186
|
return [];
|
|
176
187
|
}
|
|
177
188
|
}, "sendNotice");
|
|
189
|
+
const startTimer = /* @__PURE__ */ __name((task, session, timeout, forcePass, target) => {
|
|
190
|
+
if (typeof timeout !== "number") return;
|
|
191
|
+
const finalPass = task.specialMode === "vote" ? false : forcePass ?? timeout > 0;
|
|
192
|
+
task.timer = setTimeout(async () => {
|
|
193
|
+
if (!activeTasks.has(task.messages[0])) return;
|
|
194
|
+
task.messages.forEach((id) => activeTasks.delete(id));
|
|
195
|
+
await executeAction(session, task.kind, finalPass, finalPass ? "" : "等待超时,自动拒绝");
|
|
196
|
+
await pushText(session, target, `已自动${finalPass ? "通过" : "拒绝"}该请求`);
|
|
197
|
+
if (config.debugMode) logger.info(`[操作] 等待超时,默认${finalPass ? "通过" : "拒绝"}`);
|
|
198
|
+
}, Math.abs(timeout) * 6e4);
|
|
199
|
+
}, "startTimer");
|
|
178
200
|
const setupManual = /* @__PURE__ */ __name(async (session, kind, specialMode, useInSitu, forceTimeoutResult) => {
|
|
179
201
|
const timeoutCfg = kind === "member" ? config.memberTimeout : config.friendTimeout;
|
|
180
202
|
let targetStr = config.notifyTarget || "";
|
|
@@ -188,24 +210,7 @@ function apply(ctx, config) {
|
|
|
188
210
|
task.votes = { yes: /* @__PURE__ */ new Set(), no: /* @__PURE__ */ new Set() };
|
|
189
211
|
}
|
|
190
212
|
msgIds.forEach((id) => activeTasks.set(id, task));
|
|
191
|
-
|
|
192
|
-
const waitMinutes = Math.abs(timeoutCfg);
|
|
193
|
-
const isPass = forceTimeoutResult !== void 0 ? forceTimeoutResult : timeoutCfg > 0;
|
|
194
|
-
task.timer = setTimeout(async () => {
|
|
195
|
-
if (!activeTasks.has(msgIds[0])) return;
|
|
196
|
-
msgIds.forEach((id) => activeTasks.delete(id));
|
|
197
|
-
let finalActionPass = isPass;
|
|
198
|
-
if (specialMode === "vote") finalActionPass = false;
|
|
199
|
-
await executeAction(session, kind, finalActionPass, finalActionPass ? "" : "等待超时,自动拒绝");
|
|
200
|
-
const [targetType, targetId] = targetStr.split(":");
|
|
201
|
-
if (targetId && session.bot) {
|
|
202
|
-
const statusText = `已自动${finalActionPass ? "通过" : "拒绝"}该请求`;
|
|
203
|
-
await (targetType === "private" ? session.bot.sendPrivateMessage(targetId, statusText) : session.bot.sendMessage(targetId, statusText)).catch(() => {
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
if (config.debugMode) logger.info(`[操作] 等待超时,默认${finalActionPass ? "通过" : "拒绝"}`);
|
|
207
|
-
}, waitMinutes * 6e4);
|
|
208
|
-
}
|
|
213
|
+
startTimer(task, session, timeoutCfg, forceTimeoutResult, targetStr);
|
|
209
214
|
}, "setupManual");
|
|
210
215
|
const hookEvent = /* @__PURE__ */ __name((kind) => async (session) => {
|
|
211
216
|
const eventData = session.event?._data || {};
|
|
@@ -214,8 +219,9 @@ function apply(ctx, config) {
|
|
|
214
219
|
const isApply = kind === "guild" && eventData.post_type === "request" && !!eventData.invited_id && String(eventData.invited_id) !== String(eventData.self_id);
|
|
215
220
|
if (isApply) session.userId = String(eventData.invited_id);
|
|
216
221
|
if (session.guildId && config.blacklist?.includes(session.guildId)) return;
|
|
222
|
+
const realKind = isApply ? "member" : kind;
|
|
217
223
|
try {
|
|
218
|
-
if (config.debugMode) logger.info(`[请求] 类型: ${
|
|
224
|
+
if (config.debugMode) logger.info(`[请求] 类型: ${realKind} 数据: ${JSON.stringify(eventData)}`);
|
|
219
225
|
const verifyText = getComment(eventData.comment);
|
|
220
226
|
if (kind === "friend") {
|
|
221
227
|
const existingTask = [...activeTasks.values()].find((t) => t.kind === "friend" && t.session.userId === session.userId);
|
|
@@ -224,34 +230,20 @@ function apply(ctx, config) {
|
|
|
224
230
|
const oldVerifyText = getComment(existingTask.session.event?._data?.comment);
|
|
225
231
|
if (oldVerifyText === verifyText) {
|
|
226
232
|
existingTask.session = session;
|
|
227
|
-
|
|
228
|
-
if (typeof timeoutCfg === "number") {
|
|
229
|
-
const isPass = timeoutCfg > 0;
|
|
230
|
-
existingTask.timer = setTimeout(async () => {
|
|
231
|
-
if (!activeTasks.has(existingTask.messages[0])) return;
|
|
232
|
-
existingTask.messages.forEach((id) => activeTasks.delete(id));
|
|
233
|
-
await executeAction(session, "friend", isPass, isPass ? "" : "等待超时,自动拒绝");
|
|
234
|
-
const [targetType, targetId] = (config.notifyTarget || "").split(":");
|
|
235
|
-
if (targetId && session.bot) {
|
|
236
|
-
const statusText = `已自动${isPass ? "通过" : "拒绝"}该请求`;
|
|
237
|
-
await (targetType === "private" ? session.bot.sendPrivateMessage(targetId, statusText) : session.bot.sendMessage(targetId, statusText)).catch(() => {
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}, Math.abs(timeoutCfg) * 6e4);
|
|
241
|
-
}
|
|
233
|
+
startTimer(existingTask, session, config.friendTimeout, void 0, config.notifyTarget);
|
|
242
234
|
return;
|
|
243
235
|
}
|
|
244
236
|
existingTask.messages.forEach((id) => activeTasks.delete(id));
|
|
245
237
|
}
|
|
246
238
|
}
|
|
247
|
-
if (
|
|
239
|
+
if (realKind === "member") {
|
|
248
240
|
const rules = config.verifyRules?.filter((r) => r.guildId === session.guildId) || [];
|
|
249
241
|
for (const rule of rules) {
|
|
250
242
|
const stats = (rule.minLevel ?? 0) > 0 && session.onebot && session.userId ? await session.onebot.getStrangerInfo(session.userId, true).catch(() => ({})) : null;
|
|
251
|
-
const levelMatch = (stats
|
|
243
|
+
const levelMatch = getQQLevel(stats) >= (rule.minLevel ?? 0);
|
|
252
244
|
const keywordMatch = !rule.keyword || new RegExp(rule.keyword, "i").test(verifyText);
|
|
253
245
|
if (config.debugMode) {
|
|
254
|
-
if ((rule.minLevel ?? 0) > 0) logger.info(`[加群请求] ${session.userId} 等级 ${stats
|
|
246
|
+
if ((rule.minLevel ?? 0) > 0) logger.info(`[加群请求] ${session.userId} 等级 ${getQQLevel(stats)} ${levelMatch ? ">" : "<"} ${rule.minLevel ?? 0}`);
|
|
255
247
|
if (rule.keyword) logger.info(`[加群请求] ${session.userId} 内容 "${verifyText}" ${keywordMatch ? "=" : "≠"} "${rule.keyword}"`);
|
|
256
248
|
}
|
|
257
249
|
if (levelMatch && keywordMatch) {
|
|
@@ -259,40 +251,40 @@ function apply(ctx, config) {
|
|
|
259
251
|
const isFrequent = rule.frequency && Date.now() - lastLeaveTime < rule.frequency * 6e4;
|
|
260
252
|
if (isFrequent) {
|
|
261
253
|
if (config.frequencyMode === "reject") {
|
|
262
|
-
await executeAction(session,
|
|
263
|
-
await sendNotice(session,
|
|
254
|
+
await executeAction(session, realKind, false, "频繁申请,自动拒绝");
|
|
255
|
+
await sendNotice(session, realKind, "auto_reject");
|
|
264
256
|
return;
|
|
265
257
|
} else if (config.frequencyMode === "ignore") {
|
|
266
|
-
return await setupManual(session,
|
|
258
|
+
return await setupManual(session, realKind);
|
|
267
259
|
} else if (config.frequencyMode === "delay") {
|
|
268
|
-
return await setupManual(session,
|
|
260
|
+
return await setupManual(session, realKind, void 0, false, rule.action && rule.action === "accept");
|
|
269
261
|
}
|
|
270
262
|
}
|
|
271
263
|
if (rule.action) {
|
|
272
|
-
await executeAction(session,
|
|
273
|
-
await sendNotice(session,
|
|
264
|
+
await executeAction(session, realKind, rule.action === "accept", rule.action === "accept" ? "" : "错误回答,自动拒绝");
|
|
265
|
+
await sendNotice(session, realKind, rule.action === "accept" ? "auto_pass" : "auto_reject");
|
|
274
266
|
return;
|
|
275
267
|
}
|
|
276
268
|
}
|
|
277
269
|
}
|
|
278
270
|
const specialRule = config.specialRules?.find((r) => r.guildId === session.guildId);
|
|
279
271
|
if (specialRule) {
|
|
280
|
-
if (specialRule.mode === "vote") return await setupManual(session,
|
|
272
|
+
if (specialRule.mode === "vote") return await setupManual(session, realKind, "vote", config.voteInSitu);
|
|
281
273
|
if (specialRule.mode === "captcha") {
|
|
282
|
-
await executeAction(session,
|
|
283
|
-
await sendNotice(session,
|
|
274
|
+
await executeAction(session, realKind, true, "验证码验证,自动通过");
|
|
275
|
+
await sendNotice(session, realKind, "auto_pass");
|
|
284
276
|
return;
|
|
285
277
|
}
|
|
286
278
|
}
|
|
287
|
-
return await setupManual(session,
|
|
279
|
+
return await setupManual(session, realKind);
|
|
288
280
|
}
|
|
289
281
|
let verdict = false;
|
|
290
282
|
if (kind === "friend") {
|
|
291
283
|
let levelPass = true, regexPass = true;
|
|
292
284
|
if (config.friendLevel && config.friendLevel > 0 && session.onebot && session.userId) {
|
|
293
285
|
const stats = await session.onebot.getStrangerInfo(session.userId, true).catch(() => ({}));
|
|
294
|
-
levelPass = (stats
|
|
295
|
-
if (config.debugMode) logger.info(`[好友验证] ${session.userId} 等级 ${stats
|
|
286
|
+
levelPass = getQQLevel(stats) >= config.friendLevel;
|
|
287
|
+
if (config.debugMode) logger.info(`[好友验证] ${session.userId} 等级 ${getQQLevel(stats)} ${levelPass ? ">" : "<"} ${config.friendLevel}`);
|
|
296
288
|
}
|
|
297
289
|
if (config.friendRegex) {
|
|
298
290
|
regexPass = new RegExp(config.friendRegex, "i").test(verifyText);
|
|
@@ -370,7 +362,7 @@ function apply(ctx, config) {
|
|
|
370
362
|
if (config.verifyRules?.some((r) => r.guildId === session.guildId)) historyMap.set(`${session.userId}:${session.guildId}`, Date.now());
|
|
371
363
|
});
|
|
372
364
|
ctx.on("guild-member-added", async (session) => {
|
|
373
|
-
if (!config.specialRules || !session.guildId || !session.userId || config.blacklist?.includes(session.guildId)) return;
|
|
365
|
+
if (!config.specialRules || !session.guildId || !session.userId || session.userId === session.selfId || config.blacklist?.includes(session.guildId)) return;
|
|
374
366
|
const rule = config.specialRules.find((r) => r.guildId === session.guildId);
|
|
375
367
|
if (rule?.mode === "captcha") {
|
|
376
368
|
let a, b, op = "+", answer;
|
|
@@ -400,8 +392,10 @@ function apply(ctx, config) {
|
|
|
400
392
|
const timer = setTimeout(async () => {
|
|
401
393
|
if (activeCaptchas.has(`${session.userId}:${session.guildId}`)) {
|
|
402
394
|
activeCaptchas.delete(`${session.userId}:${session.guildId}`);
|
|
403
|
-
await session.send(`<at id="${session.userId}"/> 验证失败,将被移出本群。`)
|
|
404
|
-
|
|
395
|
+
await session.send(`<at id="${session.userId}"/> 验证失败,将被移出本群。`).catch(() => {
|
|
396
|
+
});
|
|
397
|
+
await session.onebot?.setGroupKick(session.guildId, session.userId, false).catch(() => {
|
|
398
|
+
});
|
|
405
399
|
}
|
|
406
400
|
}, 6e4);
|
|
407
401
|
activeCaptchas.set(`${session.userId}:${session.guildId}`, { guildId: session.guildId, userId: session.userId, answer, timer });
|
|
@@ -420,7 +414,7 @@ function apply(ctx, config) {
|
|
|
420
414
|
inviterMap.delete(session.guildId);
|
|
421
415
|
if (config.debugMode) logger.info(`[操作] 删除邀请者好友: ${inviterId}`);
|
|
422
416
|
}
|
|
423
|
-
const adminId = String(eventData.operator_id ||
|
|
417
|
+
const adminId = String(eventData.operator_id || "");
|
|
424
418
|
if (adminId && adminId !== inviterId) {
|
|
425
419
|
await session.onebot?.deleteFriend(adminId).catch(() => {
|
|
426
420
|
});
|
package/package.json
CHANGED