koishi-plugin-group-verification 1.0.25 → 1.0.27
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 +1 -0
- package/lib/index.js +70 -24
- package/package.json +1 -1
- package/src/index.ts +96 -42
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -443,14 +443,19 @@ async function verifyApplication(config, message, session) {
|
|
|
443
443
|
requiredThreshold = "null";
|
|
444
444
|
break;
|
|
445
445
|
case 1:
|
|
446
|
-
|
|
447
|
-
|
|
446
|
+
{
|
|
447
|
+
const thresholdNum = config.reviewParameters !== void 0 && config.reviewParameters !== null ? config.reviewParameters : 0;
|
|
448
|
+
isValid = matchedCount >= thresholdNum;
|
|
449
|
+
requiredThreshold = `${thresholdNum}`;
|
|
450
|
+
}
|
|
448
451
|
break;
|
|
449
452
|
case 2:
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
453
|
+
{
|
|
454
|
+
const thresholdPct = config.reviewParameters !== void 0 && config.reviewParameters !== null ? config.reviewParameters : 100;
|
|
455
|
+
const ratio = matchedCount / config.keywords.length;
|
|
456
|
+
isValid = ratio >= thresholdPct / 100;
|
|
457
|
+
requiredThreshold = `${thresholdPct}%`;
|
|
458
|
+
}
|
|
454
459
|
break;
|
|
455
460
|
case 3:
|
|
456
461
|
isValid = false;
|
|
@@ -485,11 +490,14 @@ async function handleFailedVerification(ctx, session, config, matchedCount, requ
|
|
|
485
490
|
groupName = guild.name || groupName;
|
|
486
491
|
} catch (error) {
|
|
487
492
|
}
|
|
493
|
+
const requestId = session.event?.requestId || session.messageId || "";
|
|
494
|
+
await ctx.database.remove("group_verification_pending", { groupId: guildId, userId });
|
|
488
495
|
await ctx.database.create("group_verification_pending", {
|
|
489
496
|
groupId: guildId,
|
|
490
497
|
userId,
|
|
491
498
|
userName: username,
|
|
492
499
|
requestMessage: message,
|
|
500
|
+
requestId,
|
|
493
501
|
applyTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
494
502
|
});
|
|
495
503
|
if (!config.reminderEnabled || !config.reminderMessage || config.reminderMessage === "") {
|
|
@@ -507,10 +515,18 @@ async function handleFailedVerification(ctx, session, config, matchedCount, requ
|
|
|
507
515
|
await session.bot.broadcast([target], reminderMsg);
|
|
508
516
|
} catch (err) {
|
|
509
517
|
logger.warn("bot.broadcast failed, fallback to ctx.broadcast", err);
|
|
510
|
-
|
|
518
|
+
if (typeof ctx.broadcast === "function") {
|
|
519
|
+
await ctx.broadcast([target], reminderMsg);
|
|
520
|
+
} else {
|
|
521
|
+
logger.info("ctx.broadcast 不可用,跳过发送");
|
|
522
|
+
}
|
|
511
523
|
}
|
|
512
524
|
} else {
|
|
513
|
-
|
|
525
|
+
if (typeof ctx.broadcast === "function") {
|
|
526
|
+
await ctx.broadcast([target], reminderMsg);
|
|
527
|
+
} else {
|
|
528
|
+
logger.info("ctx.broadcast 不可用,跳过发送");
|
|
529
|
+
}
|
|
514
530
|
}
|
|
515
531
|
}
|
|
516
532
|
__name(handleFailedVerification, "handleFailedVerification");
|
|
@@ -556,12 +572,18 @@ function apply(ctx, config) {
|
|
|
556
572
|
userId: "string",
|
|
557
573
|
userName: "string",
|
|
558
574
|
requestMessage: "string",
|
|
575
|
+
// store the raw requestId if provided by OneBot event; used for approving/rejecting
|
|
576
|
+
requestId: "string",
|
|
559
577
|
// record full timestamp as string to keep time component
|
|
560
578
|
applyTime: "string"
|
|
561
579
|
}, {
|
|
562
580
|
primary: "id",
|
|
563
581
|
autoInc: true
|
|
564
582
|
});
|
|
583
|
+
ctx.on("guild-member-request", async (session) => {
|
|
584
|
+
logger.info("收到 guild-member-request 事件,转发给处理函数");
|
|
585
|
+
await handleGuildMemberRequestEvent(ctx, session);
|
|
586
|
+
});
|
|
565
587
|
ctx.on("guild-member-added", async (session) => {
|
|
566
588
|
const groupId = session.guildId;
|
|
567
589
|
const userId = session.userId;
|
|
@@ -578,8 +600,10 @@ function apply(ctx, config) {
|
|
|
578
600
|
});
|
|
579
601
|
if (pendingRecords.length > 0) {
|
|
580
602
|
await updateStats(ctx, groupId, "autoApproved");
|
|
581
|
-
|
|
582
|
-
|
|
603
|
+
for (const rec of pendingRecords) {
|
|
604
|
+
await ctx.database.remove("group_verification_pending", { id: rec.id });
|
|
605
|
+
}
|
|
606
|
+
logger.info(`用户 ${userId} 通过验证加入群 ${groupId},已清理 ${pendingRecords.length} 条待审核记录,统计已更新`);
|
|
583
607
|
} else {
|
|
584
608
|
await updateStats(ctx, groupId, "manuallyApproved");
|
|
585
609
|
logger.info(`用户 ${userId} 被手动邀请加入群 ${groupId},手动批准统计已更新`);
|
|
@@ -894,7 +918,7 @@ ${debugInfo}`];
|
|
|
894
918
|
const methodMap = { 0: "全部同意", 1: "按数量", 2: "按比例", 3: "全部拒绝" };
|
|
895
919
|
feedbackMessage += `审核方式: ${methodMap[reviewMethod]}
|
|
896
920
|
`;
|
|
897
|
-
if (
|
|
921
|
+
if (reviewMethod === 1 || reviewMethod === 2) {
|
|
898
922
|
const thresholdDisplay = reviewMethod === 2 ? `${reviewParameters}%` : reviewParameters.toString();
|
|
899
923
|
feedbackMessage += `阈值: ${thresholdDisplay}
|
|
900
924
|
`;
|
|
@@ -956,7 +980,11 @@ ${debugInfo}`];
|
|
|
956
980
|
let approvedCount = 0;
|
|
957
981
|
for (const request2 of pendingRequests2) {
|
|
958
982
|
try {
|
|
983
|
+
if (request2.requestId) {
|
|
984
|
+
await session.bot.handleGuildMemberRequest(request2.requestId, true);
|
|
985
|
+
}
|
|
959
986
|
await ctx.database.remove("group_verification_pending", { id: request2.id });
|
|
987
|
+
await updateStats(ctx, groupId, "manuallyApproved");
|
|
960
988
|
approvedCount++;
|
|
961
989
|
} catch (error) {
|
|
962
990
|
logger.warn(`处理申请 ${request2.id} 时出错:`, error);
|
|
@@ -964,21 +992,25 @@ ${debugInfo}`];
|
|
|
964
992
|
}
|
|
965
993
|
return `已处理 ${approvedCount} 个加群申请`;
|
|
966
994
|
} else {
|
|
967
|
-
|
|
968
|
-
if (
|
|
995
|
+
let pending = await ctx.database.get("group_verification_pending", { groupId }, ["id", "userId", "userName", "applyTime"]);
|
|
996
|
+
if (pending.length === 0) {
|
|
969
997
|
return "当前无待审核的加群申请";
|
|
970
998
|
}
|
|
971
|
-
|
|
999
|
+
pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)));
|
|
1000
|
+
const request2 = pending[0];
|
|
972
1001
|
try {
|
|
973
|
-
|
|
974
|
-
|
|
1002
|
+
if (request2.requestId) {
|
|
1003
|
+
await session.bot.handleGuildMemberRequest(request2.requestId, true);
|
|
1004
|
+
}
|
|
1005
|
+
await ctx.database.remove("group_verification_pending", { groupId, userId: request2.userId });
|
|
1006
|
+
await updateStats(ctx, groupId, "manuallyApproved");
|
|
975
1007
|
return `已同意用户 ${request2.userName}(${request2.userId}) 的加群申请`;
|
|
976
1008
|
} catch (error) {
|
|
977
1009
|
return `处理申请时出错: ${error.message}`;
|
|
978
1010
|
}
|
|
979
1011
|
}
|
|
980
1012
|
}
|
|
981
|
-
|
|
1013
|
+
let pendingRequests = await ctx.database.get("group_verification_pending", {
|
|
982
1014
|
groupId,
|
|
983
1015
|
userId
|
|
984
1016
|
});
|
|
@@ -987,8 +1019,11 @@ ${debugInfo}`];
|
|
|
987
1019
|
}
|
|
988
1020
|
const request = pendingRequests[0];
|
|
989
1021
|
try {
|
|
990
|
-
|
|
991
|
-
|
|
1022
|
+
if (request.requestId) {
|
|
1023
|
+
await session.bot.handleGuildMemberRequest(request.requestId, true);
|
|
1024
|
+
}
|
|
1025
|
+
await ctx.database.remove("group_verification_pending", { groupId, userId });
|
|
1026
|
+
await updateStats(ctx, groupId, "manuallyApproved");
|
|
992
1027
|
return `已同意用户 ${request.userName}(${userId}) 的加群申请`;
|
|
993
1028
|
} catch (error) {
|
|
994
1029
|
return `处理申请时出错: ${error.message}`;
|
|
@@ -1020,6 +1055,9 @@ ${debugInfo}`];
|
|
|
1020
1055
|
let rejectedCount = 0;
|
|
1021
1056
|
for (const request2 of pendingRequests2) {
|
|
1022
1057
|
try {
|
|
1058
|
+
if (request2.requestId) {
|
|
1059
|
+
await session.bot.handleGuildMemberRequest(request2.requestId, false);
|
|
1060
|
+
}
|
|
1023
1061
|
await ctx.database.remove("group_verification_pending", { id: request2.id });
|
|
1024
1062
|
await updateStats(ctx, groupId, "rejected");
|
|
1025
1063
|
rejectedCount++;
|
|
@@ -1029,13 +1067,17 @@ ${debugInfo}`];
|
|
|
1029
1067
|
}
|
|
1030
1068
|
return `已拒绝 ${rejectedCount} 个加群申请`;
|
|
1031
1069
|
} else {
|
|
1032
|
-
|
|
1033
|
-
if (
|
|
1070
|
+
let pending = await ctx.database.get("group_verification_pending", { groupId }, ["id", "userId", "userName", "applyTime"]);
|
|
1071
|
+
if (pending.length === 0) {
|
|
1034
1072
|
return "当前无待审核的加群申请";
|
|
1035
1073
|
}
|
|
1036
|
-
|
|
1074
|
+
pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)));
|
|
1075
|
+
const request2 = pending[0];
|
|
1037
1076
|
try {
|
|
1038
|
-
|
|
1077
|
+
if (request2.requestId) {
|
|
1078
|
+
await session.bot.handleGuildMemberRequest(request2.requestId, false);
|
|
1079
|
+
}
|
|
1080
|
+
await ctx.database.remove("group_verification_pending", { groupId, userId: request2.userId });
|
|
1039
1081
|
await updateStats(ctx, groupId, "rejected");
|
|
1040
1082
|
return `已拒绝用户 ${request2.userName}(${request2.userId}) 的加群申请`;
|
|
1041
1083
|
} catch (error) {
|
|
@@ -1052,7 +1094,10 @@ ${debugInfo}`];
|
|
|
1052
1094
|
}
|
|
1053
1095
|
const request = pendingRequests[0];
|
|
1054
1096
|
try {
|
|
1055
|
-
|
|
1097
|
+
if (request.requestId) {
|
|
1098
|
+
await session.bot.handleGuildMemberRequest(request.requestId, false);
|
|
1099
|
+
}
|
|
1100
|
+
await ctx.database.remove("group_verification_pending", { groupId, userId });
|
|
1056
1101
|
await updateStats(ctx, groupId, "rejected");
|
|
1057
1102
|
return `已拒绝用户 ${request.userName}(${userId}) 的加群申请`;
|
|
1058
1103
|
} catch (error) {
|
|
@@ -1207,6 +1252,7 @@ ${debugInfo}`];
|
|
|
1207
1252
|
for (const p of pendings) {
|
|
1208
1253
|
const updates = {};
|
|
1209
1254
|
if (p.applyTime instanceof Date) updates.applyTime = p.applyTime.toISOString();
|
|
1255
|
+
if (p.requestId === void 0) updates.requestId = "";
|
|
1210
1256
|
if (Object.keys(updates).length) {
|
|
1211
1257
|
await ctx.database.set("group_verification_pending", { id: p.id }, updates);
|
|
1212
1258
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -46,6 +46,8 @@ export interface PendingVerification {
|
|
|
46
46
|
userId: string
|
|
47
47
|
userName: string
|
|
48
48
|
requestMessage: string
|
|
49
|
+
// raw OneBot requestId (may be empty string)
|
|
50
|
+
requestId?: string
|
|
49
51
|
applyTime: string | Date
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -581,14 +583,24 @@ export async function verifyApplication(config: GroupVerificationConfig, message
|
|
|
581
583
|
requiredThreshold = 'null'
|
|
582
584
|
break
|
|
583
585
|
case 1: // 按数量同意
|
|
584
|
-
|
|
585
|
-
|
|
586
|
+
{
|
|
587
|
+
// threshold may legitimately be 0 (表示全部同意)
|
|
588
|
+
const thresholdNum = config.reviewParameters !== undefined && config.reviewParameters !== null
|
|
589
|
+
? config.reviewParameters
|
|
590
|
+
: 0
|
|
591
|
+
isValid = matchedCount >= thresholdNum
|
|
592
|
+
requiredThreshold = `${thresholdNum}`
|
|
593
|
+
}
|
|
586
594
|
break
|
|
587
595
|
case 2: // 按比例同意
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
596
|
+
{
|
|
597
|
+
const thresholdPct = config.reviewParameters !== undefined && config.reviewParameters !== null
|
|
598
|
+
? config.reviewParameters
|
|
599
|
+
: 100
|
|
600
|
+
const ratio = matchedCount / config.keywords.length
|
|
601
|
+
isValid = ratio >= thresholdPct / 100
|
|
602
|
+
requiredThreshold = `${thresholdPct}%`
|
|
603
|
+
}
|
|
592
604
|
break
|
|
593
605
|
case 3: // 全部拒绝
|
|
594
606
|
isValid = false
|
|
@@ -637,12 +649,19 @@ export async function handleFailedVerification(
|
|
|
637
649
|
// 无法获取群名称时使用默认值
|
|
638
650
|
}
|
|
639
651
|
|
|
652
|
+
// extract requestId if available (OneBot event attaches it)
|
|
653
|
+
const requestId = ((session.event as any)?.requestId) || session.messageId || ''
|
|
654
|
+
|
|
655
|
+
// 删除同一用户在该群之前的所有待审核记录,保留最新一个
|
|
656
|
+
await ctx.database.remove('group_verification_pending', { groupId: guildId, userId })
|
|
657
|
+
|
|
640
658
|
// 将申请加入待审核列表
|
|
641
659
|
await ctx.database.create('group_verification_pending', {
|
|
642
660
|
groupId: guildId,
|
|
643
661
|
userId: userId,
|
|
644
662
|
userName: username,
|
|
645
663
|
requestMessage: message,
|
|
664
|
+
requestId,
|
|
646
665
|
applyTime: new Date().toISOString()
|
|
647
666
|
})
|
|
648
667
|
// 如果提醒消息被禁用,直接返回
|
|
@@ -676,10 +695,18 @@ export async function handleFailedVerification(
|
|
|
676
695
|
} catch (err) {
|
|
677
696
|
// fallback to ctx.broadcast if bot.broadcast fails for some reason
|
|
678
697
|
logger.warn('bot.broadcast failed, fallback to ctx.broadcast', err)
|
|
679
|
-
|
|
698
|
+
if (typeof (ctx.broadcast) === 'function') {
|
|
699
|
+
await (ctx.broadcast as any)([target], reminderMsg)
|
|
700
|
+
} else {
|
|
701
|
+
logger.info('ctx.broadcast 不可用,跳过发送')
|
|
702
|
+
}
|
|
680
703
|
}
|
|
681
704
|
} else {
|
|
682
|
-
|
|
705
|
+
if (typeof (ctx.broadcast) === 'function') {
|
|
706
|
+
await (ctx.broadcast as any)([target], reminderMsg)
|
|
707
|
+
} else {
|
|
708
|
+
logger.info('ctx.broadcast 不可用,跳过发送')
|
|
709
|
+
}
|
|
683
710
|
}
|
|
684
711
|
}
|
|
685
712
|
|
|
@@ -728,21 +755,30 @@ export function apply(ctx: Context, config: Config) {
|
|
|
728
755
|
autoInc: true
|
|
729
756
|
})
|
|
730
757
|
|
|
758
|
+
// cast schema to any to avoid type conflicts when adding new fields
|
|
731
759
|
ctx.model.extend('group_verification_pending', {
|
|
732
760
|
id: 'unsigned',
|
|
733
761
|
groupId: 'string',
|
|
734
762
|
userId: 'string',
|
|
735
763
|
userName: 'string',
|
|
736
764
|
requestMessage: 'string',
|
|
765
|
+
// store the raw requestId if provided by OneBot event; used for approving/rejecting
|
|
766
|
+
requestId: 'string',
|
|
737
767
|
// record full timestamp as string to keep time component
|
|
738
768
|
applyTime: 'string'
|
|
739
|
-
}, {
|
|
769
|
+
} as any, {
|
|
740
770
|
primary: 'id',
|
|
741
771
|
autoInc: true
|
|
742
772
|
})
|
|
743
773
|
|
|
744
774
|
|
|
745
775
|
|
|
776
|
+
// 监听 guild-member-request 事件,以便对新申请执行自动审批或拒绝
|
|
777
|
+
ctx.on('guild-member-request', async (session) => {
|
|
778
|
+
logger.info('收到 guild-member-request 事件,转发给处理函数')
|
|
779
|
+
await handleGuildMemberRequestEvent(ctx, session)
|
|
780
|
+
})
|
|
781
|
+
|
|
746
782
|
// 监听群成员增加事件(包括手动邀请入群)
|
|
747
783
|
ctx.on('guild-member-added', async (session) => {
|
|
748
784
|
const groupId = session.guildId
|
|
@@ -766,9 +802,11 @@ export function apply(ctx: Context, config: Config) {
|
|
|
766
802
|
if (pendingRecords.length > 0) {
|
|
767
803
|
// 通过验证的用户入群,更新统计
|
|
768
804
|
await updateStats(ctx, groupId, 'autoApproved')
|
|
769
|
-
//
|
|
770
|
-
|
|
771
|
-
|
|
805
|
+
// 清除所有该用户的待审核记录
|
|
806
|
+
for (const rec of pendingRecords) {
|
|
807
|
+
await ctx.database.remove('group_verification_pending', { id: rec.id })
|
|
808
|
+
}
|
|
809
|
+
logger.info(`用户 ${userId} 通过验证加入群 ${groupId},已清理 ${pendingRecords.length} 条待审核记录,统计已更新`)
|
|
772
810
|
} else {
|
|
773
811
|
// 手动邀请入群,记录到手动批准统计
|
|
774
812
|
await updateStats(ctx, groupId, 'manuallyApproved')
|
|
@@ -1206,7 +1244,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1206
1244
|
const methodMap = {0: '全部同意', 1: '按数量', 2: '按比例', 3: '全部拒绝'}
|
|
1207
1245
|
feedbackMessage += `审核方式: ${methodMap[reviewMethod]}\n`
|
|
1208
1246
|
|
|
1209
|
-
|
|
1247
|
+
// 显示阈值(即便为 0)
|
|
1248
|
+
if (reviewMethod === 1 || reviewMethod === 2) {
|
|
1210
1249
|
const thresholdDisplay = reviewMethod === 2 ? `${reviewParameters}%` : reviewParameters.toString()
|
|
1211
1250
|
feedbackMessage += `阈值: ${thresholdDisplay}\n`
|
|
1212
1251
|
}
|
|
@@ -1269,7 +1308,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1269
1308
|
if (configs.length > 0 && configs[0].reviewMethod === 3) {
|
|
1270
1309
|
return '该群已设为全部拒绝,无法手动同意任何申请'
|
|
1271
1310
|
}
|
|
1272
|
-
// 处理默认情况和all情况
|
|
1311
|
+
// 处理默认情况和 all 情况
|
|
1273
1312
|
if (!userId || userId.toLowerCase() === 'all') {
|
|
1274
1313
|
if (userId?.toLowerCase() === 'all') {
|
|
1275
1314
|
// 处理所有待审核申请
|
|
@@ -1281,9 +1320,11 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1281
1320
|
let approvedCount = 0
|
|
1282
1321
|
for (const request of pendingRequests) {
|
|
1283
1322
|
try {
|
|
1284
|
-
|
|
1285
|
-
|
|
1323
|
+
if (request.requestId) {
|
|
1324
|
+
await session.bot.handleGuildMemberRequest(request.requestId, true)
|
|
1325
|
+
}
|
|
1286
1326
|
await ctx.database.remove('group_verification_pending', { id: request.id })
|
|
1327
|
+
await updateStats(ctx, groupId, 'manuallyApproved')
|
|
1287
1328
|
approvedCount++
|
|
1288
1329
|
} catch (error) {
|
|
1289
1330
|
logger.warn(`处理申请 ${request.id} 时出错:`, error)
|
|
@@ -1292,17 +1333,20 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1292
1333
|
|
|
1293
1334
|
return `已处理 ${approvedCount} 个加群申请`
|
|
1294
1335
|
} else {
|
|
1295
|
-
//
|
|
1296
|
-
|
|
1297
|
-
if (
|
|
1336
|
+
// 处理最近的一个申请(按时间降序)
|
|
1337
|
+
let pending: any[] = await ctx.database.get('group_verification_pending', { groupId }, ['id', 'userId', 'userName', 'applyTime'])
|
|
1338
|
+
if (pending.length === 0) {
|
|
1298
1339
|
return '当前无待审核的加群申请'
|
|
1299
1340
|
}
|
|
1300
|
-
|
|
1301
|
-
const request =
|
|
1341
|
+
pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)))
|
|
1342
|
+
const request: any = pending[0]
|
|
1302
1343
|
try {
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1344
|
+
if (request.requestId) {
|
|
1345
|
+
await session.bot.handleGuildMemberRequest(request.requestId, true)
|
|
1346
|
+
}
|
|
1347
|
+
// 清除该用户的所有待审核记录
|
|
1348
|
+
await ctx.database.remove('group_verification_pending', { groupId, userId: request.userId })
|
|
1349
|
+
await updateStats(ctx, groupId, 'manuallyApproved')
|
|
1306
1350
|
return `已同意用户 ${request.userName}(${request.userId}) 的加群申请`
|
|
1307
1351
|
} catch (error) {
|
|
1308
1352
|
return `处理申请时出错: ${error.message}`
|
|
@@ -1311,7 +1355,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1311
1355
|
}
|
|
1312
1356
|
|
|
1313
1357
|
// 处理指定用户ID的情况
|
|
1314
|
-
|
|
1358
|
+
let pendingRequests = await ctx.database.get('group_verification_pending', {
|
|
1315
1359
|
groupId,
|
|
1316
1360
|
userId: userId
|
|
1317
1361
|
})
|
|
@@ -1322,9 +1366,12 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1322
1366
|
|
|
1323
1367
|
const request = pendingRequests[0]
|
|
1324
1368
|
try {
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1369
|
+
if (request.requestId) {
|
|
1370
|
+
await session.bot.handleGuildMemberRequest(request.requestId, true)
|
|
1371
|
+
}
|
|
1372
|
+
// 删除该用户的所有记录
|
|
1373
|
+
await ctx.database.remove('group_verification_pending', { groupId, userId })
|
|
1374
|
+
await updateStats(ctx, groupId, 'manuallyApproved')
|
|
1328
1375
|
return `已同意用户 ${request.userName}(${userId}) 的加群申请`
|
|
1329
1376
|
} catch (error) {
|
|
1330
1377
|
return `处理申请时出错: ${error.message}`
|
|
@@ -1351,7 +1398,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1351
1398
|
return '请在群聊中使用此命令'
|
|
1352
1399
|
}
|
|
1353
1400
|
|
|
1354
|
-
// 处理默认情况和all情况
|
|
1401
|
+
// 处理默认情况和 all 情况
|
|
1355
1402
|
if (!userId || userId.toLowerCase() === 'all') {
|
|
1356
1403
|
if (userId?.toLowerCase() === 'all') {
|
|
1357
1404
|
// 拒绝所有待审核申请
|
|
@@ -1363,8 +1410,9 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1363
1410
|
let rejectedCount = 0
|
|
1364
1411
|
for (const request of pendingRequests) {
|
|
1365
1412
|
try {
|
|
1366
|
-
|
|
1367
|
-
|
|
1413
|
+
if (request.requestId) {
|
|
1414
|
+
await session.bot.handleGuildMemberRequest(request.requestId, false)
|
|
1415
|
+
}
|
|
1368
1416
|
await ctx.database.remove('group_verification_pending', { id: request.id })
|
|
1369
1417
|
await updateStats(ctx, groupId, 'rejected')
|
|
1370
1418
|
rejectedCount++
|
|
@@ -1375,17 +1423,19 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1375
1423
|
|
|
1376
1424
|
return `已拒绝 ${rejectedCount} 个加群申请`
|
|
1377
1425
|
} else {
|
|
1378
|
-
//
|
|
1379
|
-
|
|
1380
|
-
if (
|
|
1426
|
+
// 拒绝最近的一个申请(按 applyTime 降序)
|
|
1427
|
+
let pending: any[] = await ctx.database.get('group_verification_pending', { groupId }, ['id', 'userId', 'userName', 'applyTime'])
|
|
1428
|
+
if (pending.length === 0) {
|
|
1381
1429
|
return '当前无待审核的加群申请'
|
|
1382
1430
|
}
|
|
1383
|
-
|
|
1384
|
-
const request =
|
|
1431
|
+
pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)))
|
|
1432
|
+
const request: any = pending[0]
|
|
1385
1433
|
try {
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1434
|
+
if (request.requestId) {
|
|
1435
|
+
await session.bot.handleGuildMemberRequest(request.requestId, false)
|
|
1436
|
+
}
|
|
1437
|
+
// 删除该用户的所有记录
|
|
1438
|
+
await ctx.database.remove('group_verification_pending', { groupId, userId: request.userId })
|
|
1389
1439
|
await updateStats(ctx, groupId, 'rejected')
|
|
1390
1440
|
return `已拒绝用户 ${request.userName}(${request.userId}) 的加群申请`
|
|
1391
1441
|
} catch (error) {
|
|
@@ -1406,9 +1456,11 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1406
1456
|
|
|
1407
1457
|
const request = pendingRequests[0]
|
|
1408
1458
|
try {
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1459
|
+
if (request.requestId) {
|
|
1460
|
+
await session.bot.handleGuildMemberRequest(request.requestId, false)
|
|
1461
|
+
}
|
|
1462
|
+
// 删除该用户的所有记录
|
|
1463
|
+
await ctx.database.remove('group_verification_pending', { groupId, userId })
|
|
1412
1464
|
await updateStats(ctx, groupId, 'rejected')
|
|
1413
1465
|
return `已拒绝用户 ${request.userName}(${userId}) 的加群申请`
|
|
1414
1466
|
} catch (error) {
|
|
@@ -1593,6 +1645,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1593
1645
|
for (const p of pendings) {
|
|
1594
1646
|
const updates: any = {}
|
|
1595
1647
|
if (p.applyTime instanceof Date) updates.applyTime = p.applyTime.toISOString()
|
|
1648
|
+
// add default empty requestId if record pre-dates the new column
|
|
1649
|
+
if (p.requestId === undefined) updates.requestId = ''
|
|
1596
1650
|
if (Object.keys(updates).length) {
|
|
1597
1651
|
await ctx.database.set('group_verification_pending', { id: p.id }, updates)
|
|
1598
1652
|
}
|