koishi-plugin-group-verification 1.0.17 → 1.0.19

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
@@ -95,4 +95,9 @@ export declare function mergeReminder(existingConfig: any | null, cleanedOptions
95
95
  * 若检测到格式错误(如纯空格分隔关键词),返回 error 字段。
96
96
  */
97
97
  export declare function parseConfigArgs(raw: string): ParsedArgs;
98
+ export declare function verifyApplication(config: GroupVerificationConfig, message: string, session: any): Promise<{
99
+ isValid: boolean;
100
+ matchedCount: number;
101
+ requiredThreshold: string;
102
+ }>;
98
103
  export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -26,11 +26,13 @@ __export(src_exports, {
26
26
  mergeReminder: () => mergeReminder,
27
27
  name: () => name,
28
28
  parseConfigArgs: () => parseConfigArgs,
29
- tokenize: () => tokenize
29
+ tokenize: () => tokenize,
30
+ verifyApplication: () => verifyApplication
30
31
  });
31
32
  module.exports = __toCommonJS(src_exports);
32
33
  var import_koishi = require("koishi");
33
34
  var name = "group-verification";
35
+ var logger = console;
34
36
  var Config = import_koishi.Schema.object({
35
37
  defaultReminderMessage: import_koishi.Schema.string().description("默认提醒消息模板").default("{user}({id}) 申请加入群 {gname}({group})\n申请理由:{question}\n匹配情况:{answer}/{threshold}"),
36
38
  enableStrictGroupCheck: import_koishi.Schema.boolean().description("是否启用严格的群号检查(检查群号长度)").default(false),
@@ -140,7 +142,7 @@ function validateKeywordFormat(raw) {
140
142
  return true;
141
143
  }
142
144
  __name(validateKeywordFormat, "validateKeywordFormat");
143
- function mergeReminder(existingConfig, cleanedOptions, hasRealMessageParam, hasRealEnableMessageParam, hasRealDisableMessageParam, logger) {
145
+ function mergeReminder(existingConfig, cleanedOptions, hasRealMessageParam, hasRealEnableMessageParam, hasRealDisableMessageParam, logger2) {
144
146
  let reminderEnabled = true;
145
147
  let reminderMessage = "{user}({id}) 申请加入群 {gname}({group})\n申请理由:{question}\n匹配情况:{answer}/{threshold}";
146
148
  if (existingConfig) {
@@ -149,15 +151,15 @@ function mergeReminder(existingConfig, cleanedOptions, hasRealMessageParam, hasR
149
151
  }
150
152
  if (hasRealDisableMessageParam) {
151
153
  reminderEnabled = false;
152
- logger.info("禁用提醒消息功能 (保留现有内容)");
154
+ logger2.info("禁用提醒消息功能 (保留现有内容)");
153
155
  } else if (hasRealEnableMessageParam) {
154
156
  reminderEnabled = true;
155
- logger.info(`启用提醒消息(保留原消息): ${reminderMessage.substring(0, 50)}...`);
157
+ logger2.info(`启用提醒消息(保留原消息): ${reminderMessage.substring(0, 50)}...`);
156
158
  } else if (hasRealMessageParam) {
157
159
  reminderEnabled = true;
158
160
  if (cleanedOptions.message !== void 0) {
159
161
  reminderMessage = cleanedOptions.message.replace(/\\n/g, "\n");
160
- logger.info(`设置自定义提醒消息: ${reminderMessage.substring(0, 50)}...`);
162
+ logger2.info(`设置自定义提醒消息: ${reminderMessage.substring(0, 50)}...`);
161
163
  }
162
164
  }
163
165
  return { reminderEnabled, reminderMessage };
@@ -247,6 +249,44 @@ function parseConfigArgs(raw) {
247
249
  return { keywords, flags, error };
248
250
  }
249
251
  __name(parseConfigArgs, "parseConfigArgs");
252
+ async function verifyApplication(config, message, session) {
253
+ const lowered = message.toLowerCase();
254
+ const matched = /* @__PURE__ */ new Set();
255
+ for (const keyword of config.keywords) {
256
+ if (lowered.includes(keyword.toLowerCase())) {
257
+ matched.add(keyword);
258
+ }
259
+ }
260
+ const matchedCount = matched.size;
261
+ let isValid = false;
262
+ let requiredThreshold = "";
263
+ switch (config.reviewMethod) {
264
+ case 0:
265
+ isValid = true;
266
+ requiredThreshold = "null";
267
+ break;
268
+ case 1:
269
+ isValid = matchedCount >= (config.reviewParameters || 1);
270
+ requiredThreshold = `${config.reviewParameters || 1}`;
271
+ break;
272
+ case 2:
273
+ const ratio = matchedCount / config.keywords.length;
274
+ const requiredRatio = (config.reviewParameters || 100) / 100;
275
+ isValid = ratio >= requiredRatio;
276
+ requiredThreshold = `${config.reviewParameters || 100}%`;
277
+ break;
278
+ case 3:
279
+ isValid = false;
280
+ requiredThreshold = "null";
281
+ break;
282
+ default:
283
+ isValid = false;
284
+ requiredThreshold = "null";
285
+ }
286
+ logger.info(`verifyApplication msg="${message}" keywords=${JSON.stringify(config.keywords)} matched=${matchedCount} threshold=${requiredThreshold} valid=${isValid}`);
287
+ return { isValid, matchedCount, requiredThreshold };
288
+ }
289
+ __name(verifyApplication, "verifyApplication");
250
290
  function apply(ctx, config) {
251
291
  ctx.model.extend("group_verification_config", {
252
292
  id: "unsigned",
@@ -265,7 +305,7 @@ function apply(ctx, config) {
265
305
  primary: "id",
266
306
  autoInc: true
267
307
  });
268
- const logger = ctx.logger("group-verification");
308
+ logger = ctx.logger("group-verification");
269
309
  logger.info("群组验证插件已启动");
270
310
  logger.info(`默认提醒消息: ${config.defaultReminderMessage}`);
271
311
  logger.info(`严格群号检查: ${config.enableStrictGroupCheck ? "启用" : "禁用"}`);
@@ -292,10 +332,17 @@ function apply(ctx, config) {
292
332
  primary: "id",
293
333
  autoInc: true
294
334
  });
335
+ const autoQueue = /* @__PURE__ */ new Map();
295
336
  ctx.on("guild-member-request", async (session) => {
296
- const guildId = session.guildId;
337
+ logger.debug("guild-member-request event", session);
338
+ let guildId = (session.guildId || session.channelId || "").toString().trim();
297
339
  const userId = session.userId;
298
340
  const message = session.content || "";
341
+ if (!guildId) {
342
+ logger.warn("guild-member-request 没有 guildId,跳过处理");
343
+ return;
344
+ }
345
+ const requestId = session.event?.requestId || session.messageId || "";
299
346
  const groupConfig = await ctx.database.get("group_verification_config", {
300
347
  groupId: guildId
301
348
  });
@@ -304,8 +351,18 @@ function apply(ctx, config) {
304
351
  }
305
352
  const config2 = groupConfig[0];
306
353
  const { isValid, matchedCount, requiredThreshold } = await verifyApplication(config2, message, session);
354
+ logger.info(`验证结果 guild=${guildId} user=${userId} msg="${message}" matched=${matchedCount} threshold=${requiredThreshold} valid=${isValid}`);
307
355
  if (isValid) {
308
- await updateStats(guildId, "autoApproved");
356
+ if (requestId) {
357
+ try {
358
+ await session.bot.handleGuildMemberRequest(requestId, true);
359
+ logger.info(`自动同意 requestId=${requestId}`);
360
+ if (!autoQueue.has(guildId)) autoQueue.set(guildId, /* @__PURE__ */ new Set());
361
+ autoQueue.get(guildId).add(userId);
362
+ } catch (e) {
363
+ logger.warn("自动同意失败", e);
364
+ }
365
+ }
309
366
  } else {
310
367
  await handleFailedVerification(ctx, session, config2);
311
368
  }
@@ -313,6 +370,13 @@ function apply(ctx, config) {
313
370
  ctx.on("guild-member-added", async (session) => {
314
371
  const groupId = session.guildId;
315
372
  const userId = session.userId;
373
+ const set = autoQueue.get(groupId);
374
+ if (set && set.has(userId)) {
375
+ await updateStats(groupId, "autoApproved");
376
+ set.delete(userId);
377
+ logger.info(`用户 ${userId} 通过机器人审批加入群 ${groupId}(autoQueue),统计已更新`);
378
+ return;
379
+ }
316
380
  const pendingRecords = await ctx.database.get("group_verification_pending", {
317
381
  groupId,
318
382
  userId
@@ -345,6 +409,10 @@ function apply(ctx, config) {
345
409
  requestMessage: message,
346
410
  applyTime: /* @__PURE__ */ new Date()
347
411
  });
412
+ if (!guildId) {
413
+ logger.warn("handleFailedVerification 收到无效 guildId,已放弃发送");
414
+ return;
415
+ }
348
416
  if (!config2.reminderEnabled || !config2.reminderMessage || config2.reminderMessage === "") {
349
417
  logger.info(`群 ${guildId} 的提醒消息已被禁用,跳过发送`);
350
418
  return;
@@ -354,38 +422,6 @@ function apply(ctx, config) {
354
422
  await ctx2.broadcast([guildId], reminderMsg);
355
423
  }
356
424
  __name(handleFailedVerification, "handleFailedVerification");
357
- async function verifyApplication(config2, message, session) {
358
- const matchedCount = config2.keywords.filter(
359
- (keyword) => message.toLowerCase().includes(keyword.toLowerCase())
360
- ).length;
361
- let isValid = false;
362
- let requiredThreshold = "";
363
- switch (config2.reviewMethod) {
364
- case 0:
365
- isValid = true;
366
- requiredThreshold = "null";
367
- break;
368
- case 1:
369
- isValid = matchedCount >= (config2.reviewParameters || 1);
370
- requiredThreshold = `${config2.reviewParameters || 1}`;
371
- break;
372
- case 2:
373
- const ratio = matchedCount / config2.keywords.length;
374
- const requiredRatio = (config2.reviewParameters || 100) / 100;
375
- isValid = ratio >= requiredRatio;
376
- requiredThreshold = `${config2.reviewParameters || 100}%`;
377
- break;
378
- case 3:
379
- isValid = false;
380
- requiredThreshold = "null";
381
- break;
382
- default:
383
- isValid = false;
384
- requiredThreshold = "null";
385
- }
386
- return { isValid, matchedCount, requiredThreshold };
387
- }
388
- __name(verifyApplication, "verifyApplication");
389
425
  async function updateStats(groupId, action) {
390
426
  const existingStats = await ctx.database.get("group_verification_stats", { groupId });
391
427
  if (existingStats.length > 0) {
@@ -777,7 +813,8 @@ gvc -r # 删除配置`;
777
813
  for (const request2 of pendingRequests2) {
778
814
  try {
779
815
  await ctx.database.remove("group_verification_pending", { id: request2.id });
780
- await updateStats(groupId, "manuallyApproved");
816
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, /* @__PURE__ */ new Set());
817
+ autoQueue.get(groupId).add(request2.userId);
781
818
  approvedCount++;
782
819
  } catch (error) {
783
820
  logger.warn(`处理申请 ${request2.id} 时出错:`, error);
@@ -793,7 +830,8 @@ gvc -r # 删除配置`;
793
830
  try {
794
831
  await session.bot.handleGuildMemberRequest(request2.userId, true);
795
832
  await ctx.database.remove("group_verification_pending", { id: request2.id });
796
- await updateStats(groupId, "manuallyApproved");
833
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, /* @__PURE__ */ new Set());
834
+ autoQueue.get(groupId).add(request2.userId);
797
835
  return `已同意用户 ${request2.userName}(${request2.userId}) 的加群申请`;
798
836
  } catch (error) {
799
837
  return `处理申请时出错: ${error.message}`;
@@ -811,7 +849,8 @@ gvc -r # 删除配置`;
811
849
  try {
812
850
  await session.bot.handleGuildMemberRequest(request.userId, true);
813
851
  await ctx.database.remove("group_verification_pending", { id: request.id });
814
- await updateStats(groupId, "manuallyApproved");
852
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, /* @__PURE__ */ new Set());
853
+ autoQueue.get(groupId).add(userId);
815
854
  return `已同意用户 ${request.userName}(${userId}) 的加群申请`;
816
855
  } catch (error) {
817
856
  return `处理申请时出错: ${error.message}`;
@@ -1083,5 +1122,6 @@ __name(apply, "apply");
1083
1122
  mergeReminder,
1084
1123
  name,
1085
1124
  parseConfigArgs,
1086
- tokenize
1125
+ tokenize,
1126
+ verifyApplication
1087
1127
  });
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.17",
4
+ "version": "1.0.19",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/src/index.ts CHANGED
@@ -2,6 +2,9 @@ import { Context, Schema, Session } from 'koishi'
2
2
 
3
3
  export const name = 'group-verification'
4
4
 
5
+ // 模块级日志器,测试时使用 console
6
+ let logger: any = console
7
+
5
8
  // 数据库模型定义
6
9
  declare module 'koishi' {
7
10
  interface Tables {
@@ -358,6 +361,50 @@ export function parseConfigArgs(raw: string): ParsedArgs {
358
361
 
359
362
  return { keywords, flags, error };
360
363
  }
364
+
365
+ // 验证申请(提取到外层,供测试调用)
366
+ export async function verifyApplication(config: GroupVerificationConfig, message: string, session: any): Promise<{isValid: boolean, matchedCount: number, requiredThreshold: string}> {
367
+ // 统计匹配的关键词数量(允许相互重叠)
368
+ const lowered = message.toLowerCase()
369
+ const matched = new Set<string>()
370
+ for (const keyword of config.keywords) {
371
+ if (lowered.includes(keyword.toLowerCase())) {
372
+ matched.add(keyword)
373
+ }
374
+ }
375
+ const matchedCount = matched.size
376
+
377
+ let isValid = false
378
+ let requiredThreshold = ''
379
+
380
+ switch (config.reviewMethod) {
381
+ case 0: // 全部同意
382
+ isValid = true
383
+ requiredThreshold = 'null'
384
+ break
385
+ case 1: // 按数量同意
386
+ isValid = matchedCount >= (config.reviewParameters || 1)
387
+ requiredThreshold = `${config.reviewParameters || 1}`
388
+ break
389
+ case 2: // 按比例同意
390
+ const ratio = matchedCount / config.keywords.length
391
+ const requiredRatio = (config.reviewParameters || 100) / 100
392
+ isValid = ratio >= requiredRatio
393
+ requiredThreshold = `${config.reviewParameters || 100}%`
394
+ break
395
+ case 3: // 全部拒绝
396
+ isValid = false
397
+ requiredThreshold = 'null'
398
+ break
399
+ default:
400
+ isValid = false
401
+ requiredThreshold = 'null'
402
+ }
403
+
404
+ logger.info(`verifyApplication msg="${message}" keywords=${JSON.stringify(config.keywords)} matched=${matchedCount} threshold=${requiredThreshold} valid=${isValid}`)
405
+ return { isValid, matchedCount, requiredThreshold }
406
+ }
407
+
361
408
  export function apply(ctx: Context, config: Config) {
362
409
  // 创建数据库表
363
410
  ctx.model.extend('group_verification_config', {
@@ -377,8 +424,8 @@ export function apply(ctx: Context, config: Config) {
377
424
  autoInc: true
378
425
  })
379
426
 
380
- // 获取logger实例
381
- const logger = ctx.logger('group-verification')
427
+ // 获取logger实例并保存到模块级变量
428
+ logger = ctx.logger('group-verification')
382
429
 
383
430
  // 设置日志级别
384
431
  // 注意:Koishi logger的level设置可能需要不同的方式
@@ -413,52 +460,78 @@ export function apply(ctx: Context, config: Config) {
413
460
  autoInc: true
414
461
  })
415
462
 
463
+ // 缓存正在审批的用户,用于避免 guild-member-added 重复计数
464
+ const autoQueue = new Map<string, Set<string>>();
465
+
416
466
  // 监听加群申请事件
417
467
  ctx.on('guild-member-request', async (session) => {
418
- const guildId = session.guildId
419
- const userId = session.userId
420
- const message = session.content || ''
421
-
468
+ // debug: 输出整个 session 以便定位字段名
469
+ logger.debug('guild-member-request event', session)
470
+
471
+ let guildId = (session.guildId || session.channelId || '').toString().trim();
472
+ const userId = session.userId;
473
+ const message = session.content || '';
474
+
475
+ if (!guildId) {
476
+ logger.warn('guild-member-request 没有 guildId,跳过处理');
477
+ return;
478
+ }
479
+
480
+ // 获取 requestId(不同平台字段不同)
481
+ const requestId = ((session.event as any)?.requestId) || session.messageId || '';
482
+
422
483
  // 获取群组配置
423
484
  const groupConfig = await ctx.database.get('group_verification_config', {
424
485
  groupId: guildId
425
- })
426
-
486
+ });
487
+
427
488
  if (!groupConfig || groupConfig.length === 0) {
428
- // 如果没有配置,默认同意
429
- // 在实际使用中需要传入正确的requestId
430
- // await session.bot.handleGuildMemberRequest(requestId, true)
431
- return
489
+ // 无配置直接放行(需要有 requestId)
490
+ return;
432
491
  }
433
-
434
- const config = groupConfig[0]
435
-
436
- // 执行验证
437
- const { isValid, matchedCount, requiredThreshold } = await verifyApplication(config, message, session)
438
-
492
+ const config = groupConfig[0];
493
+
494
+ // 执行验证,记录详细情况
495
+ const { isValid, matchedCount, requiredThreshold } = await verifyApplication(config, message, session);
496
+ logger.info(`验证结果 guild=${guildId} user=${userId} msg="${message}" matched=${matchedCount} threshold=${requiredThreshold} valid=${isValid}`);
497
+
439
498
  if (isValid) {
440
- // 验证成功,自动同意入群
441
- // 在实际使用中需要传入正确的requestId
442
- // await session.bot.handleGuildMemberRequest(requestId, true)
443
- // 更新统计信息
444
- await updateStats(guildId, 'autoApproved')
499
+ if (requestId) {
500
+ try {
501
+ await session.bot.handleGuildMemberRequest(requestId, true);
502
+ logger.info(`自动同意 requestId=${requestId}`);
503
+ // 将此用户标记为自动批准,等待 guild-member-added 更新统计
504
+ if (!autoQueue.has(guildId)) autoQueue.set(guildId, new Set());
505
+ autoQueue.get(guildId)!.add(userId);
506
+ } catch (e) {
507
+ logger.warn('自动同意失败', e);
508
+ }
509
+ }
445
510
  } else {
446
- // 验证失败,发送提醒到群内
447
- await handleFailedVerification(ctx, session, config)
511
+ await handleFailedVerification(ctx, session, config);
448
512
  }
449
- })
513
+ });
450
514
 
451
515
  // 监听群成员增加事件(包括手动邀请入群)
452
516
  ctx.on('guild-member-added', async (session) => {
453
517
  const groupId = session.guildId
454
518
  const userId = session.userId
455
-
519
+
520
+ // 先检查 autoQueue
521
+ const set = autoQueue.get(groupId)
522
+ if (set && set.has(userId)) {
523
+ await updateStats(groupId, 'autoApproved')
524
+ set.delete(userId)
525
+ logger.info(`用户 ${userId} 通过机器人审批加入群 ${groupId}(autoQueue),统计已更新`)
526
+ return
527
+ }
528
+
456
529
  // 检查是否有待审核记录
457
530
  const pendingRecords = await ctx.database.get('group_verification_pending', {
458
531
  groupId: groupId,
459
532
  userId: userId
460
533
  })
461
-
534
+
462
535
  if (pendingRecords.length > 0) {
463
536
  // 通过验证的用户入群,更新统计
464
537
  await updateStats(groupId, 'autoApproved')
@@ -500,6 +573,11 @@ export function apply(ctx: Context, config: Config) {
500
573
  applyTime: new Date()
501
574
  })
502
575
 
576
+ // 如果 guildId 不合法,跳过
577
+ if (!guildId) {
578
+ logger.warn('handleFailedVerification 收到无效 guildId,已放弃发送')
579
+ return
580
+ }
503
581
  // 如果提醒消息被禁用,直接返回
504
582
  if (!config.reminderEnabled || !config.reminderMessage || config.reminderMessage === '') {
505
583
  logger.info(`群 ${guildId} 的提醒消息已被禁用,跳过发送`)
@@ -521,42 +599,6 @@ export function apply(ctx: Context, config: Config) {
521
599
  await ctx.broadcast([guildId], reminderMsg)
522
600
  }
523
601
 
524
- // 验证申请
525
- async function verifyApplication(config: GroupVerificationConfig, message: string, session: any): Promise<{isValid: boolean, matchedCount: number, requiredThreshold: string}> {
526
- // 统计匹配的关键词数量
527
- const matchedCount = config.keywords.filter(keyword =>
528
- message.toLowerCase().includes(keyword.toLowerCase())
529
- ).length
530
-
531
- let isValid = false
532
- let requiredThreshold = ''
533
-
534
- switch (config.reviewMethod) {
535
- case 0: // 全部同意
536
- isValid = true
537
- requiredThreshold = 'null'
538
- break
539
- case 1: // 按数量同意
540
- isValid = matchedCount >= (config.reviewParameters || 1)
541
- requiredThreshold = `${config.reviewParameters || 1}`
542
- break
543
- case 2: // 按比例同意
544
- const ratio = matchedCount / config.keywords.length
545
- const requiredRatio = (config.reviewParameters || 100) / 100
546
- isValid = ratio >= requiredRatio
547
- requiredThreshold = `${config.reviewParameters || 100}%`
548
- break
549
- case 3: // 全部拒绝
550
- isValid = false
551
- requiredThreshold = 'null'
552
- break
553
- default:
554
- isValid = false
555
- requiredThreshold = 'null'
556
- }
557
-
558
- return { isValid, matchedCount, requiredThreshold }
559
- }
560
602
 
561
603
  // 更新统计信息
562
604
  async function updateStats(groupId: string, action: 'autoApproved' | 'manuallyApproved' | 'rejected') {
@@ -1084,7 +1126,9 @@ gvc -r # 删除配置`
1084
1126
  // TODO: 需要获取实际的requestId来进行审批
1085
1127
  // await session.bot.handleGuildMemberRequest(request.requestId, true)
1086
1128
  await ctx.database.remove('group_verification_pending', { id: request.id })
1087
- await updateStats(groupId, 'manuallyApproved')
1129
+ // 标记为自动批准,实际统计在 guild-member-added 处理
1130
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, new Set())
1131
+ autoQueue.get(groupId)!.add(request.userId)
1088
1132
  approvedCount++
1089
1133
  } catch (error) {
1090
1134
  logger.warn(`处理申请 ${request.id} 时出错:`, error)
@@ -1104,7 +1148,8 @@ gvc -r # 删除配置`
1104
1148
  // 这里需要获取实际的requestId,暂时用userId作为示例
1105
1149
  await session.bot.handleGuildMemberRequest(request.userId, true)
1106
1150
  await ctx.database.remove('group_verification_pending', { id: request.id })
1107
- await updateStats(groupId, 'manuallyApproved')
1151
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, new Set())
1152
+ autoQueue.get(groupId)!.add(request.userId)
1108
1153
  return `已同意用户 ${request.userName}(${request.userId}) 的加群申请`
1109
1154
  } catch (error) {
1110
1155
  return `处理申请时出错: ${error.message}`
@@ -1127,7 +1172,8 @@ gvc -r # 删除配置`
1127
1172
  // 这里需要获取实际的requestId来进行审批
1128
1173
  await session.bot.handleGuildMemberRequest(request.userId, true)
1129
1174
  await ctx.database.remove('group_verification_pending', { id: request.id })
1130
- await updateStats(groupId, 'manuallyApproved')
1175
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, new Set())
1176
+ autoQueue.get(groupId)!.add(userId)
1131
1177
  return `已同意用户 ${request.userName}(${userId}) 的加群申请`
1132
1178
  } catch (error) {
1133
1179
  return `处理申请时出错: ${error.message}`