koishi-plugin-bind-bot 2.1.8 → 2.2.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.
@@ -37,6 +37,7 @@ exports.GroupExporter = void 0;
37
37
  const XLSX = __importStar(require("xlsx"));
38
38
  const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
+ const bind_status_1 = require("./utils/bind-status");
40
41
  class GroupExporter {
41
42
  logger;
42
43
  ctx;
@@ -142,8 +143,8 @@ class GroupExporter {
142
143
  // 判断绑定状态
143
144
  let bindingStatus = '未绑定';
144
145
  if (binding) {
145
- const hasMc = binding.mcUsername && !binding.mcUsername.startsWith('_temp_');
146
- const hasBuid = binding.buidUid;
146
+ const hasMc = bind_status_1.BindStatus.hasValidMcBind(binding);
147
+ const hasBuid = bind_status_1.BindStatus.hasValidBuidBind(binding);
147
148
  if (hasMc && hasBuid) {
148
149
  bindingStatus = '完全绑定';
149
150
  }
@@ -164,7 +165,7 @@ class GroupExporter {
164
165
  角色: member.role,
165
166
  加群时间: this.formatTimestamp(member.join_time),
166
167
  最后发言: this.formatTimestamp(member.last_sent_time),
167
- MC用户名: binding?.mcUsername && !binding.mcUsername.startsWith('_temp_') ? binding.mcUsername : '',
168
+ MC用户名: bind_status_1.BindStatus.getDisplayMcUsername(binding, ''),
168
169
  MC_UUID: binding?.mcUuid || '',
169
170
  B站UID: binding?.buidUid || '',
170
171
  B站用户名: binding?.buidUsername || '',
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BindingHandler = void 0;
4
4
  const koishi_1 = require("koishi");
5
5
  const base_handler_1 = require("./base.handler");
6
+ const bind_status_1 = require("../utils/bind-status");
6
7
  /**
7
8
  * 交互式绑定命令处理器
8
9
  * 处理 "绑定" 命令,引导用户完成 MC 和 B站双重绑定
@@ -60,12 +61,10 @@ class BindingHandler extends base_handler_1.BaseHandler {
60
61
  // 检查目标用户当前绑定状态
61
62
  const targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
62
63
  // 如果两个账号都已绑定,不需要进入绑定流程
63
- if (targetBind && targetBind.mcUsername && targetBind.buidUid) {
64
+ if (bind_status_1.BindStatus.hasCompletedAllBinds(targetBind)) {
64
65
  this.logger.info('交互绑定', `QQ(${normalizedTargetId})已完成全部绑定`, true);
65
66
  // 显示当前绑定信息
66
- const displayUsername = targetBind.mcUsername && !targetBind.mcUsername.startsWith('_temp_')
67
- ? targetBind.mcUsername
68
- : '未绑定';
67
+ const displayUsername = bind_status_1.BindStatus.getDisplayMcUsername(targetBind, '未绑定');
69
68
  let bindInfo = `用户 ${normalizedTargetId} 已完成全部账号绑定:\n✅ MC账号: ${displayUsername}\n✅ B站账号: ${targetBind.buidUsername} (UID: ${targetBind.buidUid})`;
70
69
  if (targetBind.guardLevel > 0) {
71
70
  bindInfo += `\n舰长等级: ${targetBind.guardLevelText}`;
@@ -78,20 +77,18 @@ class BindingHandler extends base_handler_1.BaseHandler {
78
77
  // 为目标用户创建绑定会话
79
78
  this.deps.createBindingSession(target, channelId, 'waiting_buid');
80
79
  // 如果已绑定MC但未绑定B站,直接进入B站绑定流程
81
- if (targetBind && targetBind.mcUsername && !targetBind.buidUid) {
80
+ if (bind_status_1.BindStatus.hasValidMcBind(targetBind) && !bind_status_1.BindStatus.hasValidBuidBind(targetBind)) {
82
81
  this.logger.info('交互绑定', `QQ(${normalizedTargetId})已绑定MC,进入B站绑定流程`, true);
83
82
  // 更新会话状态
84
83
  this.deps.updateBindingSession(target, channelId, {
85
84
  state: 'waiting_buid',
86
- mcUsername: targetBind.mcUsername && !targetBind.mcUsername.startsWith('_temp_')
85
+ mcUsername: bind_status_1.BindStatus.hasValidMcBind(targetBind)
87
86
  ? targetBind.mcUsername
88
87
  : null,
89
88
  mcUuid: targetBind.mcUuid
90
89
  });
91
90
  // 向目标用户发送提示(@他们)
92
- const displayUsername = targetBind.mcUsername && !targetBind.mcUsername.startsWith('_temp_')
93
- ? targetBind.mcUsername
94
- : '未绑定';
91
+ const displayUsername = bind_status_1.BindStatus.getDisplayMcUsername(targetBind, '未绑定');
95
92
  await this.deps.sendMessage(session, [
96
93
  koishi_1.h.at(normalizedTargetId),
97
94
  koishi_1.h.text(` 管理员为您启动了B站绑定流程\n🎮 已绑定MC: ${displayUsername}\n🔗 请发送您的B站UID`)
@@ -118,10 +115,7 @@ class BindingHandler extends base_handler_1.BaseHandler {
118
115
  // 检查用户当前绑定状态
119
116
  const existingBind = await this.deps.databaseService.getMcBindByQQId(normalizedUserId);
120
117
  // 如果两个账号都已绑定(且MC不是temp用户名),不需要进入绑定流程
121
- if (existingBind &&
122
- existingBind.mcUsername &&
123
- !existingBind.mcUsername.startsWith('_temp_') &&
124
- existingBind.buidUid) {
118
+ if (existingBind && bind_status_1.BindStatus.hasValidMcBind(existingBind) && existingBind.buidUid) {
125
119
  this.logger.info('交互绑定', `QQ(${normalizedUserId})已完成全部绑定`, true);
126
120
  // 显示当前绑定信息
127
121
  const displayUsername = existingBind.mcUsername;
@@ -136,10 +130,7 @@ class BindingHandler extends base_handler_1.BaseHandler {
136
130
  return this.deps.sendMessage(session, [koishi_1.h.text(bindInfo)]);
137
131
  }
138
132
  // 如果已绑定MC(且不是temp用户名)但未绑定B站,直接进入B站绑定流程
139
- if (existingBind &&
140
- existingBind.mcUsername &&
141
- !existingBind.mcUsername.startsWith('_temp_') &&
142
- !existingBind.buidUid) {
133
+ if (existingBind && bind_status_1.BindStatus.hasValidMcBind(existingBind) && !existingBind.buidUid) {
143
134
  this.logger.info('交互绑定', `QQ(${normalizedUserId})已绑定MC,进入B站绑定流程`, true);
144
135
  // 创建绑定会话,状态直接设为等待B站UID
145
136
  const timeout = setTimeout(() => {
@@ -172,8 +163,7 @@ class BindingHandler extends base_handler_1.BaseHandler {
172
163
  if (existingBind &&
173
164
  existingBind.buidUid &&
174
165
  existingBind.buidUsername &&
175
- existingBind.mcUsername &&
176
- existingBind.mcUsername.startsWith('_temp_')) {
166
+ !bind_status_1.BindStatus.hasValidMcBind(existingBind)) {
177
167
  this.logger.info('交互绑定', `QQ(${normalizedUserId})只绑定了B站,进入MC绑定流程`, true);
178
168
  // 创建绑定会话,状态设为等待MC用户名
179
169
  this.deps.createBindingSession(session.userId, channelId, 'waiting_mc_username');
@@ -7,6 +7,7 @@ exports.BuidHandler = void 0;
7
7
  const koishi_1 = require("koishi");
8
8
  const base_handler_1 = require("./base.handler");
9
9
  const axios_1 = __importDefault(require("axios"));
10
+ const bind_status_1 = require("../utils/bind-status");
10
11
  /**
11
12
  * BUID 命令处理器
12
13
  * 处理 B站账号相关命令
@@ -256,27 +257,16 @@ class BuidHandler extends base_handler_1.BaseHandler {
256
257
  try {
257
258
  const normalizedUserId = this.deps.normalizeQQId(session.userId);
258
259
  this.logger.info('解绑', `QQ(${normalizedUserId})尝试解绑B站账号`);
259
- // 查询当前绑定
260
- const bind = await this.repos.mcidbind.findByQQId(normalizedUserId);
261
- if (!bind || !bind.buidUid) {
262
- this.logger.warn('解绑', `QQ(${normalizedUserId})尝试解绑未绑定的B站账号`);
260
+ // 使用 DatabaseService 的解绑方法
261
+ const success = await this.deps.databaseService.deleteBuidBind(normalizedUserId);
262
+ if (success) {
263
+ this.logger.info('解绑', `QQ(${normalizedUserId})成功解绑B站账号`);
264
+ return this.deps.sendMessage(session, [koishi_1.h.text('已成功解绑B站账号')]);
265
+ }
266
+ else {
267
+ this.logger.warn('解绑', `QQ(${normalizedUserId})解绑B站账号失败`);
263
268
  return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定B站账号')]);
264
269
  }
265
- // 更新绑定信息
266
- const updateData = {
267
- buidUid: '',
268
- buidUsername: '',
269
- guardLevel: 0,
270
- guardLevelText: '',
271
- medalName: '',
272
- medalLevel: 0,
273
- wealthMedalLevel: 0,
274
- lastActiveTime: null,
275
- lastModified: new Date()
276
- };
277
- await this.repos.mcidbind.update(normalizedUserId, updateData);
278
- this.logger.info('解绑', `QQ(${normalizedUserId})成功解绑B站账号`);
279
- return this.deps.sendMessage(session, [koishi_1.h.text('已成功解绑B站账号')]);
280
270
  }
281
271
  catch (error) {
282
272
  this.logger.error('解绑', session.userId, error);
@@ -400,22 +390,25 @@ class BuidHandler extends base_handler_1.BaseHandler {
400
390
  lastModified: new Date()
401
391
  };
402
392
  if (bind) {
393
+ // 添加 hasBuidBind 标志
394
+ updateData.hasBuidBind = true;
403
395
  await this.repos.mcidbind.update(normalizedQQId, updateData);
404
396
  this.logger.info('B站账号绑定', `更新绑定: QQ=${normalizedQQId}, B站UID=${buidUser.uid}, 用户名=${buidUser.username}`);
405
397
  }
406
398
  else {
407
- const tempMcUsername = `_temp_skip_${normalizedQQId}_${Date.now()}`;
408
399
  const newBind = {
409
400
  qqId: normalizedQQId,
410
- mcUsername: tempMcUsername,
401
+ mcUsername: '',
411
402
  mcUuid: '',
412
403
  isAdmin: false,
413
404
  whitelist: [],
414
405
  tags: [],
406
+ hasMcBind: false,
407
+ hasBuidBind: true,
415
408
  ...updateData
416
409
  };
417
410
  await this.repos.mcidbind.create(newBind);
418
- this.logger.info('B站账号绑定', `创建绑定(跳过MC): QQ=${normalizedQQId}, B站UID=${buidUser.uid}, 用户名=${buidUser.username}, 临时MC用户名=${tempMcUsername}`);
411
+ this.logger.info('B站账号绑定', `创建绑定(跳过MC): QQ=${normalizedQQId}, B站UID=${buidUser.uid}, 用户名=${buidUser.username}`);
419
412
  }
420
413
  return true;
421
414
  }
@@ -523,7 +516,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
523
516
  try {
524
517
  const latestTargetBind = await this.repos.mcidbind.findByQQId(normalizedTargetId);
525
518
  if (latestTargetBind) {
526
- const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_')
519
+ const mcName = bind_status_1.BindStatus.hasValidMcBind(latestTargetBind)
527
520
  ? latestTargetBind.mcUsername
528
521
  : null;
529
522
  await this.deps.nicknameService.autoSetGroupNickname(session, mcName, enhancedUser.username, String(enhancedUser.uid), normalizedTargetId);
@@ -560,7 +553,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
560
553
  try {
561
554
  const latestBind = await this.repos.mcidbind.findByQQId(operatorQQId);
562
555
  if (latestBind) {
563
- const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_')
556
+ const mcName = bind_status_1.BindStatus.hasValidMcBind(latestBind)
564
557
  ? latestBind.mcUsername
565
558
  : null;
566
559
  await this.deps.nicknameService.autoSetGroupNickname(session, mcName, enhancedUser.username, String(enhancedUser.uid));
@@ -641,7 +634,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
641
634
  try {
642
635
  const latestTargetBind = await this.repos.mcidbind.findByQQId(normalizedTargetId);
643
636
  if (latestTargetBind) {
644
- const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_')
637
+ const mcName = bind_status_1.BindStatus.hasValidMcBind(latestTargetBind)
645
638
  ? latestTargetBind.mcUsername
646
639
  : null;
647
640
  await this.deps.nicknameService.autoSetGroupNickname(session, mcName, buidUser.username, actualUid, normalizedTargetId);
@@ -701,7 +694,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
701
694
  try {
702
695
  const latestBind = await this.repos.mcidbind.findByQQId(operatorQQId);
703
696
  if (latestBind) {
704
- const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_')
697
+ const mcName = bind_status_1.BindStatus.hasValidMcBind(latestBind)
705
698
  ? latestBind.mcUsername
706
699
  : null;
707
700
  await this.deps.nicknameService.autoSetGroupNickname(session, mcName, buidUser.username, actualUid);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GroupRequestReviewHandler = void 0;
4
4
  const koishi_1 = require("koishi");
5
5
  const base_handler_1 = require("./base.handler");
6
+ const bind_status_1 = require("../utils/bind-status");
6
7
  /**
7
8
  * 入群申请审批处理器
8
9
  *
@@ -85,7 +86,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
85
86
  status: 'pending'
86
87
  };
87
88
  this.pendingRequests.set(broadcastMsgId, pendingReq);
88
- this.logger.info('入群审批', `[DEBUG] 已保存待审批记录 - 申请人: ${normalizedUserId}, 播报消息ID: ${broadcastMsgId}, 目标群: ${this.reviewConfig.reviewGroupId}`, true);
89
+ this.logger.info('入群审批', `已保存待审批记录 - 申请人: ${normalizedUserId}, 播报消息ID: ${broadcastMsgId}`, true);
89
90
  // 自动添加表情回应选项
90
91
  await this.addReactionOptions(broadcastMsgId, session.bot);
91
92
  }
@@ -98,23 +99,12 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
98
99
  */
99
100
  async handleNotice(session) {
100
101
  try {
101
- // 【调试】最早期日志 - 记录所有收到的notice事件
102
- this.logger.info('入群审批', `[DEBUG] 收到notice事件 - type: ${session.type}, subtype: ${session.subtype}, guildId: ${session.guildId}`, true);
103
102
  // 只处理群表情回应事件
104
103
  if (session.subtype !== 'group-msg-emoji-like') {
105
104
  return;
106
105
  }
107
106
  // 获取原始事件数据(直接访问 session.onebot,参考luckydraw实现)
108
107
  const data = session.onebot;
109
- // 【调试】输出完整的原始事件数据
110
- this.logger.info('入群审批', `[DEBUG] 表情回应原始数据: ${JSON.stringify({
111
- session_guildId: session.guildId,
112
- session_channelId: session.channelId,
113
- onebot_group_id: data?.group_id,
114
- onebot_message_id: data?.message_id,
115
- onebot_user_id: data?.user_id,
116
- onebot_likes: data?.likes
117
- })}`, true);
118
108
  const messageId = data?.message_id;
119
109
  const userId = data?.user_id?.toString();
120
110
  const likes = data?.likes || [];
@@ -128,8 +118,6 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
128
118
  // 检查是否是待审批的消息
129
119
  const pendingReq = this.pendingRequests.get(msgId);
130
120
  if (!pendingReq) {
131
- this.logger.info('入群审批', `[DEBUG] 消息${msgId}不在待审批列表中`, true);
132
- this.logger.info('入群审批', `[DEBUG] 当前待审批消息ID列表: [${Array.from(this.pendingRequests.keys()).join(', ')}]`, true);
133
121
  return;
134
122
  }
135
123
  // 检查是否已处理
@@ -249,7 +237,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
249
237
  koishi_1.h.image(avatar),
250
238
  koishi_1.h.text(`\n👤 QQ 昵称:${nickname}\n`),
251
239
  koishi_1.h.text(`🆔 QQ 号:${qq}\n`),
252
- koishi_1.h.text(`💬 入群问题:${answer}\n\n`)
240
+ koishi_1.h.text(`💬 ${answer}\n\n`)
253
241
  ];
254
242
  // B 站信息
255
243
  if (buidUid) {
@@ -265,7 +253,7 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
265
253
  else {
266
254
  elements.push(koishi_1.h.text(`⚠️ 未提供有效的 B 站 UID\n\n`));
267
255
  }
268
- elements.push(koishi_1.h.text('━━━━━━━━━━━━━━━\n'), koishi_1.h.text('请管理员点击表情回应:\n'), koishi_1.h.text('👍 /太赞了 - 通过并自动绑定\n'), koishi_1.h.text('😊 /偷感 - 通过并交互式绑定\n'), koishi_1.h.text('❌ /NO - 拒绝申请'));
256
+ elements.push(koishi_1.h.text('请点击表情回应:\n'), koishi_1.h.text('👍 - 通过并自动绑定\n'), koishi_1.h.text('😊 - 通过并交互式绑定\n'), koishi_1.h.text('❌ - 拒绝申请'));
269
257
  try {
270
258
  const result = await session.bot.sendMessage(this.reviewConfig.reviewGroupId, elements);
271
259
  // result 通常是数组,第一个元素是消息ID
@@ -627,11 +615,10 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
627
615
  // 3. 获取或创建绑定记录
628
616
  let bind = await this.repos.mcidbind.findByQQId(qq);
629
617
  if (!bind) {
630
- // 创建新绑定(使用临时MC用户名)
631
- const tempMcUsername = `_temp_${Date.now()}`;
618
+ // 创建新绑定(不使用临时MC用户名)
632
619
  bind = await this.repos.mcidbind.create({
633
620
  qqId: qq,
634
- mcUsername: tempMcUsername,
621
+ mcUsername: '',
635
622
  mcUuid: '',
636
623
  buidUid: zminfoUser.uid,
637
624
  buidUsername: finalUsername,
@@ -643,7 +630,9 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
643
630
  medalLevel: zminfoUser.medal?.level || 0,
644
631
  wealthMedalLevel: zminfoUser.wealthMedalLevel || 0,
645
632
  lastActiveTime: new Date(),
646
- lastModified: new Date()
633
+ lastModified: new Date(),
634
+ hasMcBind: false,
635
+ hasBuidBind: true
647
636
  });
648
637
  this.logger.info('入群审批', `已创建新绑定 - QQ: ${qq}, UID: ${uid}`, true);
649
638
  }
@@ -662,16 +651,15 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
662
651
  medalLevel: zminfoUser.medal?.level || 0,
663
652
  wealthMedalLevel: zminfoUser.wealthMedalLevel || 0,
664
653
  lastActiveTime: new Date(),
665
- lastModified: new Date()
654
+ lastModified: new Date(),
655
+ hasBuidBind: true
666
656
  });
667
657
  this.logger.info('入群审批', `已更新绑定 - QQ: ${qq}, UID: ${uid}`, true);
668
658
  }
669
659
  // 4. 更新群昵称(使用标准格式)
670
660
  try {
671
661
  const groupId = this.reviewConfig.targetGroupId;
672
- const mcInfo = bind.mcUsername && !bind.mcUsername.startsWith('_temp_')
673
- ? bind.mcUsername
674
- : '未绑定';
662
+ const mcInfo = bind_status_1.BindStatus.getDisplayMcUsername(bind, '未绑定');
675
663
  const nickname = `${finalUsername}(ID:${mcInfo})`;
676
664
  await bot.internal.setGroupCard(groupId, qq, nickname);
677
665
  this.logger.info('入群审批', `已更新群昵称 - QQ: ${qq}, 昵称: ${nickname}`);
@@ -140,7 +140,8 @@ class LotteryHandler extends base_handler_1.BaseHandler {
140
140
  for (let i = 0; i < displayUsers.length; i++) {
141
141
  const user = displayUsers[i];
142
142
  const index = i + 1;
143
- const displayMcName = user.mcUsername && !user.mcUsername.startsWith('_temp_') ? user.mcUsername : '未绑定';
143
+ // 注意:这里的user是简化对象,不是完整的MCIDBIND
144
+ const displayMcName = user.mcUsername || '未绑定';
144
145
  groupMessage += `${index}. ${user.buidUsername} (UID: ${user.uid})\n`;
145
146
  groupMessage += ` QQ: ${user.qqId} | MC: ${displayMcName}\n`;
146
147
  }
@@ -176,9 +177,8 @@ class LotteryHandler extends base_handler_1.BaseHandler {
176
177
  // 查找对应的绑定用户
177
178
  const matchedUser = stats.matchedUsers.find(user => user.uid === winner.uid);
178
179
  if (matchedUser) {
179
- const displayMcName = matchedUser.mcUsername && !matchedUser.mcUsername.startsWith('_temp_')
180
- ? matchedUser.mcUsername
181
- : '未绑定';
180
+ // 注意:matchedUser是简化对象,不是完整的MCIDBIND
181
+ const displayMcName = matchedUser.mcUsername || '未绑定';
182
182
  privateMessage += `${index}. ${winner.username} (UID: ${winner.uid})\n`;
183
183
  privateMessage += ` QQ: ${matchedUser.qqId} | MC: ${displayMcName}\n`;
184
184
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.McidCommandHandler = void 0;
4
4
  const koishi_1 = require("koishi");
5
5
  const base_handler_1 = require("./base.handler");
6
+ const bind_status_1 = require("../utils/bind-status");
6
7
  class McidCommandHandler extends base_handler_1.BaseHandler {
7
8
  /**
8
9
  * 注册所有MCID命令
@@ -80,7 +81,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
80
81
  }
81
82
  this.logger.info('查询', `QQ(${normalizedUserId})查询QQ(${normalizedTargetId})的MC账号信息`);
82
83
  const targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
83
- if (!targetBind || !targetBind.mcUsername || targetBind.mcUsername.startsWith('_temp_')) {
84
+ if (!targetBind || !bind_status_1.BindStatus.hasValidMcBind(targetBind)) {
84
85
  this.logger.info('查询', `QQ(${normalizedTargetId})未绑定MC账号`);
85
86
  // 检查是否绑定了B站
86
87
  if (targetBind && targetBind.buidUid) {
@@ -120,7 +121,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
120
121
  // 查询自己
121
122
  this.logger.info('查询', `QQ(${normalizedUserId})查询自己的MC账号信息`);
122
123
  const selfBind = await this.deps.databaseService.getMcBindByQQId(normalizedUserId);
123
- if (!selfBind || !selfBind.mcUsername || selfBind.mcUsername.startsWith('_temp_')) {
124
+ if (!selfBind || !bind_status_1.BindStatus.hasValidMcBind(selfBind)) {
124
125
  this.logger.info('查询', `QQ(${normalizedUserId})未绑定MC账号`);
125
126
  // 检查是否绑定了B站
126
127
  if (selfBind && selfBind.buidUid) {
@@ -237,7 +238,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
237
238
  : `您尚未绑定B站账号,使用 ${this.deps.formatCommand('buid bind <B站UID>')} 进行绑定`;
238
239
  }
239
240
  this.logger.info('查询', `QQ(${bind.qqId})的MC账号信息:用户名=${bind.mcUsername}, UUID=${bind.mcUuid}`);
240
- const displayUsername = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : '未绑定';
241
+ const displayUsername = bind_status_1.BindStatus.getDisplayMcUsername(bind, '未绑定');
241
242
  const prefix = targetId ? `用户 ${targetId} 的` : '您的';
242
243
  const messageElements = [
243
244
  koishi_1.h.text(`${prefix}MC账号信息:\n用户名: ${displayUsername}\nUUID: ${formattedUuid}${whitelistInfo}`),
@@ -249,7 +250,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
249
250
  const sendPromise = this.deps.sendMessage(session, messageElements);
250
251
  // 异步设置群昵称
251
252
  if (bind.buidUid && bind.buidUsername) {
252
- const mcName = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : null;
253
+ const mcName = bind_status_1.BindStatus.hasValidMcBind(bind) ? bind.mcUsername : null;
253
254
  this.deps.nicknameService
254
255
  .autoSetGroupNickname(session, mcName, bind.buidUsername, bind.buidUid, targetId || undefined)
255
256
  .catch(err => this.logger.warn('查询', `群昵称设置失败: ${err.message}`));
@@ -310,7 +311,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
310
311
  adminInfo += `\n管理员权限: ${bind.isAdmin ? '是' : '否'}`;
311
312
  }
312
313
  this.logger.info('反向查询', `成功: MC用户名"${username}"被QQ(${bind.qqId})绑定`);
313
- const displayUsername = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : '未绑定';
314
+ const displayUsername = bind_status_1.BindStatus.getDisplayMcUsername(bind, '未绑定');
314
315
  return this.deps.sendMessage(session, [
315
316
  koishi_1.h.text(`MC用户名"${displayUsername}"绑定信息:\nQQ号: ${bind.qqId}\nUUID: ${formattedUuid}${adminInfo}`),
316
317
  ...(mcAvatarUrl ? [koishi_1.h.image(mcAvatarUrl)] : [])
@@ -432,7 +433,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
432
433
  // 检查是否已绑定
433
434
  const selfBind = await this.deps.databaseService.getMcBindByQQId(operatorId);
434
435
  if (selfBind && selfBind.mcUsername) {
435
- const isTempUsername = selfBind.mcUsername.startsWith('_temp_');
436
+ const isTempUsername = !bind_status_1.BindStatus.hasValidMcBind(selfBind);
436
437
  if (!isTempUsername) {
437
438
  // 检查冷却时间
438
439
  if (!(await this.deps.isAdmin(session.userId)) &&
@@ -443,9 +444,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
443
444
  const passedDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
444
445
  const remainingDays = days - passedDays;
445
446
  this.logger.warn('绑定', `QQ(${operatorId})已绑定MC账号"${selfBind.mcUsername}",且在冷却期内`);
446
- const displayUsername = selfBind.mcUsername && !selfBind.mcUsername.startsWith('_temp_')
447
- ? selfBind.mcUsername
448
- : '未绑定';
447
+ const displayUsername = bind_status_1.BindStatus.getDisplayMcUsername(selfBind, '未绑定');
449
448
  return this.deps.sendMessage(session, [
450
449
  koishi_1.h.text(`您已绑定MC账号: ${displayUsername},如需修改,请在冷却期结束后(还需${remainingDays}天)使用 ` +
451
450
  this.deps.formatCommand('mcid change') +
@@ -453,9 +452,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
453
452
  ]);
454
453
  }
455
454
  this.logger.debug('绑定', `QQ(${operatorId})已绑定MC账号"${selfBind.mcUsername}",建议使用change命令`);
456
- const displayUsername = selfBind.mcUsername && !selfBind.mcUsername.startsWith('_temp_')
457
- ? selfBind.mcUsername
458
- : '未绑定';
455
+ const displayUsername = bind_status_1.BindStatus.getDisplayMcUsername(selfBind, '未绑定');
459
456
  return this.deps.sendMessage(session, [
460
457
  koishi_1.h.text(`您已绑定MC账号: ${displayUsername},如需修改请使用 ` +
461
458
  this.deps.formatCommand('mcid change') +
@@ -714,17 +711,16 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
714
711
  this.logger.warn('解绑', `QQ(${normalizedTargetId})尚未绑定MC账号`);
715
712
  return this.deps.sendMessage(session, [koishi_1.h.text(`用户 ${normalizedTargetId} 尚未绑定MC账号`)]);
716
713
  }
717
- const oldUsername = targetBind.mcUsername && !targetBind.mcUsername.startsWith('_temp_')
718
- ? targetBind.mcUsername
719
- : '未绑定';
720
- const oldBuidInfo = targetBind.buidUid
721
- ? ` 和 B站账号: ${targetBind.buidUsername}(${targetBind.buidUid})`
714
+ const oldUsername = bind_status_1.BindStatus.getDisplayMcUsername(targetBind, '未绑定');
715
+ const hasBuidBind = targetBind.buidUid && targetBind.buidUid.trim() !== '';
716
+ const buidKeepInfo = hasBuidBind
717
+ ? `\n✅ 该用户的B站绑定已保留: ${targetBind.buidUsername}(${targetBind.buidUid})`
722
718
  : '';
723
- // 删除绑定记录
719
+ // 解绑MC账号
724
720
  await this.deps.databaseService.deleteMcBind(target);
725
- this.logger.info('解绑', `成功: 管理员QQ(${operatorId})为QQ(${normalizedTargetId})解绑MC账号: ${oldUsername}${oldBuidInfo}`);
721
+ this.logger.info('解绑', `成功: 管理员QQ(${operatorId})为QQ(${normalizedTargetId})解绑MC账号: ${oldUsername}`);
726
722
  return this.deps.sendMessage(session, [
727
- koishi_1.h.text(`已成功为用户 ${normalizedTargetId} 解绑MC账号: ${oldUsername}${oldBuidInfo}`)
723
+ koishi_1.h.text(`已成功为用户 ${normalizedTargetId} 解绑MC账号: ${oldUsername}${buidKeepInfo}`)
728
724
  ]);
729
725
  }
730
726
  async handleUnbindForSelf(session, operatorId) {
@@ -734,17 +730,16 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
734
730
  this.logger.warn('解绑', `QQ(${operatorId})尚未绑定MC账号`);
735
731
  return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定MC账号')]);
736
732
  }
737
- const oldUsername = selfBind.mcUsername && !selfBind.mcUsername.startsWith('_temp_')
738
- ? selfBind.mcUsername
739
- : '未绑定';
740
- const oldBuidInfo = selfBind.buidUid
741
- ? ` 和 B站账号: ${selfBind.buidUsername}(${selfBind.buidUid})`
733
+ const oldUsername = bind_status_1.BindStatus.getDisplayMcUsername(selfBind, '未绑定');
734
+ const hasBuidBind = selfBind.buidUid && selfBind.buidUid.trim() !== '';
735
+ const buidKeepInfo = hasBuidBind
736
+ ? `\n✅ 您的B站绑定已保留: ${selfBind.buidUsername}(${selfBind.buidUid})`
742
737
  : '';
743
- // 删除绑定记录
738
+ // 解绑MC账号
744
739
  await this.deps.databaseService.deleteMcBind(operatorId);
745
- this.logger.info('解绑', `成功: QQ(${operatorId})解绑MC账号: ${oldUsername}${oldBuidInfo}`);
740
+ this.logger.info('解绑', `成功: QQ(${operatorId})解绑MC账号: ${oldUsername}`);
746
741
  return this.deps.sendMessage(session, [
747
- koishi_1.h.text(`已成功解绑MC账号: ${oldUsername}${oldBuidInfo}`)
742
+ koishi_1.h.text(`已成功解绑MC账号: ${oldUsername}${buidKeepInfo}`)
748
743
  ]);
749
744
  }
750
745
  /**
@@ -779,14 +774,15 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
779
774
  }
780
775
  else {
781
776
  // 用户不存在绑定记录,创建一个新记录并设为管理员
782
- const tempUsername = `_temp_${normalizedTargetId}`;
783
777
  try {
784
778
  await this.repos.mcidbind.create({
785
779
  qqId: normalizedTargetId,
786
- mcUsername: tempUsername,
780
+ mcUsername: '',
787
781
  mcUuid: '',
788
782
  lastModified: new Date(),
789
- isAdmin: true
783
+ isAdmin: true,
784
+ hasMcBind: false,
785
+ hasBuidBind: false
790
786
  });
791
787
  this.logger.info('管理员', `成功: 主人QQ(${normalizedUserId})将QQ(${normalizedTargetId})设为管理员 (创建新记录)`);
792
788
  return this.deps.sendMessage(session, [
@@ -865,7 +861,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
865
861
  // 格式化管理员列表
866
862
  const adminList = admins
867
863
  .map(admin => {
868
- const displayUsername = admin.mcUsername && !admin.mcUsername.startsWith('_temp_') ? admin.mcUsername : null;
864
+ const displayUsername = bind_status_1.BindStatus.hasValidMcBind(admin) ? admin.mcUsername : null;
869
865
  return `- ${admin.qqId}${displayUsername ? ` (MC: ${displayUsername})` : ''}`;
870
866
  })
871
867
  .join('\n');
@@ -898,12 +894,10 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
898
894
  let mcidBoundUsers = 0;
899
895
  let buidBoundUsers = 0;
900
896
  for (const bind of allBinds) {
901
- const hasMcid = bind.mcUsername && !bind.mcUsername.startsWith('_temp_');
902
- if (hasMcid) {
897
+ if (bind_status_1.BindStatus.hasValidMcBind(bind)) {
903
898
  mcidBoundUsers++;
904
899
  }
905
- const hasBuid = bind.buidUid && bind.buidUid.trim() !== '';
906
- if (hasBuid) {
900
+ if (bind_status_1.BindStatus.hasValidBuidBind(bind)) {
907
901
  buidBoundUsers++;
908
902
  }
909
903
  }
@@ -977,7 +971,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
977
971
  continue;
978
972
  }
979
973
  // 检查昵称格式
980
- const mcInfo = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : null;
974
+ const mcInfo = bind_status_1.BindStatus.hasValidMcBind(bind) ? bind.mcUsername : null;
981
975
  const isCorrect = this.deps.nicknameService.checkNicknameFormat(currentNickname, bind.buidUsername, mcInfo);
982
976
  if (!isCorrect) {
983
977
  // 修复群昵称
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TagHandler = void 0;
4
4
  const koishi_1 = require("koishi");
5
5
  const base_handler_1 = require("./base.handler");
6
+ const bind_status_1 = require("../utils/bind-status");
6
7
  class TagHandler extends base_handler_1.BaseHandler {
7
8
  register() {
8
9
  const cmd = this.ctx.command('mcid', 'Minecraft账号和B站账号绑定管理');
@@ -78,15 +79,16 @@ class TagHandler extends base_handler_1.BaseHandler {
78
79
  this.logger.info('标签', `管理员QQ(${normalizedUserId})尝试为QQ(${normalizedTargetId})添加标签"${tagName}"`, true);
79
80
  let targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
80
81
  if (!targetBind) {
81
- const tempUsername = `_temp_${normalizedTargetId}`;
82
82
  await this.repos.mcidbind.create({
83
83
  qqId: normalizedTargetId,
84
- mcUsername: tempUsername,
84
+ mcUsername: '',
85
85
  mcUuid: '',
86
86
  lastModified: new Date(),
87
87
  isAdmin: false,
88
88
  whitelist: [],
89
- tags: []
89
+ tags: [],
90
+ hasMcBind: false,
91
+ hasBuidBind: false
90
92
  });
91
93
  targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
92
94
  }
@@ -115,15 +117,16 @@ class TagHandler extends base_handler_1.BaseHandler {
115
117
  try {
116
118
  let targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
117
119
  if (!targetBind) {
118
- const tempUsername = `_temp_${normalizedTargetId}`;
119
120
  await this.repos.mcidbind.create({
120
121
  qqId: normalizedTargetId,
121
- mcUsername: tempUsername,
122
+ mcUsername: '',
122
123
  mcUuid: '',
123
124
  lastModified: new Date(),
124
125
  isAdmin: false,
125
126
  whitelist: [],
126
- tags: []
127
+ tags: [],
128
+ hasMcBind: false,
129
+ hasBuidBind: false
127
130
  });
128
131
  targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
129
132
  }
@@ -314,7 +317,7 @@ class TagHandler extends base_handler_1.BaseHandler {
314
317
  }
315
318
  const userList = usersWithTag
316
319
  .map(bind => {
317
- const mcInfo = bind.mcUsername && !bind.mcUsername.startsWith('_temp_')
320
+ const mcInfo = bind_status_1.BindStatus.hasValidMcBind(bind)
318
321
  ? ` (MC: ${bind.mcUsername})`
319
322
  : '';
320
323
  return `• ${bind.qqId}${mcInfo}`;