koishi-plugin-bind-bot 2.2.8 → 2.3.0
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 +2 -1
- package/lib/handlers/binding.handler.d.ts +28 -0
- package/lib/handlers/binding.handler.js +169 -107
- package/lib/handlers/buid.handler.js +7 -10
- package/lib/handlers/group-request-review.handler.d.ts +6 -1
- package/lib/handlers/group-request-review.handler.js +86 -84
- package/lib/handlers/mcid.handler.js +10 -9
- package/lib/index.js +14 -298
- package/lib/repositories/mcidbind.repository.d.ts +4 -86
- package/lib/repositories/mcidbind.repository.js +61 -127
- package/lib/services/database.service.js +0 -6
- package/lib/types/config.d.ts +6 -2
- package/lib/types/database.d.ts +0 -6
- package/lib/types/update-data.d.ts +0 -11
- package/lib/utils/bind-status.d.ts +14 -0
- package/lib/utils/bind-status.js +22 -0
- package/lib/utils/helpers.d.ts +1 -9
- package/lib/utils/helpers.js +5 -0
- package/lib/utils/supabase-client.d.ts +14 -0
- package/lib/utils/supabase-client.js +44 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ exports.McidCommandHandler = void 0;
|
|
|
4
4
|
const koishi_1 = require("koishi");
|
|
5
5
|
const base_handler_1 = require("./base.handler");
|
|
6
6
|
const bind_status_1 = require("../utils/bind-status");
|
|
7
|
+
const helpers_1 = require("../utils/helpers");
|
|
7
8
|
class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
8
9
|
/**
|
|
9
10
|
* 注册所有MCID命令
|
|
@@ -92,14 +93,14 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
92
93
|
if (refreshedBind) {
|
|
93
94
|
let buidInfo = `该用户尚未绑定MC账号\n\nB站账号信息:\nB站UID: ${refreshedBind.buidUid}\n用户名: ${refreshedBind.buidUsername}`;
|
|
94
95
|
if (refreshedBind.guardLevel > 0) {
|
|
95
|
-
buidInfo += `\n舰长等级: ${refreshedBind.
|
|
96
|
+
buidInfo += `\n舰长等级: ${(0, helpers_1.getGuardLevelText)(refreshedBind.guardLevel)} (${refreshedBind.guardLevel})`;
|
|
96
97
|
if (refreshedBind.maxGuardLevel > 0 &&
|
|
97
98
|
refreshedBind.maxGuardLevel < refreshedBind.guardLevel) {
|
|
98
|
-
buidInfo += `\n历史最高: ${refreshedBind.
|
|
99
|
+
buidInfo += `\n历史最高: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
else if (refreshedBind.maxGuardLevel > 0) {
|
|
102
|
-
buidInfo += `\n历史舰长: ${refreshedBind.
|
|
103
|
+
buidInfo += `\n历史舰长: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
|
|
103
104
|
}
|
|
104
105
|
if (refreshedBind.medalName) {
|
|
105
106
|
buidInfo += `\n粉丝牌: ${refreshedBind.medalName} Lv.${refreshedBind.medalLevel}`;
|
|
@@ -132,14 +133,14 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
132
133
|
if (refreshedBind) {
|
|
133
134
|
let buidInfo = `您尚未绑定MC账号\n\nB站账号信息:\nB站UID: ${refreshedBind.buidUid}\n用户名: ${refreshedBind.buidUsername}`;
|
|
134
135
|
if (refreshedBind.guardLevel > 0) {
|
|
135
|
-
buidInfo += `\n舰长等级: ${refreshedBind.
|
|
136
|
+
buidInfo += `\n舰长等级: ${(0, helpers_1.getGuardLevelText)(refreshedBind.guardLevel)} (${refreshedBind.guardLevel})`;
|
|
136
137
|
if (refreshedBind.maxGuardLevel > 0 &&
|
|
137
138
|
refreshedBind.maxGuardLevel < refreshedBind.guardLevel) {
|
|
138
|
-
buidInfo += `\n历史最高: ${refreshedBind.
|
|
139
|
+
buidInfo += `\n历史最高: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
|
|
139
140
|
}
|
|
140
141
|
}
|
|
141
142
|
else if (refreshedBind.maxGuardLevel > 0) {
|
|
142
|
-
buidInfo += `\n历史舰长: ${refreshedBind.
|
|
143
|
+
buidInfo += `\n历史舰长: ${(0, helpers_1.getGuardLevelText)(refreshedBind.maxGuardLevel)} (${refreshedBind.maxGuardLevel})`;
|
|
143
144
|
}
|
|
144
145
|
if (refreshedBind.medalName) {
|
|
145
146
|
buidInfo += `\n粉丝牌: ${refreshedBind.medalName} Lv.${refreshedBind.medalLevel}`;
|
|
@@ -217,13 +218,13 @@ class McidCommandHandler extends base_handler_1.BaseHandler {
|
|
|
217
218
|
if (bind.buidUid) {
|
|
218
219
|
buidInfo = `B站账号信息:\nB站UID: ${bind.buidUid}\n用户名: ${bind.buidUsername}`;
|
|
219
220
|
if (bind.guardLevel > 0) {
|
|
220
|
-
buidInfo += `\n舰长等级: ${bind.
|
|
221
|
+
buidInfo += `\n舰长等级: ${(0, helpers_1.getGuardLevelText)(bind.guardLevel)} (${bind.guardLevel})`;
|
|
221
222
|
if (bind.maxGuardLevel > 0 && bind.maxGuardLevel < bind.guardLevel) {
|
|
222
|
-
buidInfo += `\n历史最高: ${bind.
|
|
223
|
+
buidInfo += `\n历史最高: ${(0, helpers_1.getGuardLevelText)(bind.maxGuardLevel)} (${bind.maxGuardLevel})`;
|
|
223
224
|
}
|
|
224
225
|
}
|
|
225
226
|
else if (bind.maxGuardLevel > 0) {
|
|
226
|
-
buidInfo += `\n历史舰长: ${bind.
|
|
227
|
+
buidInfo += `\n历史舰长: ${(0, helpers_1.getGuardLevelText)(bind.maxGuardLevel)} (${bind.maxGuardLevel})`;
|
|
227
228
|
}
|
|
228
229
|
if (bind.medalName) {
|
|
229
230
|
buidInfo += `\n粉丝牌: ${bind.medalName} Lv.${bind.medalLevel}`;
|
package/lib/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const rate_limiter_1 = require("./utils/rate-limiter");
|
|
|
11
11
|
const helpers_1 = require("./utils/helpers");
|
|
12
12
|
const error_utils_1 = require("./utils/error-utils");
|
|
13
13
|
const mcidbind_repository_1 = require("./repositories/mcidbind.repository");
|
|
14
|
+
const supabase_client_1 = require("./utils/supabase-client");
|
|
14
15
|
const schedule_mute_repository_1 = require("./repositories/schedule-mute.repository");
|
|
15
16
|
const handlers_1 = require("./handlers");
|
|
16
17
|
const service_container_1 = require("./services/service-container");
|
|
@@ -53,6 +54,12 @@ exports.Config = koishi_1.Schema.object({
|
|
|
53
54
|
forceBindTargetUpUid: koishi_1.Schema.number().description('强制绑定目标UP主UID').default(686127),
|
|
54
55
|
forceBindTargetRoomId: koishi_1.Schema.number().description('强制绑定目标房间号').default(544853),
|
|
55
56
|
forceBindTargetMedalName: koishi_1.Schema.string().description('强制绑定目标粉丝牌名称').default('生态'),
|
|
57
|
+
supabaseUrl: koishi_1.Schema.string()
|
|
58
|
+
.description('Supabase项目URL')
|
|
59
|
+
.default(''),
|
|
60
|
+
supabaseKey: koishi_1.Schema.string()
|
|
61
|
+
.description('Supabase API Key (anon/service_role key)')
|
|
62
|
+
.default(''),
|
|
56
63
|
groupRequestReview: koishi_1.Schema.object({
|
|
57
64
|
enabled: koishi_1.Schema.boolean().description('是否启用入群申请审批功能').default(false),
|
|
58
65
|
targetGroupId: koishi_1.Schema.string()
|
|
@@ -60,11 +67,11 @@ exports.Config = koishi_1.Schema.object({
|
|
|
60
67
|
reviewGroupId: koishi_1.Schema.string()
|
|
61
68
|
.description('管理员审批操作所在的群ID(播报群)'),
|
|
62
69
|
approveAutoBindEmoji: koishi_1.Schema.string()
|
|
63
|
-
.description('批准并自动绑定的表情ID
|
|
64
|
-
.default('
|
|
70
|
+
.description('批准并自动绑定的表情ID(/赞)')
|
|
71
|
+
.default('76'),
|
|
65
72
|
approveInteractiveBindEmoji: koishi_1.Schema.string()
|
|
66
|
-
.description('批准并交互式绑定的表情ID
|
|
67
|
-
.default('
|
|
73
|
+
.description('批准并交互式绑定的表情ID(/OK)')
|
|
74
|
+
.default('124'),
|
|
68
75
|
rejectEmoji: koishi_1.Schema.string().description('拒绝申请的表情ID(/NO)').default('123'),
|
|
69
76
|
autoCleanupHours: koishi_1.Schema.number()
|
|
70
77
|
.description('待审批记录自动清理时间(小时)')
|
|
@@ -109,7 +116,8 @@ function apply(ctx, config) {
|
|
|
109
116
|
const logger = new koishi_1.Logger('bind-bot');
|
|
110
117
|
const loggerService = new logger_1.LoggerService(logger, config.debugMode);
|
|
111
118
|
// 创建数据仓储实例
|
|
112
|
-
const
|
|
119
|
+
const supabaseClient = new supabase_client_1.SupabaseClient({ url: config.supabaseUrl, key: config.supabaseKey });
|
|
120
|
+
const mcidbindRepo = new mcidbind_repository_1.MCIDBINDRepository(supabaseClient, loggerService);
|
|
113
121
|
const scheduleMuteRepo = new schedule_mute_repository_1.ScheduleMuteRepository(ctx, loggerService);
|
|
114
122
|
// 交互型绑定会话管理
|
|
115
123
|
const bindingSessions = new Map();
|
|
@@ -583,299 +591,7 @@ function apply(ctx, config) {
|
|
|
583
591
|
content.body = 'Internal Server Error';
|
|
584
592
|
}
|
|
585
593
|
});
|
|
586
|
-
//
|
|
587
|
-
ctx.model.extend('mcidbind', {
|
|
588
|
-
qqId: {
|
|
589
|
-
type: 'string'
|
|
590
|
-
},
|
|
591
|
-
mcUsername: {
|
|
592
|
-
type: 'string',
|
|
593
|
-
initial: null
|
|
594
|
-
},
|
|
595
|
-
mcUuid: {
|
|
596
|
-
type: 'string',
|
|
597
|
-
initial: null
|
|
598
|
-
},
|
|
599
|
-
lastModified: {
|
|
600
|
-
type: 'timestamp',
|
|
601
|
-
initial: null
|
|
602
|
-
},
|
|
603
|
-
isAdmin: {
|
|
604
|
-
type: 'boolean',
|
|
605
|
-
initial: false
|
|
606
|
-
},
|
|
607
|
-
whitelist: {
|
|
608
|
-
type: 'json',
|
|
609
|
-
initial: []
|
|
610
|
-
},
|
|
611
|
-
tags: {
|
|
612
|
-
type: 'json',
|
|
613
|
-
initial: []
|
|
614
|
-
},
|
|
615
|
-
// BUID相关字段
|
|
616
|
-
buidUid: {
|
|
617
|
-
type: 'string',
|
|
618
|
-
initial: ''
|
|
619
|
-
},
|
|
620
|
-
buidUsername: {
|
|
621
|
-
type: 'string',
|
|
622
|
-
initial: ''
|
|
623
|
-
},
|
|
624
|
-
guardLevel: {
|
|
625
|
-
type: 'integer',
|
|
626
|
-
initial: 0
|
|
627
|
-
},
|
|
628
|
-
guardLevelText: {
|
|
629
|
-
type: 'string',
|
|
630
|
-
initial: ''
|
|
631
|
-
},
|
|
632
|
-
maxGuardLevel: {
|
|
633
|
-
type: 'integer',
|
|
634
|
-
initial: 0
|
|
635
|
-
},
|
|
636
|
-
maxGuardLevelText: {
|
|
637
|
-
type: 'string',
|
|
638
|
-
initial: ''
|
|
639
|
-
},
|
|
640
|
-
medalName: {
|
|
641
|
-
type: 'string',
|
|
642
|
-
initial: ''
|
|
643
|
-
},
|
|
644
|
-
medalLevel: {
|
|
645
|
-
type: 'integer',
|
|
646
|
-
initial: 0
|
|
647
|
-
},
|
|
648
|
-
wealthMedalLevel: {
|
|
649
|
-
type: 'integer',
|
|
650
|
-
initial: 0
|
|
651
|
-
},
|
|
652
|
-
lastActiveTime: {
|
|
653
|
-
type: 'timestamp',
|
|
654
|
-
initial: null
|
|
655
|
-
},
|
|
656
|
-
reminderCount: {
|
|
657
|
-
type: 'integer',
|
|
658
|
-
initial: 0
|
|
659
|
-
},
|
|
660
|
-
usernameLastChecked: {
|
|
661
|
-
type: 'timestamp',
|
|
662
|
-
initial: null
|
|
663
|
-
},
|
|
664
|
-
usernameCheckFailCount: {
|
|
665
|
-
type: 'integer',
|
|
666
|
-
initial: 0
|
|
667
|
-
},
|
|
668
|
-
// 绑定状态标志字段
|
|
669
|
-
hasMcBind: {
|
|
670
|
-
type: 'boolean',
|
|
671
|
-
initial: false
|
|
672
|
-
},
|
|
673
|
-
hasBuidBind: {
|
|
674
|
-
type: 'boolean',
|
|
675
|
-
initial: false
|
|
676
|
-
}
|
|
677
|
-
}, {
|
|
678
|
-
// 设置主键为qqId
|
|
679
|
-
primary: 'qqId',
|
|
680
|
-
// 添加索引
|
|
681
|
-
unique: [['mcUsername'], ['buidUid']],
|
|
682
|
-
// 添加isAdmin索引,提高查询效率
|
|
683
|
-
indexes: [['isAdmin'], ['buidUid']]
|
|
684
|
-
});
|
|
685
|
-
// 检查表结构是否包含旧字段
|
|
686
|
-
const checkTableStructure = async () => {
|
|
687
|
-
try {
|
|
688
|
-
// 尝试获取一条记录来检查字段
|
|
689
|
-
const records = await mcidbindRepo.findAll({ limit: 1 });
|
|
690
|
-
// 如果没有记录,不需要迁移
|
|
691
|
-
if (!records || records.length === 0)
|
|
692
|
-
return false;
|
|
693
|
-
// 检查记录中是否包含id或userId字段,或缺少whitelist字段
|
|
694
|
-
const record = records[0];
|
|
695
|
-
return 'id' in record || 'userId' in record || !('whitelist' in record);
|
|
696
|
-
}
|
|
697
|
-
catch (error) {
|
|
698
|
-
logger.error(`[初始化] 检查表结构失败: ${error.message}`);
|
|
699
|
-
return false;
|
|
700
|
-
}
|
|
701
|
-
};
|
|
702
|
-
// 添加缺失字段
|
|
703
|
-
const addMissingFields = async () => {
|
|
704
|
-
try {
|
|
705
|
-
// 获取所有记录
|
|
706
|
-
const records = await mcidbindRepo.findAll();
|
|
707
|
-
let updatedCount = 0;
|
|
708
|
-
// 更新每个缺少字段的记录
|
|
709
|
-
for (const record of records) {
|
|
710
|
-
let needUpdate = false;
|
|
711
|
-
const updateData = {};
|
|
712
|
-
const qqId = record.qqId; // 提前提取 qqId,避免类型推断问题
|
|
713
|
-
// 检查并添加whitelist字段
|
|
714
|
-
if (!record.whitelist) {
|
|
715
|
-
updateData.whitelist = [];
|
|
716
|
-
needUpdate = true;
|
|
717
|
-
}
|
|
718
|
-
// 检查并添加tags字段
|
|
719
|
-
if (!record.tags) {
|
|
720
|
-
updateData.tags = [];
|
|
721
|
-
needUpdate = true;
|
|
722
|
-
}
|
|
723
|
-
// 检查并添加maxGuardLevel字段
|
|
724
|
-
if (!('maxGuardLevel' in record)) {
|
|
725
|
-
updateData.maxGuardLevel = 0;
|
|
726
|
-
needUpdate = true;
|
|
727
|
-
}
|
|
728
|
-
// 检查并添加maxGuardLevelText字段
|
|
729
|
-
if (!('maxGuardLevelText' in record)) {
|
|
730
|
-
updateData.maxGuardLevelText = '';
|
|
731
|
-
needUpdate = true;
|
|
732
|
-
}
|
|
733
|
-
// 检查并添加reminderCount字段
|
|
734
|
-
if (!('reminderCount' in record)) {
|
|
735
|
-
updateData.reminderCount = 0;
|
|
736
|
-
needUpdate = true;
|
|
737
|
-
}
|
|
738
|
-
// 检查并修复hasMcBind字段(数据迁移 + 数据一致性检查)
|
|
739
|
-
const currentHasMcBind = record.hasMcBind;
|
|
740
|
-
const mcUsername = record.mcUsername;
|
|
741
|
-
const hasValidMc = !!(mcUsername && !mcUsername.startsWith('_temp_'));
|
|
742
|
-
// 情况1:字段不存在,需要添加
|
|
743
|
-
if (currentHasMcBind === undefined || currentHasMcBind === null) {
|
|
744
|
-
updateData.hasMcBind = hasValidMc;
|
|
745
|
-
needUpdate = true;
|
|
746
|
-
logger.debug(`[数据迁移] 添加hasMcBind字段 QQ(${qqId}): ${hasValidMc}`);
|
|
747
|
-
}
|
|
748
|
-
// 情况2:字段存在但值不正确,需要修复
|
|
749
|
-
else if (currentHasMcBind !== hasValidMc) {
|
|
750
|
-
updateData.hasMcBind = hasValidMc;
|
|
751
|
-
needUpdate = true;
|
|
752
|
-
logger.info(`[数据修复] 修正hasMcBind QQ(${qqId}): ${currentHasMcBind} -> ${hasValidMc}`);
|
|
753
|
-
}
|
|
754
|
-
// 清理临时用户名(无论hasMcBind字段是否存在)
|
|
755
|
-
if (!hasValidMc && mcUsername && mcUsername.startsWith('_temp_')) {
|
|
756
|
-
updateData.mcUsername = null;
|
|
757
|
-
updateData.mcUuid = null;
|
|
758
|
-
updateData.whitelist = [];
|
|
759
|
-
needUpdate = true;
|
|
760
|
-
logger.info(`[数据清理] 清理QQ(${qqId})的临时用户名: ${mcUsername}`);
|
|
761
|
-
}
|
|
762
|
-
// 检查并修复hasBuidBind字段(数据迁移 + 数据一致性检查)
|
|
763
|
-
const currentHasBuidBind = record.hasBuidBind;
|
|
764
|
-
const buidUid = record.buidUid;
|
|
765
|
-
const hasValidBuid = !!(buidUid && buidUid.length > 0);
|
|
766
|
-
// 情况1:字段不存在,需要添加
|
|
767
|
-
if (currentHasBuidBind === undefined || currentHasBuidBind === null) {
|
|
768
|
-
updateData.hasBuidBind = hasValidBuid;
|
|
769
|
-
needUpdate = true;
|
|
770
|
-
logger.debug(`[数据迁移] 添加hasBuidBind字段 QQ(${qqId}): ${hasValidBuid}`);
|
|
771
|
-
}
|
|
772
|
-
// 情况2:字段存在但值不正确,需要修复
|
|
773
|
-
else if (currentHasBuidBind !== hasValidBuid) {
|
|
774
|
-
updateData.hasBuidBind = hasValidBuid;
|
|
775
|
-
needUpdate = true;
|
|
776
|
-
logger.info(`[数据修复] 修正hasBuidBind QQ(${qqId}): ${currentHasBuidBind} -> ${hasValidBuid}`);
|
|
777
|
-
}
|
|
778
|
-
// 如果需要更新,执行更新操作
|
|
779
|
-
if (needUpdate) {
|
|
780
|
-
await mcidbindRepo.update(qqId, updateData);
|
|
781
|
-
updatedCount++;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
if (updatedCount > 0) {
|
|
785
|
-
logger.info(`[初始化] 成功为${updatedCount}条记录添加缺失字段`);
|
|
786
|
-
}
|
|
787
|
-
else {
|
|
788
|
-
logger.info('[初始化] 所有记录都包含必要字段,无需更新');
|
|
789
|
-
}
|
|
790
|
-
return true;
|
|
791
|
-
}
|
|
792
|
-
catch (error) {
|
|
793
|
-
logger.error(`[初始化] 添加缺失字段失败: ${error.message}`);
|
|
794
|
-
return false;
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
// 在插件启动时执行数据迁移(放在函数定义之后)
|
|
798
|
-
ctx.on('ready', async () => {
|
|
799
|
-
logger.info('[初始化] 开始数据迁移和一致性检查...');
|
|
800
|
-
await addMissingFields();
|
|
801
|
-
});
|
|
802
|
-
// 重建MCIDBIND表
|
|
803
|
-
const rebuildMcidBindTable = async () => {
|
|
804
|
-
try {
|
|
805
|
-
// 备份现有数据
|
|
806
|
-
const oldRecords = await mcidbindRepo.findAll();
|
|
807
|
-
logger.info(`[初始化] 成功备份${oldRecords.length}条记录`);
|
|
808
|
-
// 创建数据备份(用于恢复)
|
|
809
|
-
const backupData = JSON.parse(JSON.stringify(oldRecords));
|
|
810
|
-
try {
|
|
811
|
-
// 提取有效数据
|
|
812
|
-
const validRecords = oldRecords
|
|
813
|
-
.map(record => {
|
|
814
|
-
// 确保qqId存在
|
|
815
|
-
if (!record.qqId) {
|
|
816
|
-
// 如果没有qqId但有userId,尝试从userId提取
|
|
817
|
-
if ('userId' in record && record.userId) {
|
|
818
|
-
record.qqId = normalizeQQId(String(record.userId));
|
|
819
|
-
}
|
|
820
|
-
else {
|
|
821
|
-
// 既没有qqId也没有userId,跳过此记录
|
|
822
|
-
return null;
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
return {
|
|
826
|
-
qqId: record.qqId,
|
|
827
|
-
mcUsername: record.mcUsername || '',
|
|
828
|
-
mcUuid: record.mcUuid || '',
|
|
829
|
-
lastModified: record.lastModified || new Date(),
|
|
830
|
-
isAdmin: record.isAdmin || false,
|
|
831
|
-
whitelist: record.whitelist || [],
|
|
832
|
-
tags: record.tags || []
|
|
833
|
-
};
|
|
834
|
-
})
|
|
835
|
-
.filter(record => record !== null);
|
|
836
|
-
// 删除现有表
|
|
837
|
-
await mcidbindRepo.deleteAll();
|
|
838
|
-
logger.info('[初始化] 成功删除旧表数据');
|
|
839
|
-
// 重新创建记录
|
|
840
|
-
let successCount = 0;
|
|
841
|
-
let errorCount = 0;
|
|
842
|
-
for (const record of validRecords) {
|
|
843
|
-
try {
|
|
844
|
-
await mcidbindRepo.create(record);
|
|
845
|
-
successCount++;
|
|
846
|
-
}
|
|
847
|
-
catch (e) {
|
|
848
|
-
errorCount++;
|
|
849
|
-
logger.warn(`[初始化] 重建记录失败 (QQ=${record.qqId}): ${e.message}`);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
logger.info(`[初始化] 成功重建了${successCount}条记录,失败${errorCount}条`);
|
|
853
|
-
return true;
|
|
854
|
-
}
|
|
855
|
-
catch (migrationError) {
|
|
856
|
-
// 迁移过程出错,尝试恢复
|
|
857
|
-
logger.error(`[初始化] 表重建过程失败,尝试恢复数据: ${migrationError.message}`);
|
|
858
|
-
try {
|
|
859
|
-
// 清空表以避免重复数据
|
|
860
|
-
await mcidbindRepo.deleteAll();
|
|
861
|
-
// 恢复原始数据
|
|
862
|
-
for (const record of backupData) {
|
|
863
|
-
await mcidbindRepo.create(record);
|
|
864
|
-
}
|
|
865
|
-
logger.info(`[初始化] 成功恢复${backupData.length}条原始记录`);
|
|
866
|
-
}
|
|
867
|
-
catch (recoveryError) {
|
|
868
|
-
logger.error(`[初始化] 数据恢复失败,可能导致数据丢失: ${recoveryError.message}`);
|
|
869
|
-
throw new Error('数据迁移失败且无法恢复');
|
|
870
|
-
}
|
|
871
|
-
throw migrationError;
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
catch (error) {
|
|
875
|
-
logger.error(`[初始化] 重建表失败: ${error.message}`);
|
|
876
|
-
throw error;
|
|
877
|
-
}
|
|
878
|
-
};
|
|
594
|
+
// mcidbind 表已迁移至 Supabase,无需在 Koishi 中注册模型
|
|
879
595
|
// 处理用户ID,去除平台前缀,只保留QQ号
|
|
880
596
|
const normalizeQQId = (userId) => {
|
|
881
597
|
// 处理空值情况
|
|
@@ -1,117 +1,35 @@
|
|
|
1
|
-
import { Context } from 'koishi';
|
|
2
1
|
import { LoggerService } from '../utils/logger';
|
|
2
|
+
import { SupabaseClient } from '../utils/supabase-client';
|
|
3
3
|
import type { MCIDBIND } from '../types';
|
|
4
4
|
/**
|
|
5
5
|
* MCIDBIND 数据仓储类
|
|
6
|
-
*
|
|
6
|
+
* 通过 Supabase REST API 操作 user 表
|
|
7
7
|
*/
|
|
8
8
|
export declare class MCIDBINDRepository {
|
|
9
|
-
private
|
|
9
|
+
private supabase;
|
|
10
10
|
private logger;
|
|
11
|
-
constructor(
|
|
12
|
-
/**
|
|
13
|
-
* 根据 QQ 号查询绑定信息
|
|
14
|
-
* @param qqId QQ号(已规范化)
|
|
15
|
-
* @returns 绑定信息或 null
|
|
16
|
-
*/
|
|
11
|
+
constructor(supabase: SupabaseClient, logger: LoggerService);
|
|
17
12
|
findByQQId(qqId: string): Promise<MCIDBIND | null>;
|
|
18
|
-
/**
|
|
19
|
-
* 根据 MC 用户名查询绑定信息(精确匹配)
|
|
20
|
-
* @param mcUsername MC用户名
|
|
21
|
-
* @returns 绑定信息或 null
|
|
22
|
-
*/
|
|
23
13
|
findByMCUsername(mcUsername: string): Promise<MCIDBIND | null>;
|
|
24
|
-
/**
|
|
25
|
-
* 根据 MC 用户名查询绑定信息(不区分大小写)
|
|
26
|
-
* @param mcUsername MC用户名
|
|
27
|
-
* @returns 绑定信息或 null
|
|
28
|
-
*/
|
|
29
14
|
findByUsernameIgnoreCase(mcUsername: string): Promise<MCIDBIND | null>;
|
|
30
|
-
/**
|
|
31
|
-
* 根据 MC UUID 查询绑定信息
|
|
32
|
-
* @param mcUuid MC UUID(可带或不带连字符)
|
|
33
|
-
* @returns 绑定信息或 null
|
|
34
|
-
*/
|
|
35
15
|
findByUuid(mcUuid: string): Promise<MCIDBIND | null>;
|
|
36
|
-
/**
|
|
37
|
-
* 根据 B站 UID 查询绑定信息
|
|
38
|
-
* @param buidUid B站UID
|
|
39
|
-
* @returns 绑定信息或 null
|
|
40
|
-
*/
|
|
41
16
|
findByBuidUid(buidUid: string): Promise<MCIDBIND | null>;
|
|
42
|
-
/**
|
|
43
|
-
* 获取所有绑定记录
|
|
44
|
-
* @param options 查询选项
|
|
45
|
-
* @returns 绑定记录列表
|
|
46
|
-
*/
|
|
47
17
|
findAll(options?: {
|
|
48
18
|
limit?: number;
|
|
49
19
|
}): Promise<MCIDBIND[]>;
|
|
50
|
-
/**
|
|
51
|
-
* 根据标签查询绑定记录
|
|
52
|
-
* @param tag 标签名称
|
|
53
|
-
* @returns 包含该标签的绑定记录列表
|
|
54
|
-
*/
|
|
55
20
|
findByTag(tag: string): Promise<MCIDBIND[]>;
|
|
56
|
-
/**
|
|
57
|
-
* 创建新的绑定记录
|
|
58
|
-
* @param data 绑定数据
|
|
59
|
-
* @returns 创建的记录
|
|
60
|
-
*/
|
|
61
21
|
create(data: Partial<MCIDBIND> & {
|
|
62
22
|
qqId: string;
|
|
63
23
|
}): Promise<MCIDBIND>;
|
|
64
|
-
/**
|
|
65
|
-
* 更新绑定记录(部分字段)
|
|
66
|
-
* @param qqId QQ号
|
|
67
|
-
* @param data 要更新的字段
|
|
68
|
-
*/
|
|
69
24
|
update(qqId: string, data: Partial<MCIDBIND>): Promise<void>;
|
|
70
|
-
/**
|
|
71
|
-
* 删除绑定记录
|
|
72
|
-
* @param qqId QQ号
|
|
73
|
-
* @returns 删除的记录数
|
|
74
|
-
*/
|
|
75
25
|
delete(qqId: string): Promise<number>;
|
|
76
|
-
/**
|
|
77
|
-
* 删除所有绑定记录
|
|
78
|
-
* @returns 删除的记录数
|
|
79
|
-
*/
|
|
80
26
|
deleteAll(): Promise<number>;
|
|
81
|
-
/**
|
|
82
|
-
* 批量创建绑定记录
|
|
83
|
-
* @param records 绑定记录列表
|
|
84
|
-
*/
|
|
85
27
|
batchCreate(records: Array<Partial<MCIDBIND> & {
|
|
86
28
|
qqId: string;
|
|
87
29
|
}>): Promise<void>;
|
|
88
|
-
/**
|
|
89
|
-
* 为用户添加标签
|
|
90
|
-
* @param qqId QQ号
|
|
91
|
-
* @param tag 标签名称
|
|
92
|
-
*/
|
|
93
30
|
addTag(qqId: string, tag: string): Promise<void>;
|
|
94
|
-
/**
|
|
95
|
-
* 为用户移除标签
|
|
96
|
-
* @param qqId QQ号
|
|
97
|
-
* @param tag 标签名称
|
|
98
|
-
*/
|
|
99
31
|
removeTag(qqId: string, tag: string): Promise<void>;
|
|
100
|
-
/**
|
|
101
|
-
* 为用户添加白名单服务器
|
|
102
|
-
* @param qqId QQ号
|
|
103
|
-
* @param serverId 服务器ID
|
|
104
|
-
*/
|
|
105
32
|
addWhitelist(qqId: string, serverId: string): Promise<void>;
|
|
106
|
-
/**
|
|
107
|
-
* 为用户移除白名单服务器
|
|
108
|
-
* @param qqId QQ号
|
|
109
|
-
* @param serverId 服务器ID
|
|
110
|
-
*/
|
|
111
33
|
removeWhitelist(qqId: string, serverId: string): Promise<void>;
|
|
112
|
-
/**
|
|
113
|
-
* 获取所有管理员
|
|
114
|
-
* @returns 管理员列表
|
|
115
|
-
*/
|
|
116
34
|
findAllAdmins(): Promise<MCIDBIND[]>;
|
|
117
35
|
}
|