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 CHANGED
@@ -34,6 +34,7 @@ export interface PendingVerification {
34
34
  userId: string;
35
35
  userName: string;
36
36
  requestMessage: string;
37
+ requestId?: string;
37
38
  applyTime: string | Date;
38
39
  }
39
40
  export interface Config {
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
- isValid = matchedCount >= (config.reviewParameters || 1);
447
- requiredThreshold = `${config.reviewParameters || 1}`;
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
- const ratio = matchedCount / config.keywords.length;
451
- const requiredRatio = (config.reviewParameters || 100) / 100;
452
- isValid = ratio >= requiredRatio;
453
- requiredThreshold = `${config.reviewParameters || 100}%`;
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
- await ctx.broadcast([target], reminderMsg);
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
- await ctx.broadcast([target], reminderMsg);
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
- await ctx.database.remove("group_verification_pending", { id: pendingRecords[0].id });
582
- logger.info(`用户 ${userId} 通过验证加入群 ${groupId},统计已更新`);
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 (reviewParameters !== 0) {
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
- const recentRequest = await ctx.database.get("group_verification_pending", { groupId }, ["id", "userId", "userName"]);
968
- if (recentRequest.length === 0) {
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
- const request2 = recentRequest[0];
999
+ pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)));
1000
+ const request2 = pending[0];
972
1001
  try {
973
- await session.bot.handleGuildMemberRequest(request2.userId, true);
974
- await ctx.database.remove("group_verification_pending", { id: request2.id });
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
- const pendingRequests = await ctx.database.get("group_verification_pending", {
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
- await session.bot.handleGuildMemberRequest(request.userId, true);
991
- await ctx.database.remove("group_verification_pending", { id: request.id });
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
- const recentRequest = await ctx.database.get("group_verification_pending", { groupId }, ["id", "userId", "userName"]);
1033
- if (recentRequest.length === 0) {
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
- const request2 = recentRequest[0];
1074
+ pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)));
1075
+ const request2 = pending[0];
1037
1076
  try {
1038
- await ctx.database.remove("group_verification_pending", { id: request2.id });
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
- await ctx.database.remove("group_verification_pending", { id: request.id });
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-group-verification",
3
3
  "description": "[WIP] Koishi 群组加群验证插件,支持多关键词匹配审核、多种审核方式和详细统计功能(开发中)",
4
- "version": "1.0.25",
4
+ "version": "1.0.27",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
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
- isValid = matchedCount >= (config.reviewParameters || 1)
585
- requiredThreshold = `${config.reviewParameters || 1}`
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
- const ratio = matchedCount / config.keywords.length
589
- const requiredRatio = (config.reviewParameters || 100) / 100
590
- isValid = ratio >= requiredRatio
591
- requiredThreshold = `${config.reviewParameters || 100}%`
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
- await (ctx.broadcast as any)([target], reminderMsg)
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
- await (ctx.broadcast as any)([target], reminderMsg)
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
- await ctx.database.remove('group_verification_pending', { id: pendingRecords[0].id })
771
- logger.info(`用户 ${userId} 通过验证加入群 ${groupId},统计已更新`)
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
- if (reviewParameters !== 0) {
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
- // TODO: 需要获取实际的requestId来进行审批
1285
- // await session.bot.handleGuildMemberRequest(request.requestId, true)
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
- const recentRequest = await ctx.database.get('group_verification_pending', { groupId }, ['id', 'userId', 'userName'])
1297
- if (recentRequest.length === 0) {
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 = recentRequest[0]
1341
+ pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)))
1342
+ const request: any = pending[0]
1302
1343
  try {
1303
- // 这里需要获取实际的requestId,暂时用userId作为示例
1304
- await session.bot.handleGuildMemberRequest(request.userId, true)
1305
- await ctx.database.remove('group_verification_pending', { id: request.id })
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
- const pendingRequests = await ctx.database.get('group_verification_pending', {
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
- // 这里需要获取实际的requestId来进行审批
1326
- await session.bot.handleGuildMemberRequest(request.userId, true)
1327
- await ctx.database.remove('group_verification_pending', { id: request.id })
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
- // TODO: 需要获取实际的requestId来进行拒绝
1367
- // await session.bot.handleGuildMemberRequest(request.requestId, false)
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
- const recentRequest = await ctx.database.get('group_verification_pending', { groupId }, ['id', 'userId', 'userName'])
1380
- if (recentRequest.length === 0) {
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 = recentRequest[0]
1431
+ pending.sort((a, b) => String(b.applyTime).localeCompare(String(a.applyTime)))
1432
+ const request: any = pending[0]
1385
1433
  try {
1386
- // TODO: 需要获取实际的requestId来进行拒绝
1387
- // await session.bot.handleGuildMemberRequest(request.requestId, false)
1388
- await ctx.database.remove('group_verification_pending', { id: request.id })
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
- // TODO: 需要获取实际的requestId来进行拒绝
1410
- // await session.bot.handleGuildMemberRequest(request.requestId, false)
1411
- await ctx.database.remove('group_verification_pending', { id: request.id })
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
  }