koishi-plugin-bind-bot 2.2.4 → 2.2.5

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.
@@ -175,21 +175,37 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
175
175
  this.logger.debug('入群审批', `[DEBUG] parseUID结果: ${parsedUid ? parsedUid : 'null'}`);
176
176
  if (parsedUid) {
177
177
  buidUid = parsedUid;
178
- // 并行查询官方API和ZMINFO API
179
- const [officialInfo, zminfoData] = await Promise.all([
180
- this.deps.apiService.getBilibiliOfficialUserInfo(parsedUid).catch(() => null),
181
- this.deps.apiService.validateBUID(parsedUid).catch(() => null)
182
- ]);
183
- // 用户名:优先使用官方API(最准确),降级到ZMINFO
184
- if (officialInfo?.name) {
185
- buidUsername = officialInfo.name;
186
- this.logger.debug('入群审批', `✅ 使用官方API用户名: ${buidUsername}`);
187
- }
188
- else if (zminfoData?.username) {
189
- buidUsername = zminfoData.username;
190
- this.logger.debug('入群审批', `⚠️ 官方API失败,使用ZMINFO用户名: ${buidUsername}`);
191
- }
192
- // 粉丝牌信息:只能从ZMINFO获取(官方API不提供)
178
+ // 尝试使用强制绑定模式获取完整信息(避免频率限制)
179
+ let zminfoData = null;
180
+ if (this.config.forceBindSessdata) {
181
+ try {
182
+ this.logger.debug('入群审批', '使用强制绑定模式获取用户信息...');
183
+ const enhancedUser = await this.deps.forceBinder.forceBindUser(parsedUid);
184
+ const standardUser = this.deps.forceBinder.convertToZminfoUser(enhancedUser);
185
+ buidUsername = standardUser.username;
186
+ zminfoData = standardUser;
187
+ this.logger.debug('入群审批', `✅ 强制绑定模式获取成功: ${buidUsername}`);
188
+ }
189
+ catch (error) {
190
+ this.logger.warn('入群审批', `强制绑定获取用户信息失败: ${error.message},降级到ZMINFO`);
191
+ // 降级:使用ZMINFO
192
+ zminfoData = await this.deps.apiService.validateBUID(parsedUid).catch(() => null);
193
+ if (zminfoData) {
194
+ buidUsername = zminfoData.username;
195
+ this.logger.debug('入群审批', `⚠️ 降级到ZMINFO用户名: ${buidUsername}`);
196
+ }
197
+ }
198
+ }
199
+ else {
200
+ // 未配置Cookie,直接使用ZMINFO
201
+ this.logger.debug('入群审批', '未配置强制绑定Cookie,使用ZMINFO获取用户信息...');
202
+ zminfoData = await this.deps.apiService.validateBUID(parsedUid).catch(() => null);
203
+ if (zminfoData) {
204
+ buidUsername = zminfoData.username;
205
+ this.logger.debug('入群审批', `✅ ZMINFO用户名: ${buidUsername}`);
206
+ }
207
+ }
208
+ // 粉丝牌信息:从ZMINFO或强制绑定结果获取
193
209
  if (zminfoData) {
194
210
  const medalLevel = zminfoData.medal?.level || 0;
195
211
  const medalName = zminfoData.medal?.name || '';
@@ -204,7 +220,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
204
220
  }
205
221
  }
206
222
  else {
207
- this.logger.warn('入群审批', 'ZMINFO API查询失败,无法获取粉丝牌信息');
223
+ this.logger.warn('入群审批', 'B站用户信息查询失败,无法获取粉丝牌信息');
208
224
  }
209
225
  // 绑定状态:查询数据库
210
226
  if (buidUsername) {
@@ -222,7 +238,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
222
238
  }
223
239
  }
224
240
  else {
225
- bindStatus = '❌ UID 查询失败(官方API和ZMINFO均失败)';
241
+ bindStatus = '❌ UID 查询失败';
226
242
  }
227
243
  }
228
244
  return { qq, nickname, avatar, answer, buidUid, buidUsername, medalInfo, bindStatus };
@@ -319,17 +335,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
319
335
  */
320
336
  async approveAndAutoBind(pendingReq, operatorId, session) {
321
337
  try {
322
- // 1. 批准入群
323
- await session.bot.handleGuildMemberRequest(pendingReq.requestFlag, true, '欢迎加入!');
324
- this.logger.info('入群审批', `已批准入群 - QQ: ${pendingReq.applicantQQ}`, true);
325
- // 2. 等待用户进群
326
- const joined = await this.waitForUserJoin(pendingReq.applicantQQ, pendingReq.targetGroupId, 10000);
327
- if (!joined) {
328
- await this.notifyAdmin(operatorId, session, `⚠️ 已批准 ${pendingReq.applicantQQ} 入群,但用户未在10秒内进群`);
329
- pendingReq.status = 'approved';
330
- return;
331
- }
332
- // 3. 解析UID
338
+ // 1. 解析UID(在批准入群前先检查)
333
339
  const uid = this.parseUID(pendingReq.answer);
334
340
  if (!uid) {
335
341
  await this.notifyAdmin(operatorId, session, `⚠️ 无法解析UID"${pendingReq.answer}",请手动处理\n申请人: ${pendingReq.applicantQQ}`);
@@ -337,10 +343,19 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
337
343
  return;
338
344
  }
339
345
  this.logger.info('入群审批', `开始自动绑定 - QQ: ${pendingReq.applicantQQ}, UID: ${uid}`);
340
- // 4. 调用 BuidHandler 的绑定逻辑(需要从 handlers 获取)
341
- // 注意:这里需要访问其他 handler,可能需要调整架构
342
- // 暂时先记录日志,稍后实现具体绑定逻辑
346
+ // 2. 先执行绑定(在批准入群前)
343
347
  await this.performAutoBind(pendingReq.applicantQQ, uid, session.bot);
348
+ this.logger.info('入群审批', `预绑定完成 - QQ: ${pendingReq.applicantQQ}, UID: ${uid}`);
349
+ // 3. 批准入群
350
+ await session.bot.handleGuildMemberRequest(pendingReq.requestFlag, true, '欢迎加入!');
351
+ this.logger.info('入群审批', `已批准入群 - QQ: ${pendingReq.applicantQQ}`, true);
352
+ // 4. 等待用户进群
353
+ const joined = await this.waitForUserJoin(pendingReq.applicantQQ, pendingReq.targetGroupId, 10000);
354
+ if (!joined) {
355
+ await this.notifyAdmin(operatorId, session, `⚠️ 已完成绑定并批准 ${pendingReq.applicantQQ} 入群,但用户未在10秒内进群`);
356
+ pendingReq.status = 'approved';
357
+ return;
358
+ }
344
359
  // 5. 通知管理员
345
360
  await this.notifyAdmin(operatorId, session, `✅ 已批准 ${pendingReq.applicantQQ} 入群并完成自动绑定\nUID: ${uid}`);
346
361
  pendingReq.status = 'approved';
@@ -582,34 +597,16 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
582
597
  */
583
598
  async performAutoBind(qq, uid, bot) {
584
599
  try {
585
- // 1. 使用双API数据源获取最新用户信息(优先B站官方API)
600
+ // 1. 使用强制绑定模式获取最新用户信息(避免频率限制)
586
601
  this.logger.debug('入群审批', `开始获取 B站 UID ${uid} 的信息`);
587
- // 尝试获取B站官方API的用户信息(最权威)
588
- let officialUsername = null;
589
- try {
590
- this.logger.debug('入群审批', '正在查询B站官方API...');
591
- const officialInfo = await this.deps.apiService.getBilibiliOfficialUserInfo(uid);
592
- if (officialInfo && officialInfo.name) {
593
- officialUsername = officialInfo.name;
594
- this.logger.info('入群审批', `[官方API] ✅ 获取到用户名: "${officialUsername}"`, true);
595
- }
596
- else {
597
- this.logger.warn('入群审批', '[官方API] ❌ 查询失败');
598
- }
599
- }
600
- catch (officialError) {
601
- this.logger.warn('入群审批', `[官方API] ❌ 查询出错: ${officialError.message}`);
602
- }
603
- // 获取ZMINFO API的完整用户信息(包含粉丝牌、大航海等数据)
604
- this.logger.debug('入群审批', '正在查询ZMINFO API...');
605
- const zminfoUser = await this.deps.apiService.validateBUID(uid);
602
+ // 使用强制绑定模式获取完整信息(与 bind -f 保持一致)
603
+ this.logger.debug('入群审批', '正在使用强制绑定模式获取B站用户信息...');
604
+ const enhancedUser = await this.deps.forceBinder.forceBindUser(uid);
605
+ const zminfoUser = this.deps.forceBinder.convertToZminfoUser(enhancedUser);
606
606
  if (!zminfoUser) {
607
607
  throw new Error(`无法验证B站UID: ${uid}`);
608
608
  }
609
- this.logger.debug('入群审批', `[ZMINFO] 获取到用户名: "${zminfoUser.username}"`);
610
- // 使用官方API的用户名(如果可用),否则使用ZMINFO的
611
- const finalUsername = officialUsername || zminfoUser.username;
612
- this.logger.info('入群审批', `🎯 最终采用用户名: "${finalUsername}"`, true);
609
+ this.logger.info('入群审批', `✅ 获取到用户名: "${zminfoUser.username}"`, true);
613
610
  // 2. 检查是否已被其他人绑定
614
611
  const existingBind = await this.repos.mcidbind.findByBuidUid(uid);
615
612
  if (existingBind && existingBind.qqId !== qq) {
@@ -624,7 +621,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
624
621
  mcUsername: null,
625
622
  mcUuid: null,
626
623
  buidUid: zminfoUser.uid,
627
- buidUsername: finalUsername,
624
+ buidUsername: zminfoUser.username,
628
625
  guardLevel: zminfoUser.guard_level || 0,
629
626
  guardLevelText: zminfoUser.guard_level_text || '',
630
627
  maxGuardLevel: zminfoUser.guard_level || 0,
@@ -643,7 +640,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
643
640
  // 更新现有绑定
644
641
  await this.repos.mcidbind.update(qq, {
645
642
  buidUid: zminfoUser.uid,
646
- buidUsername: finalUsername,
643
+ buidUsername: zminfoUser.username,
647
644
  guardLevel: zminfoUser.guard_level || 0,
648
645
  guardLevelText: zminfoUser.guard_level_text || '',
649
646
  maxGuardLevel: Math.max(bind.maxGuardLevel || 0, zminfoUser.guard_level || 0),
@@ -663,7 +660,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
663
660
  try {
664
661
  const groupId = this.reviewConfig.targetGroupId;
665
662
  const mcInfo = bind_status_1.BindStatus.getDisplayMcUsername(bind, '未绑定');
666
- const nickname = `${finalUsername}(ID:${mcInfo})`;
663
+ const nickname = `${zminfoUser.username}(ID:${mcInfo})`;
667
664
  await bot.internal.setGroupCard(groupId, qq, nickname);
668
665
  this.logger.info('入群审批', `已更新群昵称 - QQ: ${qq}, 昵称: ${nickname}`);
669
666
  }
@@ -671,7 +668,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
671
668
  this.logger.warn('入群审批', `更新群昵称失败: ${error.message}`);
672
669
  // 昵称更新失败不影响绑定
673
670
  }
674
- this.logger.info('入群审批', `自动绑定完成 - QQ: ${qq}, UID: ${uid}, 用户名: ${finalUsername}`, true);
671
+ this.logger.info('入群审批', `自动绑定完成 - QQ: ${qq}, UID: ${uid}, 用户名: ${zminfoUser.username}`, true);
675
672
  }
676
673
  catch (error) {
677
674
  this.logger.error('入群审批', `自动绑定失败: ${error.message}`, error);
package/lib/index.js CHANGED
@@ -428,6 +428,18 @@ function apply(ctx, config) {
428
428
  logger.info(`[新人绑定] 用户QQ(${normalizedUserId})加入群聊,准备发送绑定提醒`);
429
429
  // 检查用户是否已有绑定记录
430
430
  const existingBind = await services.database.getMcBindByQQId(normalizedUserId);
431
+ // 检查是否刚刚通过入群审批的自动绑定完成(lastModified 在最近 15 秒内且已绑定 B 站)
432
+ const isRecentAutoBind = existingBind &&
433
+ existingBind.lastModified &&
434
+ Date.now() - new Date(existingBind.lastModified).getTime() < 15000 &&
435
+ bind_status_1.BindStatus.hasValidBuidBind(existingBind);
436
+ if (isRecentAutoBind) {
437
+ // 刚刚完成自动绑定,只发送欢迎消息,不启动交互式绑定
438
+ logger.info(`[新人绑定] 用户QQ(${normalizedUserId})刚刚通过入群审批完成自动绑定,仅发送欢迎消息`);
439
+ const welcomeMessage = `🎉 欢迎 ${koishi_1.h.at(session.userId)} 加入群聊!\n\n✅ 您的B站账号已自动绑定完成\nB站: ${existingBind.buidUsername}\n\n💡 使用 ${formatCommand('mcid bind <用户名>')} 可绑定MC账号`;
440
+ await session.bot.sendMessage(session.channelId, welcomeMessage);
441
+ return;
442
+ }
431
443
  // 如果用户已完成全部绑定,不需要提醒
432
444
  if (bind_status_1.BindStatus.hasCompletedAllBinds(existingBind)) {
433
445
  logger.info(`[新人绑定] 用户QQ(${normalizedUserId})已完成全部绑定,跳过提醒`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-bind-bot",
3
3
  "description": "[WittF自用] BIND-BOT - 账号绑定管理机器人,支持Minecraft账号和B站账号绑定与管理。",
4
- "version": "2.2.4",
4
+ "version": "2.2.5",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [