koishi-plugin-bind-bot 2.1.1 → 2.1.3
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.
- package/lib/export-utils.js +13 -6
- package/lib/force-bind-utils.js +12 -8
- package/lib/handlers/binding.handler.js +63 -27
- package/lib/handlers/buid.handler.js +102 -45
- package/lib/handlers/group-request-review.handler.d.ts +97 -0
- package/lib/handlers/group-request-review.handler.js +582 -0
- package/lib/handlers/index.d.ts +1 -0
- package/lib/handlers/index.js +1 -0
- package/lib/handlers/lottery.handler.js +11 -9
- package/lib/handlers/mcid.handler.js +197 -86
- package/lib/handlers/tag.handler.js +86 -31
- package/lib/handlers/whitelist.handler.js +252 -77
- package/lib/index.js +282 -142
- package/lib/repositories/mcidbind.repository.js +2 -2
- package/lib/repositories/schedule-mute.repository.js +2 -2
- package/lib/services/api.service.js +27 -23
- package/lib/services/database.service.js +16 -14
- package/lib/services/nickname.service.js +12 -16
- package/lib/types/api.d.ts +90 -0
- package/lib/types/common.d.ts +45 -0
- package/lib/types/config.d.ts +88 -0
- package/lib/types/database.d.ts +50 -0
- package/lib/types/update-data.d.ts +83 -0
- package/lib/utils/error-utils.js +7 -8
- package/lib/utils/helpers.js +45 -7
- package/lib/utils/message-utils.js +36 -23
- package/lib/utils/session-manager.js +6 -1
- package/package.json +12 -2
|
@@ -18,31 +18,34 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
18
18
|
register() {
|
|
19
19
|
const buidCmd = this.ctx.command('buid', 'B站UID绑定管理');
|
|
20
20
|
// 查询BUID绑定
|
|
21
|
-
buidCmd
|
|
21
|
+
buidCmd
|
|
22
|
+
.subcommand('.query [target:string]', '查询用户绑定的BUID')
|
|
22
23
|
.action(async ({ session }, target) => {
|
|
23
24
|
return this.handleQuery(session, target);
|
|
24
25
|
});
|
|
25
26
|
// 绑定BUID(支持强制模式)
|
|
26
|
-
buidCmd
|
|
27
|
+
buidCmd
|
|
28
|
+
.subcommand('.bind <uid:string> [target:string]', '绑定B站UID')
|
|
27
29
|
.option('force', '-f', { fallback: false })
|
|
28
30
|
.action(async ({ session, options }, uid, target) => {
|
|
29
31
|
return this.handleBind(session, uid, target, !!options.force);
|
|
30
32
|
});
|
|
31
33
|
// 通过BUID查找用户
|
|
32
|
-
buidCmd
|
|
34
|
+
buidCmd
|
|
35
|
+
.subcommand('.finduser <uid:string>', '[管理员]通过BUID查询绑定的QQ账号')
|
|
33
36
|
.action(async ({ session }, uid) => {
|
|
34
37
|
return this.handleFindUser(session, uid);
|
|
35
38
|
});
|
|
36
39
|
// mcid 命令组中的 BUID 相关子命令
|
|
37
40
|
const mcidCmd = this.ctx.command('mcid');
|
|
38
41
|
// 绑定B站账号(mcid.bindbuid)
|
|
39
|
-
mcidCmd
|
|
42
|
+
mcidCmd
|
|
43
|
+
.subcommand('.bindbuid <buid:string>', '绑定B站账号')
|
|
40
44
|
.action(async ({ session }, buid) => {
|
|
41
45
|
return this.handleBindBuid(session, buid);
|
|
42
46
|
});
|
|
43
47
|
// 解绑B站账号(mcid.unbindbuid)
|
|
44
|
-
mcidCmd.subcommand('.unbindbuid', '解绑B站账号')
|
|
45
|
-
.action(async ({ session }) => {
|
|
48
|
+
mcidCmd.subcommand('.unbindbuid', '解绑B站账号').action(async ({ session }) => {
|
|
46
49
|
return this.handleUnbindBuid(session);
|
|
47
50
|
});
|
|
48
51
|
}
|
|
@@ -63,7 +66,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
63
66
|
if (!bind || !bind.buidUid) {
|
|
64
67
|
return this.deps.sendMessage(session, [
|
|
65
68
|
koishi_1.h.text(target
|
|
66
|
-
?
|
|
69
|
+
? '该用户尚未绑定B站账号'
|
|
67
70
|
: `您尚未绑定B站账号,请使用 ${this.deps.formatCommand('buid bind <UID>')} 进行绑定`)
|
|
68
71
|
]);
|
|
69
72
|
}
|
|
@@ -125,7 +128,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
125
128
|
}
|
|
126
129
|
catch (error) {
|
|
127
130
|
this.logger.error('绑定', session.userId, error);
|
|
128
|
-
return this.deps.sendMessage(session, [
|
|
131
|
+
return this.deps.sendMessage(session, [
|
|
132
|
+
koishi_1.h.text(`绑定失败:${this.getFriendlyErrorMessage(error)}`)
|
|
133
|
+
]);
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
136
|
/**
|
|
@@ -195,43 +200,53 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
195
200
|
// 验证格式
|
|
196
201
|
if (!buid || !/^\d+$/.test(buid)) {
|
|
197
202
|
this.logger.warn('绑定', `QQ(${normalizedUserId})尝试绑定无效的B站UID格式: ${buid}`);
|
|
198
|
-
return this.deps.sendMessage(session, [koishi_1.h.text(
|
|
203
|
+
return this.deps.sendMessage(session, [koishi_1.h.text('无效的B站UID格式,请输入正确的B站UID')]);
|
|
199
204
|
}
|
|
200
205
|
// 检查是否已被他人绑定
|
|
201
206
|
const existingBind = await this.repos.mcidbind.findByBuidUid(buid);
|
|
202
207
|
if (existingBind) {
|
|
203
208
|
const existingQQId = existingBind.qqId;
|
|
204
209
|
this.logger.warn('绑定', `QQ(${normalizedUserId})尝试绑定已被QQ(${existingQQId})绑定的B站UID(${buid})`);
|
|
205
|
-
return this.deps.sendMessage(session, [koishi_1.h.text(
|
|
210
|
+
return this.deps.sendMessage(session, [koishi_1.h.text('该B站UID已被其他用户绑定')]);
|
|
206
211
|
}
|
|
207
212
|
// 验证B站UID
|
|
208
213
|
const buidUser = await this.validateBUID(buid);
|
|
209
214
|
if (!buidUser) {
|
|
210
215
|
this.logger.warn('绑定', `QQ(${normalizedUserId})尝试绑定不存在的B站UID(${buid})`);
|
|
211
|
-
return this.deps.sendMessage(session, [koishi_1.h.text(
|
|
216
|
+
return this.deps.sendMessage(session, [koishi_1.h.text('无法验证B站UID,请确认输入正确')]);
|
|
212
217
|
}
|
|
213
218
|
// 创建或更新绑定
|
|
214
219
|
const success = await this.createOrUpdateBuidBind(normalizedUserId, buidUser);
|
|
215
220
|
if (success) {
|
|
216
221
|
this.logger.info('绑定', `QQ(${normalizedUserId})成功绑定B站UID(${buid})`);
|
|
217
222
|
return this.deps.sendMessage(session, [
|
|
218
|
-
koishi_1.h.text(
|
|
223
|
+
koishi_1.h.text('成功绑定B站账号!\n'),
|
|
219
224
|
koishi_1.h.text(`B站UID: ${buidUser.uid}\n`),
|
|
220
225
|
koishi_1.h.text(`用户名: ${buidUser.username}\n`),
|
|
221
|
-
buidUser.guard_level > 0
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
226
|
+
buidUser.guard_level > 0
|
|
227
|
+
? koishi_1.h.text(`舰长等级: ${buidUser.guard_level_text} (${buidUser.guard_level})\n`)
|
|
228
|
+
: null,
|
|
229
|
+
buidUser.medal
|
|
230
|
+
? koishi_1.h.text(`粉丝牌: ${buidUser.medal.name} Lv.${buidUser.medal.level}\n`)
|
|
231
|
+
: null,
|
|
232
|
+
buidUser.wealthMedalLevel > 0
|
|
233
|
+
? koishi_1.h.text(`荣耀等级: ${buidUser.wealthMedalLevel}\n`)
|
|
234
|
+
: null,
|
|
235
|
+
...(this.config?.showAvatar
|
|
236
|
+
? [koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${buidUser.uid}?size=160`)]
|
|
237
|
+
: [])
|
|
225
238
|
].filter(Boolean));
|
|
226
239
|
}
|
|
227
240
|
else {
|
|
228
241
|
this.logger.error('绑定', normalizedUserId, `QQ(${normalizedUserId})绑定B站UID(${buid})失败`);
|
|
229
|
-
return this.deps.sendMessage(session, [koishi_1.h.text(
|
|
242
|
+
return this.deps.sendMessage(session, [koishi_1.h.text('绑定失败,请稍后重试')]);
|
|
230
243
|
}
|
|
231
244
|
}
|
|
232
245
|
catch (error) {
|
|
233
246
|
this.logger.error('绑定', session.userId, error);
|
|
234
|
-
return this.deps.sendMessage(session, [
|
|
247
|
+
return this.deps.sendMessage(session, [
|
|
248
|
+
koishi_1.h.text(`绑定失败:${this.getFriendlyErrorMessage(error)}`)
|
|
249
|
+
]);
|
|
235
250
|
}
|
|
236
251
|
}
|
|
237
252
|
/**
|
|
@@ -245,7 +260,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
245
260
|
const bind = await this.repos.mcidbind.findByQQId(normalizedUserId);
|
|
246
261
|
if (!bind || !bind.buidUid) {
|
|
247
262
|
this.logger.warn('解绑', `QQ(${normalizedUserId})尝试解绑未绑定的B站账号`);
|
|
248
|
-
return this.deps.sendMessage(session, [koishi_1.h.text(
|
|
263
|
+
return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定B站账号')]);
|
|
249
264
|
}
|
|
250
265
|
// 更新绑定信息
|
|
251
266
|
const updateData = {
|
|
@@ -261,11 +276,13 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
261
276
|
};
|
|
262
277
|
await this.repos.mcidbind.update(normalizedUserId, updateData);
|
|
263
278
|
this.logger.info('解绑', `QQ(${normalizedUserId})成功解绑B站账号`);
|
|
264
|
-
return this.deps.sendMessage(session, [koishi_1.h.text(
|
|
279
|
+
return this.deps.sendMessage(session, [koishi_1.h.text('已成功解绑B站账号')]);
|
|
265
280
|
}
|
|
266
281
|
catch (error) {
|
|
267
282
|
this.logger.error('解绑', session.userId, error);
|
|
268
|
-
return this.deps.sendMessage(session, [
|
|
283
|
+
return this.deps.sendMessage(session, [
|
|
284
|
+
koishi_1.h.text(`解绑失败:${this.getFriendlyErrorMessage(error)}`)
|
|
285
|
+
]);
|
|
269
286
|
}
|
|
270
287
|
}
|
|
271
288
|
// ========== 私有辅助方法 ==========
|
|
@@ -357,7 +374,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
357
374
|
try {
|
|
358
375
|
const normalizedQQId = this.deps.normalizeQQId(userId);
|
|
359
376
|
if (!normalizedQQId) {
|
|
360
|
-
this.logger.error('B站账号绑定', 'system',
|
|
377
|
+
this.logger.error('B站账号绑定', 'system', '创建/更新绑定失败: 无法提取有效的QQ号');
|
|
361
378
|
return false;
|
|
362
379
|
}
|
|
363
380
|
// 安全检查
|
|
@@ -377,7 +394,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
377
394
|
medalName: buidUser.medal?.name || '',
|
|
378
395
|
medalLevel: buidUser.medal?.level || 0,
|
|
379
396
|
wealthMedalLevel: buidUser.wealthMedalLevel || 0,
|
|
380
|
-
lastActiveTime: buidUser.last_active_time
|
|
397
|
+
lastActiveTime: buidUser.last_active_time
|
|
398
|
+
? new Date(buidUser.last_active_time)
|
|
399
|
+
: new Date(),
|
|
381
400
|
lastModified: new Date()
|
|
382
401
|
};
|
|
383
402
|
if (bind) {
|
|
@@ -412,7 +431,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
412
431
|
try {
|
|
413
432
|
const normalizedQQId = this.deps.normalizeQQId(userId);
|
|
414
433
|
if (!normalizedQQId) {
|
|
415
|
-
this.logger.error('B站账号信息更新', 'system',
|
|
434
|
+
this.logger.error('B站账号信息更新', 'system', '更新失败: 无法提取有效的QQ号');
|
|
416
435
|
return false;
|
|
417
436
|
}
|
|
418
437
|
const bind = await this.repos.mcidbind.findByQQId(normalizedQQId);
|
|
@@ -467,10 +486,14 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
467
486
|
// 检查配置
|
|
468
487
|
if (!this.config.forceBindSessdata) {
|
|
469
488
|
this.logger.warn('强制BUID绑定', `QQ(${operatorQQId})尝试强制绑定但未配置Cookie`);
|
|
470
|
-
return this.deps.sendMessage(session, [
|
|
489
|
+
return this.deps.sendMessage(session, [
|
|
490
|
+
koishi_1.h.text('❌ 强制绑定功能未配置,请联系管理员设置B站Cookie信息')
|
|
491
|
+
]);
|
|
471
492
|
}
|
|
472
493
|
try {
|
|
473
|
-
await this.deps.sendMessage(session, [
|
|
494
|
+
await this.deps.sendMessage(session, [
|
|
495
|
+
koishi_1.h.text('🔄 正在使用强制模式获取用户信息和粉丝牌数据,请稍候...')
|
|
496
|
+
]);
|
|
474
497
|
// 执行强制绑定
|
|
475
498
|
const enhancedUser = await this.deps.forceBinder.forceBindUser(actualUid);
|
|
476
499
|
const standardUser = this.deps.forceBinder.convertToZminfoUser(enhancedUser);
|
|
@@ -490,7 +513,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
490
513
|
// 检查UID是否已被占用
|
|
491
514
|
if (await this.checkBuidExists(actualUid, target)) {
|
|
492
515
|
this.logger.warn('强制BUID绑定', `BUID"${actualUid}"已被其他QQ号绑定`);
|
|
493
|
-
return this.deps.sendMessage(session, [
|
|
516
|
+
return this.deps.sendMessage(session, [
|
|
517
|
+
koishi_1.h.text(`❌ UID ${actualUid} 已被其他用户绑定,即使使用强制模式也无法绑定已被占用的UID`)
|
|
518
|
+
]);
|
|
494
519
|
}
|
|
495
520
|
const bindResult = await this.createOrUpdateBuidBind(normalizedTargetId, standardUser);
|
|
496
521
|
if (bindResult) {
|
|
@@ -498,7 +523,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
498
523
|
try {
|
|
499
524
|
const latestTargetBind = await this.repos.mcidbind.findByQQId(normalizedTargetId);
|
|
500
525
|
if (latestTargetBind) {
|
|
501
|
-
const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_')
|
|
526
|
+
const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_')
|
|
527
|
+
? latestTargetBind.mcUsername
|
|
528
|
+
: null;
|
|
502
529
|
await this.deps.nicknameService.autoSetGroupNickname(session, mcName, enhancedUser.username, String(enhancedUser.uid), normalizedTargetId);
|
|
503
530
|
}
|
|
504
531
|
}
|
|
@@ -510,7 +537,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
510
537
|
this.deps.removeBindingSession(target, session.channelId);
|
|
511
538
|
this.logger.info('强制绑定', `管理员为QQ(${normalizedTargetId})强制绑定B站账号后,已清理该用户的交互式绑定会话`);
|
|
512
539
|
const medalDetails = this.deps.forceBinder.getTargetMedalDetails(enhancedUser);
|
|
513
|
-
return this.deps.sendMessage(session, [
|
|
540
|
+
return this.deps.sendMessage(session, [
|
|
541
|
+
koishi_1.h.text(`✅ 已成功为用户 ${normalizedTargetId} 强制绑定B站账号\n用户名: ${enhancedUser.username}\nUID: ${actualUid}\n\n${medalDetails}`)
|
|
542
|
+
]);
|
|
514
543
|
}
|
|
515
544
|
else {
|
|
516
545
|
this.logger.error('强制BUID绑定', operatorQQId, `为QQ(${normalizedTargetId})强制绑定失败`);
|
|
@@ -521,7 +550,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
521
550
|
// 为自己强制绑定
|
|
522
551
|
if (await this.checkBuidExists(actualUid, session.userId)) {
|
|
523
552
|
this.logger.warn('强制BUID绑定', `BUID"${actualUid}"已被其他QQ号绑定`);
|
|
524
|
-
return this.deps.sendMessage(session, [
|
|
553
|
+
return this.deps.sendMessage(session, [
|
|
554
|
+
koishi_1.h.text(`❌ UID ${actualUid} 已被其他用户绑定,即使使用强制模式也无法绑定已被占用的UID`)
|
|
555
|
+
]);
|
|
525
556
|
}
|
|
526
557
|
const bindResult = await this.createOrUpdateBuidBind(session.userId, standardUser);
|
|
527
558
|
if (bindResult) {
|
|
@@ -529,7 +560,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
529
560
|
try {
|
|
530
561
|
const latestBind = await this.repos.mcidbind.findByQQId(operatorQQId);
|
|
531
562
|
if (latestBind) {
|
|
532
|
-
const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_')
|
|
563
|
+
const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_')
|
|
564
|
+
? latestBind.mcUsername
|
|
565
|
+
: null;
|
|
533
566
|
await this.deps.nicknameService.autoSetGroupNickname(session, mcName, enhancedUser.username, String(enhancedUser.uid));
|
|
534
567
|
}
|
|
535
568
|
}
|
|
@@ -540,11 +573,13 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
540
573
|
const medalDetails = this.deps.forceBinder.getTargetMedalDetails(enhancedUser);
|
|
541
574
|
return this.deps.sendMessage(session, [
|
|
542
575
|
koishi_1.h.text(`✅ 强制绑定成功!\nB站UID: ${enhancedUser.uid}\n用户名: ${enhancedUser.username}\n\n${medalDetails}`),
|
|
543
|
-
...(this.config?.showAvatar
|
|
576
|
+
...(this.config?.showAvatar
|
|
577
|
+
? [koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${enhancedUser.uid}?size=160`)]
|
|
578
|
+
: [])
|
|
544
579
|
]);
|
|
545
580
|
}
|
|
546
581
|
else {
|
|
547
|
-
this.logger.error('强制BUID绑定', operatorQQId,
|
|
582
|
+
this.logger.error('强制BUID绑定', operatorQQId, '强制绑定失败');
|
|
548
583
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 强制绑定失败,数据库操作出错')]);
|
|
549
584
|
}
|
|
550
585
|
}
|
|
@@ -562,9 +597,13 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
562
597
|
if (!normalizedTargetId) {
|
|
563
598
|
this.logger.warn('BUID绑定', `QQ(${operatorQQId})提供的目标用户ID"${target}"无效`);
|
|
564
599
|
if (target.startsWith('@')) {
|
|
565
|
-
return this.deps.sendMessage(session, [
|
|
600
|
+
return this.deps.sendMessage(session, [
|
|
601
|
+
koishi_1.h.text('❌ 请使用真正的@功能,而不是手动输入@符号\n正确做法:点击或长按用户头像选择@功能')
|
|
602
|
+
]);
|
|
566
603
|
}
|
|
567
|
-
return this.deps.sendMessage(session, [
|
|
604
|
+
return this.deps.sendMessage(session, [
|
|
605
|
+
koishi_1.h.text('❌ 目标用户ID无效\n请提供有效的QQ号或使用@功能选择用户')
|
|
606
|
+
]);
|
|
568
607
|
}
|
|
569
608
|
this.logger.debug('BUID绑定', `QQ(${operatorQQId})尝试为QQ(${normalizedTargetId})绑定BUID: ${actualUid}`);
|
|
570
609
|
// 检查权限
|
|
@@ -582,13 +621,17 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
582
621
|
const buidUser = await this.validateBUID(actualUid);
|
|
583
622
|
if (!buidUser) {
|
|
584
623
|
this.logger.warn('BUID绑定', `QQ(${operatorQQId})提供的UID"${actualUid}"不存在`);
|
|
585
|
-
return this.deps.sendMessage(session, [
|
|
624
|
+
return this.deps.sendMessage(session, [
|
|
625
|
+
koishi_1.h.text(`无法验证UID: ${actualUid},该用户可能不存在或未被发现,你可以去直播间发个弹幕回来再绑定`)
|
|
626
|
+
]);
|
|
586
627
|
}
|
|
587
628
|
// 创建或更新绑定
|
|
588
629
|
const bindResult = await this.createOrUpdateBuidBind(normalizedTargetId, buidUser);
|
|
589
630
|
if (!bindResult) {
|
|
590
631
|
this.logger.error('BUID绑定', operatorQQId, `管理员QQ(${operatorQQId})为QQ(${normalizedTargetId})绑定BUID"${actualUid}"失败`);
|
|
591
|
-
return this.deps.sendMessage(session, [
|
|
632
|
+
return this.deps.sendMessage(session, [
|
|
633
|
+
koishi_1.h.text(`为用户 ${normalizedTargetId} 绑定BUID失败: 数据库操作出错,请联系管理员`)
|
|
634
|
+
]);
|
|
592
635
|
}
|
|
593
636
|
this.logger.info('为他人绑定BUID', `管理员QQ(${operatorQQId})为QQ(${normalizedTargetId})绑定BUID: ${actualUid}(${buidUser.username})`, true);
|
|
594
637
|
// 清理目标用户的绑定会话
|
|
@@ -598,7 +641,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
598
641
|
try {
|
|
599
642
|
const latestTargetBind = await this.repos.mcidbind.findByQQId(normalizedTargetId);
|
|
600
643
|
if (latestTargetBind) {
|
|
601
|
-
const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_')
|
|
644
|
+
const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_')
|
|
645
|
+
? latestTargetBind.mcUsername
|
|
646
|
+
: null;
|
|
602
647
|
await this.deps.nicknameService.autoSetGroupNickname(session, mcName, buidUser.username, actualUid, normalizedTargetId);
|
|
603
648
|
this.logger.info('绑定', `管理员QQ(${operatorQQId})为QQ(${normalizedTargetId})B站绑定完成,已尝试设置群昵称`);
|
|
604
649
|
}
|
|
@@ -626,7 +671,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
626
671
|
const passedDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
627
672
|
const remainingDays = days - passedDays;
|
|
628
673
|
this.logger.warn('BUID绑定', `QQ(${operatorQQId})已绑定BUID"${selfBind.buidUid}",且在冷却期内,还需${remainingDays}天`);
|
|
629
|
-
return this.deps.sendMessage(session, [
|
|
674
|
+
return this.deps.sendMessage(session, [
|
|
675
|
+
koishi_1.h.text(`您已绑定B站UID: ${selfBind.buidUid},如需修改,请在冷却期结束后(还需${remainingDays}天)或联系管理员。`)
|
|
676
|
+
]);
|
|
630
677
|
}
|
|
631
678
|
this.logger.debug('BUID绑定', `QQ(${operatorQQId})已绑定BUID"${selfBind.buidUid}",将进行更新`);
|
|
632
679
|
}
|
|
@@ -639,7 +686,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
639
686
|
const buidUser = await this.validateBUID(actualUid);
|
|
640
687
|
if (!buidUser) {
|
|
641
688
|
this.logger.warn('BUID绑定', `QQ(${operatorQQId})提供的UID"${actualUid}"不存在`);
|
|
642
|
-
return this.deps.sendMessage(session, [
|
|
689
|
+
return this.deps.sendMessage(session, [
|
|
690
|
+
koishi_1.h.text(`无法验证UID: ${actualUid},该用户可能不存在或未被发现,你可以去直播间逛一圈,发个弹幕回来再绑定`)
|
|
691
|
+
]);
|
|
643
692
|
}
|
|
644
693
|
// 创建或更新绑定
|
|
645
694
|
const bindResult = await this.createOrUpdateBuidBind(session.userId, buidUser);
|
|
@@ -652,7 +701,9 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
652
701
|
try {
|
|
653
702
|
const latestBind = await this.repos.mcidbind.findByQQId(operatorQQId);
|
|
654
703
|
if (latestBind) {
|
|
655
|
-
const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_')
|
|
704
|
+
const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_')
|
|
705
|
+
? latestBind.mcUsername
|
|
706
|
+
: null;
|
|
656
707
|
await this.deps.nicknameService.autoSetGroupNickname(session, mcName, buidUser.username, actualUid);
|
|
657
708
|
this.logger.info('绑定', `QQ(${operatorQQId})B站绑定完成,已尝试设置群昵称`);
|
|
658
709
|
}
|
|
@@ -662,13 +713,19 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
662
713
|
}
|
|
663
714
|
this.logger.info('绑定', `QQ(${operatorQQId})成功绑定B站UID(${actualUid})`);
|
|
664
715
|
return this.deps.sendMessage(session, [
|
|
665
|
-
koishi_1.h.text(
|
|
716
|
+
koishi_1.h.text('成功绑定B站账号!\n'),
|
|
666
717
|
koishi_1.h.text(`B站UID: ${buidUser.uid}\n`),
|
|
667
718
|
koishi_1.h.text(`用户名: ${buidUser.username}\n`),
|
|
668
|
-
buidUser.guard_level > 0
|
|
669
|
-
|
|
719
|
+
buidUser.guard_level > 0
|
|
720
|
+
? koishi_1.h.text(`舰长等级: ${buidUser.guard_level_text} (${buidUser.guard_level})\n`)
|
|
721
|
+
: null,
|
|
722
|
+
buidUser.medal
|
|
723
|
+
? koishi_1.h.text(`粉丝牌: ${buidUser.medal.name} Lv.${buidUser.medal.level}\n`)
|
|
724
|
+
: null,
|
|
670
725
|
buidUser.wealthMedalLevel > 0 ? koishi_1.h.text(`荣耀等级: ${buidUser.wealthMedalLevel}\n`) : null,
|
|
671
|
-
...(this.config?.showAvatar
|
|
726
|
+
...(this.config?.showAvatar
|
|
727
|
+
? [koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${buidUser.uid}?size=160`)]
|
|
728
|
+
: [])
|
|
672
729
|
].filter(Boolean));
|
|
673
730
|
}
|
|
674
731
|
/**
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { BaseHandler } from './base.handler';
|
|
2
|
+
/**
|
|
3
|
+
* 入群申请审批处理器
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* 该处理器实现了通过表情回应审批入群申请的功能:
|
|
7
|
+
* - 监听指定群的入群申请
|
|
8
|
+
* - 生成播报消息到管理群
|
|
9
|
+
* - 自动添加表情选项
|
|
10
|
+
* - 处理管理员的表情回应
|
|
11
|
+
* - 执行批准/拒绝操作
|
|
12
|
+
* - 支持自动绑定和交互式绑定
|
|
13
|
+
*/
|
|
14
|
+
export declare class GroupRequestReviewHandler extends BaseHandler {
|
|
15
|
+
/** 待审批的申请记录 Map<broadcastMessageId, PendingRequest> */
|
|
16
|
+
private pendingRequests;
|
|
17
|
+
/** 拒绝流程状态 Map<askMessageId, RejectFlow> */
|
|
18
|
+
private rejectFlows;
|
|
19
|
+
/** 管理员权限缓存 Map<groupId, AdminCache> */
|
|
20
|
+
private adminCache;
|
|
21
|
+
/** 用户进群等待列表 Map<userId, resolve> */
|
|
22
|
+
private userJoinWaiters;
|
|
23
|
+
/** 配置 */
|
|
24
|
+
private reviewConfig;
|
|
25
|
+
/**
|
|
26
|
+
* 注册事件监听和中间件
|
|
27
|
+
*/
|
|
28
|
+
register(): void;
|
|
29
|
+
/**
|
|
30
|
+
* 处理入群申请事件
|
|
31
|
+
*/
|
|
32
|
+
private handleRequest;
|
|
33
|
+
/**
|
|
34
|
+
* 处理通知事件(包括表情回应)
|
|
35
|
+
*/
|
|
36
|
+
private handleNotice;
|
|
37
|
+
/**
|
|
38
|
+
* 获取申请人信息
|
|
39
|
+
*/
|
|
40
|
+
private getApplicantInfo;
|
|
41
|
+
/**
|
|
42
|
+
* 发送播报消息到管理群
|
|
43
|
+
*/
|
|
44
|
+
private sendBroadcastMessage;
|
|
45
|
+
/**
|
|
46
|
+
* 自动添加表情回应选项
|
|
47
|
+
*/
|
|
48
|
+
private addReactionOptions;
|
|
49
|
+
/**
|
|
50
|
+
* 处理表情回应动作
|
|
51
|
+
*/
|
|
52
|
+
private handleEmojiReaction;
|
|
53
|
+
/**
|
|
54
|
+
* 批准并自动绑定
|
|
55
|
+
*/
|
|
56
|
+
private approveAndAutoBind;
|
|
57
|
+
/**
|
|
58
|
+
* 批准并启动交互式绑定
|
|
59
|
+
*/
|
|
60
|
+
private approveAndInteractiveBind;
|
|
61
|
+
/**
|
|
62
|
+
* 发起拒绝流程
|
|
63
|
+
*/
|
|
64
|
+
private initRejectFlow;
|
|
65
|
+
/**
|
|
66
|
+
* 处理拒绝理由(中间件)
|
|
67
|
+
*/
|
|
68
|
+
private handleRejectReason;
|
|
69
|
+
/**
|
|
70
|
+
* 处理用户成功进群事件
|
|
71
|
+
*/
|
|
72
|
+
private handleUserJoined;
|
|
73
|
+
/**
|
|
74
|
+
* 等待用户进群
|
|
75
|
+
*/
|
|
76
|
+
private waitForUserJoin;
|
|
77
|
+
/**
|
|
78
|
+
* 检查管理员权限
|
|
79
|
+
*/
|
|
80
|
+
private checkAdminPermission;
|
|
81
|
+
/**
|
|
82
|
+
* 解析UID(支持多种格式)
|
|
83
|
+
*/
|
|
84
|
+
private parseUID;
|
|
85
|
+
/**
|
|
86
|
+
* 通知管理员
|
|
87
|
+
*/
|
|
88
|
+
private notifyAdmin;
|
|
89
|
+
/**
|
|
90
|
+
* 执行自动绑定
|
|
91
|
+
*/
|
|
92
|
+
private performAutoBind;
|
|
93
|
+
/**
|
|
94
|
+
* 定时清理过期记录
|
|
95
|
+
*/
|
|
96
|
+
private cleanupExpiredRecords;
|
|
97
|
+
}
|