koishi-plugin-bind-bot 2.2.6 → 2.2.8
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.
|
@@ -24,6 +24,14 @@ export declare class BuidHandler extends BaseHandler {
|
|
|
24
24
|
* 处理 buid.unbind 命令
|
|
25
25
|
*/
|
|
26
26
|
private handleUnbind;
|
|
27
|
+
/**
|
|
28
|
+
* 管理员为他人解绑B站账号
|
|
29
|
+
*/
|
|
30
|
+
private handleUnbindForOther;
|
|
31
|
+
/**
|
|
32
|
+
* 为自己解绑B站账号
|
|
33
|
+
*/
|
|
34
|
+
private handleUnbindForSelf;
|
|
27
35
|
/**
|
|
28
36
|
* 解析UID输入(支持多种格式)
|
|
29
37
|
*/
|
|
@@ -39,9 +39,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
39
39
|
});
|
|
40
40
|
// 解绑BUID
|
|
41
41
|
buidCmd
|
|
42
|
-
.subcommand('.unbind', '解绑B站账号')
|
|
43
|
-
.action(async ({ session }) => {
|
|
44
|
-
return this.handleUnbind(session);
|
|
42
|
+
.subcommand('.unbind [target:string]', '解绑B站账号')
|
|
43
|
+
.action(async ({ session }, target) => {
|
|
44
|
+
return this.handleUnbind(session, target);
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
@@ -192,27 +192,84 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
192
192
|
/**
|
|
193
193
|
* 处理 buid.unbind 命令
|
|
194
194
|
*/
|
|
195
|
-
async handleUnbind(session) {
|
|
195
|
+
async handleUnbind(session, target) {
|
|
196
196
|
try {
|
|
197
197
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (success) {
|
|
202
|
-
this.logger.info('解绑', `QQ(${normalizedUserId})成功解绑B站账号`);
|
|
203
|
-
return this.deps.sendMessage(session, [koishi_1.h.text('已成功解绑B站账号')]);
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
this.logger.warn('解绑', `QQ(${normalizedUserId})解绑B站账号失败`);
|
|
207
|
-
return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定B站账号')]);
|
|
198
|
+
// 管理员为他人解绑
|
|
199
|
+
if (target) {
|
|
200
|
+
return this.handleUnbindForOther(session, target, normalizedUserId);
|
|
208
201
|
}
|
|
202
|
+
// 为自己解绑
|
|
203
|
+
return this.handleUnbindForSelf(session, normalizedUserId);
|
|
209
204
|
}
|
|
210
205
|
catch (error) {
|
|
211
|
-
this.
|
|
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))]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 管理员为他人解绑B站账号
|
|
214
|
+
*/
|
|
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
|
+
]);
|
|
223
|
+
}
|
|
212
224
|
return this.deps.sendMessage(session, [
|
|
213
|
-
koishi_1.h.text(
|
|
225
|
+
koishi_1.h.text('❌ 目标用户ID无效\n请提供有效的QQ号或使用@功能选择用户')
|
|
214
226
|
]);
|
|
215
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
|
+
]);
|
|
216
273
|
}
|
|
217
274
|
// ========== 私有辅助方法 ==========
|
|
218
275
|
/**
|
|
@@ -114,6 +114,12 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
|
|
|
114
114
|
const msgId = messageId.toString();
|
|
115
115
|
const emojiData = likes;
|
|
116
116
|
const operatorId = this.deps.normalizeQQId(userId);
|
|
117
|
+
// 忽略 bot 自己的表情回应(addReactionOptions 添加表情时也会触发此事件)
|
|
118
|
+
const botId = this.deps.normalizeQQId(session.bot.selfId);
|
|
119
|
+
if (operatorId === botId) {
|
|
120
|
+
this.logger.debug('入群审批', `忽略 bot 自己的表情回应 - 消息: ${msgId}`);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
117
123
|
this.logger.debug('入群审批', `收到表情回应 - 消息: ${msgId}, 操作者: ${operatorId}, 表情数: ${emojiData.length}`);
|
|
118
124
|
// 检查是否是待审批的消息
|
|
119
125
|
const pendingReq = this.pendingRequests.get(msgId);
|
|
@@ -177,6 +183,8 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
|
|
|
177
183
|
buidUid = parsedUid;
|
|
178
184
|
// 尝试使用强制绑定模式获取完整信息(避免频率限制)
|
|
179
185
|
let zminfoData = null;
|
|
186
|
+
// 存储强制绑定模式下获取的目标粉丝牌信息
|
|
187
|
+
let targetMedalInfo = null;
|
|
180
188
|
if (this.config.forceBindSessdata) {
|
|
181
189
|
try {
|
|
182
190
|
this.logger.debug('入群审批', '使用强制绑定模式获取用户信息...');
|
|
@@ -184,7 +192,9 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
|
|
|
184
192
|
const standardUser = this.deps.forceBinder.convertToZminfoUser(enhancedUser);
|
|
185
193
|
buidUsername = standardUser.username;
|
|
186
194
|
zminfoData = standardUser;
|
|
187
|
-
|
|
195
|
+
// 保存目标粉丝牌信息,用于后续显示
|
|
196
|
+
targetMedalInfo = enhancedUser.targetMedal || null;
|
|
197
|
+
this.logger.debug('入群审批', `✅ 强制绑定模式获取成功: ${buidUsername}, 目标粉丝牌: ${targetMedalInfo?.found ? '已找到' : '未找到'}`);
|
|
188
198
|
}
|
|
189
199
|
catch (error) {
|
|
190
200
|
this.logger.warn('入群审批', `强制绑定获取用户信息失败: ${error.message},降级到ZMINFO`);
|
|
@@ -205,8 +215,21 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
|
|
|
205
215
|
this.logger.debug('入群审批', `✅ ZMINFO用户名: ${buidUsername}`);
|
|
206
216
|
}
|
|
207
217
|
}
|
|
208
|
-
//
|
|
209
|
-
if (
|
|
218
|
+
// 粉丝牌信息:优先使用强制绑定获取的目标粉丝牌,其次使用ZMINFO的当前佩戴粉丝牌
|
|
219
|
+
if (targetMedalInfo) {
|
|
220
|
+
// 使用强制绑定模式获取的目标粉丝牌信息(从B站粉丝牌墙获取,更准确)
|
|
221
|
+
if (targetMedalInfo.found && targetMedalInfo.name && targetMedalInfo.level !== undefined) {
|
|
222
|
+
medalInfo = `🎖️ ${targetMedalInfo.name} Lv.${targetMedalInfo.level}`;
|
|
223
|
+
if (targetMedalInfo.wearing_status === 1) {
|
|
224
|
+
medalInfo += ' 【已佩戴】';
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
medalInfo = `⚠️ 未获取到 "${this.config.forceBindTargetMedalName}" 粉丝牌`;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else if (zminfoData) {
|
|
232
|
+
// 降级:使用ZMINFO的当前佩戴粉丝牌信息
|
|
210
233
|
const medalLevel = zminfoData.medal?.level || 0;
|
|
211
234
|
const medalName = zminfoData.medal?.name || '';
|
|
212
235
|
if (medalName === this.config.forceBindTargetMedalName) {
|
|
@@ -495,30 +518,19 @@ class GroupRequestReviewHandler extends base_handler_1.BaseHandler {
|
|
|
495
518
|
* 检查管理员权限
|
|
496
519
|
*/
|
|
497
520
|
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
521
|
try {
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
return
|
|
522
|
+
const normalizedUserId = this.deps.normalizeQQId(userId);
|
|
523
|
+
// 检查是否是 masterId
|
|
524
|
+
if (this.config.masterId && normalizedUserId === this.config.masterId) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
// 检查数据库中的管理员标记(与其他功能保持一致)
|
|
528
|
+
const bind = await this.repos.mcidbind.findByQQId(normalizedUserId);
|
|
529
|
+
return bind?.isAdmin === true;
|
|
517
530
|
}
|
|
518
531
|
catch (error) {
|
|
519
|
-
this.logger.error('入群审批',
|
|
520
|
-
|
|
521
|
-
return userId === this.config.masterId;
|
|
532
|
+
this.logger.error('入群审批', `检查管理员权限失败: ${error.message}`);
|
|
533
|
+
return false;
|
|
522
534
|
}
|
|
523
535
|
}
|
|
524
536
|
/**
|