koishi-plugin-onebot-verifier 1.2.9 → 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 +66 -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,32 +210,18 @@ 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 || {};
|
|
212
217
|
if (eventData.user_id) session.userId = String(eventData.user_id);
|
|
213
218
|
if (eventData.group_id) session.guildId = String(eventData.group_id);
|
|
219
|
+
const isApply = kind === "guild" && eventData.post_type === "request" && !!eventData.invited_id && String(eventData.invited_id) !== String(eventData.self_id);
|
|
220
|
+
if (isApply) session.userId = String(eventData.invited_id);
|
|
214
221
|
if (session.guildId && config.blacklist?.includes(session.guildId)) return;
|
|
222
|
+
const realKind = isApply ? "member" : kind;
|
|
215
223
|
try {
|
|
216
|
-
if (config.debugMode) logger.info(`[请求] 类型: ${
|
|
224
|
+
if (config.debugMode) logger.info(`[请求] 类型: ${realKind} 数据: ${JSON.stringify(eventData)}`);
|
|
217
225
|
const verifyText = getComment(eventData.comment);
|
|
218
226
|
if (kind === "friend") {
|
|
219
227
|
const existingTask = [...activeTasks.values()].find((t) => t.kind === "friend" && t.session.userId === session.userId);
|
|
@@ -222,34 +230,20 @@ function apply(ctx, config) {
|
|
|
222
230
|
const oldVerifyText = getComment(existingTask.session.event?._data?.comment);
|
|
223
231
|
if (oldVerifyText === verifyText) {
|
|
224
232
|
existingTask.session = session;
|
|
225
|
-
|
|
226
|
-
if (typeof timeoutCfg === "number") {
|
|
227
|
-
const isPass = timeoutCfg > 0;
|
|
228
|
-
existingTask.timer = setTimeout(async () => {
|
|
229
|
-
if (!activeTasks.has(existingTask.messages[0])) return;
|
|
230
|
-
existingTask.messages.forEach((id) => activeTasks.delete(id));
|
|
231
|
-
await executeAction(session, "friend", isPass, isPass ? "" : "等待超时,自动拒绝");
|
|
232
|
-
const [targetType, targetId] = (config.notifyTarget || "").split(":");
|
|
233
|
-
if (targetId && session.bot) {
|
|
234
|
-
const statusText = `已自动${isPass ? "通过" : "拒绝"}该请求`;
|
|
235
|
-
await (targetType === "private" ? session.bot.sendPrivateMessage(targetId, statusText) : session.bot.sendMessage(targetId, statusText)).catch(() => {
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
}, Math.abs(timeoutCfg) * 6e4);
|
|
239
|
-
}
|
|
233
|
+
startTimer(existingTask, session, config.friendTimeout, void 0, config.notifyTarget);
|
|
240
234
|
return;
|
|
241
235
|
}
|
|
242
236
|
existingTask.messages.forEach((id) => activeTasks.delete(id));
|
|
243
237
|
}
|
|
244
238
|
}
|
|
245
|
-
if (
|
|
239
|
+
if (realKind === "member") {
|
|
246
240
|
const rules = config.verifyRules?.filter((r) => r.guildId === session.guildId) || [];
|
|
247
241
|
for (const rule of rules) {
|
|
248
242
|
const stats = (rule.minLevel ?? 0) > 0 && session.onebot && session.userId ? await session.onebot.getStrangerInfo(session.userId, true).catch(() => ({})) : null;
|
|
249
|
-
const levelMatch = (stats
|
|
243
|
+
const levelMatch = getQQLevel(stats) >= (rule.minLevel ?? 0);
|
|
250
244
|
const keywordMatch = !rule.keyword || new RegExp(rule.keyword, "i").test(verifyText);
|
|
251
245
|
if (config.debugMode) {
|
|
252
|
-
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}`);
|
|
253
247
|
if (rule.keyword) logger.info(`[加群请求] ${session.userId} 内容 "${verifyText}" ${keywordMatch ? "=" : "≠"} "${rule.keyword}"`);
|
|
254
248
|
}
|
|
255
249
|
if (levelMatch && keywordMatch) {
|
|
@@ -257,40 +251,40 @@ function apply(ctx, config) {
|
|
|
257
251
|
const isFrequent = rule.frequency && Date.now() - lastLeaveTime < rule.frequency * 6e4;
|
|
258
252
|
if (isFrequent) {
|
|
259
253
|
if (config.frequencyMode === "reject") {
|
|
260
|
-
await executeAction(session,
|
|
261
|
-
await sendNotice(session,
|
|
254
|
+
await executeAction(session, realKind, false, "频繁申请,自动拒绝");
|
|
255
|
+
await sendNotice(session, realKind, "auto_reject");
|
|
262
256
|
return;
|
|
263
257
|
} else if (config.frequencyMode === "ignore") {
|
|
264
|
-
return await setupManual(session,
|
|
258
|
+
return await setupManual(session, realKind);
|
|
265
259
|
} else if (config.frequencyMode === "delay") {
|
|
266
|
-
return await setupManual(session,
|
|
260
|
+
return await setupManual(session, realKind, void 0, false, rule.action && rule.action === "accept");
|
|
267
261
|
}
|
|
268
262
|
}
|
|
269
263
|
if (rule.action) {
|
|
270
|
-
await executeAction(session,
|
|
271
|
-
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");
|
|
272
266
|
return;
|
|
273
267
|
}
|
|
274
268
|
}
|
|
275
269
|
}
|
|
276
270
|
const specialRule = config.specialRules?.find((r) => r.guildId === session.guildId);
|
|
277
271
|
if (specialRule) {
|
|
278
|
-
if (specialRule.mode === "vote") return await setupManual(session,
|
|
272
|
+
if (specialRule.mode === "vote") return await setupManual(session, realKind, "vote", config.voteInSitu);
|
|
279
273
|
if (specialRule.mode === "captcha") {
|
|
280
|
-
await executeAction(session,
|
|
281
|
-
await sendNotice(session,
|
|
274
|
+
await executeAction(session, realKind, true, "验证码验证,自动通过");
|
|
275
|
+
await sendNotice(session, realKind, "auto_pass");
|
|
282
276
|
return;
|
|
283
277
|
}
|
|
284
278
|
}
|
|
285
|
-
return await setupManual(session,
|
|
279
|
+
return await setupManual(session, realKind);
|
|
286
280
|
}
|
|
287
281
|
let verdict = false;
|
|
288
282
|
if (kind === "friend") {
|
|
289
283
|
let levelPass = true, regexPass = true;
|
|
290
284
|
if (config.friendLevel && config.friendLevel > 0 && session.onebot && session.userId) {
|
|
291
285
|
const stats = await session.onebot.getStrangerInfo(session.userId, true).catch(() => ({}));
|
|
292
|
-
levelPass = (stats
|
|
293
|
-
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}`);
|
|
294
288
|
}
|
|
295
289
|
if (config.friendRegex) {
|
|
296
290
|
regexPass = new RegExp(config.friendRegex, "i").test(verifyText);
|
|
@@ -368,7 +362,7 @@ function apply(ctx, config) {
|
|
|
368
362
|
if (config.verifyRules?.some((r) => r.guildId === session.guildId)) historyMap.set(`${session.userId}:${session.guildId}`, Date.now());
|
|
369
363
|
});
|
|
370
364
|
ctx.on("guild-member-added", async (session) => {
|
|
371
|
-
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;
|
|
372
366
|
const rule = config.specialRules.find((r) => r.guildId === session.guildId);
|
|
373
367
|
if (rule?.mode === "captcha") {
|
|
374
368
|
let a, b, op = "+", answer;
|
|
@@ -398,8 +392,10 @@ function apply(ctx, config) {
|
|
|
398
392
|
const timer = setTimeout(async () => {
|
|
399
393
|
if (activeCaptchas.has(`${session.userId}:${session.guildId}`)) {
|
|
400
394
|
activeCaptchas.delete(`${session.userId}:${session.guildId}`);
|
|
401
|
-
await session.send(`<at id="${session.userId}"/> 验证失败,将被移出本群。`)
|
|
402
|
-
|
|
395
|
+
await session.send(`<at id="${session.userId}"/> 验证失败,将被移出本群。`).catch(() => {
|
|
396
|
+
});
|
|
397
|
+
await session.onebot?.setGroupKick(session.guildId, session.userId, false).catch(() => {
|
|
398
|
+
});
|
|
403
399
|
}
|
|
404
400
|
}, 6e4);
|
|
405
401
|
activeCaptchas.set(`${session.userId}:${session.guildId}`, { guildId: session.guildId, userId: session.userId, answer, timer });
|
|
@@ -418,7 +414,7 @@ function apply(ctx, config) {
|
|
|
418
414
|
inviterMap.delete(session.guildId);
|
|
419
415
|
if (config.debugMode) logger.info(`[操作] 删除邀请者好友: ${inviterId}`);
|
|
420
416
|
}
|
|
421
|
-
const adminId = String(eventData.operator_id ||
|
|
417
|
+
const adminId = String(eventData.operator_id || "");
|
|
422
418
|
if (adminId && adminId !== inviterId) {
|
|
423
419
|
await session.onebot?.deleteFriend(adminId).catch(() => {
|
|
424
420
|
});
|
package/package.json
CHANGED