koishi-plugin-bind-bot 2.2.5 → 2.2.7

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.
@@ -21,13 +21,17 @@ export declare class BuidHandler extends BaseHandler {
21
21
  */
22
22
  private handleFindUser;
23
23
  /**
24
- * 处理 mcid.bindbuid 命令
24
+ * 处理 buid.unbind 命令
25
25
  */
26
- private handleBindBuid;
26
+ private handleUnbind;
27
27
  /**
28
- * 处理 mcid.unbindbuid 命令
28
+ * 管理员为他人解绑B站账号
29
29
  */
30
- private handleUnbindBuid;
30
+ private handleUnbindForOther;
31
+ /**
32
+ * 为自己解绑B站账号
33
+ */
34
+ private handleUnbindForSelf;
31
35
  /**
32
36
  * 解析UID输入(支持多种格式)
33
37
  */
@@ -37,17 +37,11 @@ class BuidHandler extends base_handler_1.BaseHandler {
37
37
  .action(async ({ session }, uid) => {
38
38
  return this.handleFindUser(session, uid);
39
39
  });
40
- // mcid 命令组中的 BUID 相关子命令
41
- const mcidCmd = this.ctx.command('mcid');
42
- // 绑定B站账号(mcid.bindbuid)
43
- mcidCmd
44
- .subcommand('.bindbuid <buid:string>', '绑定B站账号')
45
- .action(async ({ session }, buid) => {
46
- return this.handleBindBuid(session, buid);
47
- });
48
- // 解绑B站账号(mcid.unbindbuid)
49
- mcidCmd.subcommand('.unbindbuid', '解绑B站账号').action(async ({ session }) => {
50
- return this.handleUnbindBuid(session);
40
+ // 解绑BUID
41
+ buidCmd
42
+ .subcommand('.unbind [target:string]', '解绑B站账号')
43
+ .action(async ({ session }, target) => {
44
+ return this.handleUnbind(session, target);
51
45
  });
52
46
  }
53
47
  /**
@@ -71,12 +65,16 @@ class BuidHandler extends base_handler_1.BaseHandler {
71
65
  : `您尚未绑定B站账号,请使用 ${this.deps.formatCommand('buid bind <UID>')} 进行绑定`)
72
66
  ]);
73
67
  }
74
- // 每次查询都刷新B站数据
68
+ // 每次查询都必须从API获取最新数据
75
69
  const buidUser = await this.validateBUID(bind.buidUid);
76
- if (buidUser) {
77
- await this.updateBuidInfoOnly(bind.qqId, buidUser);
78
- bind = await this.repos.mcidbind.findByQQId(bind.qqId);
70
+ if (!buidUser) {
71
+ return this.deps.sendMessage(session, [
72
+ koishi_1.h.text(`无法从API获取B站UID ${bind.buidUid} 的最新数据,该用户可能不存在或API服务暂时不可用`)
73
+ ]);
79
74
  }
75
+ // 更新本地数据库中的信息
76
+ await this.updateBuidInfoOnly(bind.qqId, buidUser);
77
+ bind = await this.repos.mcidbind.findByQQId(bind.qqId);
80
78
  const userInfo = `${target ? `用户 ${bind.qqId} 的` : '您的'}B站账号信息:\nB站UID: ${bind.buidUid}\n用户名: ${bind.buidUsername}`;
81
79
  let detailInfo = '';
82
80
  if (bind.guardLevel > 0) {
@@ -192,88 +190,86 @@ class BuidHandler extends base_handler_1.BaseHandler {
192
190
  }
193
191
  }
194
192
  /**
195
- * 处理 mcid.bindbuid 命令
193
+ * 处理 buid.unbind 命令
196
194
  */
197
- async handleBindBuid(session, buid) {
195
+ async handleUnbind(session, target) {
198
196
  try {
199
197
  const normalizedUserId = this.deps.normalizeQQId(session.userId);
200
- this.logger.info('绑定', `QQ(${normalizedUserId})尝试绑定B站UID(${buid})`);
201
- // 验证格式
202
- if (!buid || !/^\d+$/.test(buid)) {
203
- this.logger.warn('绑定', `QQ(${normalizedUserId})尝试绑定无效的B站UID格式: ${buid}`);
204
- return this.deps.sendMessage(session, [koishi_1.h.text('无效的B站UID格式,请输入正确的B站UID')]);
205
- }
206
- // 检查是否已被他人绑定
207
- const existingBind = await this.repos.mcidbind.findByBuidUid(buid);
208
- if (existingBind) {
209
- const existingQQId = existingBind.qqId;
210
- this.logger.warn('绑定', `QQ(${normalizedUserId})尝试绑定已被QQ(${existingQQId})绑定的B站UID(${buid})`);
211
- return this.deps.sendMessage(session, [koishi_1.h.text('该B站UID已被其他用户绑定')]);
212
- }
213
- // 验证B站UID
214
- const buidUser = await this.validateBUID(buid);
215
- if (!buidUser) {
216
- this.logger.warn('绑定', `QQ(${normalizedUserId})尝试绑定不存在的B站UID(${buid})`);
217
- return this.deps.sendMessage(session, [koishi_1.h.text('无法验证B站UID,请确认输入正确')]);
218
- }
219
- // 创建或更新绑定
220
- const success = await this.createOrUpdateBuidBind(normalizedUserId, buidUser);
221
- if (success) {
222
- this.logger.info('绑定', `QQ(${normalizedUserId})成功绑定B站UID(${buid})`);
223
- return this.deps.sendMessage(session, [
224
- koishi_1.h.text('成功绑定B站账号!\n'),
225
- koishi_1.h.text(`B站UID: ${buidUser.uid}\n`),
226
- koishi_1.h.text(`用户名: ${buidUser.username}\n`),
227
- buidUser.guard_level > 0
228
- ? koishi_1.h.text(`舰长等级: ${buidUser.guard_level_text} (${buidUser.guard_level})\n`)
229
- : null,
230
- buidUser.medal
231
- ? koishi_1.h.text(`粉丝牌: ${buidUser.medal.name} Lv.${buidUser.medal.level}\n`)
232
- : null,
233
- buidUser.wealthMedalLevel > 0
234
- ? koishi_1.h.text(`荣耀等级: ${buidUser.wealthMedalLevel}\n`)
235
- : null,
236
- ...(this.config?.showAvatar
237
- ? [koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${buidUser.uid}?size=160`)]
238
- : [])
239
- ].filter(Boolean));
240
- }
241
- else {
242
- this.logger.error('绑定', normalizedUserId, `QQ(${normalizedUserId})绑定B站UID(${buid})失败`);
243
- return this.deps.sendMessage(session, [koishi_1.h.text('绑定失败,请稍后重试')]);
198
+ // 管理员为他人解绑
199
+ if (target) {
200
+ return this.handleUnbindForOther(session, target, normalizedUserId);
244
201
  }
202
+ // 为自己解绑
203
+ return this.handleUnbindForSelf(session, normalizedUserId);
245
204
  }
246
205
  catch (error) {
247
- this.logger.error('绑定', session.userId, error);
248
- return this.deps.sendMessage(session, [
249
- koishi_1.h.text(`绑定失败:${this.getFriendlyErrorMessage(error)}`)
250
- ]);
206
+ const normalizedUserId = this.deps.normalizeQQId(session.userId);
207
+ const targetInfo = target ? `为QQ(${this.deps.normalizeQQId(target)})` : '';
208
+ this.logger.error('解绑', `QQ(${normalizedUserId})${targetInfo}解绑B站账号失败: ${error.message}`);
209
+ return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
251
210
  }
252
211
  }
253
212
  /**
254
- * 处理 mcid.unbindbuid 命令
213
+ * 管理员为他人解绑B站账号
255
214
  */
256
- async handleUnbindBuid(session) {
257
- try {
258
- const normalizedUserId = this.deps.normalizeQQId(session.userId);
259
- this.logger.info('解绑', `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站账号失败`);
268
- return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定B站账号')]);
215
+ async handleUnbindForOther(session, target, operatorId) {
216
+ const normalizedTargetId = this.deps.normalizeQQId(target);
217
+ if (!normalizedTargetId) {
218
+ this.logger.warn('解绑', `QQ(${operatorId})提供的目标用户ID"${target}"无效`);
219
+ if (target.startsWith('@')) {
220
+ return this.deps.sendMessage(session, [
221
+ koishi_1.h.text('❌ 请使用真正的@功能,而不是手动输入@符号\n正确做法:点击或长按用户头像选择@功能')
222
+ ]);
269
223
  }
270
- }
271
- catch (error) {
272
- this.logger.error('解绑', session.userId, error);
273
224
  return this.deps.sendMessage(session, [
274
- koishi_1.h.text(`解绑失败:${this.getFriendlyErrorMessage(error)}`)
225
+ koishi_1.h.text('❌ 目标用户ID无效\n请提供有效的QQ号或使用@功能选择用户')
275
226
  ]);
276
227
  }
228
+ this.logger.info('解绑', `QQ(${operatorId})尝试为QQ(${normalizedTargetId})解绑B站账号`);
229
+ // 检查权限
230
+ if (!(await this.deps.isAdmin(session.userId))) {
231
+ this.logger.warn('解绑', `权限不足: QQ(${operatorId})不是管理员`);
232
+ return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能为其他用户解绑B站账号')]);
233
+ }
234
+ // 获取目标用户信息
235
+ const targetBind = await this.deps.databaseService.getMcBindByQQId(normalizedTargetId);
236
+ if (!targetBind || !targetBind.buidUid) {
237
+ this.logger.warn('解绑', `QQ(${normalizedTargetId})尚未绑定B站账号`);
238
+ return this.deps.sendMessage(session, [koishi_1.h.text(`用户 ${normalizedTargetId} 尚未绑定B站账号`)]);
239
+ }
240
+ const oldBuidUsername = targetBind.buidUsername || targetBind.buidUid;
241
+ const hasMcBind = targetBind.mcUsername && targetBind.mcUsername.trim() !== '';
242
+ const mcKeepInfo = hasMcBind
243
+ ? `\n✅ 该用户的MC绑定已保留: ${targetBind.mcUsername}`
244
+ : '';
245
+ // 解绑B站账号
246
+ await this.deps.databaseService.deleteBuidBind(normalizedTargetId);
247
+ this.logger.info('解绑', `成功: 管理员QQ(${operatorId})为QQ(${normalizedTargetId})解绑B站账号: ${oldBuidUsername}(${targetBind.buidUid})`);
248
+ return this.deps.sendMessage(session, [
249
+ koishi_1.h.text(`已成功为用户 ${normalizedTargetId} 解绑B站账号: ${oldBuidUsername}(${targetBind.buidUid})${mcKeepInfo}`)
250
+ ]);
251
+ }
252
+ /**
253
+ * 为自己解绑B站账号
254
+ */
255
+ async handleUnbindForSelf(session, operatorId) {
256
+ this.logger.info('解绑', `QQ(${operatorId})尝试解绑自己的B站账号`);
257
+ const selfBind = await this.deps.databaseService.getMcBindByQQId(operatorId);
258
+ if (!selfBind || !selfBind.buidUid) {
259
+ this.logger.warn('解绑', `QQ(${operatorId})尚未绑定B站账号`);
260
+ return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定B站账号')]);
261
+ }
262
+ const oldBuidUsername = selfBind.buidUsername || selfBind.buidUid;
263
+ const hasMcBind = selfBind.mcUsername && selfBind.mcUsername.trim() !== '';
264
+ const mcKeepInfo = hasMcBind
265
+ ? `\n✅ 您的MC绑定已保留: ${selfBind.mcUsername}`
266
+ : '';
267
+ // 解绑B站账号
268
+ await this.deps.databaseService.deleteBuidBind(operatorId);
269
+ this.logger.info('解绑', `成功: QQ(${operatorId})解绑B站账号: ${oldBuidUsername}`);
270
+ return this.deps.sendMessage(session, [
271
+ koishi_1.h.text(`已成功解绑B站账号: ${oldBuidUsername}${mcKeepInfo}`)
272
+ ]);
277
273
  }
278
274
  // ========== 私有辅助方法 ==========
279
275
  /**
@@ -495,30 +495,19 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
495
495
  * 检查管理员权限
496
496
  */
497
497
  async checkAdminPermission(userId, groupId, bot) {
498
- // 检查是否是 masterId
499
- if (userId === this.config.masterId) {
500
- return true;
501
- }
502
- // 先检查缓存
503
- const cache = this.adminCache.get(groupId);
504
- if (cache && Date.now() - cache.lastUpdate < 5 * 60 * 1000) {
505
- return cache.admins.includes(userId);
506
- }
507
- // 调用 NapCat 扩展 API 获取群信息
508
498
  try {
509
- const groupInfo = await bot.internal.getGroupInfoEx(groupId);
510
- const admins = (groupInfo.admins || []).map(String);
511
- // 更新缓存
512
- this.adminCache.set(groupId, {
513
- admins,
514
- lastUpdate: Date.now()
515
- });
516
- return admins.includes(userId);
499
+ const normalizedUserId = this.deps.normalizeQQId(userId);
500
+ // 检查是否是 masterId
501
+ if (this.config.masterId && normalizedUserId === this.config.masterId) {
502
+ return true;
503
+ }
504
+ // 检查数据库中的管理员标记(与其他功能保持一致)
505
+ const bind = await this.repos.mcidbind.findByQQId(normalizedUserId);
506
+ return bind?.isAdmin === true;
517
507
  }
518
508
  catch (error) {
519
- this.logger.error('入群审批', `获取管理员列表失败: ${error.message}`);
520
- // 降级方案:只允许 masterId
521
- return userId === this.config.masterId;
509
+ this.logger.error('入群审批', `检查管理员权限失败: ${error.message}`);
510
+ return false;
522
511
  }
523
512
  }
524
513
  /**
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.5",
4
+ "version": "2.2.7",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [