koishi-plugin-bind-bot 2.3.0 → 2.4.0

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.
@@ -17,10 +17,6 @@ export declare class ForceBinder {
17
17
  * 获取用户的粉丝勋章信息(使用B站API)
18
18
  */
19
19
  private getBilibiliMedals;
20
- /**
21
- * 获取用户的基本信息(使用ZMINFO API)
22
- */
23
- private getZminfoUserInfo;
24
20
  /**
25
21
  * 检查是否拥有目标粉丝牌
26
22
  */
@@ -103,32 +103,6 @@ class ForceBinder {
103
103
  throw error;
104
104
  }
105
105
  }
106
- /**
107
- * 获取用户的基本信息(使用ZMINFO API)
108
- */
109
- async getZminfoUserInfo(uid) {
110
- this.logger.debug('强制绑定', `开始获取用户 ${uid} 的ZMINFO信息`);
111
- try {
112
- const response = await axios_1.default.get(`${this.config.zminfoApiUrl}/api/user/${uid}`, {
113
- timeout: 10000,
114
- headers: {
115
- 'User-Agent': 'Koishi-MCID-Bot/1.0'
116
- }
117
- });
118
- if (response.data.success && response.data.data && response.data.data.user) {
119
- this.logger.debug('强制绑定', `ZMINFO API 用户信息获取成功: ${response.data.data.user.username}`);
120
- return response.data.data.user;
121
- }
122
- else {
123
- this.logger.warn('强制绑定', `ZMINFO API 返回失败: ${response.data.message}`);
124
- return null;
125
- }
126
- }
127
- catch (error) {
128
- this.logger.error('强制绑定', '获取ZMINFO用户信息失败', error);
129
- throw new Error(`无法获取用户信息: ${error.message}`);
130
- }
131
- }
132
106
  /**
133
107
  * 检查是否拥有目标粉丝牌
134
108
  */
@@ -37,7 +37,7 @@ export declare class BuidHandler extends BaseHandler {
37
37
  */
38
38
  private parseUidInput;
39
39
  /**
40
- * 验证B站UID
40
+ * 验证B站UID(通过Supabase events表查询)
41
41
  */
42
42
  private validateBUID;
43
43
  /**
@@ -46,12 +46,9 @@ export declare class BuidHandler extends BaseHandler {
46
46
  private checkBuidExists;
47
47
  /**
48
48
  * 创建或更新B站账号绑定
49
+ * 只写入 buidUid 和 buidUsername,详细字段由数据库触发器填充
49
50
  */
50
51
  private createOrUpdateBuidBind;
51
- /**
52
- * 仅更新B站信息,不更新绑定时间
53
- */
54
- private updateBuidInfoOnly;
55
52
  /**
56
53
  * 检查是否为管理员
57
54
  */
@@ -1,12 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.BuidHandler = void 0;
7
4
  const koishi_1 = require("koishi");
8
5
  const base_handler_1 = require("./base.handler");
9
- const axios_1 = __importDefault(require("axios"));
10
6
  const bind_status_1 = require("../utils/bind-status");
11
7
  const helpers_1 = require("../utils/helpers");
12
8
  /**
@@ -66,16 +62,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
66
62
  : `您尚未绑定B站账号,请使用 ${this.deps.formatCommand('buid bind <UID>')} 进行绑定`)
67
63
  ]);
68
64
  }
69
- // 每次查询都必须从API获取最新数据
70
- const buidUser = await this.validateBUID(bind.buidUid);
71
- if (!buidUser) {
72
- return this.deps.sendMessage(session, [
73
- koishi_1.h.text(`无法从API获取B站UID ${bind.buidUid} 的最新数据,该用户可能不存在或API服务暂时不可用`)
74
- ]);
75
- }
76
- // 更新本地数据库中的信息
77
- await this.updateBuidInfoOnly(bind.qqId, buidUser);
78
- bind = await this.repos.mcidbind.findByQQId(bind.qqId);
65
+ // 直接从数据库读取(数据由触发器自动刷新)
79
66
  const userInfo = `${target ? `用户 ${bind.qqId} 的` : '您的'}B站账号信息:\nB站UID: ${bind.buidUid}\n用户名: ${bind.buidUsername}`;
80
67
  let detailInfo = '';
81
68
  if (bind.guardLevel > 0) {
@@ -301,39 +288,10 @@ class BuidHandler extends base_handler_1.BaseHandler {
301
288
  return actualUid;
302
289
  }
303
290
  /**
304
- * 验证B站UID
291
+ * 验证B站UID(通过Supabase events表查询)
305
292
  */
306
293
  async validateBUID(buid) {
307
- try {
308
- if (!buid || !/^\d+$/.test(buid)) {
309
- this.logger.warn('B站账号验证', `无效的B站UID格式: ${buid}`);
310
- return null;
311
- }
312
- this.logger.debug('B站账号验证', `验证B站UID: ${buid}`);
313
- const response = await axios_1.default.get(`${this.config.zminfoApiUrl}/api/user/${buid}`, {
314
- timeout: 10000,
315
- headers: {
316
- 'User-Agent': 'Koishi-MCID-Bot/1.0'
317
- }
318
- });
319
- if (response.data.success && response.data.data && response.data.data.user) {
320
- const user = response.data.data.user;
321
- this.logger.debug('B站账号验证', `B站UID ${buid} 验证成功: ${user.username}`);
322
- return user;
323
- }
324
- else {
325
- this.logger.warn('B站账号验证', `B站UID ${buid} 不存在或API返回失败: ${response.data.message}`);
326
- return null;
327
- }
328
- }
329
- catch (error) {
330
- if (error.response?.status === 404) {
331
- this.logger.warn('B站账号验证', `B站UID ${buid} 不存在`);
332
- return null;
333
- }
334
- this.logger.error('B站账号验证', 'system', `验证B站UID ${buid} 时出错: ${error.message}`);
335
- throw new Error(`无法验证B站UID: ${error.message}`);
336
- }
294
+ return this.repos.mcidbind.validateBuidUid(buid);
337
295
  }
338
296
  /**
339
297
  * 检查B站UID是否已被其他用户绑定
@@ -356,6 +314,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
356
314
  }
357
315
  /**
358
316
  * 创建或更新B站账号绑定
317
+ * 只写入 buidUid 和 buidUsername,详细字段由数据库触发器填充
359
318
  */
360
319
  async createOrUpdateBuidBind(userId, buidUser) {
361
320
  try {
@@ -374,14 +333,6 @@ class BuidHandler extends base_handler_1.BaseHandler {
374
333
  const updateData = {
375
334
  buidUid: buidUser.uid,
376
335
  buidUsername: buidUser.username,
377
- guardLevel: buidUser.guard_level || 0,
378
- maxGuardLevel: buidUser.max_guard_level || 0,
379
- medalName: buidUser.medal?.name || '',
380
- medalLevel: buidUser.medal?.level || 0,
381
- wealthMedalLevel: buidUser.wealthMedalLevel || 0,
382
- lastActiveTime: buidUser.last_active_time
383
- ? new Date(buidUser.last_active_time)
384
- : new Date(),
385
336
  lastModified: new Date()
386
337
  };
387
338
  if (bind) {
@@ -412,39 +363,6 @@ class BuidHandler extends base_handler_1.BaseHandler {
412
363
  return false;
413
364
  }
414
365
  }
415
- /**
416
- * 仅更新B站信息,不更新绑定时间
417
- */
418
- async updateBuidInfoOnly(userId, buidUser) {
419
- try {
420
- const normalizedQQId = this.deps.normalizeQQId(userId);
421
- if (!normalizedQQId) {
422
- this.logger.error('B站账号信息更新', 'system', '更新失败: 无法提取有效的QQ号');
423
- return false;
424
- }
425
- const bind = await this.repos.mcidbind.findByQQId(normalizedQQId);
426
- if (!bind) {
427
- this.logger.warn('B站账号信息更新', `QQ(${normalizedQQId})没有绑定记录,无法更新B站信息`);
428
- return false;
429
- }
430
- const updateData = {
431
- buidUsername: buidUser.username,
432
- guardLevel: buidUser.guard_level || 0,
433
- maxGuardLevel: buidUser.max_guard_level || 0,
434
- medalName: buidUser.medal?.name || '',
435
- medalLevel: buidUser.medal?.level || 0,
436
- wealthMedalLevel: buidUser.wealthMedalLevel || 0,
437
- lastActiveTime: buidUser.last_active_time ? new Date(buidUser.last_active_time) : new Date()
438
- };
439
- await this.repos.mcidbind.update(normalizedQQId, updateData);
440
- this.logger.info('B站账号信息更新', `刷新信息: QQ=${normalizedQQId}, B站UID=${bind.buidUid}, 用户名=${buidUser.username}`);
441
- return true;
442
- }
443
- catch (error) {
444
- this.logger.error('B站账号信息更新', userId, `更新B站账号信息失败: ${error.message}`);
445
- return false;
446
- }
447
- }
448
366
  /**
449
367
  * 检查是否为管理员
450
368
  */
@@ -638,7 +556,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
638
556
  this.logger.warn('绑定', `管理员QQ(${operatorQQId})为QQ(${normalizedTargetId})B站绑定后群昵称设置失败: ${renameError.message}`);
639
557
  }
640
558
  return this.deps.sendMessage(session, [
641
- koishi_1.h.text(`已成功为用户 ${normalizedTargetId} 绑定B站账号\n用户名: ${buidUser.username}\nUID: ${actualUid}\n${buidUser.guard_level > 0 ? `舰长等级: ${buidUser.guard_level_text}\n` : ''}${buidUser.medal ? `粉丝牌: ${buidUser.medal.name} Lv.${buidUser.medal.level}` : ''}`)
559
+ koishi_1.h.text(`已成功为用户 ${normalizedTargetId} 绑定B站账号\n用户名: ${buidUser.username}\nUID: ${actualUid}`)
642
560
  ]);
643
561
  }
644
562
  /**
@@ -702,13 +620,6 @@ class BuidHandler extends base_handler_1.BaseHandler {
702
620
  koishi_1.h.text('成功绑定B站账号!\n'),
703
621
  koishi_1.h.text(`B站UID: ${buidUser.uid}\n`),
704
622
  koishi_1.h.text(`用户名: ${buidUser.username}\n`),
705
- buidUser.guard_level > 0
706
- ? koishi_1.h.text(`舰长等级: ${buidUser.guard_level_text} (${buidUser.guard_level})\n`)
707
- : null,
708
- buidUser.medal
709
- ? koishi_1.h.text(`粉丝牌: ${buidUser.medal.name} Lv.${buidUser.medal.level}\n`)
710
- : null,
711
- buidUser.wealthMedalLevel > 0 ? koishi_1.h.text(`荣耀等级: ${buidUser.wealthMedalLevel}\n`) : null,
712
623
  ...(this.config?.showAvatar
713
624
  ? [koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${buidUser.uid}?size=160`)]
714
625
  : [])
@@ -197,22 +197,22 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
197
197
  this.logger.debug('入群审批', `✅ 强制绑定模式获取成功: ${buidUsername}, 目标粉丝牌: ${targetMedalInfo?.found ? '已找到' : '未找到'}`);
198
198
  }
199
199
  catch (error) {
200
- this.logger.warn('入群审批', `强制绑定获取用户信息失败: ${error.message},降级到ZMINFO`);
201
- // 降级:使用ZMINFO
202
- zminfoData = await this.deps.apiService.validateBUID(parsedUid).catch(() => null);
203
- if (zminfoData) {
204
- buidUsername = zminfoData.username;
205
- this.logger.debug('入群审批', `⚠️ 降级到ZMINFO用户名: ${buidUsername}`);
200
+ this.logger.warn('入群审批', `强制绑定获取用户信息失败: ${error.message},降级到数据库查询`);
201
+ // 降级:使用Supabase events表查询
202
+ const dbResult = await this.repos.mcidbind.validateBuidUid(parsedUid).catch(() => null);
203
+ if (dbResult) {
204
+ buidUsername = dbResult.username;
205
+ this.logger.debug('入群审批', `⚠️ 降级到数据库查询用户名: ${buidUsername}`);
206
206
  }
207
207
  }
208
208
  }
209
209
  else {
210
- // 未配置Cookie,直接使用ZMINFO
211
- this.logger.debug('入群审批', '未配置强制绑定Cookie,使用ZMINFO获取用户信息...');
212
- zminfoData = await this.deps.apiService.validateBUID(parsedUid).catch(() => null);
213
- if (zminfoData) {
214
- buidUsername = zminfoData.username;
215
- this.logger.debug('入群审批', `✅ ZMINFO用户名: ${buidUsername}`);
210
+ // 未配置Cookie,使用Supabase events表查询
211
+ this.logger.debug('入群审批', '未配置强制绑定Cookie,使用数据库查询用户信息...');
212
+ const dbResult = await this.repos.mcidbind.validateBuidUid(parsedUid).catch(() => null);
213
+ if (dbResult) {
214
+ buidUsername = dbResult.username;
215
+ this.logger.debug('入群审批', `✅ 数据库查询用户名: ${buidUsername}`);
216
216
  }
217
217
  }
218
218
  // 粉丝牌信息:优先使用强制绑定获取的目标粉丝牌,其次使用ZMINFO的当前佩戴粉丝牌
@@ -84,34 +84,27 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
84
84
  const targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
85
85
  if (!targetBind || !bind_status_1.BindStatus.hasValidMcBind(targetBind)) {
86
86
  this.logger.info('查询', `QQ(${normalizedTargetId})未绑定MC账号`);
87
- // 检查是否绑定了B
87
+ // 检查是否绑定了B站(直接从数据库读取,数据由触发器自动刷新)
88
88
  if (targetBind && targetBind.buidUid) {
89
- const buidUser = await this.deps.apiService.validateBUID(targetBind.buidUid);
90
- if (buidUser) {
91
- await this.deps.databaseService.updateBuidInfoOnly(targetBind.qqId, buidUser);
92
- const refreshedBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
93
- if (refreshedBind) {
94
- let buidInfo = `该用户尚未绑定MC账号\n\nB站账号信息:\nB站UID: ${refreshedBind.buidUid}\n用户名: ${refreshedBind.buidUsername}`;
95
- if (refreshedBind.guardLevel > 0) {
96
- buidInfo += `\n舰长等级: ${(0, helpers_1.getGuardLevelText)(refreshedBind.guardLevel)} (${refreshedBind.guardLevel})`;
97
- if (refreshedBind.maxGuardLevel > 0 &&
98
- refreshedBind.maxGuardLevel < refreshedBind.guardLevel) {
99
- buidInfo += `\n历史最高: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
100
- }
101
- }
102
- else if (refreshedBind.maxGuardLevel > 0) {
103
- buidInfo += `\n历史舰长: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
104
- }
105
- if (refreshedBind.medalName) {
106
- buidInfo += `\n粉丝牌: ${refreshedBind.medalName} Lv.${refreshedBind.medalLevel}`;
107
- }
108
- const messageElements = [koishi_1.h.text(buidInfo)];
109
- if (this.config.showAvatar) {
110
- messageElements.push(koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${refreshedBind.buidUid}?size=160`));
111
- }
112
- return this.deps.sendMessage(session, messageElements);
89
+ let buidInfo = `该用户尚未绑定MC账号\n\nB站账号信息:\nB站UID: ${targetBind.buidUid}\n用户名: ${targetBind.buidUsername}`;
90
+ if (targetBind.guardLevel > 0) {
91
+ buidInfo += `\n舰长等级: ${(0, helpers_1.getGuardLevelText)(targetBind.guardLevel)} (${targetBind.guardLevel})`;
92
+ if (targetBind.maxGuardLevel > 0 &&
93
+ targetBind.maxGuardLevel < targetBind.guardLevel) {
94
+ buidInfo += `\n历史最高: ${(0, helpers_1.getGuardLevelText)(targetBind.maxGuardLevel)} (${targetBind.maxGuardLevel})`;
113
95
  }
114
96
  }
97
+ else if (targetBind.maxGuardLevel > 0) {
98
+ buidInfo += `\n历史舰长: ${(0, helpers_1.getGuardLevelText)(targetBind.maxGuardLevel)} (${targetBind.maxGuardLevel})`;
99
+ }
100
+ if (targetBind.medalName) {
101
+ buidInfo += `\n粉丝牌: ${targetBind.medalName} Lv.${targetBind.medalLevel}`;
102
+ }
103
+ const messageElements = [koishi_1.h.text(buidInfo)];
104
+ if (this.config.showAvatar) {
105
+ messageElements.push(koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${targetBind.buidUid}?size=160`));
106
+ }
107
+ return this.deps.sendMessage(session, messageElements);
115
108
  }
116
109
  return this.deps.sendMessage(session, [koishi_1.h.text('该用户尚未绑定MC账号')]);
117
110
  }
@@ -124,35 +117,28 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
124
117
  const selfBind = await this.deps.databaseService.getMcBindByQQId(normalizedUserId);
125
118
  if (!selfBind || !bind_status_1.BindStatus.hasValidMcBind(selfBind)) {
126
119
  this.logger.info('查询', `QQ(${normalizedUserId})未绑定MC账号`);
127
- // 检查是否绑定了B
120
+ // 检查是否绑定了B站(直接从数据库读取,数据由触发器自动刷新)
128
121
  if (selfBind && selfBind.buidUid) {
129
- const buidUser = await this.deps.apiService.validateBUID(selfBind.buidUid);
130
- if (buidUser) {
131
- await this.deps.databaseService.updateBuidInfoOnly(selfBind.qqId, buidUser);
132
- const refreshedBind = await this.deps.databaseService.getMcBindByQQId(normalizedUserId);
133
- if (refreshedBind) {
134
- let buidInfo = `您尚未绑定MC账号\n\nB站账号信息:\nB站UID: ${refreshedBind.buidUid}\n用户名: ${refreshedBind.buidUsername}`;
135
- if (refreshedBind.guardLevel > 0) {
136
- buidInfo += `\n舰长等级: ${(0, helpers_1.getGuardLevelText)(refreshedBind.guardLevel)} (${refreshedBind.guardLevel})`;
137
- if (refreshedBind.maxGuardLevel > 0 &&
138
- refreshedBind.maxGuardLevel < refreshedBind.guardLevel) {
139
- buidInfo += `\n历史最高: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
140
- }
141
- }
142
- else if (refreshedBind.maxGuardLevel > 0) {
143
- buidInfo += `\n历史舰长: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
144
- }
145
- if (refreshedBind.medalName) {
146
- buidInfo += `\n粉丝牌: ${refreshedBind.medalName} Lv.${refreshedBind.medalLevel}`;
147
- }
148
- buidInfo += `\n\n💡 您可以使用 ${this.deps.formatCommand('mcid bind <用户名>')} 绑定MC账号`;
149
- const messageElements = [koishi_1.h.text(buidInfo)];
150
- if (this.config.showAvatar) {
151
- messageElements.push(koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${refreshedBind.buidUid}?size=160`));
152
- }
153
- return this.deps.sendMessage(session, messageElements);
122
+ let buidInfo = `您尚未绑定MC账号\n\nB站账号信息:\nB站UID: ${selfBind.buidUid}\n用户名: ${selfBind.buidUsername}`;
123
+ if (selfBind.guardLevel > 0) {
124
+ buidInfo += `\n舰长等级: ${(0, helpers_1.getGuardLevelText)(selfBind.guardLevel)} (${selfBind.guardLevel})`;
125
+ if (selfBind.maxGuardLevel > 0 &&
126
+ selfBind.maxGuardLevel < selfBind.guardLevel) {
127
+ buidInfo += `\n历史最高: ${(0, helpers_1.getGuardLevelText)(selfBind.maxGuardLevel)} (${selfBind.maxGuardLevel})`;
154
128
  }
155
129
  }
130
+ else if (selfBind.maxGuardLevel > 0) {
131
+ buidInfo += `\n历史舰长: ${(0, helpers_1.getGuardLevelText)(selfBind.maxGuardLevel)} (${selfBind.maxGuardLevel})`;
132
+ }
133
+ if (selfBind.medalName) {
134
+ buidInfo += `\n粉丝牌: ${selfBind.medalName} Lv.${selfBind.medalLevel}`;
135
+ }
136
+ buidInfo += `\n\n💡 您可以使用 ${this.deps.formatCommand('mcid bind <用户名>')} 绑定MC账号`;
137
+ const messageElements = [koishi_1.h.text(buidInfo)];
138
+ if (this.config.showAvatar) {
139
+ messageElements.push(koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${selfBind.buidUid}?size=160`));
140
+ }
141
+ return this.deps.sendMessage(session, messageElements);
156
142
  }
157
143
  return this.deps.sendMessage(session, [
158
144
  koishi_1.h.text('您尚未绑定MC账号,请使用 ' +
package/lib/index.js CHANGED
@@ -41,9 +41,6 @@ exports.Config = koishi_1.Schema.object({
41
41
  showMcSkin: koishi_1.Schema.boolean()
42
42
  .description('是否使用MC皮肤渲染图(需要先开启showAvatar)')
43
43
  .default(false),
44
- zminfoApiUrl: koishi_1.Schema.string()
45
- .description('ZMINFO API地址')
46
- .default('https://zminfo-api.wittf.com'),
47
44
  enableLotteryBroadcast: koishi_1.Schema.boolean().description('是否启用天选开奖播报功能').default(false),
48
45
  lotteryTargetGroupId: koishi_1.Schema.string().description('天选开奖播报目标群ID'),
49
46
  lotteryTargetPrivateId: koishi_1.Schema.string().description('天选开奖播报私聊目标ID(格式:private:QQ号)'),
@@ -859,7 +856,6 @@ function apply(ctx, config) {
859
856
  // 创建 ForceBinder 实例
860
857
  const forceBindConfig = {
861
858
  SESSDATA: config.forceBindSessdata,
862
- zminfoApiUrl: config.zminfoApiUrl,
863
859
  targetUpUid: config.forceBindTargetUpUid,
864
860
  targetRoomId: config.forceBindTargetRoomId,
865
861
  targetMedalName: config.forceBindTargetMedalName,
@@ -1479,8 +1475,8 @@ function apply(ctx, config) {
1479
1475
  ]);
1480
1476
  return;
1481
1477
  }
1482
- // 验证UID是否存在
1483
- const buidUser = await services.api.validateBUID(actualUid);
1478
+ // 验证UID是否存在(通过Supabase events表查询)
1479
+ const buidUser = await mcidbindRepo.validateBuidUid(actualUid);
1484
1480
  if (!buidUser) {
1485
1481
  logger.warn(`[交互绑定] QQ(${normalizedUserId})输入的B站UID"${actualUid}"不存在`);
1486
1482
  await sendMessage(session, [
@@ -1517,16 +1513,6 @@ function apply(ctx, config) {
1517
1513
  }
1518
1514
  // 发送完整的绑定成功消息
1519
1515
  const buidInfo = `B站UID: ${buidUser.uid}\n用户名: ${buidUser.username}`;
1520
- let extraInfo = '';
1521
- if (buidUser.guard_level > 0) {
1522
- extraInfo += `\n舰长等级: ${buidUser.guard_level_text} (${buidUser.guard_level})`;
1523
- }
1524
- if (buidUser.medal) {
1525
- extraInfo += `\n粉丝牌: ${buidUser.medal.name} Lv.${buidUser.medal.level}`;
1526
- }
1527
- if (buidUser.wealthMedalLevel > 0) {
1528
- extraInfo += `\n荣耀等级: ${buidUser.wealthMedalLevel}`;
1529
- }
1530
1516
  // 准备完成消息
1531
1517
  const displayMcName = bindingSession.mcUsername || null;
1532
1518
  const mcInfo = displayMcName ? `MC: ${displayMcName}` : 'MC: 未绑定';
@@ -1536,7 +1522,7 @@ function apply(ctx, config) {
1536
1522
  extraTip = `\n\n💡 您可以随时使用 ${formatCommand('mcid bind <用户名>')} 绑定MC账号`;
1537
1523
  }
1538
1524
  await sendMessage(session, [
1539
- koishi_1.h.text(`🎉 绑定完成!\n${mcInfo}\nB站: ${buidUser.username}${extraInfo}${extraTip}`),
1525
+ koishi_1.h.text(`🎉 绑定完成!\n${mcInfo}\nB站: ${buidUser.username}${extraTip}`),
1540
1526
  ...(config?.showAvatar
1541
1527
  ? [koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${buidUser.uid}?size=160`)]
1542
1528
  : [])
@@ -13,6 +13,10 @@ export declare class MCIDBINDRepository {
13
13
  findByMCUsername(mcUsername: string): Promise<MCIDBIND | null>;
14
14
  findByUsernameIgnoreCase(mcUsername: string): Promise<MCIDBIND | null>;
15
15
  findByUuid(mcUuid: string): Promise<MCIDBIND | null>;
16
+ validateBuidUid(uid: string): Promise<{
17
+ uid: string;
18
+ username: string;
19
+ } | null>;
16
20
  findByBuidUid(buidUid: string): Promise<MCIDBIND | null>;
17
21
  findAll(options?: {
18
22
  limit?: number;
@@ -89,6 +89,19 @@ class MCIDBINDRepository {
89
89
  return null;
90
90
  }
91
91
  }
92
+ async validateBuidUid(uid) {
93
+ try {
94
+ this.logger.debug('数据库', `验证B站UID(${uid})是否存在`);
95
+ const rows = await this.supabase.get('events', `uid=eq.${uid}&uname=not.is.null&order=created_at.desc&limit=1&select=uid,uname`);
96
+ if (rows.length === 0)
97
+ return null;
98
+ return { uid: rows[0].uid.toString(), username: rows[0].uname };
99
+ }
100
+ catch (error) {
101
+ this.logger.error('数据库', `验证B站UID(${uid})失败: ${error.message}`);
102
+ return null;
103
+ }
104
+ }
92
105
  async findByBuidUid(buidUid) {
93
106
  try {
94
107
  this.logger.debug('数据库', `查询B站UID(${buidUid})的绑定信息`);
@@ -1,15 +1,14 @@
1
1
  import { LoggerService } from '../utils/logger';
2
- import type { MojangProfile, ZminfoUser } from '../types';
2
+ import type { MojangProfile } from '../types';
3
3
  /**
4
4
  * API 服务层
5
- * 统一管理外部 API 调用(Mojang API、ZMINFO API 等)
5
+ * 统一管理外部 API 调用(Mojang API、Bilibili 官方 API 等)
6
6
  */
7
7
  export declare class ApiService {
8
8
  private logger;
9
9
  private config;
10
10
  private cookieString;
11
11
  constructor(logger: LoggerService, config: {
12
- zminfoApiUrl: string;
13
12
  SESSDATA?: string;
14
13
  });
15
14
  /**
@@ -49,12 +48,6 @@ export declare class ApiService {
49
48
  name: string;
50
49
  mid: number;
51
50
  } | null>;
52
- /**
53
- * 验证 B 站 UID 是否存在
54
- * @param buid B站UID
55
- * @returns ZminfoUser 或 null
56
- */
57
- validateBUID(buid: string): Promise<ZminfoUser | null>;
58
51
  /**
59
52
  * 获取 MC 头图 URL (Crafatar)
60
53
  * @param uuid MC UUID
@@ -7,7 +7,7 @@ exports.ApiService = void 0;
7
7
  const axios_1 = __importDefault(require("axios"));
8
8
  /**
9
9
  * API 服务层
10
- * 统一管理外部 API 调用(Mojang API、ZMINFO API 等)
10
+ * 统一管理外部 API 调用(Mojang API、Bilibili 官方 API 等)
11
11
  */
12
12
  class ApiService {
13
13
  logger;
@@ -260,44 +260,6 @@ class ApiService {
260
260
  return null;
261
261
  }
262
262
  }
263
- // =========== ZMINFO API ===========
264
- /**
265
- * 验证 B 站 UID 是否存在
266
- * @param buid B站UID
267
- * @returns ZminfoUser 或 null
268
- */
269
- async validateBUID(buid) {
270
- try {
271
- if (!buid || !/^\d+$/.test(buid)) {
272
- this.logger.warn('B站账号验证', `无效的B站UID格式: ${buid}`);
273
- return null;
274
- }
275
- this.logger.debug('B站账号验证', `验证B站UID: ${buid}`);
276
- const response = await axios_1.default.get(`${this.config.zminfoApiUrl}/api/user/${buid}`, {
277
- timeout: 10000,
278
- headers: {
279
- 'User-Agent': 'Koishi-MCID-Bot/1.0'
280
- }
281
- });
282
- if (response.data.success && response.data.data && response.data.data.user) {
283
- const user = response.data.data.user;
284
- this.logger.debug('B站账号验证', `B站UID ${buid} 验证成功: ${user.username}`);
285
- return user;
286
- }
287
- else {
288
- this.logger.warn('B站账号验证', `B站UID ${buid} 不存在或API返回失败: ${response.data.message}`);
289
- return null;
290
- }
291
- }
292
- catch (error) {
293
- if (error.response?.status === 404) {
294
- this.logger.warn('B站账号验证', `B站UID ${buid} 不存在`);
295
- return null;
296
- }
297
- this.logger.error('B站账号验证', `验证B站UID ${buid} 时出错: ${error.message}`);
298
- throw new Error(`无法验证B站UID: ${error.message}`);
299
- }
300
- }
301
263
  // =========== 工具方法 ===========
302
264
  /**
303
265
  * 获取 MC 头图 URL (Crafatar)
@@ -1,7 +1,7 @@
1
1
  import { Context } from 'koishi';
2
2
  import { LoggerService } from '../utils/logger';
3
3
  import { MCIDBINDRepository } from '../repositories/mcidbind.repository';
4
- import type { MCIDBIND, ZminfoUser } from '../types';
4
+ import type { MCIDBIND } from '../types';
5
5
  /**
6
6
  * 数据库服务层
7
7
  * 统一管理数据库操作,包括 MC 绑定和 BUID 绑定的 CRUD
@@ -43,12 +43,19 @@ export declare class DatabaseService {
43
43
  checkBuidExists(buid: string, currentUserId?: string): Promise<boolean>;
44
44
  /**
45
45
  * 创建或更新 B 站账号绑定
46
+ * 只写入 buidUid 和 buidUsername,详细字段由数据库触发器填充
46
47
  */
47
- createOrUpdateBuidBind(userId: string, buidUser: ZminfoUser): Promise<boolean>;
48
+ createOrUpdateBuidBind(userId: string, buidUser: {
49
+ uid: string;
50
+ username: string;
51
+ }): Promise<boolean>;
48
52
  /**
49
- * 仅更新 B 站信息,不更新绑定时间(用于查询时刷新数据)
53
+ * 仅更新 B 站用户名,不更新绑定时间(用于昵称同步等场景)
54
+ * 详细字段(guardLevel, medal等)由数据库触发器自动维护
50
55
  */
51
- updateBuidInfoOnly(userId: string, buidUser: ZminfoUser): Promise<boolean>;
56
+ updateBuidInfoOnly(userId: string, buidUser: {
57
+ username: string;
58
+ }): Promise<boolean>;
52
59
  /**
53
60
  * 解绑 B 站账号(只清空 B 站字段,保留 MC 绑定)
54
61
  */
@@ -254,6 +254,7 @@ class DatabaseService {
254
254
  }
255
255
  /**
256
256
  * 创建或更新 B 站账号绑定
257
+ * 只写入 buidUid 和 buidUsername,详细字段由数据库触发器填充
257
258
  */
258
259
  async createOrUpdateBuidBind(userId, buidUser) {
259
260
  try {
@@ -271,16 +272,8 @@ class DatabaseService {
271
272
  // 查询是否已存在绑定记录
272
273
  let bind = await this.getMcBindByQQId(normalizedQQId);
273
274
  const updateData = {
274
- buidUid: buidUser.uid.toString(), // 转换为字符串存储
275
+ buidUid: buidUser.uid.toString(),
275
276
  buidUsername: buidUser.username,
276
- guardLevel: buidUser.guard_level || 0,
277
- maxGuardLevel: buidUser.max_guard_level || 0,
278
- medalName: buidUser.medal?.name || '',
279
- medalLevel: buidUser.medal?.level || 0,
280
- wealthMedalLevel: buidUser.wealthMedalLevel || 0,
281
- lastActiveTime: buidUser.last_active_time
282
- ? new Date(buidUser.last_active_time)
283
- : new Date(),
284
277
  lastModified: new Date()
285
278
  };
286
279
  if (bind) {
@@ -313,7 +306,8 @@ class DatabaseService {
313
306
  }
314
307
  }
315
308
  /**
316
- * 仅更新 B 站信息,不更新绑定时间(用于查询时刷新数据)
309
+ * 仅更新 B 站用户名,不更新绑定时间(用于昵称同步等场景)
310
+ * 详细字段(guardLevel, medal等)由数据库触发器自动维护
317
311
  */
318
312
  async updateBuidInfoOnly(userId, buidUser) {
319
313
  try {
@@ -328,17 +322,9 @@ class DatabaseService {
328
322
  this.logger.warn('B站账号信息更新', `QQ(${normalizedQQId})没有绑定记录,无法更新B站信息`);
329
323
  return false;
330
324
  }
331
- // 仅更新B站相关字段,不更新lastModified
332
- const updateData = {
333
- buidUsername: buidUser.username,
334
- guardLevel: buidUser.guard_level || 0,
335
- maxGuardLevel: buidUser.max_guard_level || 0,
336
- medalName: buidUser.medal?.name || '',
337
- medalLevel: buidUser.medal?.level || 0,
338
- wealthMedalLevel: buidUser.wealthMedalLevel || 0,
339
- lastActiveTime: buidUser.last_active_time ? new Date(buidUser.last_active_time) : new Date()
340
- };
341
- await this.mcidbindRepo.update(normalizedQQId, updateData);
325
+ await this.mcidbindRepo.update(normalizedQQId, {
326
+ buidUsername: buidUser.username
327
+ });
342
328
  this.logger.info('B站账号信息更新', `刷新信息: QQ=${normalizedQQId}, B站UID=${bind.buidUid}, 用户名=${buidUser.username}`, true);
343
329
  return true;
344
330
  }
@@ -1,6 +1,5 @@
1
1
  import { Session } from 'koishi';
2
2
  import { LoggerService } from '../utils/logger';
3
- import type { ZminfoUser } from '../types';
4
3
  /**
5
4
  * 群昵称管理服务
6
5
  * 负责自动设置和验证群昵称
@@ -9,26 +8,27 @@ export declare class NicknameService {
9
8
  private logger;
10
9
  private config;
11
10
  private normalizeQQId;
12
- private validateBUID;
13
11
  private getBilibiliOfficialUserInfo;
14
12
  private updateBuidInfoOnly;
15
13
  constructor(logger: LoggerService, config: {
16
14
  autoNicknameGroupId: string;
17
- }, normalizeQQId: (userId: string) => string, validateBUID: (buid: string) => Promise<ZminfoUser | null>, getBilibiliOfficialUserInfo: (uid: string) => Promise<{
15
+ }, normalizeQQId: (userId: string) => string, getBilibiliOfficialUserInfo: (uid: string) => Promise<{
18
16
  name: string;
19
17
  mid: number;
20
- } | null>, updateBuidInfoOnly: (userId: string, buidUser: ZminfoUser) => Promise<boolean>);
18
+ } | null>, updateBuidInfoOnly: (userId: string, buidUser: {
19
+ username: string;
20
+ }) => Promise<boolean>);
21
21
  /**
22
22
  * 检查群昵称格式是否正确
23
23
  */
24
24
  checkNicknameFormat(nickname: string, buidUsername: string, mcUsername: string | null): boolean;
25
25
  /**
26
- * 使用四层判断逻辑获取最准确的B站用户名
27
- * 优先级:官方API > ZMINFO > 数据库
26
+ * 获取最准确的B站用户名
27
+ * 优先级:官方API > 数据库
28
28
  */
29
29
  private getLatestBuidUsername;
30
30
  /**
31
- * 同步数据库中的B站用户信息
31
+ * 同步数据库中的B站用户名
32
32
  */
33
33
  private syncDatabaseIfNeeded;
34
34
  /**
@@ -10,14 +10,12 @@ class NicknameService {
10
10
  logger;
11
11
  config;
12
12
  normalizeQQId;
13
- validateBUID;
14
13
  getBilibiliOfficialUserInfo;
15
14
  updateBuidInfoOnly;
16
- constructor(logger, config, normalizeQQId, validateBUID, getBilibiliOfficialUserInfo, updateBuidInfoOnly) {
15
+ constructor(logger, config, normalizeQQId, getBilibiliOfficialUserInfo, updateBuidInfoOnly) {
17
16
  this.logger = logger;
18
17
  this.config = config;
19
18
  this.normalizeQQId = normalizeQQId;
20
- this.validateBUID = validateBUID;
21
19
  this.getBilibiliOfficialUserInfo = getBilibiliOfficialUserInfo;
22
20
  this.updateBuidInfoOnly = updateBuidInfoOnly;
23
21
  }
@@ -33,8 +31,8 @@ class NicknameService {
33
31
  return nickname === expectedFormat;
34
32
  }
35
33
  /**
36
- * 使用四层判断逻辑获取最准确的B站用户名
37
- * 优先级:官方API > ZMINFO > 数据库
34
+ * 获取最准确的B站用户名
35
+ * 优先级:官方API > 数据库
38
36
  */
39
37
  async getLatestBuidUsername(buidUid, currentDbUsername) {
40
38
  // 1. 尝试获取B站官方API的用户信息(最权威)
@@ -53,40 +51,16 @@ class NicknameService {
53
51
  catch (officialError) {
54
52
  this.logger.warn('群昵称设置', `[层1-官方API] ❌ 查询出错: ${officialError.message}`);
55
53
  }
56
- // 2. 尝试获取ZMINFO API的用户信息(可能有缓存)
57
- let zminfoUserData = null;
58
- try {
59
- this.logger.debug('群昵称设置', '正在查询ZMINFO API...');
60
- zminfoUserData = await this.validateBUID(buidUid);
61
- if (zminfoUserData && zminfoUserData.username) {
62
- this.logger.debug('群昵称设置', `[层2-ZMINFO] "${zminfoUserData.username}"`);
63
- }
64
- else {
65
- this.logger.warn('群昵称设置', '[层2-ZMINFO] 查询失败');
66
- }
67
- }
68
- catch (zminfoError) {
69
- this.logger.warn('群昵称设置', `[层2-ZMINFO] 查询出错: ${zminfoError.message}`);
70
- }
71
- // 3. 根据优先级返回结果
54
+ // 2. 根据优先级返回结果
72
55
  if (officialUsername) {
73
56
  this.logger.info('群昵称设置', `🎯 采用官方API结果: "${officialUsername}"`, true);
74
57
  return {
75
58
  username: officialUsername,
76
- source: 'official',
77
- zminfoData: zminfoUserData || undefined
78
- };
79
- }
80
- else if (zminfoUserData && zminfoUserData.username) {
81
- this.logger.info('群昵称设置', `⚠️ 官方API不可用,降级使用ZMINFO: "${zminfoUserData.username}"`, true);
82
- return {
83
- username: zminfoUserData.username,
84
- source: 'zminfo',
85
- zminfoData: zminfoUserData
59
+ source: 'official'
86
60
  };
87
61
  }
88
62
  else {
89
- this.logger.warn('群昵称设置', `⚠️ 官方API和ZMINFO都不可用,使用数据库名称: "${currentDbUsername}"`);
63
+ this.logger.warn('群昵称设置', `⚠️ 官方API不可用,使用数据库名称: "${currentDbUsername}"`);
90
64
  return {
91
65
  username: currentDbUsername,
92
66
  source: 'database'
@@ -94,19 +68,14 @@ class NicknameService {
94
68
  }
95
69
  }
96
70
  /**
97
- * 同步数据库中的B站用户信息
71
+ * 同步数据库中的B站用户名
98
72
  */
99
- async syncDatabaseIfNeeded(normalizedUserId, latestUsername, currentDbUsername, zminfoData) {
73
+ async syncDatabaseIfNeeded(normalizedUserId, latestUsername, currentDbUsername) {
100
74
  if (latestUsername === currentDbUsername) {
101
75
  return; // 无需更新
102
76
  }
103
- if (!zminfoData) {
104
- this.logger.debug('群昵称设置', '无ZMINFO数据,跳过数据库同步');
105
- return;
106
- }
107
77
  try {
108
- const updatedData = { ...zminfoData, username: latestUsername };
109
- await this.updateBuidInfoOnly(normalizedUserId, updatedData);
78
+ await this.updateBuidInfoOnly(normalizedUserId, { username: latestUsername });
110
79
  this.logger.info('群昵称设置', `已同步数据库: "${currentDbUsername}" → "${latestUsername}"`, true);
111
80
  }
112
81
  catch (updateError) {
@@ -178,7 +147,7 @@ class NicknameService {
178
147
  const result = await this.getLatestBuidUsername(buidUid, buidUsername);
179
148
  latestBuidUsername = result.username;
180
149
  // 尝试同步数据库
181
- await this.syncDatabaseIfNeeded(normalizedUserId, latestBuidUsername, buidUsername, result.zminfoData);
150
+ await this.syncDatabaseIfNeeded(normalizedUserId, latestBuidUsername, buidUsername);
182
151
  }
183
152
  // 生成目标昵称
184
153
  const targetNickname = `${latestBuidUsername}(ID:${mcInfo})`;
@@ -15,13 +15,12 @@ class ServiceContainer {
15
15
  constructor(ctx, config, logger, mcidbindRepo, normalizeQQId) {
16
16
  // 1. 实例化 API 服务(无依赖)
17
17
  this.api = new api_service_1.ApiService(logger.createChild('API服务'), {
18
- zminfoApiUrl: config.zminfoApiUrl,
19
18
  SESSDATA: config.forceBindSessdata
20
19
  });
21
20
  // 2. 实例化数据库服务(依赖 API 服务)
22
21
  this.database = new database_service_1.DatabaseService(ctx, logger.createChild('数据库服务'), mcidbindRepo, normalizeQQId, (uuid) => this.api.getUsernameByUuid(uuid));
23
22
  // 3. 实例化群昵称服务(依赖 API 和数据库服务)
24
- this.nickname = new nickname_service_1.NicknameService(logger.createChild('群昵称服务'), { autoNicknameGroupId: config.autoNicknameGroupId }, normalizeQQId, (buid) => this.api.validateBUID(buid), (uid) => this.api.getBilibiliOfficialUserInfo(uid), (userId, buidUser) => this.database.updateBuidInfoOnly(userId, buidUser));
23
+ this.nickname = new nickname_service_1.NicknameService(logger.createChild('群昵称服务'), { autoNicknameGroupId: config.autoNicknameGroupId }, normalizeQQId, (uid) => this.api.getBilibiliOfficialUserInfo(uid), (userId, buidUser) => this.database.updateBuidInfoOnly(userId, buidUser));
25
24
  }
26
25
  }
27
26
  exports.ServiceContainer = ServiceContainer;
@@ -35,8 +35,6 @@ export interface Config {
35
35
  showAvatar: boolean;
36
36
  /** 是否显示MC皮肤渲染 */
37
37
  showMcSkin: boolean;
38
- /** ZMINFO API 地址 (用于获取B站用户信息) */
39
- zminfoApiUrl: string;
40
38
  /** 是否启用天选播报功能 */
41
39
  enableLotteryBroadcast: boolean;
42
40
  /** 天选播报目标群ID (为空则不播报到群) */
@@ -116,7 +114,6 @@ export interface ServerConfig {
116
114
  */
117
115
  export interface ForceBindConfig {
118
116
  SESSDATA: string;
119
- zminfoApiUrl: string;
120
117
  targetUpUid: number;
121
118
  targetRoomId: number;
122
119
  targetMedalName: string;
@@ -18,17 +18,13 @@ export declare class MessageUtils {
18
18
  private config;
19
19
  private logger;
20
20
  private getBindingSessionFn;
21
- private validateBUID?;
22
- private updateBuidInfoOnly?;
23
21
  /**
24
22
  * 创建消息工具实例
25
23
  * @param config 消息工具配置
26
24
  * @param logger 日志服务
27
25
  * @param getBindingSessionFn 获取绑定会话的函数
28
- * @param validateBUID 验证B站UID的函数(可选)
29
- * @param updateBuidInfoOnly 更新B站信息的函数(可选)
30
26
  */
31
- constructor(config: MessageUtilsConfig, logger: LoggerService, getBindingSessionFn: (userId: string, channelId: string) => BindingSession | null, validateBUID?: (uid: string) => Promise<any>, updateBuidInfoOnly?: (qqId: string, buidUser: any) => Promise<boolean>);
27
+ constructor(config: MessageUtilsConfig, logger: LoggerService, getBindingSessionFn: (userId: string, channelId: string) => BindingSession | null);
32
28
  /**
33
29
  * 发送消息并处理自动撤回
34
30
  * @param session Koishi Session对象
@@ -11,22 +11,16 @@ class MessageUtils {
11
11
  config;
12
12
  logger;
13
13
  getBindingSessionFn;
14
- validateBUID;
15
- updateBuidInfoOnly;
16
14
  /**
17
15
  * 创建消息工具实例
18
16
  * @param config 消息工具配置
19
17
  * @param logger 日志服务
20
18
  * @param getBindingSessionFn 获取绑定会话的函数
21
- * @param validateBUID 验证B站UID的函数(可选)
22
- * @param updateBuidInfoOnly 更新B站信息的函数(可选)
23
19
  */
24
- constructor(config, logger, getBindingSessionFn, validateBUID, updateBuidInfoOnly) {
20
+ constructor(config, logger, getBindingSessionFn) {
25
21
  this.config = config;
26
22
  this.logger = logger;
27
23
  this.getBindingSessionFn = getBindingSessionFn;
28
- this.validateBUID = validateBUID;
29
- this.updateBuidInfoOnly = updateBuidInfoOnly;
30
24
  }
31
25
  /**
32
26
  * 发送消息并处理自动撤回
@@ -184,68 +178,7 @@ class MessageUtils {
184
178
  this.logger.info('群昵称设置', `QQ(${normalizedUserId})群昵称已经是"${newNickname}",跳过修改`);
185
179
  return;
186
180
  }
187
- // 昵称不一致,先尝试获取最新的B站用户信息
188
- if (buidUid && this.validateBUID && this.updateBuidInfoOnly) {
189
- this.logger.debug('群昵称设置', `检测到昵称不一致,尝试获取B站UID ${buidUid} 的最新信息...`);
190
- // 1. 提取当前群昵称中的B站用户名
191
- const currentNicknameUsername = (0, helpers_1.extractBuidUsernameFromNickname)(currentNickname);
192
- this.logger.debug('群昵称设置', `从当前群昵称"${currentNickname}"中提取到B站名称: ${currentNicknameUsername || '(无法提取)'}`);
193
- try {
194
- const latestBuidUser = await this.validateBUID(buidUid);
195
- if (latestBuidUser && latestBuidUser.username) {
196
- this.logger.debug('群昵称设置', `API返回B站用户名: "${latestBuidUser.username}"`);
197
- // 2. 智能三层判断
198
- // 情况A: API返回 == 当前群昵称中的名称
199
- if (currentNicknameUsername &&
200
- latestBuidUser.username === currentNicknameUsername) {
201
- this.logger.info('群昵称设置', `✅ 当前群昵称"${currentNickname}"已包含正确的B站名称"${currentNicknameUsername}"`);
202
- // 群昵称已经正确,仅需更新数据库(如果数据库是旧的)
203
- if (latestBuidUser.username !== buidUsername) {
204
- this.logger.info('群昵称设置', `数据库中的B站名称需要更新: "${buidUsername}" → "${latestBuidUser.username}"`);
205
- try {
206
- await this.updateBuidInfoOnly(normalizedUserId, latestBuidUser);
207
- this.logger.info('群昵称设置', '已更新数据库中的B站用户名');
208
- }
209
- catch (updateError) {
210
- this.logger.warn('群昵称设置', `更新数据库失败: ${updateError.message}`);
211
- }
212
- }
213
- else {
214
- this.logger.debug('群昵称设置', '数据库中的B站名称已是最新,无需更新');
215
- }
216
- // 跳过群昵称修改
217
- this.logger.info('群昵称设置', '群昵称格式正确且名称最新,跳过修改');
218
- return;
219
- }
220
- // 情况B: API返回 == 数据库(都是旧的)
221
- if (latestBuidUser.username === buidUsername) {
222
- this.logger.warn('群昵称设置', `⚠️ API返回的B站名称"${latestBuidUser.username}"与数据库一致,但与群昵称不符`);
223
- this.logger.warn('群昵称设置', '可能是API缓存未刷新,采用保守策略:不修改群昵称');
224
- return;
225
- }
226
- // 情况C: API返回新数据(!= 群昵称 且 != 数据库)
227
- this.logger.info('群昵称设置', `检测到B站用户名已更新: "${buidUsername}" → "${latestBuidUser.username}"`);
228
- currentBuidUsername = latestBuidUser.username;
229
- // 更新数据库中的B站信息
230
- try {
231
- await this.updateBuidInfoOnly(normalizedUserId, latestBuidUser);
232
- this.logger.info('群昵称设置', `已更新数据库中的B站用户名为: ${currentBuidUsername}`);
233
- }
234
- catch (updateError) {
235
- this.logger.warn('群昵称设置', `更新数据库中的B站用户名失败: ${updateError.message}`);
236
- // 即使更新数据库失败,也继续使用最新的用户名设置昵称
237
- }
238
- }
239
- else {
240
- this.logger.warn('群昵称设置', `获取最新B站用户信息失败,使用数据库中的用户名: ${currentBuidUsername}`);
241
- }
242
- }
243
- catch (validateError) {
244
- this.logger.warn('群昵称设置', `获取最新B站用户信息时出错: ${validateError.message},使用数据库中的用户名: ${currentBuidUsername}`);
245
- // API调用失败时降级处理,使用数据库中的旧名称
246
- }
247
- }
248
- // 使用(可能已更新的)用户名重新生成昵称
181
+ // 使用数据库中的用户名生成昵称(数据由触发器自动刷新)
249
182
  const finalNickname = `${currentBuidUsername}(ID:${mcInfo})`;
250
183
  // 昵称不一致,执行修改
251
184
  this.logger.debug('群昵称设置', `昵称不一致,正在修改群昵称为: "${finalNickname}"`);
@@ -272,39 +205,6 @@ class MessageUtils {
272
205
  this.logger.warn('群昵称设置', `获取QQ(${normalizedUserId})当前群昵称失败: ${getInfoError.message}`);
273
206
  this.logger.warn('群昵称设置', `错误详情: ${JSON.stringify(getInfoError)}`);
274
207
  this.logger.debug('群昵称设置', '将直接尝试设置新昵称...');
275
- // 如果传入了 buidUid,尝试获取最新的B站用户信息
276
- if (buidUid && this.validateBUID && this.updateBuidInfoOnly) {
277
- this.logger.debug('群昵称设置', `尝试获取B站UID ${buidUid} 的最新信息...`);
278
- try {
279
- const latestBuidUser = await this.validateBUID(buidUid);
280
- if (latestBuidUser && latestBuidUser.username) {
281
- this.logger.debug('群昵称设置', `API返回B站用户名: "${latestBuidUser.username}"`);
282
- // 智能判断:API返回 == 数据库(都是旧的)
283
- if (latestBuidUser.username === buidUsername) {
284
- this.logger.warn('群昵称设置', `⚠️ API返回的B站名称"${latestBuidUser.username}"与数据库一致`);
285
- this.logger.warn('群昵称设置', '可能是API缓存未刷新,且无法获取当前群昵称,采用保守策略:跳过修改');
286
- return;
287
- }
288
- // API返回新数据(!= 数据库)
289
- this.logger.info('群昵称设置', `检测到B站用户名已更新: "${buidUsername}" → "${latestBuidUser.username}"`);
290
- currentBuidUsername = latestBuidUser.username;
291
- // 更新数据库
292
- try {
293
- await this.updateBuidInfoOnly(normalizedUserId, latestBuidUser);
294
- this.logger.info('群昵称设置', `已更新数据库中的B站用户名为: ${currentBuidUsername}`);
295
- }
296
- catch (updateError) {
297
- this.logger.warn('群昵称设置', `更新数据库失败: ${updateError.message}`);
298
- }
299
- }
300
- else {
301
- this.logger.warn('群昵称设置', '获取最新B站用户信息失败');
302
- }
303
- }
304
- catch (validateError) {
305
- this.logger.warn('群昵称设置', `获取最新B站用户信息失败: ${validateError.message}`);
306
- }
307
- }
308
208
  try {
309
209
  // 使用(可能已更新的)用户名生成昵称
310
210
  const nicknameToSet = `${currentBuidUsername}(ID:${mcInfo})`;
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.3.0",
4
+ "version": "2.4.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [