koishi-plugin-bind-bot 2.0.0 → 2.0.2
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/LICENSE +35 -0
- package/lib/handlers/base.handler.d.ts +15 -1
- package/lib/handlers/mcid.handler.d.ts +3 -39
- package/lib/handlers/mcid.handler.js +135 -139
- package/lib/handlers/whitelist.handler.d.ts +0 -4
- package/lib/handlers/whitelist.handler.js +3 -32
- package/lib/index.js +24 -155
- package/lib/utils/error-utils.d.ts +30 -0
- package/lib/utils/error-utils.js +111 -0
- package/lib/utils/helpers.d.ts +15 -0
- package/lib/utils/helpers.js +46 -0
- package/package.json +2 -2
|
@@ -2,17 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.McidCommandHandler = void 0;
|
|
4
4
|
const koishi_1 = require("koishi");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
deps;
|
|
8
|
-
constructor(ctx, deps) {
|
|
9
|
-
this.ctx = ctx;
|
|
10
|
-
this.deps = deps;
|
|
11
|
-
}
|
|
5
|
+
const base_handler_1 = require("./base.handler");
|
|
6
|
+
class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
12
7
|
/**
|
|
13
8
|
* 注册所有MCID命令
|
|
14
9
|
*/
|
|
15
|
-
|
|
10
|
+
register() {
|
|
11
|
+
const cmd = this.ctx.command('mcid', 'MC账号绑定管理');
|
|
16
12
|
// mcid.query - 查询MC账号
|
|
17
13
|
cmd.subcommand('.query [target:string]', '查询用户绑定的MC账号')
|
|
18
14
|
.action(async ({ session }, target) => this.handleQuery(session, target));
|
|
@@ -60,16 +56,16 @@ class McidCommandHandler {
|
|
|
60
56
|
if (target) {
|
|
61
57
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
62
58
|
if (!normalizedTargetId) {
|
|
63
|
-
this.
|
|
59
|
+
this.logger.warn('查询', `QQ(${normalizedUserId})提供的目标用户ID"${target}"无效`);
|
|
64
60
|
if (target.startsWith('@')) {
|
|
65
61
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 请使用真正的@功能,而不是手动输入@符号\n正确做法:点击或长按用户头像选择@功能')]);
|
|
66
62
|
}
|
|
67
63
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 目标用户ID无效\n请提供有效的QQ号或使用@功能选择用户')]);
|
|
68
64
|
}
|
|
69
|
-
this.
|
|
65
|
+
this.logger.info('查询', `QQ(${normalizedUserId})查询QQ(${normalizedTargetId})的MC账号信息`);
|
|
70
66
|
const targetBind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
71
67
|
if (!targetBind || !targetBind.mcUsername || targetBind.mcUsername.startsWith('_temp_')) {
|
|
72
|
-
this.
|
|
68
|
+
this.logger.info('查询', `QQ(${normalizedTargetId})未绑定MC账号`);
|
|
73
69
|
// 检查是否绑定了B站
|
|
74
70
|
if (targetBind && targetBind.buidUid) {
|
|
75
71
|
const buidUser = await this.deps.validateBUID(targetBind.buidUid);
|
|
@@ -91,7 +87,7 @@ class McidCommandHandler {
|
|
|
91
87
|
buidInfo += `\n粉丝牌: ${refreshedBind.medalName} Lv.${refreshedBind.medalLevel}`;
|
|
92
88
|
}
|
|
93
89
|
const messageElements = [koishi_1.h.text(buidInfo)];
|
|
94
|
-
if (this.
|
|
90
|
+
if (this.config.showAvatar) {
|
|
95
91
|
messageElements.push(koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${refreshedBind.buidUid}?size=160`));
|
|
96
92
|
}
|
|
97
93
|
return this.deps.sendMessage(session, messageElements);
|
|
@@ -105,10 +101,10 @@ class McidCommandHandler {
|
|
|
105
101
|
return this.buildQueryResponse(session, updatedBind, normalizedTargetId);
|
|
106
102
|
}
|
|
107
103
|
// 查询自己
|
|
108
|
-
this.
|
|
104
|
+
this.logger.info('查询', `QQ(${normalizedUserId})查询自己的MC账号信息`);
|
|
109
105
|
const selfBind = await this.deps.getMcBindByQQId(normalizedUserId);
|
|
110
106
|
if (!selfBind || !selfBind.mcUsername || selfBind.mcUsername.startsWith('_temp_')) {
|
|
111
|
-
this.
|
|
107
|
+
this.logger.info('查询', `QQ(${normalizedUserId})未绑定MC账号`);
|
|
112
108
|
// 检查是否绑定了B站
|
|
113
109
|
if (selfBind && selfBind.buidUid) {
|
|
114
110
|
const buidUser = await this.deps.validateBUID(selfBind.buidUid);
|
|
@@ -131,7 +127,7 @@ class McidCommandHandler {
|
|
|
131
127
|
}
|
|
132
128
|
buidInfo += `\n\n💡 您可以使用 ${this.deps.formatCommand('mcid bind <用户名>')} 绑定MC账号`;
|
|
133
129
|
const messageElements = [koishi_1.h.text(buidInfo)];
|
|
134
|
-
if (this.
|
|
130
|
+
if (this.config.showAvatar) {
|
|
135
131
|
messageElements.push(koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${refreshedBind.buidUid}?size=160`));
|
|
136
132
|
}
|
|
137
133
|
return this.deps.sendMessage(session, messageElements);
|
|
@@ -145,7 +141,7 @@ class McidCommandHandler {
|
|
|
145
141
|
}
|
|
146
142
|
catch (error) {
|
|
147
143
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
148
|
-
this.
|
|
144
|
+
this.logger.error('查询', `QQ(${normalizedUserId})查询MC账号失败: ${error.message}`);
|
|
149
145
|
return this.deps.sendMessage(session, [koishi_1.h.text(`查询失败: ${error.message}`)]);
|
|
150
146
|
}
|
|
151
147
|
}
|
|
@@ -156,8 +152,8 @@ class McidCommandHandler {
|
|
|
156
152
|
const formattedUuid = this.deps.formatUuid(bind.mcUuid);
|
|
157
153
|
// MC头像
|
|
158
154
|
let mcAvatarUrl = null;
|
|
159
|
-
if (this.
|
|
160
|
-
if (this.
|
|
155
|
+
if (this.config.showAvatar) {
|
|
156
|
+
if (this.config.showMcSkin) {
|
|
161
157
|
mcAvatarUrl = this.deps.getStarlightSkinUrl(bind.mcUsername);
|
|
162
158
|
}
|
|
163
159
|
else {
|
|
@@ -171,7 +167,7 @@ class McidCommandHandler {
|
|
|
171
167
|
const serverList = bind.whitelist.map((serverId, index) => {
|
|
172
168
|
const server = this.deps.getServerConfigById(serverId);
|
|
173
169
|
if (!server) {
|
|
174
|
-
const disabledServer = this.
|
|
170
|
+
const disabledServer = this.config.servers?.find(s => s.id === serverId);
|
|
175
171
|
if (disabledServer && disabledServer.enabled === false) {
|
|
176
172
|
return `${index < circledNumbers.length ? circledNumbers[index] : (index + 1)} ${disabledServer.name} [已停用]`;
|
|
177
173
|
}
|
|
@@ -206,21 +202,21 @@ class McidCommandHandler {
|
|
|
206
202
|
if (bind.medalName) {
|
|
207
203
|
buidInfo += `\n粉丝牌: ${bind.medalName} Lv.${bind.medalLevel}`;
|
|
208
204
|
}
|
|
209
|
-
if (this.
|
|
205
|
+
if (this.config.showAvatar) {
|
|
210
206
|
buidAvatar = koishi_1.h.image(`https://workers.vrp.moe/bilibili/avatar/${bind.buidUid}?size=160`);
|
|
211
207
|
}
|
|
212
208
|
}
|
|
213
209
|
else {
|
|
214
210
|
buidInfo = targetId ? '该用户尚未绑定B站账号' : `您尚未绑定B站账号,使用 ${this.deps.formatCommand('buid bind <B站UID>')} 进行绑定`;
|
|
215
211
|
}
|
|
216
|
-
this.
|
|
212
|
+
this.logger.info('查询', `QQ(${bind.qqId})的MC账号信息:用户名=${bind.mcUsername}, UUID=${bind.mcUuid}`);
|
|
217
213
|
// 自动设置群昵称
|
|
218
214
|
if (bind.buidUid && bind.buidUsername) {
|
|
219
215
|
const mcName = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : null;
|
|
220
216
|
await this.deps.autoSetGroupNickname(session, mcName, bind.buidUsername, targetId || undefined);
|
|
221
217
|
}
|
|
222
218
|
else {
|
|
223
|
-
this.
|
|
219
|
+
this.logger.info('查询', `QQ(${bind.qqId})未绑定B站账号,跳过群昵称设置`);
|
|
224
220
|
}
|
|
225
221
|
const displayUsername = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : '未绑定';
|
|
226
222
|
const prefix = targetId ? `用户 ${targetId} 的` : '您的';
|
|
@@ -240,23 +236,23 @@ class McidCommandHandler {
|
|
|
240
236
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
241
237
|
// 检查权限
|
|
242
238
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
243
|
-
this.
|
|
239
|
+
this.logger.warn('反向查询', `权限不足: QQ(${normalizedUserId})不是管理员`);
|
|
244
240
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能使用此命令')]);
|
|
245
241
|
}
|
|
246
242
|
if (!username) {
|
|
247
|
-
this.
|
|
243
|
+
this.logger.warn('反向查询', `QQ(${normalizedUserId})未提供MC用户名`);
|
|
248
244
|
return this.deps.sendMessage(session, [koishi_1.h.text('请提供要查询的MC用户名')]);
|
|
249
245
|
}
|
|
250
|
-
this.
|
|
246
|
+
this.logger.info('反向查询', `QQ(${normalizedUserId})尝试通过MC用户名"${username}"查询绑定的QQ账号`);
|
|
251
247
|
const bind = await this.deps.getMcBindByUsername(username);
|
|
252
248
|
if (!bind || !bind.qqId) {
|
|
253
|
-
this.
|
|
249
|
+
this.logger.info('反向查询', `MC用户名"${username}"未被任何QQ账号绑定`);
|
|
254
250
|
return this.deps.sendMessage(session, [koishi_1.h.text(`未找到绑定MC用户名"${username}"的QQ账号`)]);
|
|
255
251
|
}
|
|
256
252
|
// MC头像
|
|
257
253
|
let mcAvatarUrl = null;
|
|
258
|
-
if (this.
|
|
259
|
-
if (this.
|
|
254
|
+
if (this.config.showAvatar) {
|
|
255
|
+
if (this.config.showMcSkin) {
|
|
260
256
|
mcAvatarUrl = this.deps.getStarlightSkinUrl(bind.mcUsername);
|
|
261
257
|
}
|
|
262
258
|
else {
|
|
@@ -280,7 +276,7 @@ class McidCommandHandler {
|
|
|
280
276
|
adminInfo += `\n绑定时间: ${bind.lastModified ? new Date(bind.lastModified).toLocaleString() : '未知'}`;
|
|
281
277
|
adminInfo += `\n管理员权限: ${bind.isAdmin ? '是' : '否'}`;
|
|
282
278
|
}
|
|
283
|
-
this.
|
|
279
|
+
this.logger.info('反向查询', `成功: MC用户名"${username}"被QQ(${bind.qqId})绑定`);
|
|
284
280
|
const displayUsername = bind.mcUsername && !bind.mcUsername.startsWith('_temp_') ? bind.mcUsername : '未绑定';
|
|
285
281
|
return this.deps.sendMessage(session, [
|
|
286
282
|
koishi_1.h.text(`MC用户名"${displayUsername}"绑定信息:\nQQ号: ${bind.qqId}\nUUID: ${formattedUuid}${adminInfo}`),
|
|
@@ -289,7 +285,7 @@ class McidCommandHandler {
|
|
|
289
285
|
}
|
|
290
286
|
catch (error) {
|
|
291
287
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
292
|
-
this.
|
|
288
|
+
this.logger.error('反向查询', `QQ(${normalizedUserId})通过MC用户名"${username}"查询失败: ${error.message}`);
|
|
293
289
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
294
290
|
}
|
|
295
291
|
}
|
|
@@ -301,13 +297,13 @@ class McidCommandHandler {
|
|
|
301
297
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
302
298
|
// 检查用户名格式
|
|
303
299
|
if (!username || !/^[a-zA-Z0-9_]{3,16}$/.test(username)) {
|
|
304
|
-
this.
|
|
300
|
+
this.logger.warn('绑定', `QQ(${normalizedUserId})提供的用户名"${username}"格式无效`);
|
|
305
301
|
return this.deps.sendMessage(session, [koishi_1.h.text('请提供有效的Minecraft用户名(3-16位字母、数字、下划线)')]);
|
|
306
302
|
}
|
|
307
303
|
// 验证用户名是否存在
|
|
308
304
|
const profile = await this.deps.validateUsername(username);
|
|
309
305
|
if (!profile) {
|
|
310
|
-
this.
|
|
306
|
+
this.logger.warn('绑定', `QQ(${normalizedUserId})提供的用户名"${username}"不存在`);
|
|
311
307
|
return this.deps.sendMessage(session, [koishi_1.h.text(`无法验证用户名: ${username},该用户可能不存在`)]);
|
|
312
308
|
}
|
|
313
309
|
username = profile.name;
|
|
@@ -321,61 +317,61 @@ class McidCommandHandler {
|
|
|
321
317
|
}
|
|
322
318
|
catch (error) {
|
|
323
319
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
324
|
-
this.
|
|
320
|
+
this.logger.error('绑定', `QQ(${normalizedUserId})绑定MC账号"${username}"失败: ${error.message}`);
|
|
325
321
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
326
322
|
}
|
|
327
323
|
}
|
|
328
324
|
async handleBindForOther(session, username, uuid, target, operatorId) {
|
|
329
325
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
330
326
|
if (!normalizedTargetId) {
|
|
331
|
-
this.
|
|
327
|
+
this.logger.warn('绑定', `QQ(${operatorId})提供的目标用户ID"${target}"无效`);
|
|
332
328
|
if (target.startsWith('@')) {
|
|
333
329
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 请使用真正的@功能,而不是手动输入@符号\n正确做法:点击或长按用户头像选择@功能')]);
|
|
334
330
|
}
|
|
335
331
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 目标用户ID无效\n请提供有效的QQ号或使用@功能选择用户')]);
|
|
336
332
|
}
|
|
337
|
-
this.
|
|
333
|
+
this.logger.debug('绑定', `QQ(${operatorId})尝试为QQ(${normalizedTargetId})绑定MC账号: ${username}(${uuid})`);
|
|
338
334
|
// 检查权限
|
|
339
335
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
340
|
-
this.
|
|
336
|
+
this.logger.warn('绑定', `权限不足: QQ(${operatorId})不是管理员`);
|
|
341
337
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能为其他用户绑定MC账号')]);
|
|
342
338
|
}
|
|
343
339
|
// 检查用户名是否已被占用
|
|
344
340
|
if (await this.deps.checkUsernameExists(username, target)) {
|
|
345
|
-
this.
|
|
341
|
+
this.logger.warn('绑定', `MC用户名"${username}"已被其他QQ号绑定`);
|
|
346
342
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户名 ${username} 已被其他用户绑定`)]);
|
|
347
343
|
}
|
|
348
344
|
// 绑定
|
|
349
345
|
const bindResult = await this.deps.createOrUpdateMcBind(target, username, uuid);
|
|
350
346
|
if (!bindResult) {
|
|
351
|
-
this.
|
|
347
|
+
this.logger.error('绑定', `管理员QQ(${operatorId})为QQ(${normalizedTargetId})绑定MC账号"${username}"失败`);
|
|
352
348
|
return this.deps.sendMessage(session, [koishi_1.h.text(`为用户 ${normalizedTargetId} 绑定MC账号失败: 数据库操作出错,请联系管理员`)]);
|
|
353
349
|
}
|
|
354
|
-
this.
|
|
350
|
+
this.logger.info('绑定', `成功: 管理员QQ(${operatorId})为QQ(${normalizedTargetId})绑定MC账号: ${username}(${uuid})`);
|
|
355
351
|
// 清理绑定会话
|
|
356
352
|
this.deps.removeBindingSession(target, session.channelId);
|
|
357
|
-
this.
|
|
353
|
+
this.logger.info('绑定', `管理员为QQ(${normalizedTargetId})绑定MC账号后,已清理该用户的交互式绑定会话`);
|
|
358
354
|
// 尝试设置群昵称
|
|
359
355
|
let targetBuidStatus = '';
|
|
360
356
|
try {
|
|
361
357
|
const latestTargetBind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
362
358
|
if (latestTargetBind && latestTargetBind.buidUid && latestTargetBind.buidUsername) {
|
|
363
359
|
await this.deps.autoSetGroupNickname(session, username, latestTargetBind.buidUsername, normalizedTargetId);
|
|
364
|
-
this.
|
|
360
|
+
this.logger.info('绑定', `管理员QQ(${operatorId})为QQ(${normalizedTargetId})MC绑定完成,已尝试设置群昵称`);
|
|
365
361
|
targetBuidStatus = '\n✅ 该用户已绑定B站账号,群昵称已更新';
|
|
366
362
|
}
|
|
367
363
|
else {
|
|
368
|
-
this.
|
|
364
|
+
this.logger.info('绑定', `管理员QQ(${operatorId})为QQ(${normalizedTargetId})MC绑定完成,但目标用户未绑定B站账号`);
|
|
369
365
|
targetBuidStatus = '\n⚠️ 该用户尚未绑定B站账号,建议提醒其使用 buid bind 命令完成B站绑定';
|
|
370
366
|
}
|
|
371
367
|
}
|
|
372
368
|
catch (renameError) {
|
|
373
|
-
this.
|
|
369
|
+
this.logger.warn('绑定', `管理员QQ(${operatorId})为QQ(${normalizedTargetId})MC绑定后群昵称设置失败: ${renameError.message}`);
|
|
374
370
|
}
|
|
375
371
|
// MC头像
|
|
376
372
|
let mcAvatarUrl = null;
|
|
377
|
-
if (this.
|
|
378
|
-
if (this.
|
|
373
|
+
if (this.config.showAvatar) {
|
|
374
|
+
if (this.config.showMcSkin) {
|
|
379
375
|
mcAvatarUrl = this.deps.getStarlightSkinUrl(username);
|
|
380
376
|
}
|
|
381
377
|
else {
|
|
@@ -389,7 +385,7 @@ class McidCommandHandler {
|
|
|
389
385
|
]);
|
|
390
386
|
}
|
|
391
387
|
async handleBindForSelf(session, username, uuid, operatorId) {
|
|
392
|
-
this.
|
|
388
|
+
this.logger.debug('绑定', `QQ(${operatorId})尝试绑定MC账号: ${username}(${uuid})`);
|
|
393
389
|
// 检查是否已绑定
|
|
394
390
|
const selfBind = await this.deps.getMcBindByQQId(operatorId);
|
|
395
391
|
if (selfBind && selfBind.mcUsername) {
|
|
@@ -397,55 +393,55 @@ class McidCommandHandler {
|
|
|
397
393
|
if (!isTempUsername) {
|
|
398
394
|
// 检查冷却时间
|
|
399
395
|
if (!await this.deps.isAdmin(session.userId) && !this.deps.checkCooldown(selfBind.lastModified)) {
|
|
400
|
-
const days = this.
|
|
396
|
+
const days = this.config.cooldownDays;
|
|
401
397
|
const now = new Date();
|
|
402
398
|
const diffTime = now.getTime() - selfBind.lastModified.getTime();
|
|
403
399
|
const passedDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
404
400
|
const remainingDays = days - passedDays;
|
|
405
|
-
this.
|
|
401
|
+
this.logger.warn('绑定', `QQ(${operatorId})已绑定MC账号"${selfBind.mcUsername}",且在冷却期内`);
|
|
406
402
|
const displayUsername = selfBind.mcUsername && !selfBind.mcUsername.startsWith('_temp_') ? selfBind.mcUsername : '未绑定';
|
|
407
403
|
return this.deps.sendMessage(session, [koishi_1.h.text(`您已绑定MC账号: ${displayUsername},如需修改,请在冷却期结束后(还需${remainingDays}天)使用 ` + this.deps.formatCommand('mcid change') + ` 命令或联系管理员。`)]);
|
|
408
404
|
}
|
|
409
|
-
this.
|
|
405
|
+
this.logger.debug('绑定', `QQ(${operatorId})已绑定MC账号"${selfBind.mcUsername}",建议使用change命令`);
|
|
410
406
|
const displayUsername = selfBind.mcUsername && !selfBind.mcUsername.startsWith('_temp_') ? selfBind.mcUsername : '未绑定';
|
|
411
407
|
return this.deps.sendMessage(session, [koishi_1.h.text(`您已绑定MC账号: ${displayUsername},如需修改请使用 ` + this.deps.formatCommand('mcid change') + ` 命令。`)]);
|
|
412
408
|
}
|
|
413
409
|
else {
|
|
414
|
-
this.
|
|
410
|
+
this.logger.debug('绑定', `QQ(${operatorId})之前绑定的是临时用户名"${selfBind.mcUsername}",允许直接使用bind命令`);
|
|
415
411
|
}
|
|
416
412
|
}
|
|
417
413
|
// 检查用户名是否已被占用
|
|
418
414
|
if (await this.deps.checkUsernameExists(username)) {
|
|
419
|
-
this.
|
|
415
|
+
this.logger.warn('绑定', `MC用户名"${username}"已被其他QQ号绑定`);
|
|
420
416
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户名 ${username} 已被其他用户绑定`)]);
|
|
421
417
|
}
|
|
422
418
|
// 绑定
|
|
423
419
|
const bindResult = await this.deps.createOrUpdateMcBind(session.userId, username, uuid);
|
|
424
420
|
if (!bindResult) {
|
|
425
|
-
this.
|
|
421
|
+
this.logger.error('绑定', `QQ(${operatorId})绑定MC账号"${username}"失败`);
|
|
426
422
|
return this.deps.sendMessage(session, [koishi_1.h.text('绑定失败,数据库操作出错,请联系管理员')]);
|
|
427
423
|
}
|
|
428
|
-
this.
|
|
424
|
+
this.logger.info('绑定', `成功: QQ(${operatorId})绑定MC账号: ${username}(${uuid})`);
|
|
429
425
|
// 尝试设置群昵称
|
|
430
426
|
let buidReminder = '';
|
|
431
427
|
try {
|
|
432
428
|
const latestBind = await this.deps.getMcBindByQQId(operatorId);
|
|
433
429
|
if (latestBind && latestBind.buidUid && latestBind.buidUsername) {
|
|
434
430
|
await this.deps.autoSetGroupNickname(session, username, latestBind.buidUsername);
|
|
435
|
-
this.
|
|
431
|
+
this.logger.info('绑定', `QQ(${operatorId})MC绑定完成,已尝试设置群昵称`);
|
|
436
432
|
}
|
|
437
433
|
else {
|
|
438
434
|
buidReminder = `\n\n💡 提醒:您还未绑定B站账号,建议使用 ${this.deps.formatCommand('buid bind <B站UID>')} 完成B站绑定以享受完整功能`;
|
|
439
|
-
this.
|
|
435
|
+
this.logger.info('绑定', `QQ(${operatorId})MC绑定完成,但未绑定B站账号`);
|
|
440
436
|
}
|
|
441
437
|
}
|
|
442
438
|
catch (renameError) {
|
|
443
|
-
this.
|
|
439
|
+
this.logger.warn('绑定', `QQ(${operatorId})MC绑定后群昵称设置失败: ${renameError.message}`);
|
|
444
440
|
}
|
|
445
441
|
// MC头像
|
|
446
442
|
let mcAvatarUrl = null;
|
|
447
|
-
if (this.
|
|
448
|
-
if (this.
|
|
443
|
+
if (this.config.showAvatar) {
|
|
444
|
+
if (this.config.showMcSkin) {
|
|
449
445
|
mcAvatarUrl = this.deps.getStarlightSkinUrl(username);
|
|
450
446
|
}
|
|
451
447
|
else {
|
|
@@ -466,13 +462,13 @@ class McidCommandHandler {
|
|
|
466
462
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
467
463
|
// 检查用户名格式
|
|
468
464
|
if (!username || !/^[a-zA-Z0-9_]{3,16}$/.test(username)) {
|
|
469
|
-
this.
|
|
465
|
+
this.logger.warn('修改', `QQ(${normalizedUserId})提供的用户名"${username}"格式无效`);
|
|
470
466
|
return this.deps.sendMessage(session, [koishi_1.h.text('请提供有效的Minecraft用户名(3-16位字母、数字、下划线)')]);
|
|
471
467
|
}
|
|
472
468
|
// 验证用户名是否存在
|
|
473
469
|
const profile = await this.deps.validateUsername(username);
|
|
474
470
|
if (!profile) {
|
|
475
|
-
this.
|
|
471
|
+
this.logger.warn('修改', `QQ(${normalizedUserId})提供的用户名"${username}"不存在`);
|
|
476
472
|
return this.deps.sendMessage(session, [koishi_1.h.text(`无法验证用户名: ${username},该用户可能不存在`)]);
|
|
477
473
|
}
|
|
478
474
|
username = profile.name;
|
|
@@ -486,53 +482,53 @@ class McidCommandHandler {
|
|
|
486
482
|
}
|
|
487
483
|
catch (error) {
|
|
488
484
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
489
|
-
this.
|
|
485
|
+
this.logger.error('修改', `QQ(${normalizedUserId})修改MC账号为"${username}"失败: ${error.message}`);
|
|
490
486
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
491
487
|
}
|
|
492
488
|
}
|
|
493
489
|
async handleChangeForOther(session, username, uuid, target, operatorId) {
|
|
494
490
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
495
491
|
if (!normalizedTargetId) {
|
|
496
|
-
this.
|
|
492
|
+
this.logger.warn('修改', `QQ(${operatorId})提供的目标用户ID"${target}"无效`);
|
|
497
493
|
if (target.startsWith('@')) {
|
|
498
494
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 请使用真正的@功能,而不是手动输入@符号\n正确做法:点击或长按用户头像选择@功能')]);
|
|
499
495
|
}
|
|
500
496
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 目标用户ID无效\n请提供有效的QQ号或使用@功能选择用户')]);
|
|
501
497
|
}
|
|
502
|
-
this.
|
|
498
|
+
this.logger.info('修改', `QQ(${operatorId})尝试修改QQ(${normalizedTargetId})的MC账号为: ${username}(${uuid})`);
|
|
503
499
|
// 检查权限
|
|
504
500
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
505
|
-
this.
|
|
501
|
+
this.logger.warn('修改', `权限不足: QQ(${operatorId})不是管理员`);
|
|
506
502
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能修改其他用户的MC账号')]);
|
|
507
503
|
}
|
|
508
504
|
// 获取目标用户信息
|
|
509
505
|
const targetBind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
510
506
|
if (!targetBind || !targetBind.mcUsername) {
|
|
511
|
-
this.
|
|
507
|
+
this.logger.warn('修改', `QQ(${normalizedTargetId})尚未绑定MC账号`);
|
|
512
508
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户 ${normalizedTargetId} 尚未绑定MC账号,请先使用 ` + this.deps.formatCommand('mcid bind') + ` 命令进行绑定`)]);
|
|
513
509
|
}
|
|
514
510
|
// 检查是否与当前用户名相同
|
|
515
511
|
if (targetBind.mcUsername === username) {
|
|
516
|
-
this.
|
|
512
|
+
this.logger.warn('修改', `QQ(${normalizedTargetId})已绑定相同的MC账号"${username}"`);
|
|
517
513
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户 ${normalizedTargetId} 当前已绑定此用户名: ${username}`)]);
|
|
518
514
|
}
|
|
519
515
|
// 检查用户名是否已被占用
|
|
520
516
|
if (await this.deps.checkUsernameExists(username, target)) {
|
|
521
|
-
this.
|
|
517
|
+
this.logger.warn('修改', `MC用户名"${username}"已被其他QQ号绑定`);
|
|
522
518
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户名 ${username} 已被其他用户绑定`)]);
|
|
523
519
|
}
|
|
524
520
|
const oldUsername = targetBind.mcUsername;
|
|
525
521
|
// 更新绑定信息
|
|
526
522
|
const bindResult = await this.deps.createOrUpdateMcBind(target, username, uuid);
|
|
527
523
|
if (!bindResult) {
|
|
528
|
-
this.
|
|
524
|
+
this.logger.error('修改', `管理员QQ(${operatorId})修改QQ(${normalizedTargetId})的MC账号失败`);
|
|
529
525
|
return this.deps.sendMessage(session, [koishi_1.h.text(`修改用户 ${normalizedTargetId} 的MC账号失败: 数据库操作出错,请联系管理员`)]);
|
|
530
526
|
}
|
|
531
|
-
this.
|
|
527
|
+
this.logger.info('修改', `成功: 管理员QQ(${operatorId})修改QQ(${normalizedTargetId})的MC账号: ${oldUsername} -> ${username}(${uuid})`);
|
|
532
528
|
// MC头像
|
|
533
529
|
let mcAvatarUrl = null;
|
|
534
|
-
if (this.
|
|
535
|
-
if (this.
|
|
530
|
+
if (this.config.showAvatar) {
|
|
531
|
+
if (this.config.showMcSkin) {
|
|
536
532
|
mcAvatarUrl = this.deps.getStarlightSkinUrl(username);
|
|
537
533
|
}
|
|
538
534
|
else {
|
|
@@ -549,41 +545,41 @@ class McidCommandHandler {
|
|
|
549
545
|
const selfBind = await this.deps.getMcBindByQQId(operatorId);
|
|
550
546
|
// 检查是否已绑定
|
|
551
547
|
if (!selfBind || !selfBind.mcUsername) {
|
|
552
|
-
this.
|
|
548
|
+
this.logger.warn('修改', `QQ(${operatorId})尚未绑定MC账号`);
|
|
553
549
|
return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定MC账号,请使用 ' + this.deps.formatCommand('mcid bind') + ' 命令进行绑定')]);
|
|
554
550
|
}
|
|
555
551
|
// 检查是否与当前用户名相同
|
|
556
552
|
if (selfBind.mcUsername === username) {
|
|
557
|
-
this.
|
|
553
|
+
this.logger.warn('修改', `QQ(${operatorId})已绑定相同的MC账号"${username}"`);
|
|
558
554
|
return this.deps.sendMessage(session, [koishi_1.h.text(`您当前已绑定此用户名: ${username}`)]);
|
|
559
555
|
}
|
|
560
556
|
// 检查冷却时间
|
|
561
557
|
if (!await this.deps.isAdmin(session.userId) && !this.deps.checkCooldown(selfBind.lastModified)) {
|
|
562
|
-
const days = this.
|
|
558
|
+
const days = this.config.cooldownDays;
|
|
563
559
|
const now = new Date();
|
|
564
560
|
const diffTime = now.getTime() - selfBind.lastModified.getTime();
|
|
565
561
|
const passedDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
566
562
|
const remainingDays = days - passedDays;
|
|
567
|
-
this.
|
|
563
|
+
this.logger.warn('修改', `QQ(${operatorId})在冷却期内,无法修改MC账号`);
|
|
568
564
|
return this.deps.sendMessage(session, [koishi_1.h.text(`您的MC账号绑定在冷却期内,还需${remainingDays}天才能修改。如需立即修改,请联系管理员。`)]);
|
|
569
565
|
}
|
|
570
566
|
// 检查用户名是否已被占用
|
|
571
567
|
if (await this.deps.checkUsernameExists(username, session.userId)) {
|
|
572
|
-
this.
|
|
568
|
+
this.logger.warn('修改', `MC用户名"${username}"已被其他QQ号绑定`);
|
|
573
569
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户名 ${username} 已被其他用户绑定`)]);
|
|
574
570
|
}
|
|
575
571
|
const oldUsername = selfBind.mcUsername;
|
|
576
572
|
// 更新绑定信息
|
|
577
573
|
const bindResult = await this.deps.createOrUpdateMcBind(session.userId, username, uuid);
|
|
578
574
|
if (!bindResult) {
|
|
579
|
-
this.
|
|
575
|
+
this.logger.error('修改', `QQ(${operatorId})修改MC账号失败`);
|
|
580
576
|
return this.deps.sendMessage(session, [koishi_1.h.text('修改失败,数据库操作出错,请联系管理员')]);
|
|
581
577
|
}
|
|
582
|
-
this.
|
|
578
|
+
this.logger.info('修改', `成功: QQ(${operatorId})修改MC账号: ${oldUsername} -> ${username}(${uuid})`);
|
|
583
579
|
// MC头像
|
|
584
580
|
let mcAvatarUrl = null;
|
|
585
|
-
if (this.
|
|
586
|
-
if (this.
|
|
581
|
+
if (this.config.showAvatar) {
|
|
582
|
+
if (this.config.showMcSkin) {
|
|
587
583
|
mcAvatarUrl = this.deps.getStarlightSkinUrl(username);
|
|
588
584
|
}
|
|
589
585
|
else {
|
|
@@ -612,50 +608,50 @@ class McidCommandHandler {
|
|
|
612
608
|
catch (error) {
|
|
613
609
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
614
610
|
const targetInfo = target ? `为QQ(${this.deps.normalizeQQId(target)})` : '';
|
|
615
|
-
this.
|
|
611
|
+
this.logger.error('解绑', `QQ(${normalizedUserId})${targetInfo}解绑MC账号失败: ${error.message}`);
|
|
616
612
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
617
613
|
}
|
|
618
614
|
}
|
|
619
615
|
async handleUnbindForOther(session, target, operatorId) {
|
|
620
616
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
621
617
|
if (!normalizedTargetId) {
|
|
622
|
-
this.
|
|
618
|
+
this.logger.warn('解绑', `QQ(${operatorId})提供的目标用户ID"${target}"无效`);
|
|
623
619
|
if (target.startsWith('@')) {
|
|
624
620
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 请使用真正的@功能,而不是手动输入@符号\n正确做法:点击或长按用户头像选择@功能')]);
|
|
625
621
|
}
|
|
626
622
|
return this.deps.sendMessage(session, [koishi_1.h.text('❌ 目标用户ID无效\n请提供有效的QQ号或使用@功能选择用户')]);
|
|
627
623
|
}
|
|
628
|
-
this.
|
|
624
|
+
this.logger.info('解绑', `QQ(${operatorId})尝试为QQ(${normalizedTargetId})解绑MC账号`);
|
|
629
625
|
// 检查权限
|
|
630
626
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
631
|
-
this.
|
|
627
|
+
this.logger.warn('解绑', `权限不足: QQ(${operatorId})不是管理员`);
|
|
632
628
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能为其他用户解绑MC账号')]);
|
|
633
629
|
}
|
|
634
630
|
// 获取目标用户信息
|
|
635
631
|
const targetBind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
636
632
|
if (!targetBind || !targetBind.mcUsername) {
|
|
637
|
-
this.
|
|
633
|
+
this.logger.warn('解绑', `QQ(${normalizedTargetId})尚未绑定MC账号`);
|
|
638
634
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户 ${normalizedTargetId} 尚未绑定MC账号`)]);
|
|
639
635
|
}
|
|
640
636
|
const oldUsername = targetBind.mcUsername && !targetBind.mcUsername.startsWith('_temp_') ? targetBind.mcUsername : '未绑定';
|
|
641
637
|
const oldBuidInfo = targetBind.buidUid ? ` 和 B站账号: ${targetBind.buidUsername}(${targetBind.buidUid})` : '';
|
|
642
638
|
// 删除绑定记录
|
|
643
639
|
await this.deps.deleteMcBind(target);
|
|
644
|
-
this.
|
|
640
|
+
this.logger.info('解绑', `成功: 管理员QQ(${operatorId})为QQ(${normalizedTargetId})解绑MC账号: ${oldUsername}${oldBuidInfo}`);
|
|
645
641
|
return this.deps.sendMessage(session, [koishi_1.h.text(`已成功为用户 ${normalizedTargetId} 解绑MC账号: ${oldUsername}${oldBuidInfo}`)]);
|
|
646
642
|
}
|
|
647
643
|
async handleUnbindForSelf(session, operatorId) {
|
|
648
|
-
this.
|
|
644
|
+
this.logger.info('解绑', `QQ(${operatorId})尝试解绑自己的MC账号`);
|
|
649
645
|
const selfBind = await this.deps.getMcBindByQQId(operatorId);
|
|
650
646
|
if (!selfBind || !selfBind.mcUsername) {
|
|
651
|
-
this.
|
|
647
|
+
this.logger.warn('解绑', `QQ(${operatorId})尚未绑定MC账号`);
|
|
652
648
|
return this.deps.sendMessage(session, [koishi_1.h.text('您尚未绑定MC账号')]);
|
|
653
649
|
}
|
|
654
650
|
const oldUsername = selfBind.mcUsername && !selfBind.mcUsername.startsWith('_temp_') ? selfBind.mcUsername : '未绑定';
|
|
655
651
|
const oldBuidInfo = selfBind.buidUid ? ` 和 B站账号: ${selfBind.buidUsername}(${selfBind.buidUid})` : '';
|
|
656
652
|
// 删除绑定记录
|
|
657
653
|
await this.deps.deleteMcBind(operatorId);
|
|
658
|
-
this.
|
|
654
|
+
this.logger.info('解绑', `成功: QQ(${operatorId})解绑MC账号: ${oldUsername}${oldBuidInfo}`);
|
|
659
655
|
return this.deps.sendMessage(session, [koishi_1.h.text(`已成功解绑MC账号: ${oldUsername}${oldBuidInfo}`)]);
|
|
660
656
|
}
|
|
661
657
|
/**
|
|
@@ -665,43 +661,43 @@ class McidCommandHandler {
|
|
|
665
661
|
try {
|
|
666
662
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
667
663
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
668
|
-
this.
|
|
664
|
+
this.logger.info('管理员', `QQ(${normalizedUserId})尝试将QQ(${normalizedTargetId})设为管理员`);
|
|
669
665
|
// 检查是否为主人
|
|
670
666
|
if (!this.deps.isMaster(session.userId)) {
|
|
671
|
-
this.
|
|
667
|
+
this.logger.warn('管理员', `权限不足: QQ(${normalizedUserId})不是主人`);
|
|
672
668
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有主人才能设置管理员')]);
|
|
673
669
|
}
|
|
674
670
|
// 检查目标用户是否已经是管理员
|
|
675
671
|
const targetBind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
676
672
|
const isAlreadyAdmin = targetBind && targetBind.isAdmin === true;
|
|
677
673
|
if (isAlreadyAdmin) {
|
|
678
|
-
this.
|
|
674
|
+
this.logger.warn('管理员', `QQ(${normalizedTargetId})已经是管理员`);
|
|
679
675
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户 ${normalizedTargetId} 已经是管理员`)]);
|
|
680
676
|
}
|
|
681
677
|
// 如果用户存在绑定记录,更新为管理员
|
|
682
678
|
if (targetBind) {
|
|
683
|
-
await this.
|
|
679
|
+
await this.repos.mcidbind.update(normalizedTargetId, {
|
|
684
680
|
isAdmin: true,
|
|
685
681
|
});
|
|
686
|
-
this.
|
|
682
|
+
this.logger.info('管理员', `成功: 主人QQ(${normalizedUserId})将QQ(${normalizedTargetId})设为管理员`);
|
|
687
683
|
return this.deps.sendMessage(session, [koishi_1.h.text(`已成功将用户 ${normalizedTargetId} 设为管理员`)]);
|
|
688
684
|
}
|
|
689
685
|
else {
|
|
690
686
|
// 用户不存在绑定记录,创建一个新记录并设为管理员
|
|
691
687
|
const tempUsername = `_temp_${normalizedTargetId}`;
|
|
692
688
|
try {
|
|
693
|
-
await this.
|
|
689
|
+
await this.repos.mcidbind.create({
|
|
694
690
|
qqId: normalizedTargetId,
|
|
695
691
|
mcUsername: tempUsername,
|
|
696
692
|
mcUuid: '',
|
|
697
693
|
lastModified: new Date(),
|
|
698
694
|
isAdmin: true
|
|
699
695
|
});
|
|
700
|
-
this.
|
|
696
|
+
this.logger.info('管理员', `成功: 主人QQ(${normalizedUserId})将QQ(${normalizedTargetId})设为管理员 (创建新记录)`);
|
|
701
697
|
return this.deps.sendMessage(session, [koishi_1.h.text(`已成功将用户 ${normalizedTargetId} 设为管理员 (未绑定MC账号)`)]);
|
|
702
698
|
}
|
|
703
699
|
catch (createError) {
|
|
704
|
-
this.
|
|
700
|
+
this.logger.error('管理员', `创建管理员记录失败: ${createError.message}`);
|
|
705
701
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(createError))]);
|
|
706
702
|
}
|
|
707
703
|
}
|
|
@@ -709,7 +705,7 @@ class McidCommandHandler {
|
|
|
709
705
|
catch (error) {
|
|
710
706
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
711
707
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
712
|
-
this.
|
|
708
|
+
this.logger.error('管理员', `QQ(${normalizedUserId})将QQ(${normalizedTargetId})设为管理员失败: ${error.message}`);
|
|
713
709
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
714
710
|
}
|
|
715
711
|
}
|
|
@@ -720,30 +716,30 @@ class McidCommandHandler {
|
|
|
720
716
|
try {
|
|
721
717
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
722
718
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
723
|
-
this.
|
|
719
|
+
this.logger.info('管理员', `QQ(${normalizedUserId})尝试撤销QQ(${normalizedTargetId})的管理员权限`);
|
|
724
720
|
// 检查是否为主人
|
|
725
721
|
if (!this.deps.isMaster(session.userId)) {
|
|
726
|
-
this.
|
|
722
|
+
this.logger.warn('管理员', `权限不足: QQ(${normalizedUserId})不是主人`);
|
|
727
723
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有主人才能撤销管理员权限')]);
|
|
728
724
|
}
|
|
729
725
|
// 检查目标用户是否是管理员
|
|
730
726
|
const targetBind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
731
727
|
const isAdmin = targetBind && targetBind.isAdmin === true;
|
|
732
728
|
if (!isAdmin) {
|
|
733
|
-
this.
|
|
729
|
+
this.logger.warn('管理员', `QQ(${normalizedTargetId})不是管理员`);
|
|
734
730
|
return this.deps.sendMessage(session, [koishi_1.h.text(`用户 ${normalizedTargetId} 不是管理员`)]);
|
|
735
731
|
}
|
|
736
732
|
// 撤销管理员权限
|
|
737
|
-
await this.
|
|
733
|
+
await this.repos.mcidbind.update(normalizedTargetId, {
|
|
738
734
|
isAdmin: false,
|
|
739
735
|
});
|
|
740
|
-
this.
|
|
736
|
+
this.logger.info('管理员', `成功: 主人QQ(${normalizedUserId})撤销了QQ(${normalizedTargetId})的管理员权限`);
|
|
741
737
|
return this.deps.sendMessage(session, [koishi_1.h.text(`已成功撤销用户 ${normalizedTargetId} 的管理员权限`)]);
|
|
742
738
|
}
|
|
743
739
|
catch (error) {
|
|
744
740
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
745
741
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
746
|
-
this.
|
|
742
|
+
this.logger.error('管理员', `QQ(${normalizedUserId})撤销QQ(${normalizedTargetId})的管理员权限失败: ${error.message}`);
|
|
747
743
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
748
744
|
}
|
|
749
745
|
}
|
|
@@ -753,16 +749,16 @@ class McidCommandHandler {
|
|
|
753
749
|
async handleAdminlist(session) {
|
|
754
750
|
try {
|
|
755
751
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
756
|
-
this.
|
|
752
|
+
this.logger.info('管理员', `QQ(${normalizedUserId})尝试查看管理员列表`);
|
|
757
753
|
// 检查是否为主人
|
|
758
754
|
if (!this.deps.isMaster(session.userId)) {
|
|
759
|
-
this.
|
|
755
|
+
this.logger.warn('管理员', `权限不足: QQ(${normalizedUserId})不是主人`);
|
|
760
756
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有主人才能查看管理员列表')]);
|
|
761
757
|
}
|
|
762
758
|
// 查询所有管理员
|
|
763
|
-
const admins = await this.
|
|
759
|
+
const admins = await this.repos.mcidbind.findAllAdmins();
|
|
764
760
|
if (admins.length === 0) {
|
|
765
|
-
this.
|
|
761
|
+
this.logger.info('管理员', `管理员列表为空`);
|
|
766
762
|
return this.deps.sendMessage(session, [koishi_1.h.text('当前没有管理员')]);
|
|
767
763
|
}
|
|
768
764
|
// 格式化管理员列表
|
|
@@ -770,12 +766,12 @@ class McidCommandHandler {
|
|
|
770
766
|
const displayUsername = admin.mcUsername && !admin.mcUsername.startsWith('_temp_') ? admin.mcUsername : null;
|
|
771
767
|
return `- ${admin.qqId}${displayUsername ? ` (MC: ${displayUsername})` : ''}`;
|
|
772
768
|
}).join('\n');
|
|
773
|
-
this.
|
|
769
|
+
this.logger.info('管理员', `成功: 主人QQ(${normalizedUserId})查看了管理员列表`);
|
|
774
770
|
return this.deps.sendMessage(session, [koishi_1.h.text(`管理员列表:\n${adminList}\n\n共 ${admins.length} 名管理员`)]);
|
|
775
771
|
}
|
|
776
772
|
catch (error) {
|
|
777
773
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
778
|
-
this.
|
|
774
|
+
this.logger.error('管理员', `QQ(${normalizedUserId})查看管理员列表失败: ${error.message}`);
|
|
779
775
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
780
776
|
}
|
|
781
777
|
}
|
|
@@ -785,14 +781,14 @@ class McidCommandHandler {
|
|
|
785
781
|
async handleStats(session) {
|
|
786
782
|
try {
|
|
787
783
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
788
|
-
this.
|
|
784
|
+
this.logger.info('统计', `QQ(${normalizedUserId})尝试查看数据库统计`);
|
|
789
785
|
// 检查权限
|
|
790
786
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
791
|
-
this.
|
|
787
|
+
this.logger.warn('统计', `权限不足: QQ(${normalizedUserId})不是管理员`);
|
|
792
788
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能查看统计信息')]);
|
|
793
789
|
}
|
|
794
790
|
// 查询所有绑定记录
|
|
795
|
-
const allBinds = await this.
|
|
791
|
+
const allBinds = await this.repos.mcidbind.findAll();
|
|
796
792
|
// 统计绑定情况
|
|
797
793
|
let mcidBoundUsers = 0;
|
|
798
794
|
let buidBoundUsers = 0;
|
|
@@ -809,12 +805,12 @@ class McidCommandHandler {
|
|
|
809
805
|
let statsInfo = `📊 绑定统计\n`;
|
|
810
806
|
statsInfo += `\n已绑定MCID: ${mcidBoundUsers}人\n`;
|
|
811
807
|
statsInfo += `已绑定BUID: ${buidBoundUsers}人`;
|
|
812
|
-
this.
|
|
808
|
+
this.logger.info('统计', `成功: 管理员QQ(${normalizedUserId})查看了数据库统计`);
|
|
813
809
|
return this.deps.sendMessage(session, [koishi_1.h.text(statsInfo)]);
|
|
814
810
|
}
|
|
815
811
|
catch (error) {
|
|
816
812
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
817
|
-
this.
|
|
813
|
+
this.logger.error('统计', `QQ(${normalizedUserId})查看统计失败: ${error.message}`);
|
|
818
814
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
819
815
|
}
|
|
820
816
|
}
|
|
@@ -826,7 +822,7 @@ class McidCommandHandler {
|
|
|
826
822
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
827
823
|
// 检查权限
|
|
828
824
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
829
|
-
this.
|
|
825
|
+
this.logger.warn('群昵称修复', `权限不足: QQ(${normalizedUserId})不是管理员`);
|
|
830
826
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能执行群昵称修复操作')]);
|
|
831
827
|
}
|
|
832
828
|
// 确定目标群ID
|
|
@@ -842,14 +838,14 @@ class McidCommandHandler {
|
|
|
842
838
|
}
|
|
843
839
|
}
|
|
844
840
|
catch (error) {
|
|
845
|
-
this.
|
|
841
|
+
this.logger.warn('群昵称修复', `Bot不在群${targetGroupId}中或无法获取群信息`);
|
|
846
842
|
return this.deps.sendMessage(session, [koishi_1.h.text(`❌ Bot不在群 ${targetGroupId} 中或无权限操作该群`)]);
|
|
847
843
|
}
|
|
848
844
|
const groupDisplayText = groupId ? `群 ${targetGroupId}` : '当前群';
|
|
849
|
-
this.
|
|
845
|
+
this.logger.info('群昵称修复', `管理员QQ(${normalizedUserId})开始批量修复${groupDisplayText}的群昵称`);
|
|
850
846
|
await this.deps.sendMessage(session, [koishi_1.h.text(`🔧 开始检查并修复${groupDisplayText}的所有用户群昵称格式,请稍候...`)]);
|
|
851
847
|
// 获取所有已绑定B站的用户
|
|
852
|
-
const allBinds = await this.
|
|
848
|
+
const allBinds = await this.repos.mcidbind.findAll();
|
|
853
849
|
const usersWithBuid = allBinds.filter(bind => bind.buidUid && bind.buidUsername);
|
|
854
850
|
let checkedCount = 0;
|
|
855
851
|
let fixedCount = 0;
|
|
@@ -894,7 +890,7 @@ class McidCommandHandler {
|
|
|
894
890
|
catch (error) {
|
|
895
891
|
errorCount++;
|
|
896
892
|
results.push(`❌ ${bind.qqId}: 处理出错 - ${error.message}`);
|
|
897
|
-
this.
|
|
893
|
+
this.logger.error('群昵称修复', `处理用户QQ(${bind.qqId})时出错: ${error.message}`);
|
|
898
894
|
}
|
|
899
895
|
}
|
|
900
896
|
// 生成最终报告
|
|
@@ -911,12 +907,12 @@ class McidCommandHandler {
|
|
|
911
907
|
}
|
|
912
908
|
}
|
|
913
909
|
}
|
|
914
|
-
this.
|
|
910
|
+
this.logger.info('群昵称修复', `修复完成: 管理员QQ(${normalizedUserId})在${groupDisplayText}检查${checkedCount}个用户,修复${fixedCount}个,错误${errorCount}个`);
|
|
915
911
|
return this.deps.sendMessage(session, [koishi_1.h.text(resultMessage)]);
|
|
916
912
|
}
|
|
917
913
|
catch (error) {
|
|
918
914
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
919
|
-
this.
|
|
915
|
+
this.logger.error('群昵称修复', `QQ(${normalizedUserId})执行群昵称修复失败: ${error.message}`);
|
|
920
916
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
921
917
|
}
|
|
922
918
|
}
|
|
@@ -928,7 +924,7 @@ class McidCommandHandler {
|
|
|
928
924
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
929
925
|
// 检查权限
|
|
930
926
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
931
|
-
this.
|
|
927
|
+
this.logger.warn('清除冷却', `权限不足: QQ(${normalizedUserId})不是管理员`);
|
|
932
928
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能清除提醒冷却和次数')]);
|
|
933
929
|
}
|
|
934
930
|
// 注意: reminderCooldown 需要从外部传入或在 deps 中提供
|
|
@@ -937,23 +933,23 @@ class McidCommandHandler {
|
|
|
937
933
|
const normalizedTargetId = this.deps.normalizeQQId(target);
|
|
938
934
|
const bind = await this.deps.getMcBindByQQId(normalizedTargetId);
|
|
939
935
|
if (bind) {
|
|
940
|
-
await this.
|
|
936
|
+
await this.repos.mcidbind.update(normalizedTargetId, { reminderCount: 0 });
|
|
941
937
|
}
|
|
942
|
-
this.
|
|
938
|
+
this.logger.info('清除冷却', `管理员QQ(${normalizedUserId})清除了QQ(${normalizedTargetId})的提醒次数`);
|
|
943
939
|
return this.deps.sendMessage(session, [koishi_1.h.text(`已清除用户 ${normalizedTargetId} 的随机提醒次数`)]);
|
|
944
940
|
}
|
|
945
941
|
else {
|
|
946
|
-
const allBinds = await this.
|
|
942
|
+
const allBinds = await this.repos.mcidbind.findAll();
|
|
947
943
|
for (const bind of allBinds) {
|
|
948
|
-
await this.
|
|
944
|
+
await this.repos.mcidbind.update(bind.qqId, { reminderCount: 0 });
|
|
949
945
|
}
|
|
950
|
-
this.
|
|
946
|
+
this.logger.info('清除冷却', `管理员QQ(${normalizedUserId})清除了所有用户的提醒次数`);
|
|
951
947
|
return this.deps.sendMessage(session, [koishi_1.h.text(`已清除所有用户的随机提醒次数`)]);
|
|
952
948
|
}
|
|
953
949
|
}
|
|
954
950
|
catch (error) {
|
|
955
951
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
956
|
-
this.
|
|
952
|
+
this.logger.error('清除冷却', `QQ(${normalizedUserId})清除提醒冷却失败: ${error.message}`);
|
|
957
953
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
958
954
|
}
|
|
959
955
|
}
|
|
@@ -965,12 +961,12 @@ class McidCommandHandler {
|
|
|
965
961
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
966
962
|
// 检查权限
|
|
967
963
|
if (!await this.deps.isAdmin(session.userId)) {
|
|
968
|
-
this.
|
|
964
|
+
this.logger.warn('数据导出', `权限不足: QQ(${normalizedUserId})不是管理员`);
|
|
969
965
|
return this.deps.sendMessage(session, [koishi_1.h.text('只有管理员才能导出群数据')]);
|
|
970
966
|
}
|
|
971
967
|
// 检查是否为私聊
|
|
972
968
|
if (!session.channelId?.startsWith('private:')) {
|
|
973
|
-
this.
|
|
969
|
+
this.logger.warn('数据导出', `QQ(${normalizedUserId})尝试在群聊中使用导出命令`);
|
|
974
970
|
return this.deps.sendMessage(session, [koishi_1.h.text('为了数据安全,导出命令仅支持在私聊中使用')]);
|
|
975
971
|
}
|
|
976
972
|
// 验证群ID格式
|
|
@@ -984,10 +980,10 @@ class McidCommandHandler {
|
|
|
984
980
|
}
|
|
985
981
|
}
|
|
986
982
|
catch (error) {
|
|
987
|
-
this.
|
|
983
|
+
this.logger.warn('数据导出', `Bot不在群${groupId}中或无法获取群信息`);
|
|
988
984
|
return this.deps.sendMessage(session, [koishi_1.h.text(`❌ Bot不在群 ${groupId} 中或无权限操作该群`)]);
|
|
989
985
|
}
|
|
990
|
-
this.
|
|
986
|
+
this.logger.info('数据导出', `管理员QQ(${normalizedUserId})开始导出群${groupId}的数据`);
|
|
991
987
|
await this.deps.sendMessage(session, [koishi_1.h.text(`📊 开始导出群 ${groupId} 的数据,请稍候...`)]);
|
|
992
988
|
try {
|
|
993
989
|
// 导出数据
|
|
@@ -1005,14 +1001,14 @@ class McidCommandHandler {
|
|
|
1005
1001
|
name: fileName
|
|
1006
1002
|
});
|
|
1007
1003
|
await this.deps.sendMessage(session, [koishi_1.h.text(`📁 文件已发送: ${fileName}`)]);
|
|
1008
|
-
this.
|
|
1004
|
+
this.logger.info('数据导出', `成功发送文件到私聊: ${fileName}`);
|
|
1009
1005
|
}
|
|
1010
1006
|
else {
|
|
1011
1007
|
throw new Error('Bot不支持内部API调用');
|
|
1012
1008
|
}
|
|
1013
1009
|
}
|
|
1014
1010
|
catch (fileError) {
|
|
1015
|
-
this.
|
|
1011
|
+
this.logger.error('数据导出', `文件发送失败: ${fileError.message}`);
|
|
1016
1012
|
// 降级方案:保存文件
|
|
1017
1013
|
try {
|
|
1018
1014
|
const filePath = await this.deps.groupExporter.saveExcelFile(excelBuffer, fileName);
|
|
@@ -1020,7 +1016,7 @@ class McidCommandHandler {
|
|
|
1020
1016
|
koishi_1.h.text(`⚠️ 直接发送失败,文件已保存\n文件路径: ${filePath}\n文件名: ${fileName}\n请联系管理员获取文件`)
|
|
1021
1017
|
]);
|
|
1022
1018
|
// 清理过期文件
|
|
1023
|
-
this.deps.groupExporter.cleanupOldFiles().catch(err => this.
|
|
1019
|
+
this.deps.groupExporter.cleanupOldFiles().catch(err => this.logger.warn('数据导出', `清理临时文件时出错: ${err.message}`));
|
|
1024
1020
|
}
|
|
1025
1021
|
catch (saveError) {
|
|
1026
1022
|
await this.deps.sendMessage(session, [
|
|
@@ -1028,16 +1024,16 @@ class McidCommandHandler {
|
|
|
1028
1024
|
]);
|
|
1029
1025
|
}
|
|
1030
1026
|
}
|
|
1031
|
-
this.
|
|
1027
|
+
this.logger.info('数据导出', `管理员QQ(${normalizedUserId})成功导出群${groupId}的数据,文件名: ${fileName}`);
|
|
1032
1028
|
}
|
|
1033
1029
|
catch (exportError) {
|
|
1034
|
-
this.
|
|
1030
|
+
this.logger.error('数据导出', `导出群${groupId}数据失败: ${exportError.message}`);
|
|
1035
1031
|
return this.deps.sendMessage(session, [koishi_1.h.text(`❌ 导出失败: ${exportError.message}`)]);
|
|
1036
1032
|
}
|
|
1037
1033
|
}
|
|
1038
1034
|
catch (error) {
|
|
1039
1035
|
const normalizedUserId = this.deps.normalizeQQId(session.userId);
|
|
1040
|
-
this.
|
|
1036
|
+
this.logger.error('数据导出', `QQ(${normalizedUserId})导出群数据失败: ${error.message}`);
|
|
1041
1037
|
return this.deps.sendMessage(session, [koishi_1.h.text(this.deps.getFriendlyErrorMessage(error))]);
|
|
1042
1038
|
}
|
|
1043
1039
|
}
|