koishi-plugin-kkk 3.7.2 → 3.9.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.
@@ -1,23 +1,20 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.BilibiliDBBase = void 0;
7
- const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
4
  const amagi_1 = require("@ikenxuan/amagi");
10
5
  const node_karin_1 = require("../../../compat/node-karin.js");
11
- const root_1 = require("../../../compat/root.js");
12
- const sqlite3_1 = __importDefault(require("../../../compat/sqlite3.js"));
13
- const utils_1 = require("../../module/utils");
14
6
  const Config_1 = require("../../module/utils/Config");
15
- /** 数据库操作类 */
7
+ const model_1 = require("./model");
8
+ /** 当前时间戳(ISO 字符串,与旧版 sqlite 里的口径一致) */
9
+ const now = () => new Date().toISOString();
10
+ /** 数据库操作类(基于 Koishi 原生数据库服务) */
16
11
  class BilibiliDBBase {
17
- db;
18
- dbPath;
19
- constructor() {
20
- this.dbPath = node_path_1.default.join(`${root_1.karinPathBase}/${utils_1.Root.pluginName}/data`, 'bilibili.db');
12
+ ctx;
13
+ constructor(ctx) {
14
+ this.ctx = ctx;
15
+ }
16
+ get db() {
17
+ return this.ctx.database;
21
18
  }
22
19
  /**
23
20
  * 初始化数据库
@@ -25,13 +22,7 @@ class BilibiliDBBase {
25
22
  async init() {
26
23
  try {
27
24
  node_karin_1.logger.debug(node_karin_1.logger.green('--------------------------[BilibiliDB] 开始初始化数据库--------------------------'));
28
- node_karin_1.logger.debug('[BilibiliDB] 正在连接数据库...');
29
- // 创建数据库连接
30
- await node_fs_1.default.promises.mkdir(node_path_1.default.dirname(this.dbPath), { recursive: true });
31
- this.db = new sqlite3_1.default.Database(this.dbPath);
32
- // 创建表结构
33
- await this.createTables();
34
- node_karin_1.logger.debug('[BilibiliDB] 数据库模型同步成功');
25
+ node_karin_1.logger.debug('[BilibiliDB] 使用 Koishi 原生数据库服务,表已由 ctx.model.extend 注册');
35
26
  node_karin_1.logger.debug('[BilibiliDB] 正在同步配置订阅...');
36
27
  node_karin_1.logger.debug('[BilibiliDB] 配置项数量:', Config_1.Config.pushlist.bilibili?.length || 0);
37
28
  await this.syncConfigSubscriptions(Config_1.Config.pushlist.bilibili);
@@ -44,139 +35,16 @@ class BilibiliDBBase {
44
35
  }
45
36
  return this;
46
37
  }
47
- /**
48
- * 创建数据库表结构
49
- */
50
- async createTables() {
51
- const queries = [
52
- // 创建机器人表
53
- `CREATE TABLE IF NOT EXISTS Bots (
54
- id TEXT PRIMARY KEY,
55
- createdAt TEXT DEFAULT CURRENT_TIMESTAMP,
56
- updatedAt TEXT DEFAULT CURRENT_TIMESTAMP
57
- )`,
58
- // 创建群组表
59
- `CREATE TABLE IF NOT EXISTS Groups (
60
- id TEXT NOT NULL,
61
- botId TEXT NOT NULL,
62
- createdAt TEXT DEFAULT CURRENT_TIMESTAMP,
63
- updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
64
- PRIMARY KEY (id, botId),
65
- FOREIGN KEY (botId) REFERENCES Bots(id)
66
- )`,
67
- // 创建B站用户表
68
- `CREATE TABLE IF NOT EXISTS BilibiliUsers (
69
- host_mid INTEGER PRIMARY KEY,
70
- remark TEXT,
71
- filterMode TEXT DEFAULT 'blacklist',
72
- createdAt TEXT DEFAULT CURRENT_TIMESTAMP,
73
- updatedAt TEXT DEFAULT CURRENT_TIMESTAMP
74
- )`,
75
- // 创建群组用户订阅关系表
76
- `CREATE TABLE IF NOT EXISTS GroupUserSubscriptions (
77
- groupId TEXT,
78
- host_mid INTEGER,
79
- createdAt TEXT DEFAULT CURRENT_TIMESTAMP,
80
- updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
81
- PRIMARY KEY (groupId, host_mid),
82
- FOREIGN KEY (groupId) REFERENCES Groups(id),
83
- FOREIGN KEY (host_mid) REFERENCES BilibiliUsers(host_mid)
84
- )`,
85
- // 创建动态缓存表
86
- `CREATE TABLE IF NOT EXISTS DynamicCaches (
87
- id INTEGER PRIMARY KEY AUTOINCREMENT,
88
- dynamic_id TEXT NOT NULL,
89
- host_mid INTEGER NOT NULL,
90
- groupId TEXT NOT NULL,
91
- dynamic_type TEXT,
92
- createdAt TEXT DEFAULT CURRENT_TIMESTAMP,
93
- updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
94
- FOREIGN KEY (host_mid) REFERENCES BilibiliUsers(host_mid),
95
- FOREIGN KEY (groupId) REFERENCES Groups(id),
96
- UNIQUE(dynamic_id, host_mid, groupId)
97
- )`,
98
- // 创建过滤词表
99
- `CREATE TABLE IF NOT EXISTS FilterWords (
100
- id INTEGER PRIMARY KEY AUTOINCREMENT,
101
- host_mid INTEGER NOT NULL,
102
- word TEXT NOT NULL,
103
- createdAt TEXT DEFAULT CURRENT_TIMESTAMP,
104
- updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
105
- FOREIGN KEY (host_mid) REFERENCES BilibiliUsers(host_mid),
106
- UNIQUE(host_mid, word)
107
- )`,
108
- // 创建过滤标签表
109
- `CREATE TABLE IF NOT EXISTS FilterTags (
110
- id INTEGER PRIMARY KEY AUTOINCREMENT,
111
- host_mid INTEGER NOT NULL,
112
- tag TEXT NOT NULL,
113
- createdAt TEXT DEFAULT CURRENT_TIMESTAMP,
114
- updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
115
- FOREIGN KEY (host_mid) REFERENCES BilibiliUsers(host_mid),
116
- UNIQUE(host_mid, tag)
117
- )`
118
- ];
119
- for (const query of queries) {
120
- await this.runQuery(query);
121
- }
122
- }
123
- /**
124
- * 执行SQL查询
125
- */
126
- runQuery(sql, params = []) {
127
- return new Promise((resolve, reject) => {
128
- this.db.run(sql, params, function (err) {
129
- if (err) {
130
- reject(err);
131
- }
132
- else {
133
- resolve({ lastID: this.lastID, changes: this.changes });
134
- }
135
- });
136
- });
137
- }
138
- /**
139
- * 执行SQL查询并获取单个结果
140
- */
141
- getQuery(sql, params = []) {
142
- return new Promise((resolve, reject) => {
143
- this.db.get(sql, params, (err, row) => {
144
- if (err) {
145
- reject(err);
146
- }
147
- else {
148
- resolve(row);
149
- }
150
- });
151
- });
152
- }
153
- /**
154
- * 执行SQL查询并获取所有结果
155
- */
156
- allQuery(sql, params = []) {
157
- return new Promise((resolve, reject) => {
158
- this.db.all(sql, params, (err, rows) => {
159
- if (err) {
160
- reject(err);
161
- }
162
- else {
163
- resolve(rows);
164
- }
165
- });
166
- });
167
- }
168
38
  /**
169
39
  * 获取或创建机器人记录
170
40
  * @param botId 机器人ID
171
41
  */
172
42
  async getOrCreateBot(botId) {
173
- let bot = await this.getQuery('SELECT * FROM Bots WHERE id = ?', [botId]);
174
- if (!bot) {
175
- const now = new Date().toISOString();
176
- await this.runQuery('INSERT INTO Bots (id, createdAt, updatedAt) VALUES (?, ?, ?)', [botId, now, now]);
177
- bot = { id: botId, createdAt: now, updatedAt: now };
178
- }
179
- return bot;
43
+ const [bot] = await this.db.get(model_1.TABLE.bilibiliBot, { id: botId });
44
+ if (bot)
45
+ return bot;
46
+ const time = now();
47
+ return await this.db.create(model_1.TABLE.bilibiliBot, { id: botId, createdAt: time, updatedAt: time });
180
48
  }
181
49
  /**
182
50
  * 获取或创建群组记录
@@ -185,13 +53,16 @@ class BilibiliDBBase {
185
53
  */
186
54
  async getOrCreateGroup(groupId, botId) {
187
55
  await this.getOrCreateBot(botId);
188
- let group = await this.getQuery('SELECT * FROM Groups WHERE id = ? AND botId = ?', [groupId, botId]);
189
- if (!group) {
190
- const now = new Date().toISOString();
191
- await this.runQuery('INSERT INTO Groups (id, botId, createdAt, updatedAt) VALUES (?, ?, ?, ?)', [groupId, botId, now, now]);
192
- group = { id: groupId, botId, createdAt: now, updatedAt: now };
193
- }
194
- return group;
56
+ const [group] = await this.db.get(model_1.TABLE.bilibiliGroup, { id: groupId, botId });
57
+ if (group)
58
+ return group;
59
+ const time = now();
60
+ return await this.db.create(model_1.TABLE.bilibiliGroup, {
61
+ id: groupId,
62
+ botId,
63
+ createdAt: time,
64
+ updatedAt: time
65
+ });
195
66
  }
196
67
  /**
197
68
  * 获取B站用户记录
@@ -199,8 +70,8 @@ class BilibiliDBBase {
199
70
  * @returns 返回用户信息,如果不存在则返回null
200
71
  */
201
72
  async getBilibiliUser(host_mid) {
202
- const user = await this.getQuery('SELECT * FROM BilibiliUsers WHERE host_mid = ?', [host_mid]);
203
- return user || null;
73
+ const [user] = await this.db.get(model_1.TABLE.bilibiliUser, { host_mid });
74
+ return user ?? null;
204
75
  }
205
76
  /**
206
77
  * 获取或创建B站用户记录
@@ -208,34 +79,25 @@ class BilibiliDBBase {
208
79
  * @param remark UP主昵称
209
80
  */
210
81
  async getOrCreateBilibiliUser(host_mid, remark = '') {
211
- let user = await this.getQuery('SELECT * FROM BilibiliUsers WHERE host_mid = ?', [host_mid]);
212
- if (!user) {
213
- const now = new Date().toISOString();
214
- await this.runQuery('INSERT INTO BilibiliUsers (host_mid, remark, filterMode, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)', [
215
- host_mid,
216
- remark,
217
- 'blacklist',
218
- now,
219
- now
220
- ]);
221
- user = {
82
+ const [row] = await this.db.get(model_1.TABLE.bilibiliUser, { host_mid });
83
+ if (!row) {
84
+ const time = now();
85
+ const created = await this.db.create(model_1.TABLE.bilibiliUser, {
222
86
  host_mid,
223
87
  remark,
224
88
  filterMode: 'blacklist',
225
- createdAt: now,
226
- updatedAt: now
227
- };
89
+ createdAt: time,
90
+ updatedAt: time
91
+ });
92
+ return created;
228
93
  }
229
- else {
230
- // 如果提供了新的remark,更新用户记录
231
- if (remark && user.remark !== remark) {
232
- const now = new Date().toISOString();
233
- await this.runQuery('UPDATE BilibiliUsers SET remark = ?, updatedAt = ? WHERE host_mid = ?', [remark, now, host_mid]);
234
- user.remark = remark;
235
- user.updatedAt = now;
236
- }
94
+ // 如果提供了新的remark,更新用户记录
95
+ if (remark && row.remark !== remark) {
96
+ const time = now();
97
+ await this.db.set(model_1.TABLE.bilibiliUser, { host_mid }, { remark, updatedAt: time });
98
+ return { ...row, remark, updatedAt: time };
237
99
  }
238
- return user;
100
+ return row;
239
101
  }
240
102
  /**
241
103
  * 订阅B站用户
@@ -247,18 +109,16 @@ class BilibiliDBBase {
247
109
  async subscribeBilibiliUser(groupId, botId, host_mid, remark = '') {
248
110
  await this.getOrCreateGroup(groupId, botId);
249
111
  await this.getOrCreateBilibiliUser(host_mid, remark);
250
- let subscription = await this.getQuery('SELECT * FROM GroupUserSubscriptions WHERE groupId = ? AND host_mid = ?', [groupId, host_mid]);
251
- if (!subscription) {
252
- const now = new Date().toISOString();
253
- await this.runQuery('INSERT INTO GroupUserSubscriptions (groupId, host_mid, createdAt, updatedAt) VALUES (?, ?, ?, ?)', [
254
- groupId,
255
- host_mid,
256
- now,
257
- now
258
- ]);
259
- subscription = { groupId, host_mid, createdAt: now, updatedAt: now };
260
- }
261
- return subscription;
112
+ const [subscription] = await this.db.get(model_1.TABLE.bilibiliSubscription, { groupId, host_mid });
113
+ if (subscription)
114
+ return subscription;
115
+ const time = now();
116
+ return await this.db.create(model_1.TABLE.bilibiliSubscription, {
117
+ groupId,
118
+ host_mid,
119
+ createdAt: time,
120
+ updatedAt: time
121
+ });
262
122
  }
263
123
  /**
264
124
  * 取消订阅B站用户
@@ -266,24 +126,21 @@ class BilibiliDBBase {
266
126
  * @param host_mid B站用户UID
267
127
  */
268
128
  async unsubscribeBilibiliUser(groupId, host_mid) {
269
- const result = await this.runQuery('DELETE FROM GroupUserSubscriptions WHERE groupId = ? AND host_mid = ?', [groupId, host_mid]);
129
+ const result = await this.db.remove(model_1.TABLE.bilibiliSubscription, { groupId, host_mid });
270
130
  // 清除相关的动态缓存
271
- await this.runQuery('DELETE FROM DynamicCaches WHERE groupId = ? AND host_mid = ?', [groupId, host_mid]);
131
+ await this.db.remove(model_1.TABLE.bilibiliDynamicCache, { groupId, host_mid });
272
132
  // 检查该用户是否还有其他群组订阅
273
- const remainingSubscriptions = await this.getQuery('SELECT COUNT(*) as count FROM GroupUserSubscriptions WHERE host_mid = ?', [host_mid]);
133
+ const remaining = await this.db.get(model_1.TABLE.bilibiliSubscription, { host_mid }, { limit: 1 });
274
134
  // 如果没有任何群组订阅该用户,删除用户记录及相关数据
275
- if (remainingSubscriptions && remainingSubscriptions.count === 0) {
135
+ if (remaining.length === 0) {
276
136
  node_karin_1.logger.info(`[BilibiliDB] 用户 ${host_mid} 已无任何群组订阅,清理相关数据`);
277
- // 删除用户记录
278
- await this.runQuery('DELETE FROM BilibiliUsers WHERE host_mid = ?', [host_mid]);
279
- // 删除过滤词
280
- await this.runQuery('DELETE FROM FilterWords WHERE host_mid = ?', [host_mid]);
281
- // 删除过滤标签
282
- await this.runQuery('DELETE FROM FilterTags WHERE host_mid = ?', [host_mid]);
137
+ await this.db.remove(model_1.TABLE.bilibiliUser, { host_mid });
138
+ await this.db.remove(model_1.TABLE.bilibiliFilterWord, { host_mid });
139
+ await this.db.remove(model_1.TABLE.bilibiliFilterTag, { host_mid });
283
140
  // 删除所有相关的动态缓存(所有群组的)
284
- await this.runQuery('DELETE FROM DynamicCaches WHERE host_mid = ?', [host_mid]);
141
+ await this.db.remove(model_1.TABLE.bilibiliDynamicCache, { host_mid });
285
142
  }
286
- return result.changes > 0;
143
+ return (result.removed ?? 0) > 0;
287
144
  }
288
145
  /**
289
146
  * 添加动态缓存
@@ -293,25 +150,18 @@ class BilibiliDBBase {
293
150
  * @param dynamic_type 动态类型
294
151
  */
295
152
  async addDynamicCache(dynamic_id, host_mid, groupId, dynamic_type) {
296
- let cache = await this.getQuery('SELECT * FROM DynamicCaches WHERE dynamic_id = ? AND host_mid = ? AND groupId = ?', [
153
+ const [cache] = await this.db.get(model_1.TABLE.bilibiliDynamicCache, { dynamic_id, host_mid, groupId });
154
+ if (cache)
155
+ return cache;
156
+ const time = now();
157
+ return await this.db.create(model_1.TABLE.bilibiliDynamicCache, {
297
158
  dynamic_id,
298
159
  host_mid,
299
- groupId
300
- ]);
301
- if (!cache) {
302
- const now = new Date().toISOString();
303
- const result = await this.runQuery('INSERT INTO DynamicCaches (dynamic_id, host_mid, groupId, dynamic_type, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?)', [dynamic_id, host_mid, groupId, dynamic_type, now, now]);
304
- cache = {
305
- id: result.lastID,
306
- dynamic_id,
307
- host_mid,
308
- groupId,
309
- dynamic_type,
310
- createdAt: now,
311
- updatedAt: now
312
- };
313
- }
314
- return cache;
160
+ groupId,
161
+ dynamic_type,
162
+ createdAt: time,
163
+ updatedAt: time
164
+ });
315
165
  }
316
166
  /**
317
167
  * 检查动态是否已推送
@@ -320,15 +170,15 @@ class BilibiliDBBase {
320
170
  * @param groupId 群组ID
321
171
  */
322
172
  async isDynamicPushed(dynamic_id, host_mid, groupId) {
323
- const result = await this.getQuery('SELECT COUNT(*) as count FROM DynamicCaches WHERE dynamic_id = ? AND host_mid = ? AND groupId = ?', [dynamic_id, host_mid, groupId]);
324
- return (result?.count || 0) > 0;
173
+ const rows = await this.db.get(model_1.TABLE.bilibiliDynamicCache, { dynamic_id, host_mid, groupId }, { limit: 1 });
174
+ return rows.length > 0;
325
175
  }
326
176
  /**
327
177
  * 获取机器人管理的所有群组
328
178
  * @param botId 机器人ID
329
179
  */
330
180
  async getBotGroups(botId) {
331
- return await this.allQuery('SELECT * FROM Groups WHERE botId = ?', [botId]);
181
+ return await this.db.get(model_1.TABLE.bilibiliGroup, { botId });
332
182
  }
333
183
  /**
334
184
  * 更新群组的机器人ID
@@ -338,43 +188,49 @@ class BilibiliDBBase {
338
188
  */
339
189
  async updateGroupBotId(groupId, oldBotId, newBotId) {
340
190
  await this.getOrCreateBot(newBotId);
341
- const now = new Date().toISOString();
342
- await this.runQuery('UPDATE Groups SET botId = ?, updatedAt = ? WHERE id = ? AND botId = ?', [newBotId, now, groupId, oldBotId]);
191
+ await this.db.set(model_1.TABLE.bilibiliGroup, { id: groupId, botId: oldBotId }, {
192
+ botId: newBotId,
193
+ updatedAt: now()
194
+ });
343
195
  }
344
196
  /**
345
197
  * 获取群组订阅的所有B站用户
346
198
  * @param groupId 群组ID
347
199
  */
348
200
  async getGroupSubscriptions(groupId) {
349
- const subscriptions = await this.allQuery(`SELECT
350
- gus.groupId, gus.host_mid, gus.createdAt, gus.updatedAt,
351
- bu.remark, bu.filterMode,
352
- bu.createdAt as bu_createdAt, bu.updatedAt as bu_updatedAt
353
- FROM GroupUserSubscriptions gus
354
- LEFT JOIN BilibiliUsers bu ON gus.host_mid = bu.host_mid
355
- WHERE gus.groupId = ?`, [groupId]);
356
- return subscriptions.map((sub) => ({
357
- groupId: sub.groupId,
358
- host_mid: sub.host_mid,
359
- createdAt: sub.createdAt,
360
- updatedAt: sub.updatedAt,
361
- bilibiliUser: {
201
+ const subscriptions = await this.db.get(model_1.TABLE.bilibiliSubscription, { groupId });
202
+ if (!subscriptions.length)
203
+ return [];
204
+ const hosts = [...new Set(subscriptions.map((item) => item.host_mid))];
205
+ const users = await this.db.get(model_1.TABLE.bilibiliUser, { host_mid: { $in: hosts } });
206
+ const userMap = new Map(users.map((user) => [user.host_mid, user]));
207
+ return subscriptions.map((sub) => {
208
+ const user = userMap.get(sub.host_mid);
209
+ return {
210
+ groupId: sub.groupId,
362
211
  host_mid: sub.host_mid,
363
- remark: sub.remark,
364
- filterMode: sub.filterMode,
365
- createdAt: sub.bu_createdAt,
366
- updatedAt: sub.bu_updatedAt
367
- }
368
- }));
212
+ createdAt: sub.createdAt,
213
+ updatedAt: sub.updatedAt,
214
+ bilibiliUser: {
215
+ host_mid: sub.host_mid,
216
+ remark: user?.remark ?? '',
217
+ filterMode: (user?.filterMode ?? 'blacklist'),
218
+ createdAt: user?.createdAt ?? sub.createdAt,
219
+ updatedAt: user?.updatedAt ?? sub.updatedAt
220
+ }
221
+ };
222
+ });
369
223
  }
370
224
  /**
371
225
  * 获取B站用户的所有订阅群组
372
226
  * @param host_mid B站用户UID
373
227
  */
374
228
  async getUserSubscribedGroups(host_mid) {
375
- return await this.allQuery(`SELECT g.* FROM Groups g
376
- INNER JOIN GroupUserSubscriptions gus ON g.id = gus.groupId
377
- WHERE gus.host_mid = ?`, [host_mid]);
229
+ const subscriptions = await this.db.get(model_1.TABLE.bilibiliSubscription, { host_mid });
230
+ if (!subscriptions.length)
231
+ return [];
232
+ const groupIds = [...new Set(subscriptions.map((item) => item.groupId))];
233
+ return (await this.db.get(model_1.TABLE.bilibiliGroup, { id: { $in: groupIds } }));
378
234
  }
379
235
  /**
380
236
  * 获取群组的动态缓存
@@ -382,14 +238,9 @@ class BilibiliDBBase {
382
238
  * @param host_mid 可选的B站用户UID过滤
383
239
  */
384
240
  async getGroupDynamicCache(groupId, host_mid) {
385
- let sql = 'SELECT * FROM DynamicCaches WHERE groupId = ?';
386
- const params = [groupId];
387
- if (host_mid) {
388
- sql += ' AND host_mid = ?';
389
- params.push(host_mid);
390
- }
391
- sql += ' ORDER BY createdAt DESC';
392
- return await this.allQuery(sql, params);
241
+ return await this.db.get(model_1.TABLE.bilibiliDynamicCache, host_mid ? { groupId, host_mid } : { groupId }, {
242
+ sort: { createdAt: 'desc' }
243
+ });
393
244
  }
394
245
  /**
395
246
  * 检查群组是否已订阅B站用户
@@ -397,75 +248,59 @@ class BilibiliDBBase {
397
248
  * @param groupId 群组ID
398
249
  */
399
250
  async isSubscribed(host_mid, groupId) {
400
- const result = await this.getQuery('SELECT COUNT(*) as count FROM GroupUserSubscriptions WHERE host_mid = ? AND groupId = ?', [host_mid, groupId]);
401
- return (result?.count || 0) > 0;
251
+ const rows = await this.db.get(model_1.TABLE.bilibiliSubscription, { host_mid, groupId }, { limit: 1 });
252
+ return rows.length > 0;
402
253
  }
403
254
  /**
404
255
  * 批量同步配置文件中的订阅到数据库
405
256
  * @param configItems 配置文件中的订阅项
406
257
  */
407
258
  async syncConfigSubscriptions(configItems) {
259
+ const items = configItems ?? [];
408
260
  // 1. 收集配置文件中的所有订阅关系
409
261
  const configSubscriptions = new Map();
410
- // 初始化每个群组的订阅UP集合
411
- for (const item of configItems) {
262
+ for (const item of items) {
412
263
  const host_mid = item.host_mid;
413
264
  const remark = item.remark ?? '';
414
265
  // 创建或更新B站用户记录
415
266
  await this.getOrCreateBilibiliUser(host_mid, remark);
416
- // 处理该UP主的所有群组订阅
417
267
  for (const groupWithBot of item.group_id) {
418
268
  const [groupId, botId] = groupWithBot.split(':');
419
269
  if (!groupId || !botId)
420
270
  continue;
421
271
  // 确保群组存在
422
272
  await this.getOrCreateGroup(groupId, botId);
423
- // 记录配置文件中的订阅关系
424
- if (!configSubscriptions.has(groupId)) {
273
+ if (!configSubscriptions.has(groupId))
425
274
  configSubscriptions.set(groupId, new Set());
426
- }
427
275
  configSubscriptions.get(groupId)?.add(host_mid);
428
- // 检查是否已订阅
429
- const isSubscribed = await this.isSubscribed(host_mid, groupId);
430
- // 如果未订阅,创建订阅关系
431
- if (!isSubscribed) {
276
+ if (!await this.isSubscribed(host_mid, groupId)) {
432
277
  await this.subscribeBilibiliUser(groupId, botId, host_mid, remark);
433
278
  }
434
279
  }
435
280
  }
436
- // 2. 获取数据库中的所有订阅关系,并与配置文件比较,删除不在配置文件中的订阅
437
- // 获取所有群组
438
- const allGroups = await this.allQuery('SELECT * FROM Groups');
281
+ // 2. 删除数据库里存在、但配置文件里没有的订阅
282
+ const allGroups = await this.db.get(model_1.TABLE.bilibiliGroup, {});
439
283
  for (const group of allGroups) {
440
284
  const groupId = group.id;
441
285
  const configUps = configSubscriptions.get(groupId) ?? new Set();
442
- // 获取该群组在数据库中的所有订阅
443
- const dbSubscriptions = await this.getGroupSubscriptions(groupId);
444
- // 找出需要删除的订阅(在数据库中存在但配置文件中不存在)
286
+ const dbSubscriptions = await this.db.get(model_1.TABLE.bilibiliSubscription, { groupId });
445
287
  for (const subscription of dbSubscriptions) {
446
- const host_mid = subscription.host_mid;
447
- if (!configUps.has(host_mid)) {
448
- // 删除订阅关系
449
- await this.unsubscribeBilibiliUser(groupId, host_mid);
450
- node_karin_1.logger.mark(`已删除群组 ${groupId} 对UP主 ${host_mid} 的订阅`);
451
- }
288
+ if (configUps.has(subscription.host_mid))
289
+ continue;
290
+ await this.unsubscribeBilibiliUser(groupId, subscription.host_mid);
291
+ node_karin_1.logger.mark(`已删除群组 ${groupId} 对UP主 ${subscription.host_mid} 的订阅`);
452
292
  }
453
293
  }
454
294
  // 3. 清理不再被任何群组订阅的UP主记录及其过滤词和过滤标签
455
- // 获取所有B站用户
456
- const allUsers = await this.allQuery('SELECT * FROM BilibiliUsers');
295
+ const allUsers = await this.db.get(model_1.TABLE.bilibiliUser, {});
457
296
  for (const user of allUsers) {
458
- const host_mid = user.host_mid;
459
- // 检查该UP主是否还有群组订阅
460
- const subscribedGroups = await this.getUserSubscribedGroups(host_mid);
461
- if (subscribedGroups.length === 0) {
462
- // 删除该UP主的过滤词和过滤标签
463
- await this.runQuery('DELETE FROM FilterWords WHERE host_mid = ?', [host_mid]);
464
- await this.runQuery('DELETE FROM FilterTags WHERE host_mid = ?', [host_mid]);
465
- // 删除该UP主记录
466
- await this.runQuery('DELETE FROM BilibiliUsers WHERE host_mid = ?', [host_mid]);
467
- node_karin_1.logger.mark(`已删除UP主 ${host_mid} 的记录及相关过滤设置(不再被任何群组订阅)`);
468
- }
297
+ const subscribedGroups = await this.getUserSubscribedGroups(user.host_mid);
298
+ if (subscribedGroups.length > 0)
299
+ continue;
300
+ await this.db.remove(model_1.TABLE.bilibiliFilterWord, { host_mid: user.host_mid });
301
+ await this.db.remove(model_1.TABLE.bilibiliFilterTag, { host_mid: user.host_mid });
302
+ await this.db.remove(model_1.TABLE.bilibiliUser, { host_mid: user.host_mid });
303
+ node_karin_1.logger.mark(`已删除UP主 ${user.host_mid} 的记录及相关过滤设置(不再被任何群组订阅)`);
469
304
  }
470
305
  }
471
306
  /**
@@ -475,9 +310,9 @@ class BilibiliDBBase {
475
310
  */
476
311
  async updateFilterMode(host_mid, filterMode) {
477
312
  const user = await this.getOrCreateBilibiliUser(host_mid);
478
- const now = new Date().toISOString();
479
- await this.runQuery('UPDATE BilibiliUsers SET filterMode = ?, updatedAt = ? WHERE host_mid = ?', [filterMode, now, host_mid]);
480
- return { ...user, filterMode, updatedAt: now };
313
+ const time = now();
314
+ await this.db.set(model_1.TABLE.bilibiliUser, { host_mid }, { filterMode, updatedAt: time });
315
+ return { ...user, filterMode, updatedAt: time };
481
316
  }
482
317
  /**
483
318
  * 添加过滤词
@@ -486,24 +321,11 @@ class BilibiliDBBase {
486
321
  */
487
322
  async addFilterWord(host_mid, word) {
488
323
  await this.getOrCreateBilibiliUser(host_mid);
489
- let filterWord = await this.getQuery('SELECT * FROM FilterWords WHERE host_mid = ? AND word = ?', [host_mid, word]);
490
- if (!filterWord) {
491
- const now = new Date().toISOString();
492
- const result = await this.runQuery('INSERT INTO FilterWords (host_mid, word, createdAt, updatedAt) VALUES (?, ?, ?, ?)', [
493
- host_mid,
494
- word,
495
- now,
496
- now
497
- ]);
498
- filterWord = {
499
- id: result.lastID,
500
- host_mid,
501
- word,
502
- createdAt: now,
503
- updatedAt: now
504
- };
505
- }
506
- return filterWord;
324
+ const [existing] = await this.db.get(model_1.TABLE.bilibiliFilterWord, { host_mid, word });
325
+ if (existing)
326
+ return existing;
327
+ const time = now();
328
+ return await this.db.create(model_1.TABLE.bilibiliFilterWord, { host_mid, word, createdAt: time, updatedAt: time });
507
329
  }
508
330
  /**
509
331
  * 删除过滤词
@@ -511,8 +333,8 @@ class BilibiliDBBase {
511
333
  * @param word 过滤词
512
334
  */
513
335
  async removeFilterWord(host_mid, word) {
514
- const result = await this.runQuery('DELETE FROM FilterWords WHERE host_mid = ? AND word = ?', [host_mid, word]);
515
- return result.changes > 0;
336
+ const result = await this.db.remove(model_1.TABLE.bilibiliFilterWord, { host_mid, word });
337
+ return (result.removed ?? 0) > 0;
516
338
  }
517
339
  /**
518
340
  * 添加过滤标签
@@ -521,24 +343,11 @@ class BilibiliDBBase {
521
343
  */
522
344
  async addFilterTag(host_mid, tag) {
523
345
  await this.getOrCreateBilibiliUser(host_mid);
524
- let filterTag = await this.getQuery('SELECT * FROM FilterTags WHERE host_mid = ? AND tag = ?', [host_mid, tag]);
525
- if (!filterTag) {
526
- const now = new Date().toISOString();
527
- const result = await this.runQuery('INSERT INTO FilterTags (host_mid, tag, createdAt, updatedAt) VALUES (?, ?, ?, ?)', [
528
- host_mid,
529
- tag,
530
- now,
531
- now
532
- ]);
533
- filterTag = {
534
- id: result.lastID,
535
- host_mid,
536
- tag,
537
- createdAt: now,
538
- updatedAt: now
539
- };
540
- }
541
- return filterTag;
346
+ const [existing] = await this.db.get(model_1.TABLE.bilibiliFilterTag, { host_mid, tag });
347
+ if (existing)
348
+ return existing;
349
+ const time = now();
350
+ return await this.db.create(model_1.TABLE.bilibiliFilterTag, { host_mid, tag, createdAt: time, updatedAt: time });
542
351
  }
543
352
  /**
544
353
  * 删除过滤标签
@@ -546,24 +355,24 @@ class BilibiliDBBase {
546
355
  * @param tag 过滤标签
547
356
  */
548
357
  async removeFilterTag(host_mid, tag) {
549
- const result = await this.runQuery('DELETE FROM FilterTags WHERE host_mid = ? AND tag = ?', [host_mid, tag]);
550
- return result.changes > 0;
358
+ const result = await this.db.remove(model_1.TABLE.bilibiliFilterTag, { host_mid, tag });
359
+ return (result.removed ?? 0) > 0;
551
360
  }
552
361
  /**
553
362
  * 获取用户的所有过滤词
554
363
  * @param host_mid B站用户UID
555
364
  */
556
365
  async getFilterWords(host_mid) {
557
- const filterWords = await this.allQuery('SELECT * FROM FilterWords WHERE host_mid = ?', [host_mid]);
558
- return filterWords.map((word) => word.word);
366
+ const rows = await this.db.get(model_1.TABLE.bilibiliFilterWord, { host_mid });
367
+ return rows.map((row) => row.word);
559
368
  }
560
369
  /**
561
370
  * 获取用户的所有过滤标签
562
371
  * @param host_mid B站用户UID
563
372
  */
564
373
  async getFilterTags(host_mid) {
565
- const filterTags = await this.allQuery('SELECT * FROM FilterTags WHERE host_mid = ?', [host_mid]);
566
- return filterTags.map((tag) => tag.tag);
374
+ const rows = await this.db.get(model_1.TABLE.bilibiliFilterTag, { host_mid });
375
+ return rows.map((row) => row.tag);
567
376
  }
568
377
  /**
569
378
  * 获取用户的过滤配置
@@ -720,9 +529,10 @@ class BilibiliDBBase {
720
529
  async cleanOldDynamicCache(days = 7) {
721
530
  const cutoffDate = new Date();
722
531
  cutoffDate.setDate(cutoffDate.getDate() - days);
723
- const cutoffDateStr = cutoffDate.toISOString();
724
- const result = await this.runQuery('DELETE FROM DynamicCaches WHERE createdAt < ?', [cutoffDateStr]);
725
- return result.changes ?? 0;
532
+ const result = await this.db.remove(model_1.TABLE.bilibiliDynamicCache, {
533
+ createdAt: { $lt: cutoffDate.toISOString() }
534
+ });
535
+ return result.removed ?? 0;
726
536
  }
727
537
  /** 为了向后兼容,保留groupRepository和dynamicCacheRepository属性 */
728
538
  get groupRepository() {
@@ -731,7 +541,7 @@ class BilibiliDBBase {
731
541
  if (options?.where?.botId) {
732
542
  return await this.getBotGroups(options.where.botId);
733
543
  }
734
- return await this.allQuery('SELECT * FROM Groups');
544
+ return (await this.db.get(model_1.TABLE.bilibiliGroup, {}));
735
545
  }
736
546
  };
737
547
  }
@@ -739,51 +549,33 @@ class BilibiliDBBase {
739
549
  return {
740
550
  find: async (options = {}) => {
741
551
  const { where = {}, order, take, relations } = options;
742
- let sql = 'SELECT * FROM DynamicCaches';
743
- const params = [];
744
552
  // 构建WHERE条件
745
- const conditions = [];
746
- if (where.groupId) {
747
- conditions.push('groupId = ?');
748
- params.push(where.groupId);
749
- }
750
- if (where.host_mid) {
751
- conditions.push('host_mid = ?');
752
- params.push(where.host_mid);
753
- }
754
- if (where.dynamic_id) {
755
- conditions.push('dynamic_id = ?');
756
- params.push(where.dynamic_id);
757
- }
758
- if (conditions.length > 0) {
759
- sql += ' WHERE ' + conditions.join(' AND ');
760
- }
761
- // 构建ORDER BY
762
- if (order) {
763
- const orderClauses = [];
764
- const allowedFields = ['id', 'dynamic_id', 'host_mid', 'groupId', 'dynamic_type', 'createdAt', 'updatedAt'];
765
- const allowedDirections = ['ASC', 'DESC'];
766
- for (const [field, direction] of Object.entries(order)) {
767
- // 验证字段名和排序方向,防止SQL注入
768
- if (allowedFields.includes(field) && allowedDirections.includes(direction)) {
769
- orderClauses.push(`${field} ${direction}`);
770
- }
771
- }
772
- if (orderClauses.length > 0) {
773
- sql += ' ORDER BY ' + orderClauses.join(', ');
774
- }
775
- }
776
- // 构建LIMIT
777
- if (take) {
778
- sql += ' LIMIT ?';
779
- params.push(take.toString());
553
+ const query = {};
554
+ if (where.groupId)
555
+ query.groupId = where.groupId;
556
+ if (where.host_mid)
557
+ query.host_mid = where.host_mid;
558
+ if (where.dynamic_id)
559
+ query.dynamic_id = where.dynamic_id;
560
+ // 构建排序(minato 只认 asc / desc)
561
+ const sort = {};
562
+ const allowedFields = ['id', 'dynamic_id', 'host_mid', 'groupId', 'dynamic_type', 'createdAt', 'updatedAt'];
563
+ for (const [field, direction] of Object.entries(order ?? {})) {
564
+ if (!allowedFields.includes(field))
565
+ continue;
566
+ sort[field] = String(direction).toLowerCase() === 'asc' ? 'asc' : 'desc';
780
567
  }
781
- const caches = await this.allQuery(sql, params);
568
+ const cursor = {};
569
+ if (Object.keys(sort).length)
570
+ cursor.sort = sort;
571
+ if (take)
572
+ cursor.limit = take;
573
+ const caches = await this.db.get(model_1.TABLE.bilibiliDynamicCache, query, cursor);
782
574
  // 如果需要关联bilibiliUser数据
783
575
  if (relations && relations.includes('bilibiliUser')) {
784
576
  const result = [];
785
577
  for (const cache of caches) {
786
- const bilibiliUser = await this.getQuery('SELECT * FROM BilibiliUsers WHERE host_mid = ?', [cache.host_mid]);
578
+ const bilibiliUser = await this.getBilibiliUser(cache.host_mid);
787
579
  result.push({
788
580
  ...cache,
789
581
  bilibiliUser,
@@ -804,24 +596,24 @@ class BilibiliDBBase {
804
596
  const { groupId, host_mid, dynamic_id } = conditions;
805
597
  // 优先处理 dynamic_id + groupId 的精确删除(单条记录)
806
598
  if (dynamic_id && groupId) {
807
- const result = await this.runQuery('DELETE FROM DynamicCaches WHERE dynamic_id = ? AND groupId = ?', [dynamic_id, groupId]);
808
- return { affected: result.changes };
599
+ const result = await this.db.remove(model_1.TABLE.bilibiliDynamicCache, { dynamic_id, groupId });
600
+ return { affected: result.removed ?? 0 };
809
601
  }
810
602
  if (groupId && host_mid) {
811
- const result = await this.runQuery('DELETE FROM DynamicCaches WHERE groupId = ? AND host_mid = ?', [groupId, host_mid]);
812
- return { affected: result.changes };
603
+ const result = await this.db.remove(model_1.TABLE.bilibiliDynamicCache, { groupId, host_mid });
604
+ return { affected: result.removed ?? 0 };
813
605
  }
814
606
  if (groupId) {
815
- const result = await this.runQuery('DELETE FROM DynamicCaches WHERE groupId = ?', [groupId]);
816
- return { affected: result.changes };
607
+ const result = await this.db.remove(model_1.TABLE.bilibiliDynamicCache, { groupId });
608
+ return { affected: result.removed ?? 0 };
817
609
  }
818
610
  if (host_mid) {
819
- const result = await this.runQuery('DELETE FROM DynamicCaches WHERE host_mid = ?', [host_mid]);
820
- return { affected: result.changes };
611
+ const result = await this.db.remove(model_1.TABLE.bilibiliDynamicCache, { host_mid });
612
+ return { affected: result.removed ?? 0 };
821
613
  }
822
614
  if (dynamic_id) {
823
- const result = await this.runQuery('DELETE FROM DynamicCaches WHERE dynamic_id = ?', [dynamic_id]);
824
- return { affected: result.changes };
615
+ const result = await this.db.remove(model_1.TABLE.bilibiliDynamicCache, { dynamic_id });
616
+ return { affected: result.removed ?? 0 };
825
617
  }
826
618
  return { affected: 0 };
827
619
  }