koishi-plugin-group-verification 1.0.18 → 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,6 +332,7 @@ 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
337
  logger.debug("guild-member-request event", session);
297
338
  let guildId = (session.guildId || session.channelId || "").toString().trim();
@@ -302,16 +343,6 @@ function apply(ctx, config) {
302
343
  return;
303
344
  }
304
345
  const requestId = session.event?.requestId || session.messageId || "";
305
- if (requestId) {
306
- try {
307
- await session.bot.handleGuildMemberRequest(requestId, true);
308
- logger.info(`自动同意申请 requestId=${requestId}`);
309
- await updateStats(guildId, "autoApproved");
310
- return;
311
- } catch (e) {
312
- logger.warn("自动同意失败", e);
313
- }
314
- }
315
346
  const groupConfig = await ctx.database.get("group_verification_config", {
316
347
  groupId: guildId
317
348
  });
@@ -320,16 +351,18 @@ function apply(ctx, config) {
320
351
  }
321
352
  const config2 = groupConfig[0];
322
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}`);
323
355
  if (isValid) {
324
356
  if (requestId) {
325
357
  try {
326
358
  await session.bot.handleGuildMemberRequest(requestId, true);
327
- logger.info(`自动同意申请 requestId=${requestId}`);
359
+ logger.info(`自动同意 requestId=${requestId}`);
360
+ if (!autoQueue.has(guildId)) autoQueue.set(guildId, /* @__PURE__ */ new Set());
361
+ autoQueue.get(guildId).add(userId);
328
362
  } catch (e) {
329
363
  logger.warn("自动同意失败", e);
330
364
  }
331
365
  }
332
- await updateStats(guildId, "autoApproved");
333
366
  } else {
334
367
  await handleFailedVerification(ctx, session, config2);
335
368
  }
@@ -337,6 +370,13 @@ function apply(ctx, config) {
337
370
  ctx.on("guild-member-added", async (session) => {
338
371
  const groupId = session.guildId;
339
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
+ }
340
380
  const pendingRecords = await ctx.database.get("group_verification_pending", {
341
381
  groupId,
342
382
  userId
@@ -382,38 +422,6 @@ function apply(ctx, config) {
382
422
  await ctx2.broadcast([guildId], reminderMsg);
383
423
  }
384
424
  __name(handleFailedVerification, "handleFailedVerification");
385
- async function verifyApplication(config2, message, session) {
386
- const matchedCount = config2.keywords.filter(
387
- (keyword) => message.toLowerCase().includes(keyword.toLowerCase())
388
- ).length;
389
- let isValid = false;
390
- let requiredThreshold = "";
391
- switch (config2.reviewMethod) {
392
- case 0:
393
- isValid = true;
394
- requiredThreshold = "null";
395
- break;
396
- case 1:
397
- isValid = matchedCount >= (config2.reviewParameters || 1);
398
- requiredThreshold = `${config2.reviewParameters || 1}`;
399
- break;
400
- case 2:
401
- const ratio = matchedCount / config2.keywords.length;
402
- const requiredRatio = (config2.reviewParameters || 100) / 100;
403
- isValid = ratio >= requiredRatio;
404
- requiredThreshold = `${config2.reviewParameters || 100}%`;
405
- break;
406
- case 3:
407
- isValid = false;
408
- requiredThreshold = "null";
409
- break;
410
- default:
411
- isValid = false;
412
- requiredThreshold = "null";
413
- }
414
- return { isValid, matchedCount, requiredThreshold };
415
- }
416
- __name(verifyApplication, "verifyApplication");
417
425
  async function updateStats(groupId, action) {
418
426
  const existingStats = await ctx.database.get("group_verification_stats", { groupId });
419
427
  if (existingStats.length > 0) {
@@ -805,7 +813,8 @@ gvc -r # 删除配置`;
805
813
  for (const request2 of pendingRequests2) {
806
814
  try {
807
815
  await ctx.database.remove("group_verification_pending", { id: request2.id });
808
- await updateStats(groupId, "manuallyApproved");
816
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, /* @__PURE__ */ new Set());
817
+ autoQueue.get(groupId).add(request2.userId);
809
818
  approvedCount++;
810
819
  } catch (error) {
811
820
  logger.warn(`处理申请 ${request2.id} 时出错:`, error);
@@ -821,7 +830,8 @@ gvc -r # 删除配置`;
821
830
  try {
822
831
  await session.bot.handleGuildMemberRequest(request2.userId, true);
823
832
  await ctx.database.remove("group_verification_pending", { id: request2.id });
824
- await updateStats(groupId, "manuallyApproved");
833
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, /* @__PURE__ */ new Set());
834
+ autoQueue.get(groupId).add(request2.userId);
825
835
  return `已同意用户 ${request2.userName}(${request2.userId}) 的加群申请`;
826
836
  } catch (error) {
827
837
  return `处理申请时出错: ${error.message}`;
@@ -839,7 +849,8 @@ gvc -r # 删除配置`;
839
849
  try {
840
850
  await session.bot.handleGuildMemberRequest(request.userId, true);
841
851
  await ctx.database.remove("group_verification_pending", { id: request.id });
842
- await updateStats(groupId, "manuallyApproved");
852
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, /* @__PURE__ */ new Set());
853
+ autoQueue.get(groupId).add(userId);
843
854
  return `已同意用户 ${request.userName}(${userId}) 的加群申请`;
844
855
  } catch (error) {
845
856
  return `处理申请时出错: ${error.message}`;
@@ -1111,5 +1122,6 @@ __name(apply, "apply");
1111
1122
  mergeReminder,
1112
1123
  name,
1113
1124
  parseConfigArgs,
1114
- tokenize
1125
+ tokenize,
1126
+ verifyApplication
1115
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.18",
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,80 +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
468
  // debug: 输出整个 session 以便定位字段名
419
469
  logger.debug('guild-member-request event', session)
420
470
 
421
- // session.guildId 有时可能带空格或为空,先做 trim 并备选 channelId
422
- let guildId = (session.guildId || session.channelId || '').toString().trim()
423
- const userId = session.userId
424
- const message = session.content || ''
471
+ let guildId = (session.guildId || session.channelId || '').toString().trim();
472
+ const userId = session.userId;
473
+ const message = session.content || '';
425
474
 
426
475
  if (!guildId) {
427
- logger.warn('guild-member-request 没有 guildId,跳过处理')
428
- return
476
+ logger.warn('guild-member-request 没有 guildId,跳过处理');
477
+ return;
429
478
  }
430
479
 
431
- // 尝试自动同意,如 event 中包含 requestId
432
- const requestId = ((session.event as any)?.requestId) || session.messageId || ''
433
- if (requestId) {
434
- try {
435
- await session.bot.handleGuildMemberRequest(requestId, true)
436
- logger.info(`自动同意申请 requestId=${requestId}`)
437
- await updateStats(guildId, 'autoApproved')
438
- // 不再执行后续验证或提醒
439
- return
440
- } catch (e) {
441
- logger.warn('自动同意失败', e)
442
- // 继续下面的验证逻辑
443
- }
444
- }
480
+ // 获取 requestId(不同平台字段不同)
481
+ const requestId = ((session.event as any)?.requestId) || session.messageId || '';
445
482
 
446
483
  // 获取群组配置
447
484
  const groupConfig = await ctx.database.get('group_verification_config', {
448
485
  groupId: guildId
449
- })
486
+ });
450
487
 
451
488
  if (!groupConfig || groupConfig.length === 0) {
452
- // 如果没有配置,默认同意(以上 auto-approve 未触发时仍然需要一个 requestId)
453
- return
489
+ // 无配置直接放行(需要有 requestId)
490
+ return;
454
491
  }
492
+ const config = groupConfig[0];
455
493
 
456
- const config = groupConfig[0]
457
-
458
- // 执行验证
459
- const { isValid, matchedCount, requiredThreshold } = await verifyApplication(config, message, session)
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}`);
460
497
 
461
498
  if (isValid) {
462
- // 验证成功,自动同意入群(同样需要 requestId)
463
499
  if (requestId) {
464
500
  try {
465
- await session.bot.handleGuildMemberRequest(requestId, true)
466
- logger.info(`自动同意申请 requestId=${requestId}`)
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);
467
506
  } catch (e) {
468
- logger.warn('自动同意失败', e)
507
+ logger.warn('自动同意失败', e);
469
508
  }
470
509
  }
471
- // 更新统计信息
472
- await updateStats(guildId, 'autoApproved')
473
510
  } else {
474
- // 验证失败,发送提醒到群内
475
- await handleFailedVerification(ctx, session, config)
511
+ await handleFailedVerification(ctx, session, config);
476
512
  }
477
- })
513
+ });
478
514
 
479
515
  // 监听群成员增加事件(包括手动邀请入群)
480
516
  ctx.on('guild-member-added', async (session) => {
481
517
  const groupId = session.guildId
482
518
  const userId = session.userId
483
-
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
+
484
529
  // 检查是否有待审核记录
485
530
  const pendingRecords = await ctx.database.get('group_verification_pending', {
486
531
  groupId: groupId,
487
532
  userId: userId
488
533
  })
489
-
534
+
490
535
  if (pendingRecords.length > 0) {
491
536
  // 通过验证的用户入群,更新统计
492
537
  await updateStats(groupId, 'autoApproved')
@@ -554,42 +599,6 @@ export function apply(ctx: Context, config: Config) {
554
599
  await ctx.broadcast([guildId], reminderMsg)
555
600
  }
556
601
 
557
- // 验证申请
558
- async function verifyApplication(config: GroupVerificationConfig, message: string, session: any): Promise<{isValid: boolean, matchedCount: number, requiredThreshold: string}> {
559
- // 统计匹配的关键词数量
560
- const matchedCount = config.keywords.filter(keyword =>
561
- message.toLowerCase().includes(keyword.toLowerCase())
562
- ).length
563
-
564
- let isValid = false
565
- let requiredThreshold = ''
566
-
567
- switch (config.reviewMethod) {
568
- case 0: // 全部同意
569
- isValid = true
570
- requiredThreshold = 'null'
571
- break
572
- case 1: // 按数量同意
573
- isValid = matchedCount >= (config.reviewParameters || 1)
574
- requiredThreshold = `${config.reviewParameters || 1}`
575
- break
576
- case 2: // 按比例同意
577
- const ratio = matchedCount / config.keywords.length
578
- const requiredRatio = (config.reviewParameters || 100) / 100
579
- isValid = ratio >= requiredRatio
580
- requiredThreshold = `${config.reviewParameters || 100}%`
581
- break
582
- case 3: // 全部拒绝
583
- isValid = false
584
- requiredThreshold = 'null'
585
- break
586
- default:
587
- isValid = false
588
- requiredThreshold = 'null'
589
- }
590
-
591
- return { isValid, matchedCount, requiredThreshold }
592
- }
593
602
 
594
603
  // 更新统计信息
595
604
  async function updateStats(groupId: string, action: 'autoApproved' | 'manuallyApproved' | 'rejected') {
@@ -1117,7 +1126,9 @@ gvc -r # 删除配置`
1117
1126
  // TODO: 需要获取实际的requestId来进行审批
1118
1127
  // await session.bot.handleGuildMemberRequest(request.requestId, true)
1119
1128
  await ctx.database.remove('group_verification_pending', { id: request.id })
1120
- 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)
1121
1132
  approvedCount++
1122
1133
  } catch (error) {
1123
1134
  logger.warn(`处理申请 ${request.id} 时出错:`, error)
@@ -1137,7 +1148,8 @@ gvc -r # 删除配置`
1137
1148
  // 这里需要获取实际的requestId,暂时用userId作为示例
1138
1149
  await session.bot.handleGuildMemberRequest(request.userId, true)
1139
1150
  await ctx.database.remove('group_verification_pending', { id: request.id })
1140
- await updateStats(groupId, 'manuallyApproved')
1151
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, new Set())
1152
+ autoQueue.get(groupId)!.add(request.userId)
1141
1153
  return `已同意用户 ${request.userName}(${request.userId}) 的加群申请`
1142
1154
  } catch (error) {
1143
1155
  return `处理申请时出错: ${error.message}`
@@ -1160,7 +1172,8 @@ gvc -r # 删除配置`
1160
1172
  // 这里需要获取实际的requestId来进行审批
1161
1173
  await session.bot.handleGuildMemberRequest(request.userId, true)
1162
1174
  await ctx.database.remove('group_verification_pending', { id: request.id })
1163
- await updateStats(groupId, 'manuallyApproved')
1175
+ if (!autoQueue.has(groupId)) autoQueue.set(groupId, new Set())
1176
+ autoQueue.get(groupId)!.add(userId)
1164
1177
  return `已同意用户 ${request.userName}(${userId}) 的加群申请`
1165
1178
  } catch (error) {
1166
1179
  return `处理申请时出错: ${error.message}`