koishi-plugin-bind-bot 2.0.3 → 2.0.5
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/handlers/base.handler.d.ts +1 -1
- package/lib/handlers/buid.handler.js +4 -4
- package/lib/handlers/mcid.handler.js +15 -12
- package/lib/index.js +123 -17
- package/lib/utils/helpers.d.ts +13 -0
- package/lib/utils/helpers.js +21 -0
- package/lib/utils/message-utils.d.ts +7 -2
- package/lib/utils/message-utils.js +117 -12
- package/package.json +1 -1
|
@@ -38,7 +38,7 @@ export interface HandlerDependencies {
|
|
|
38
38
|
isAdmin: (userId: string) => Promise<boolean>;
|
|
39
39
|
isMaster: (userId: string) => boolean;
|
|
40
40
|
sendMessage: (session: Session, content: any[], options?: any) => Promise<void>;
|
|
41
|
-
autoSetGroupNickname: (session: Session, mcUsername: string | null, buidUsername: string, targetUserId?: string, specifiedGroupId?: string) => Promise<void>;
|
|
41
|
+
autoSetGroupNickname: (session: Session, mcUsername: string | null, buidUsername: string, buidUid?: string, targetUserId?: string, specifiedGroupId?: string) => Promise<void>;
|
|
42
42
|
checkNicknameFormat: (nickname: string, buidUsername: string, mcUsername: string | null) => boolean;
|
|
43
43
|
getBindInfo: (qqId: string) => Promise<MCIDBIND | null>;
|
|
44
44
|
getServerConfigById: (serverId: string) => any;
|
|
@@ -499,7 +499,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
499
499
|
const latestTargetBind = await this.repos.mcidbind.findByQQId(normalizedTargetId);
|
|
500
500
|
if (latestTargetBind) {
|
|
501
501
|
const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_') ? latestTargetBind.mcUsername : null;
|
|
502
|
-
await this.deps.autoSetGroupNickname(session, mcName, enhancedUser.username, normalizedTargetId);
|
|
502
|
+
await this.deps.autoSetGroupNickname(session, mcName, enhancedUser.username, String(enhancedUser.uid), normalizedTargetId);
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
505
|
catch (renameError) {
|
|
@@ -530,7 +530,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
530
530
|
const latestBind = await this.repos.mcidbind.findByQQId(operatorQQId);
|
|
531
531
|
if (latestBind) {
|
|
532
532
|
const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_') ? latestBind.mcUsername : null;
|
|
533
|
-
await this.deps.autoSetGroupNickname(session, mcName, enhancedUser.username);
|
|
533
|
+
await this.deps.autoSetGroupNickname(session, mcName, enhancedUser.username, String(enhancedUser.uid));
|
|
534
534
|
}
|
|
535
535
|
}
|
|
536
536
|
catch (renameError) {
|
|
@@ -599,7 +599,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
599
599
|
const latestTargetBind = await this.repos.mcidbind.findByQQId(normalizedTargetId);
|
|
600
600
|
if (latestTargetBind) {
|
|
601
601
|
const mcName = latestTargetBind.mcUsername && !latestTargetBind.mcUsername.startsWith('_temp_') ? latestTargetBind.mcUsername : null;
|
|
602
|
-
await this.deps.autoSetGroupNickname(session, mcName, buidUser.username, normalizedTargetId);
|
|
602
|
+
await this.deps.autoSetGroupNickname(session, mcName, buidUser.username, actualUid, normalizedTargetId);
|
|
603
603
|
this.logger.info('绑定', `管理员QQ(${operatorQQId})为QQ(${normalizedTargetId})B站绑定完成,已尝试设置群昵称`);
|
|
604
604
|
}
|
|
605
605
|
}
|
|
@@ -653,7 +653,7 @@ class BuidHandler extends base_handler_1.BaseHandler {
|
|
|
653
653
|
const latestBind = await this.repos.mcidbind.findByQQId(operatorQQId);
|
|
654
654
|
if (latestBind) {
|
|
655
655
|
const mcName = latestBind.mcUsername && !latestBind.mcUsername.startsWith('_temp_') ? latestBind.mcUsername : null;
|
|
656
|
-
await this.deps.autoSetGroupNickname(session, mcName, buidUser.username);
|
|
656
|
+
await this.deps.autoSetGroupNickname(session, mcName, buidUser.username, actualUid);
|
|
657
657
|
this.logger.info('绑定', `QQ(${operatorQQId})B站绑定完成,已尝试设置群昵称`);
|
|
658
658
|
}
|
|
659
659
|
}
|
|
@@ -211,14 +211,6 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
211
211
|
buidInfo = targetId ? '该用户尚未绑定B站账号' : `您尚未绑定B站账号,使用 ${this.deps.formatCommand('buid bind <B站UID>')} 进行绑定`;
|
|
212
212
|
}
|
|
213
213
|
this.logger.info('查询', `QQ(${bind.qqId})的MC账号信息:用户名=${bind.mcUsername}, UUID=${bind.mcUuid}`);
|
|
214
|
-
// 自动设置群昵称
|
|
215
|
-
if (bind.buidUid && bind.buidUsername) {
|
|
216
|
-
const mcName = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : null;
|
|
217
|
-
await this.deps.autoSetGroupNickname(session, mcName, bind.buidUsername, targetId || undefined);
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
this.logger.info('查询', `QQ(${bind.qqId})未绑定B站账号,跳过群昵称设置`);
|
|
221
|
-
}
|
|
222
214
|
const displayUsername = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : '未绑定';
|
|
223
215
|
const prefix = targetId ? `用户 ${targetId} 的` : '您的';
|
|
224
216
|
const messageElements = [
|
|
@@ -227,7 +219,18 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
227
219
|
koishi_1.h.text(`\n${buidInfo}`),
|
|
228
220
|
...(buidAvatar ? [buidAvatar] : [])
|
|
229
221
|
];
|
|
230
|
-
|
|
222
|
+
// 先发送响应,然后异步设置群昵称
|
|
223
|
+
const sendPromise = this.deps.sendMessage(session, messageElements);
|
|
224
|
+
// 异步设置群昵称
|
|
225
|
+
if (bind.buidUid && bind.buidUsername) {
|
|
226
|
+
const mcName = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : null;
|
|
227
|
+
this.deps.autoSetGroupNickname(session, mcName, bind.buidUsername, bind.buidUid, targetId || undefined)
|
|
228
|
+
.catch(err => this.logger.warn('查询', `群昵称设置失败: ${err.message}`));
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.logger.info('查询', `QQ(${bind.qqId})未绑定B站账号,跳过群昵称设置`);
|
|
232
|
+
}
|
|
233
|
+
return sendPromise;
|
|
231
234
|
}
|
|
232
235
|
/**
|
|
233
236
|
* 通过MC用户名查询QQ号
|
|
@@ -357,7 +360,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
357
360
|
try {
|
|
358
361
|
const latestTargetBind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
359
362
|
if (latestTargetBind && latestTargetBind.buidUid && latestTargetBind.buidUsername) {
|
|
360
|
-
await this.deps.autoSetGroupNickname(session, username, latestTargetBind.buidUsername, normalizedTargetId);
|
|
363
|
+
await this.deps.autoSetGroupNickname(session, username, latestTargetBind.buidUsername, latestTargetBind.buidUid, normalizedTargetId);
|
|
361
364
|
this.logger.info('绑定', `管理员QQ(${operatorId})为QQ(${normalizedTargetId})MC绑定完成,已尝试设置群昵称`);
|
|
362
365
|
targetBuidStatus = '\n✅ 该用户已绑定B站账号,群昵称已更新';
|
|
363
366
|
}
|
|
@@ -428,7 +431,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
428
431
|
try {
|
|
429
432
|
const latestBind = await this.deps.getMcBindByQQId(operatorId);
|
|
430
433
|
if (latestBind && latestBind.buidUid && latestBind.buidUsername) {
|
|
431
|
-
await this.deps.autoSetGroupNickname(session, username, latestBind.buidUsername);
|
|
434
|
+
await this.deps.autoSetGroupNickname(session, username, latestBind.buidUsername, latestBind.buidUid);
|
|
432
435
|
this.logger.info('绑定', `QQ(${operatorId})MC绑定完成,已尝试设置群昵称`);
|
|
433
436
|
}
|
|
434
437
|
else {
|
|
@@ -873,7 +876,7 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
873
876
|
const isCorrect = this.deps.checkNicknameFormat(currentNickname, bind.buidUsername, mcInfo);
|
|
874
877
|
if (!isCorrect) {
|
|
875
878
|
// 修复群昵称
|
|
876
|
-
await this.deps.autoSetGroupNickname(session, mcInfo, bind.buidUsername, bind.qqId, targetGroupId);
|
|
879
|
+
await this.deps.autoSetGroupNickname(session, mcInfo, bind.buidUsername, bind.buidUid, bind.qqId, targetGroupId);
|
|
877
880
|
fixedCount++;
|
|
878
881
|
const expectedFormat = `${bind.buidUsername}(ID:${mcInfo || '未绑定'})`;
|
|
879
882
|
results.push(`✅ ${bind.qqId}: "${currentNickname}" → "${expectedFormat}"`);
|
package/lib/index.js
CHANGED
|
@@ -260,14 +260,15 @@ function apply(ctx, config) {
|
|
|
260
260
|
}
|
|
261
261
|
};
|
|
262
262
|
// 自动群昵称设置功能
|
|
263
|
-
const autoSetGroupNickname = async (session, mcUsername, buidUsername, targetUserId, specifiedGroupId) => {
|
|
263
|
+
const autoSetGroupNickname = async (session, mcUsername, buidUsername, buidUid, targetUserId, specifiedGroupId) => {
|
|
264
264
|
try {
|
|
265
265
|
// 如果指定了目标用户ID,使用目标用户ID,否则使用session的用户ID
|
|
266
266
|
const actualUserId = targetUserId || session.userId;
|
|
267
267
|
const normalizedUserId = normalizeQQId(actualUserId);
|
|
268
268
|
// 根据MC绑定状态设置不同的格式(临时用户名视为未绑定)
|
|
269
269
|
const mcInfo = (mcUsername && !mcUsername.startsWith('_temp_')) ? mcUsername : "未绑定";
|
|
270
|
-
|
|
270
|
+
let currentBuidUsername = buidUsername;
|
|
271
|
+
const newNickname = `${currentBuidUsername}(ID:${mcInfo})`;
|
|
271
272
|
// 使用指定的群ID,如果没有指定则使用配置的默认群ID
|
|
272
273
|
const targetGroupId = specifiedGroupId || config.autoNicknameGroupId;
|
|
273
274
|
logger.debug(`[群昵称设置] 开始处理QQ(${normalizedUserId})的群昵称设置,目标群: ${targetGroupId}`);
|
|
@@ -286,20 +287,82 @@ function apply(ctx, config) {
|
|
|
286
287
|
logger.info(`[群昵称设置] QQ(${normalizedUserId})群昵称已经是"${newNickname}",跳过修改`);
|
|
287
288
|
return;
|
|
288
289
|
}
|
|
290
|
+
// 昵称不一致,先尝试获取最新的B站用户信息
|
|
291
|
+
if (buidUid) {
|
|
292
|
+
logger.debug(`[群昵称设置] 检测到昵称不一致,尝试获取B站UID ${buidUid} 的最新信息...`);
|
|
293
|
+
// 1. 提取当前群昵称中的B站用户名
|
|
294
|
+
const currentNicknameUsername = (0, helpers_1.extractBuidUsernameFromNickname)(currentNickname);
|
|
295
|
+
logger.debug(`[群昵称设置] 从当前群昵称"${currentNickname}"中提取到B站名称: ${currentNicknameUsername || '(无法提取)'}`);
|
|
296
|
+
try {
|
|
297
|
+
const latestBuidUser = await validateBUID(buidUid);
|
|
298
|
+
if (latestBuidUser && latestBuidUser.username) {
|
|
299
|
+
logger.debug(`[群昵称设置] API返回B站用户名: "${latestBuidUser.username}"`);
|
|
300
|
+
// 2. 智能三层判断
|
|
301
|
+
// 情况A: API返回 == 当前群昵称中的名称
|
|
302
|
+
if (currentNicknameUsername && latestBuidUser.username === currentNicknameUsername) {
|
|
303
|
+
logger.info(`[群昵称设置] ✅ 当前群昵称"${currentNickname}"已包含正确的B站名称"${currentNicknameUsername}"`);
|
|
304
|
+
// 群昵称已经正确,仅需更新数据库(如果数据库是旧的)
|
|
305
|
+
if (latestBuidUser.username !== buidUsername) {
|
|
306
|
+
logger.info(`[群昵称设置] 数据库中的B站名称需要更新: "${buidUsername}" → "${latestBuidUser.username}"`);
|
|
307
|
+
try {
|
|
308
|
+
await updateBuidInfoOnly(normalizedUserId, latestBuidUser);
|
|
309
|
+
logger.info(`[群昵称设置] 已更新数据库中的B站用户名`);
|
|
310
|
+
}
|
|
311
|
+
catch (updateError) {
|
|
312
|
+
logger.warn(`[群昵称设置] 更新数据库失败: ${updateError.message}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
logger.debug(`[群昵称设置] 数据库中的B站名称已是最新,无需更新`);
|
|
317
|
+
}
|
|
318
|
+
// 跳过群昵称修改
|
|
319
|
+
logger.info(`[群昵称设置] 群昵称格式正确且名称最新,跳过修改`);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
// 情况B: API返回 == 数据库(都是旧的)
|
|
323
|
+
if (latestBuidUser.username === buidUsername) {
|
|
324
|
+
logger.warn(`[群昵称设置] ⚠️ API返回的B站名称"${latestBuidUser.username}"与数据库一致,但与群昵称不符`);
|
|
325
|
+
logger.warn(`[群昵称设置] 可能是API缓存未刷新,采用保守策略:不修改群昵称`);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
// 情况C: API返回新数据(!= 群昵称 且 != 数据库)
|
|
329
|
+
logger.info(`[群昵称设置] 检测到B站用户名已更新: "${buidUsername}" → "${latestBuidUser.username}"`);
|
|
330
|
+
currentBuidUsername = latestBuidUser.username;
|
|
331
|
+
// 更新数据库中的B站信息
|
|
332
|
+
try {
|
|
333
|
+
await updateBuidInfoOnly(normalizedUserId, latestBuidUser);
|
|
334
|
+
logger.info(`[群昵称设置] 已更新数据库中的B站用户名为: ${currentBuidUsername}`);
|
|
335
|
+
}
|
|
336
|
+
catch (updateError) {
|
|
337
|
+
logger.warn(`[群昵称设置] 更新数据库中的B站用户名失败: ${updateError.message}`);
|
|
338
|
+
// 即使更新数据库失败,也继续使用最新的用户名设置昵称
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
logger.warn(`[群昵称设置] 获取最新B站用户信息失败,使用数据库中的用户名: ${currentBuidUsername}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (validateError) {
|
|
346
|
+
logger.warn(`[群昵称设置] 获取最新B站用户信息时出错: ${validateError.message},使用数据库中的用户名: ${currentBuidUsername}`);
|
|
347
|
+
// API调用失败时降级处理,使用数据库中的旧名称
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// 使用(可能已更新的)用户名重新生成昵称
|
|
351
|
+
const finalNickname = `${currentBuidUsername}(ID:${mcInfo})`;
|
|
289
352
|
// 昵称不一致,执行修改
|
|
290
|
-
logger.debug(`[群昵称设置]
|
|
291
|
-
await session.bot.internal.setGroupCard(targetGroupId, normalizedUserId,
|
|
292
|
-
logger.info(`[群昵称设置] 成功在群${targetGroupId}中将QQ(${normalizedUserId})群昵称从"${currentNickname}"修改为"${
|
|
353
|
+
logger.debug(`[群昵称设置] 昵称不一致,正在修改群昵称为: "${finalNickname}"`);
|
|
354
|
+
await session.bot.internal.setGroupCard(targetGroupId, normalizedUserId, finalNickname);
|
|
355
|
+
logger.info(`[群昵称设置] 成功在群${targetGroupId}中将QQ(${normalizedUserId})群昵称从"${currentNickname}"修改为"${finalNickname}"`);
|
|
293
356
|
// 验证设置是否生效 - 再次获取群昵称确认
|
|
294
357
|
try {
|
|
295
358
|
await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒
|
|
296
359
|
const verifyGroupInfo = await session.bot.internal.getGroupMemberInfo(targetGroupId, normalizedUserId);
|
|
297
360
|
const verifyNickname = verifyGroupInfo.card || verifyGroupInfo.nickname || '';
|
|
298
|
-
if (verifyNickname ===
|
|
361
|
+
if (verifyNickname === finalNickname) {
|
|
299
362
|
logger.info(`[群昵称设置] ✅ 验证成功,群昵称已生效: "${verifyNickname}"`);
|
|
300
363
|
}
|
|
301
364
|
else {
|
|
302
|
-
logger.warn(`[群昵称设置] ⚠️ 验证失败,期望"${
|
|
365
|
+
logger.warn(`[群昵称设置] ⚠️ 验证失败,期望"${finalNickname}",实际"${verifyNickname}",可能是权限不足或API延迟`);
|
|
303
366
|
}
|
|
304
367
|
}
|
|
305
368
|
catch (verifyError) {
|
|
@@ -311,19 +374,54 @@ function apply(ctx, config) {
|
|
|
311
374
|
logger.warn(`[群昵称设置] 获取QQ(${normalizedUserId})当前群昵称失败: ${getInfoError.message}`);
|
|
312
375
|
logger.warn(`[群昵称设置] 错误详情: ${JSON.stringify(getInfoError)}`);
|
|
313
376
|
logger.debug(`[群昵称设置] 将直接尝试设置新昵称...`);
|
|
377
|
+
// 如果传入了 buidUid,尝试获取最新的B站用户信息
|
|
378
|
+
if (buidUid) {
|
|
379
|
+
logger.debug(`[群昵称设置] 尝试获取B站UID ${buidUid} 的最新信息...`);
|
|
380
|
+
try {
|
|
381
|
+
const latestBuidUser = await validateBUID(buidUid);
|
|
382
|
+
if (latestBuidUser && latestBuidUser.username) {
|
|
383
|
+
logger.debug(`[群昵称设置] API返回B站用户名: "${latestBuidUser.username}"`);
|
|
384
|
+
// 智能判断:API返回 == 数据库(都是旧的)
|
|
385
|
+
if (latestBuidUser.username === buidUsername) {
|
|
386
|
+
logger.warn(`[群昵称设置] ⚠️ API返回的B站名称"${latestBuidUser.username}"与数据库一致`);
|
|
387
|
+
logger.warn(`[群昵称设置] 可能是API缓存未刷新,且无法获取当前群昵称,采用保守策略:跳过修改`);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
// API返回新数据(!= 数据库)
|
|
391
|
+
logger.info(`[群昵称设置] 检测到B站用户名已更新: "${buidUsername}" → "${latestBuidUser.username}"`);
|
|
392
|
+
currentBuidUsername = latestBuidUser.username;
|
|
393
|
+
// 更新数据库
|
|
394
|
+
try {
|
|
395
|
+
await updateBuidInfoOnly(normalizedUserId, latestBuidUser);
|
|
396
|
+
logger.info(`[群昵称设置] 已更新数据库中的B站用户名为: ${currentBuidUsername}`);
|
|
397
|
+
}
|
|
398
|
+
catch (updateError) {
|
|
399
|
+
logger.warn(`[群昵称设置] 更新数据库失败: ${updateError.message}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
logger.warn(`[群昵称设置] 获取最新B站用户信息失败`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
catch (validateError) {
|
|
407
|
+
logger.warn(`[群昵称设置] 获取最新B站用户信息失败: ${validateError.message}`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
314
410
|
try {
|
|
315
|
-
|
|
316
|
-
|
|
411
|
+
// 使用(可能已更新的)用户名生成昵称
|
|
412
|
+
const fallbackNickname = `${currentBuidUsername}(ID:${mcInfo})`;
|
|
413
|
+
await session.bot.internal.setGroupCard(targetGroupId, normalizedUserId, fallbackNickname);
|
|
414
|
+
logger.info(`[群昵称设置] 成功在群${targetGroupId}中将QQ(${normalizedUserId})群昵称设置为: ${fallbackNickname}`);
|
|
317
415
|
// 验证设置是否生效
|
|
318
416
|
try {
|
|
319
417
|
await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒
|
|
320
418
|
const verifyGroupInfo = await session.bot.internal.getGroupMemberInfo(targetGroupId, normalizedUserId);
|
|
321
419
|
const verifyNickname = verifyGroupInfo.card || verifyGroupInfo.nickname || '';
|
|
322
|
-
if (verifyNickname ===
|
|
420
|
+
if (verifyNickname === fallbackNickname) {
|
|
323
421
|
logger.info(`[群昵称设置] ✅ 验证成功,群昵称已生效: "${verifyNickname}"`);
|
|
324
422
|
}
|
|
325
423
|
else {
|
|
326
|
-
logger.warn(`[群昵称设置] ⚠️ 验证失败,期望"${
|
|
424
|
+
logger.warn(`[群昵称设置] ⚠️ 验证失败,期望"${fallbackNickname}",实际"${verifyNickname}",可能是权限不足`);
|
|
327
425
|
logger.warn(`[群昵称设置] 建议检查: 1.机器人是否为群管理员 2.群设置是否允许管理员修改昵称 3.OneBot实现是否支持该功能`);
|
|
328
426
|
}
|
|
329
427
|
}
|
|
@@ -349,7 +447,7 @@ function apply(ctx, config) {
|
|
|
349
447
|
const actualUserId = targetUserId || session.userId;
|
|
350
448
|
const normalizedUserId = normalizeQQId(actualUserId);
|
|
351
449
|
logger.error(`[群昵称设置] QQ(${normalizedUserId})自动群昵称设置失败: ${error.message}`);
|
|
352
|
-
logger.error(`[
|
|
450
|
+
logger.error(`[群昵称称设置] 完整错误信息: ${JSON.stringify(error)}`);
|
|
353
451
|
}
|
|
354
452
|
};
|
|
355
453
|
// 检查是否为无关输入
|
|
@@ -718,6 +816,14 @@ function apply(ctx, config) {
|
|
|
718
816
|
type: 'integer',
|
|
719
817
|
initial: 0,
|
|
720
818
|
},
|
|
819
|
+
usernameLastChecked: {
|
|
820
|
+
type: 'timestamp',
|
|
821
|
+
initial: null,
|
|
822
|
+
},
|
|
823
|
+
usernameCheckFailCount: {
|
|
824
|
+
type: 'integer',
|
|
825
|
+
initial: 0,
|
|
826
|
+
},
|
|
721
827
|
}, {
|
|
722
828
|
// 设置主键为qqId
|
|
723
829
|
primary: 'qqId',
|
|
@@ -2052,7 +2158,7 @@ function apply(ctx, config) {
|
|
|
2052
2158
|
const reminderType = reminderCount >= 4 ? '警告' : '提醒';
|
|
2053
2159
|
const reminderPrefix = `【第${reminderCount}次${reminderType}】`;
|
|
2054
2160
|
// 自动修改群昵称
|
|
2055
|
-
await autoSetGroupNickname(session, mcInfo, bind.buidUsername);
|
|
2161
|
+
await autoSetGroupNickname(session, mcInfo, bind.buidUsername, bind.buidUid);
|
|
2056
2162
|
setReminderCooldown(normalizedUserId);
|
|
2057
2163
|
logger.info(`[随机提醒] 为仅绑定B站的用户QQ(${normalizedUserId})修复群昵称并发送第${reminderCount}次${reminderType}`);
|
|
2058
2164
|
await sendMessage(session, [
|
|
@@ -2072,7 +2178,7 @@ function apply(ctx, config) {
|
|
|
2072
2178
|
const reminderType = reminderCount >= 4 ? '警告' : '提醒';
|
|
2073
2179
|
const reminderPrefix = `【第${reminderCount}次${reminderType}】`;
|
|
2074
2180
|
// 自动修改群昵称
|
|
2075
|
-
await autoSetGroupNickname(session, bind.mcUsername, bind.buidUsername);
|
|
2181
|
+
await autoSetGroupNickname(session, bind.mcUsername, bind.buidUsername, bind.buidUid);
|
|
2076
2182
|
setReminderCooldown(normalizedUserId);
|
|
2077
2183
|
logger.info(`[随机提醒] 为已完全绑定的用户QQ(${normalizedUserId})修复群昵称并发送第${reminderCount}次${reminderType}`);
|
|
2078
2184
|
await sendMessage(session, [
|
|
@@ -2200,7 +2306,7 @@ function apply(ctx, config) {
|
|
|
2200
2306
|
removeBindingSession(session.userId, session.channelId);
|
|
2201
2307
|
// 设置群昵称
|
|
2202
2308
|
try {
|
|
2203
|
-
await autoSetGroupNickname(session, null, existingBind.buidUsername);
|
|
2309
|
+
await autoSetGroupNickname(session, null, existingBind.buidUsername, existingBind.buidUid);
|
|
2204
2310
|
logger.info(`[交互绑定] QQ(${normalizedUserId})完成绑定,已设置群昵称`);
|
|
2205
2311
|
}
|
|
2206
2312
|
catch (renameError) {
|
|
@@ -2290,7 +2396,7 @@ function apply(ctx, config) {
|
|
|
2290
2396
|
removeBindingSession(session.userId, session.channelId);
|
|
2291
2397
|
// 设置群昵称
|
|
2292
2398
|
try {
|
|
2293
|
-
await autoSetGroupNickname(session, username, updatedBind.buidUsername);
|
|
2399
|
+
await autoSetGroupNickname(session, username, updatedBind.buidUsername, updatedBind.buidUid);
|
|
2294
2400
|
logger.info(`[交互绑定] QQ(${normalizedUserId})绑定完成,已设置群昵称`);
|
|
2295
2401
|
}
|
|
2296
2402
|
catch (renameError) {
|
|
@@ -2411,7 +2517,7 @@ function apply(ctx, config) {
|
|
|
2411
2517
|
try {
|
|
2412
2518
|
// 检查是否有有效的MC用户名(不是临时用户名)
|
|
2413
2519
|
const mcName = bindingSession.mcUsername && !bindingSession.mcUsername.startsWith('_temp_') ? bindingSession.mcUsername : null;
|
|
2414
|
-
await autoSetGroupNickname(session, mcName, buidUser.username);
|
|
2520
|
+
await autoSetGroupNickname(session, mcName, buidUser.username, String(buidUser.uid));
|
|
2415
2521
|
logger.info(`[交互绑定] QQ(${normalizedUserId})绑定完成,已设置群昵称`);
|
|
2416
2522
|
}
|
|
2417
2523
|
catch (renameError) {
|
package/lib/utils/helpers.d.ts
CHANGED
|
@@ -107,3 +107,16 @@ export declare function normalizeUsername(username: string, logger?: Logger): st
|
|
|
107
107
|
* @returns 是否相同
|
|
108
108
|
*/
|
|
109
109
|
export declare function isSameUsername(username1: string, username2: string): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* 从群昵称中提取B站用户名
|
|
112
|
+
* 用于解析标准格式的群昵称:B站名称(ID:MC名称)
|
|
113
|
+
*
|
|
114
|
+
* @param nickname 群昵称字符串
|
|
115
|
+
* @returns B站用户名,如果格式不匹配返回 null
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* extractBuidUsernameFromNickname("张三(ID:Steve)") // => "张三"
|
|
119
|
+
* extractBuidUsernameFromNickname("李四(ID:未绑定)") // => "李四"
|
|
120
|
+
* extractBuidUsernameFromNickname("无效格式") // => null
|
|
121
|
+
*/
|
|
122
|
+
export declare function extractBuidUsernameFromNickname(nickname: string): string | null;
|
package/lib/utils/helpers.js
CHANGED
|
@@ -13,6 +13,7 @@ exports.levenshteinDistance = levenshteinDistance;
|
|
|
13
13
|
exports.calculateSimilarity = calculateSimilarity;
|
|
14
14
|
exports.normalizeUsername = normalizeUsername;
|
|
15
15
|
exports.isSameUsername = isSameUsername;
|
|
16
|
+
exports.extractBuidUsernameFromNickname = extractBuidUsernameFromNickname;
|
|
16
17
|
/**
|
|
17
18
|
* 通用工具函数集合
|
|
18
19
|
*/
|
|
@@ -360,3 +361,23 @@ function isSameUsername(username1, username2) {
|
|
|
360
361
|
return false;
|
|
361
362
|
return normalizeUsername(username1) === normalizeUsername(username2);
|
|
362
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* 从群昵称中提取B站用户名
|
|
366
|
+
* 用于解析标准格式的群昵称:B站名称(ID:MC名称)
|
|
367
|
+
*
|
|
368
|
+
* @param nickname 群昵称字符串
|
|
369
|
+
* @returns B站用户名,如果格式不匹配返回 null
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* extractBuidUsernameFromNickname("张三(ID:Steve)") // => "张三"
|
|
373
|
+
* extractBuidUsernameFromNickname("李四(ID:未绑定)") // => "李四"
|
|
374
|
+
* extractBuidUsernameFromNickname("无效格式") // => null
|
|
375
|
+
*/
|
|
376
|
+
function extractBuidUsernameFromNickname(nickname) {
|
|
377
|
+
if (!nickname)
|
|
378
|
+
return null;
|
|
379
|
+
// 匹配格式:任意内容(ID:任意内容)
|
|
380
|
+
// 使用非贪婪匹配 .+? 确保正确提取第一个括号前的内容
|
|
381
|
+
const match = nickname.match(/^(.+?)(ID:.+)$/);
|
|
382
|
+
return match ? match[1].trim() : null;
|
|
383
|
+
}
|
|
@@ -18,13 +18,17 @@ export declare class MessageUtils {
|
|
|
18
18
|
private config;
|
|
19
19
|
private logger;
|
|
20
20
|
private getBindingSessionFn;
|
|
21
|
+
private validateBUID?;
|
|
22
|
+
private updateBuidInfoOnly?;
|
|
21
23
|
/**
|
|
22
24
|
* 创建消息工具实例
|
|
23
25
|
* @param config 消息工具配置
|
|
24
26
|
* @param logger 日志服务
|
|
25
27
|
* @param getBindingSessionFn 获取绑定会话的函数
|
|
28
|
+
* @param validateBUID 验证B站UID的函数(可选)
|
|
29
|
+
* @param updateBuidInfoOnly 更新B站信息的函数(可选)
|
|
26
30
|
*/
|
|
27
|
-
constructor(config: MessageUtilsConfig, logger: LoggerService, getBindingSessionFn: (userId: string, channelId: string) => BindingSession | null);
|
|
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>);
|
|
28
32
|
/**
|
|
29
33
|
* 发送消息并处理自动撤回
|
|
30
34
|
* @param session Koishi Session对象
|
|
@@ -39,8 +43,9 @@ export declare class MessageUtils {
|
|
|
39
43
|
* @param session Koishi Session对象
|
|
40
44
|
* @param mcUsername MC用户名
|
|
41
45
|
* @param buidUsername B站用户名
|
|
46
|
+
* @param buidUid B站UID(可选,用于实时验证)
|
|
42
47
|
* @param targetUserId 目标用户ID(可选,用于管理员为他人设置)
|
|
43
48
|
* @param specifiedGroupId 指定的群ID(可选,默认使用配置的群ID)
|
|
44
49
|
*/
|
|
45
|
-
autoSetGroupNickname(session: Session, mcUsername: string | null, buidUsername: string, targetUserId?: string, specifiedGroupId?: string): Promise<void>;
|
|
50
|
+
autoSetGroupNickname(session: Session, mcUsername: string | null, buidUsername: string, buidUid?: string, targetUserId?: string, specifiedGroupId?: string): Promise<void>;
|
|
46
51
|
}
|
|
@@ -11,16 +11,22 @@ class MessageUtils {
|
|
|
11
11
|
config;
|
|
12
12
|
logger;
|
|
13
13
|
getBindingSessionFn;
|
|
14
|
+
validateBUID;
|
|
15
|
+
updateBuidInfoOnly;
|
|
14
16
|
/**
|
|
15
17
|
* 创建消息工具实例
|
|
16
18
|
* @param config 消息工具配置
|
|
17
19
|
* @param logger 日志服务
|
|
18
20
|
* @param getBindingSessionFn 获取绑定会话的函数
|
|
21
|
+
* @param validateBUID 验证B站UID的函数(可选)
|
|
22
|
+
* @param updateBuidInfoOnly 更新B站信息的函数(可选)
|
|
19
23
|
*/
|
|
20
|
-
constructor(config, logger, getBindingSessionFn) {
|
|
24
|
+
constructor(config, logger, getBindingSessionFn, validateBUID, updateBuidInfoOnly) {
|
|
21
25
|
this.config = config;
|
|
22
26
|
this.logger = logger;
|
|
23
27
|
this.getBindingSessionFn = getBindingSessionFn;
|
|
28
|
+
this.validateBUID = validateBUID;
|
|
29
|
+
this.updateBuidInfoOnly = updateBuidInfoOnly;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* 发送消息并处理自动撤回
|
|
@@ -135,17 +141,19 @@ class MessageUtils {
|
|
|
135
141
|
* @param session Koishi Session对象
|
|
136
142
|
* @param mcUsername MC用户名
|
|
137
143
|
* @param buidUsername B站用户名
|
|
144
|
+
* @param buidUid B站UID(可选,用于实时验证)
|
|
138
145
|
* @param targetUserId 目标用户ID(可选,用于管理员为他人设置)
|
|
139
146
|
* @param specifiedGroupId 指定的群ID(可选,默认使用配置的群ID)
|
|
140
147
|
*/
|
|
141
|
-
async autoSetGroupNickname(session, mcUsername, buidUsername, targetUserId, specifiedGroupId) {
|
|
148
|
+
async autoSetGroupNickname(session, mcUsername, buidUsername, buidUid, targetUserId, specifiedGroupId) {
|
|
142
149
|
try {
|
|
143
150
|
// 如果指定了目标用户ID,使用目标用户ID,否则使用session的用户ID
|
|
144
151
|
const actualUserId = targetUserId || session.userId;
|
|
145
152
|
const normalizedUserId = (0, helpers_1.normalizeQQId)(actualUserId);
|
|
146
153
|
// 根据MC绑定状态设置不同的格式(临时用户名视为未绑定)
|
|
147
154
|
const mcInfo = (mcUsername && !mcUsername.startsWith('_temp_')) ? mcUsername : "未绑定";
|
|
148
|
-
|
|
155
|
+
let currentBuidUsername = buidUsername;
|
|
156
|
+
const newNickname = `${currentBuidUsername}(ID:${mcInfo})`;
|
|
149
157
|
// 使用指定的群ID,如果没有指定则使用配置的默认群ID
|
|
150
158
|
const targetGroupId = specifiedGroupId || this.config.autoNicknameGroupId;
|
|
151
159
|
this.logger.debug('群昵称设置', `开始处理QQ(${normalizedUserId})的群昵称设置,目标群: ${targetGroupId}`);
|
|
@@ -164,20 +172,82 @@ class MessageUtils {
|
|
|
164
172
|
this.logger.info('群昵称设置', `QQ(${normalizedUserId})群昵称已经是"${newNickname}",跳过修改`);
|
|
165
173
|
return;
|
|
166
174
|
}
|
|
175
|
+
// 昵称不一致,先尝试获取最新的B站用户信息
|
|
176
|
+
if (buidUid && this.validateBUID && this.updateBuidInfoOnly) {
|
|
177
|
+
this.logger.debug('群昵称设置', `检测到昵称不一致,尝试获取B站UID ${buidUid} 的最新信息...`);
|
|
178
|
+
// 1. 提取当前群昵称中的B站用户名
|
|
179
|
+
const currentNicknameUsername = (0, helpers_1.extractBuidUsernameFromNickname)(currentNickname);
|
|
180
|
+
this.logger.debug('群昵称设置', `从当前群昵称"${currentNickname}"中提取到B站名称: ${currentNicknameUsername || '(无法提取)'}`);
|
|
181
|
+
try {
|
|
182
|
+
const latestBuidUser = await this.validateBUID(buidUid);
|
|
183
|
+
if (latestBuidUser && latestBuidUser.username) {
|
|
184
|
+
this.logger.debug('群昵称设置', `API返回B站用户名: "${latestBuidUser.username}"`);
|
|
185
|
+
// 2. 智能三层判断
|
|
186
|
+
// 情况A: API返回 == 当前群昵称中的名称
|
|
187
|
+
if (currentNicknameUsername && latestBuidUser.username === currentNicknameUsername) {
|
|
188
|
+
this.logger.info('群昵称设置', `✅ 当前群昵称"${currentNickname}"已包含正确的B站名称"${currentNicknameUsername}"`);
|
|
189
|
+
// 群昵称已经正确,仅需更新数据库(如果数据库是旧的)
|
|
190
|
+
if (latestBuidUser.username !== buidUsername) {
|
|
191
|
+
this.logger.info('群昵称设置', `数据库中的B站名称需要更新: "${buidUsername}" → "${latestBuidUser.username}"`);
|
|
192
|
+
try {
|
|
193
|
+
await this.updateBuidInfoOnly(normalizedUserId, latestBuidUser);
|
|
194
|
+
this.logger.info('群昵称设置', `已更新数据库中的B站用户名`);
|
|
195
|
+
}
|
|
196
|
+
catch (updateError) {
|
|
197
|
+
this.logger.warn('群昵称设置', `更新数据库失败: ${updateError.message}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
this.logger.debug('群昵称设置', `数据库中的B站名称已是最新,无需更新`);
|
|
202
|
+
}
|
|
203
|
+
// 跳过群昵称修改
|
|
204
|
+
this.logger.info('群昵称设置', `群昵称格式正确且名称最新,跳过修改`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
// 情况B: API返回 == 数据库(都是旧的)
|
|
208
|
+
if (latestBuidUser.username === buidUsername) {
|
|
209
|
+
this.logger.warn('群昵称设置', `⚠️ API返回的B站名称"${latestBuidUser.username}"与数据库一致,但与群昵称不符`);
|
|
210
|
+
this.logger.warn('群昵称设置', `可能是API缓存未刷新,采用保守策略:不修改群昵称`);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// 情况C: API返回新数据(!= 群昵称 且 != 数据库)
|
|
214
|
+
this.logger.info('群昵称设置', `检测到B站用户名已更新: "${buidUsername}" → "${latestBuidUser.username}"`);
|
|
215
|
+
currentBuidUsername = latestBuidUser.username;
|
|
216
|
+
// 更新数据库中的B站信息
|
|
217
|
+
try {
|
|
218
|
+
await this.updateBuidInfoOnly(normalizedUserId, latestBuidUser);
|
|
219
|
+
this.logger.info('群昵称设置', `已更新数据库中的B站用户名为: ${currentBuidUsername}`);
|
|
220
|
+
}
|
|
221
|
+
catch (updateError) {
|
|
222
|
+
this.logger.warn('群昵称设置', `更新数据库中的B站用户名失败: ${updateError.message}`);
|
|
223
|
+
// 即使更新数据库失败,也继续使用最新的用户名设置昵称
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
this.logger.warn('群昵称设置', `获取最新B站用户信息失败,使用数据库中的用户名: ${currentBuidUsername}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (validateError) {
|
|
231
|
+
this.logger.warn('群昵称设置', `获取最新B站用户信息时出错: ${validateError.message},使用数据库中的用户名: ${currentBuidUsername}`);
|
|
232
|
+
// API调用失败时降级处理,使用数据库中的旧名称
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// 使用(可能已更新的)用户名重新生成昵称
|
|
236
|
+
const finalNickname = `${currentBuidUsername}(ID:${mcInfo})`;
|
|
167
237
|
// 昵称不一致,执行修改
|
|
168
|
-
this.logger.debug('群昵称设置',
|
|
169
|
-
await session.bot.internal.setGroupCard(targetGroupId, normalizedUserId,
|
|
170
|
-
this.logger.info('群昵称设置', `成功在群${targetGroupId}中将QQ(${normalizedUserId})群昵称从"${currentNickname}"修改为"${
|
|
238
|
+
this.logger.debug('群昵称设置', `昵称不一致,正在修改群昵称为: "${finalNickname}"`);
|
|
239
|
+
await session.bot.internal.setGroupCard(targetGroupId, normalizedUserId, finalNickname);
|
|
240
|
+
this.logger.info('群昵称设置', `成功在群${targetGroupId}中将QQ(${normalizedUserId})群昵称从"${currentNickname}"修改为"${finalNickname}"`, true);
|
|
171
241
|
// 验证设置是否生效 - 再次获取群昵称确认
|
|
172
242
|
try {
|
|
173
243
|
await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒
|
|
174
244
|
const verifyGroupInfo = await session.bot.internal.getGroupMemberInfo(targetGroupId, normalizedUserId);
|
|
175
245
|
const verifyNickname = verifyGroupInfo.card || verifyGroupInfo.nickname || '';
|
|
176
|
-
if (verifyNickname ===
|
|
246
|
+
if (verifyNickname === finalNickname) {
|
|
177
247
|
this.logger.info('群昵称设置', `✅ 验证成功,群昵称已生效: "${verifyNickname}"`, true);
|
|
178
248
|
}
|
|
179
249
|
else {
|
|
180
|
-
this.logger.warn('群昵称设置', `⚠️ 验证失败,期望"${
|
|
250
|
+
this.logger.warn('群昵称设置', `⚠️ 验证失败,期望"${finalNickname}",实际"${verifyNickname}",可能是权限不足或API延迟`);
|
|
181
251
|
}
|
|
182
252
|
}
|
|
183
253
|
catch (verifyError) {
|
|
@@ -189,19 +259,54 @@ class MessageUtils {
|
|
|
189
259
|
this.logger.warn('群昵称设置', `获取QQ(${normalizedUserId})当前群昵称失败: ${getInfoError.message}`);
|
|
190
260
|
this.logger.warn('群昵称设置', `错误详情: ${JSON.stringify(getInfoError)}`);
|
|
191
261
|
this.logger.debug('群昵称设置', `将直接尝试设置新昵称...`);
|
|
262
|
+
// 如果传入了 buidUid,尝试获取最新的B站用户信息
|
|
263
|
+
if (buidUid && this.validateBUID && this.updateBuidInfoOnly) {
|
|
264
|
+
this.logger.debug('群昵称设置', `尝试获取B站UID ${buidUid} 的最新信息...`);
|
|
265
|
+
try {
|
|
266
|
+
const latestBuidUser = await this.validateBUID(buidUid);
|
|
267
|
+
if (latestBuidUser && latestBuidUser.username) {
|
|
268
|
+
this.logger.debug('群昵称设置', `API返回B站用户名: "${latestBuidUser.username}"`);
|
|
269
|
+
// 智能判断:API返回 == 数据库(都是旧的)
|
|
270
|
+
if (latestBuidUser.username === buidUsername) {
|
|
271
|
+
this.logger.warn('群昵称设置', `⚠️ API返回的B站名称"${latestBuidUser.username}"与数据库一致`);
|
|
272
|
+
this.logger.warn('群昵称设置', `可能是API缓存未刷新,且无法获取当前群昵称,采用保守策略:跳过修改`);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
// API返回新数据(!= 数据库)
|
|
276
|
+
this.logger.info('群昵称设置', `检测到B站用户名已更新: "${buidUsername}" → "${latestBuidUser.username}"`);
|
|
277
|
+
currentBuidUsername = latestBuidUser.username;
|
|
278
|
+
// 更新数据库
|
|
279
|
+
try {
|
|
280
|
+
await this.updateBuidInfoOnly(normalizedUserId, latestBuidUser);
|
|
281
|
+
this.logger.info('群昵称设置', `已更新数据库中的B站用户名为: ${currentBuidUsername}`);
|
|
282
|
+
}
|
|
283
|
+
catch (updateError) {
|
|
284
|
+
this.logger.warn('群昵称设置', `更新数据库失败: ${updateError.message}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
this.logger.warn('群昵称设置', `获取最新B站用户信息失败`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch (validateError) {
|
|
292
|
+
this.logger.warn('群昵称设置', `获取最新B站用户信息失败: ${validateError.message}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
192
295
|
try {
|
|
193
|
-
|
|
194
|
-
|
|
296
|
+
// 使用(可能已更新的)用户名生成昵称
|
|
297
|
+
const nicknameToSet = `${currentBuidUsername}(ID:${mcInfo})`;
|
|
298
|
+
await session.bot.internal.setGroupCard(targetGroupId, normalizedUserId, nicknameToSet);
|
|
299
|
+
this.logger.info('群昵称设置', `成功在群${targetGroupId}中将QQ(${normalizedUserId})群昵称设置为: ${nicknameToSet}`, true);
|
|
195
300
|
// 验证设置是否生效
|
|
196
301
|
try {
|
|
197
302
|
await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒
|
|
198
303
|
const verifyGroupInfo = await session.bot.internal.getGroupMemberInfo(targetGroupId, normalizedUserId);
|
|
199
304
|
const verifyNickname = verifyGroupInfo.card || verifyGroupInfo.nickname || '';
|
|
200
|
-
if (verifyNickname ===
|
|
305
|
+
if (verifyNickname === nicknameToSet) {
|
|
201
306
|
this.logger.info('群昵称设置', `✅ 验证成功,群昵称已生效: "${verifyNickname}"`, true);
|
|
202
307
|
}
|
|
203
308
|
else {
|
|
204
|
-
this.logger.warn('群昵称设置', `⚠️ 验证失败,期望"${
|
|
309
|
+
this.logger.warn('群昵称设置', `⚠️ 验证失败,期望"${nicknameToSet}",实际"${verifyNickname}",可能是权限不足`);
|
|
205
310
|
this.logger.warn('群昵称设置', `建议检查: 1.机器人是否为群管理员 2.群设置是否允许管理员修改昵称 3.OneBot实现是否支持该功能`);
|
|
206
311
|
}
|
|
207
312
|
}
|