koishi-plugin-bilibili-notify 3.0.0-alpha.14 → 3.0.0-alpha.16

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/biliAPI.d.ts CHANGED
@@ -67,7 +67,6 @@ declare class BiliAPI extends Service {
67
67
  disposeNotifier(): void;
68
68
  getRandomUserAgent(): string;
69
69
  createNewClient(): void;
70
- getTimeOfUTC8(): number;
71
70
  getCookies(): string;
72
71
  getCookiesForHeader(): Promise<string>;
73
72
  getLoginInfoIsLoaded(): boolean;
package/lib/biliAPI.js CHANGED
@@ -16,7 +16,6 @@ const axios_1 = __importDefault(require("axios"));
16
16
  const tough_cookie_1 = require("tough-cookie");
17
17
  const axios_cookiejar_support_1 = require("axios-cookiejar-support");
18
18
  const jsdom_1 = require("jsdom");
19
- const luxon_1 = require("luxon");
20
19
  const retry_1 = __importDefault(require("./utils/retry"));
21
20
  const mixinKeyEncTab = [
22
21
  46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
@@ -297,9 +296,6 @@ class BiliAPI extends koishi_1.Service {
297
296
  },
298
297
  }));
299
298
  }
300
- getTimeOfUTC8() {
301
- return Math.floor(luxon_1.DateTime.now().setZone("UTC+8").toSeconds());
302
- }
303
299
  getCookies() {
304
300
  const cookies = JSON.stringify(this.jar.serializeSync().cookies);
305
301
  return cookies;
@@ -1,4 +1,4 @@
1
- import { type Bot, type Context, type FlatPick, type Logger, Schema, type Session } from "koishi";
1
+ import { type Bot, type Context, type FlatPick, type Logger, Schema } from "koishi";
2
2
  import type { Notifier } from "@koishijs/plugin-notifier";
3
3
  import type { LoginBili } from "./database";
4
4
  declare enum LiveType {
@@ -47,7 +47,6 @@ declare class ComRegister {
47
47
  sendMsgFunc: (bot: Bot<Context, any>, channelId: string, content: any) => Promise<void>;
48
48
  constructor(ctx: Context, config: ComRegister.Config);
49
49
  init(config: ComRegister.Config): Promise<void>;
50
- splitMultiPlatformStr(str: string): Target;
51
50
  getBot(pf: string): Bot<Context, any>;
52
51
  sendPrivateMsg(content: string): Promise<void>;
53
52
  sendPrivateMsgAndRebootService(): Promise<void>;
@@ -70,7 +69,6 @@ declare class ComRegister {
70
69
  liveDetectWithAPI(): Promise<() => Promise<void>>;
71
70
  liveDetectWithListener(roomId: string, target: Target): Promise<void>;
72
71
  subShow(): string;
73
- checkIfNeedSub(liveSub: boolean, dynamicSub: boolean, session: Session, liveRoomData: any): Promise<Array<boolean>>;
74
72
  updateSubNotifier(): void;
75
73
  checkIfLoginInfoIsLoaded(): Promise<unknown>;
76
74
  subUserInBili(mid: string): Promise<{
@@ -78,12 +76,8 @@ declare class ComRegister {
78
76
  msg: string;
79
77
  }>;
80
78
  loadSubFromConfig(subs: ComRegister.Config["sub"]): Promise<void>;
81
- loadSubFromDatabase(): Promise<void>;
82
79
  checkIfDynamicDetectIsNeeded(): void;
83
80
  enableDynamicDetect(): void;
84
- unsubSingle(id: string, type: number): string;
85
- checkIfUserIsTheLastOneWhoSubDyn(): void;
86
- unsubAll(uid: string): void;
87
81
  checkIfIsLogin(): Promise<boolean>;
88
82
  }
89
83
  declare namespace ComRegister {
@@ -109,7 +103,6 @@ declare namespace ComRegister {
109
103
  masterAccount: string;
110
104
  masterAccountGuildId: string;
111
105
  };
112
- unlockSubLimits: boolean;
113
106
  automaticResend: boolean;
114
107
  liveDetectMode: "API" | "WS";
115
108
  restartPush: boolean;
@@ -183,8 +183,6 @@ class ComRegister {
183
183
  this.loginTimer();
184
184
  // 订阅手动订阅中的订阅
185
185
  await this.loadSubFromConfig(config.sub);
186
- // 订阅之前的订阅
187
- await this.loadSubFromDatabase();
188
186
  // 清除控制台通知
189
187
  ctx.ba.disposeNotifier();
190
188
  // 发送成功登录推送
@@ -201,366 +199,13 @@ class ComRegister {
201
199
  }, 1000);
202
200
  });
203
201
  biliCom
204
- .subcommand(".unsub <uid:string>", "取消订阅UP主动态、直播或全部")
205
- .usage("取消订阅,加-l为取消直播订阅,加-d为取消动态订阅,什么都不加则为全部取消")
206
- .option("live", "-l")
207
- .option("dynamic", "-d")
208
- .example("bili unsub 用户UID -ld")
209
- .action(async ({ session, options }, uid) => {
210
- this.logger.info("调用bili.unsub指令");
211
- // 若用户UID为空则直接返回
212
- if (!uid)
213
- return "用户UID不能为空";
214
- // -d -l两个选项不能同时存在
215
- if (options.dynamic && options.live)
216
- return "需要取消订阅该UP主请直接使用指令bili unsub 用户UID";
217
- // 定义是否存在
218
- let exist;
219
- await Promise.all(this.subManager.map(async (sub, i) => {
220
- if (sub.uid === uid) {
221
- // 取消单个订阅
222
- if (options.live || options.dynamic) {
223
- if (options.live)
224
- await session.send(this.unsubSingle(sub.roomId, 0)); /* 0为取消订阅Live */
225
- if (options.dynamic)
226
- await session.send(this.unsubSingle(sub.uid, 1)); /* 1为取消订阅Dynamic */
227
- // 将存在flag设置为true
228
- exist = true;
229
- // 结束循环
230
- return;
231
- }
232
- // 从数据库中删除订阅
233
- await ctx.database.remove("bilibili", {
234
- uid: this.subManager[i].uid,
235
- });
236
- // 将该订阅对象从订阅管理对象中移除
237
- this.subManager.splice(i, 1);
238
- // 将订阅对象移出订阅关注组
239
- const removeUserFromGroupData = await ctx.ba.removeUserFromGroup(sub.uid);
240
- // 判断是否移出成功 22105关注对象为自己
241
- if (removeUserFromGroupData.code !== 0 &&
242
- removeUserFromGroupData.code !== 22105) {
243
- // 移出失败
244
- await session.send("取消订阅对象失败,请稍后重试");
245
- // 将存在flag设置为true
246
- exist = true;
247
- // 结束循环
248
- return;
249
- }
250
- // id--
251
- this.num--;
252
- // 判断是否还有动态订阅
253
- this.checkIfUserIsTheLastOneWhoSubDyn();
254
- // 发送成功通知
255
- await session.send("已取消订阅该用户");
256
- // 更新控制台提示
257
- this.updateSubNotifier();
258
- // 将存在flag设置为true
259
- exist = true;
260
- }
261
- }));
262
- // 未订阅该用户,无需取消订阅
263
- if (!exist)
264
- await session.send("未订阅该用户,无需取消订阅");
265
- });
266
- biliCom
267
- .subcommand(".show", "展示订阅对象")
202
+ .subcommand(".list", "展示订阅对象")
268
203
  .usage("展示订阅对象")
269
- .example("bili show")
204
+ .example("bili list")
270
205
  .action(() => {
271
206
  const subTable = this.subShow();
272
207
  return subTable;
273
208
  });
274
- biliCom
275
- .subcommand(".sub <mid:string> [...groupId:string]", "订阅用户动态和直播通知")
276
- .option("multiplatform", "-m <value:string>", {
277
- type: /^(?:-?[A-Za-z0-9]+@?(?:,-?[A-Za-z0-9]+@?)*\.[A-Za-z0-9]+)(?:;(?:-?[A-Za-z0-9]+@?(?:,-?[A-Za-z0-9]+@?)*\.[A-Za-z0-9]+))*$/,
278
- })
279
- .option("live", "-l")
280
- .option("dynamic", "-d")
281
- .option("atAll", "-a")
282
- .usage("订阅用户动态和直播通知,若需要订阅直播请加上-l,需要订阅动态则加上-d")
283
- .example("bili sub 1194210119 目标群号或频道号 -l -d 订阅UID为1194210119的UP主的动态和直播")
284
- .action(async ({ session, options }, mid, ...groupId) => {
285
- this.logger.info("调用bili.sub指令");
286
- // 先判断是否订阅直播,再判断是否解锁订阅限制,最后判断直播订阅是否已超三个
287
- if (options.live &&
288
- !this.config.unlockSubLimits &&
289
- this.subManager.reduce((acc, cur) => acc + (cur.live ? 1 : 0), 0) >= 3) {
290
- return "直播订阅已达上限,请取消部分直播订阅后再进行订阅";
291
- }
292
- // 检查是否登录
293
- if (!(await this.checkIfIsLogin())) {
294
- // 未登录直接返回
295
- return "请使用指令bili login登录后再进行订阅操作";
296
- }
297
- // 检查必选参数是否已填
298
- if (!mid)
299
- return "请输入用户uid";
300
- // 订阅对象
301
- const subUserData = await this.subUserInBili(mid);
302
- // 判断是否订阅对象存在
303
- if (!subUserData.flag)
304
- return "订阅对象失败,请稍后重试!";
305
- // 定义目标变量
306
- let target = [];
307
- // 判断是否使用了多群组推送
308
- if (groupId.length > 0) {
309
- // 定义channelIdArr
310
- const channelIdArr = [];
311
- // 遍历输入的群组
312
- for (const group of groupId) {
313
- channelIdArr.push({
314
- channelId: group,
315
- dynamic: true,
316
- live: true,
317
- liveGuardBuy: false,
318
- atAll: options.atAll,
319
- });
320
- }
321
- target.push({
322
- channelIdArr,
323
- platform: session.event.platform,
324
- });
325
- }
326
- else {
327
- // 判断是否使用多平台功能
328
- if (options.multiplatform) {
329
- // 分割字符串,赋值给target
330
- target = this.splitMultiPlatformStr(options.multiplatform);
331
- }
332
- // 判断是否使用了多平台
333
- if (target.length > 0) {
334
- for (const [index, { channelIdArr, platform },] of target.entries()) {
335
- if (channelIdArr.length > 0) {
336
- // 输入了推送群号或频道号
337
- // 拿到对应的bot
338
- const bot = this.getBot(platform);
339
- // 判断是否配置了对应平台的机器人
340
- if (!ctx.bots.some((bot) => bot.platform === platform)) {
341
- // 发送提示消息
342
- await session.send("您未配置对应平台的机器人,不能在该平台进行订阅操作");
343
- // 直接返回
344
- return;
345
- }
346
- // 判断是否需要加入的群全部推送
347
- if (channelIdArr[0].channelId !== "all") {
348
- // 定义满足条件的群组数组
349
- const targetArr = [];
350
- // 获取机器人加入的群组
351
- const guildList = await bot.getGuildList();
352
- // 遍历target数组
353
- for (const channelId of channelIdArr) {
354
- // 定义是否加入群组标志
355
- let flag = false;
356
- // 遍历群组
357
- for (const guild of guildList.data) {
358
- // 获取频道列表
359
- const channelList = await bot.getChannelList(guild.id);
360
- // 判断机器人是否加入群聊或频道
361
- if (channelList.data.some((channel) => channel.id === channelId.channelId)) {
362
- // 加入群聊或频道
363
- targetArr.push(channelId);
364
- // 设置标志位为true
365
- flag = true;
366
- // 结束循环
367
- break;
368
- }
369
- }
370
- if (!flag) {
371
- // 不满足条件发送错误提示
372
- await session.send(`您的机器未加入${channelId.channelId},无法对该群或频道进行推送`);
373
- }
374
- }
375
- // 判断targetArr是否为空
376
- if (target.length === 0) {
377
- // 为空则默认为当前环境
378
- target = [
379
- {
380
- channelIdArr: [
381
- {
382
- channelId: session.event.channel.id,
383
- dynamic: true,
384
- live: true,
385
- liveGuardBuy: false,
386
- atAll: options.atAll ? options.atAll : false,
387
- },
388
- ],
389
- platform: session.event.platform,
390
- },
391
- ];
392
- // 没有满足条件的群组或频道
393
- await session.send("没有满足条件的群组或频道,默认订阅到当前聊天环境");
394
- }
395
- // 将符合条件的群组添加到target中
396
- target[index].channelIdArr = targetArr;
397
- }
398
- // 如果为all则全部推送,不需要进行处理
399
- }
400
- else {
401
- // 未填写群号或频道号,默认为当前环境
402
- target = [
403
- {
404
- channelIdArr: [
405
- {
406
- channelId: session.event.channel.id,
407
- dynamic: true,
408
- live: true,
409
- liveGuardBuy: false,
410
- atAll: options.atAll ? options.atAll : false,
411
- },
412
- ],
413
- platform: session.event.platform,
414
- },
415
- ];
416
- // 发送提示消息
417
- await session.send("没有填写群号或频道号,默认订阅到当前聊天环境");
418
- }
419
- }
420
- }
421
- else {
422
- // 用户直接订阅,将当前环境赋值给target
423
- target = [
424
- {
425
- channelIdArr: [
426
- {
427
- channelId: session.event.channel.id,
428
- dynamic: true,
429
- live: true,
430
- liveGuardBuy: false,
431
- atAll: options.atAll ? options.atAll : false,
432
- },
433
- ],
434
- platform: session.event.platform,
435
- },
436
- ];
437
- }
438
- }
439
- // 定义外围变量
440
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
441
- let content;
442
- try {
443
- // 获取用户信息
444
- content = await ctx.ba.getUserInfo(mid);
445
- }
446
- catch (e) {
447
- // 返回错误信息
448
- return `bili sub getUserInfo() 发生了错误,错误为:${e.message}`;
449
- }
450
- // 判断是否成功获取用户信息
451
- if (content.code !== 0) {
452
- // 定义错误消息
453
- let msg;
454
- // 判断错误代码
455
- switch (content.code) {
456
- case -400:
457
- msg = "请求错误";
458
- break;
459
- case -403:
460
- msg = "访问权限不足,请尝试重新登录";
461
- break;
462
- case -404:
463
- msg = "用户不存在";
464
- break;
465
- case -352:
466
- msg = "风控校验失败,请尝试更换UA";
467
- break;
468
- default:
469
- msg = `未知错误,错误信息:${content.message}`;
470
- break;
471
- }
472
- // 返回错误信息
473
- return msg;
474
- }
475
- // 获取data
476
- const { data } = content;
477
- // 判断是否需要订阅直播和动态
478
- const [liveMsg, dynamicMsg] = await this.checkIfNeedSub(options.live, options.dynamic, session, data.live_room);
479
- // 判断是否未订阅任何消息
480
- if (!liveMsg && !dynamicMsg)
481
- return "您未订阅该UP的任何消息";
482
- // 获取到对应的订阅对象
483
- const subUser = this.subManager.find((sub) => sub.uid === mid);
484
- // 判断要订阅的用户是否已经存在于订阅管理对象中
485
- if (subUser) {
486
- // 已存在,判断是否重复订阅直播通知
487
- if (liveMsg && subUser.live) {
488
- return "已订阅该用户直播通知,请勿重复订阅";
489
- }
490
- // 已存在,判断是否重复订阅动态通知
491
- if (dynamicMsg && subUser.dynamic) {
492
- return "已订阅该用户动态通知,请勿重复订阅";
493
- }
494
- }
495
- // 获取直播房间号
496
- const roomId = data.live_room?.roomid.toString();
497
- // 获取用户信息
498
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
499
- let userData;
500
- try {
501
- const { data } = await ctx.ba.getMasterInfo(mid);
502
- userData = data;
503
- }
504
- catch (e) {
505
- this.logger.error(`bili sub指令 getMasterInfo() 发生了错误,错误为:${e.message}`);
506
- return "订阅出错啦,请重试";
507
- }
508
- const liveDetectModeSelector = {
509
- API: async () => {
510
- // 判断是否已开启直播检测
511
- if (!this.liveDispose) {
512
- // 未开启直播检测
513
- // 开启直播检测并保存销毁函数
514
- this.liveDispose = await this.liveDetectWithAPI();
515
- }
516
- },
517
- WS: async () => {
518
- // 连接到服务器
519
- await this.liveDetectWithListener(roomId, target);
520
- },
521
- };
522
- // 订阅直播
523
- if (liveMsg) {
524
- // 判断直播订阅方式
525
- await liveDetectModeSelector[this.config.liveDetectMode]();
526
- // 发送订阅消息通知
527
- await session.send(`订阅${userData.info.uname}直播通知`);
528
- }
529
- // 订阅动态
530
- if (dynamicMsg) {
531
- // 判断是否开启动态监测
532
- if (!this.dynamicDispose) {
533
- // 开启动态监测
534
- this.enableDynamicDetect();
535
- }
536
- // 发送订阅消息通知
537
- await session.send(`订阅${userData.info.uname}动态通知`);
538
- }
539
- // 保存到数据库中
540
- const sub = await ctx.database.create("bilibili", {
541
- uid: mid,
542
- room_id: roomId,
543
- dynamic: dynamicMsg ? 1 : 0,
544
- live: liveMsg ? 1 : 0,
545
- target: JSON.stringify(target),
546
- platform: session.event.platform,
547
- time: new Date(),
548
- });
549
- // 订阅数+1
550
- this.num++;
551
- // 保存新订阅对象
552
- this.subManager.push({
553
- id: sub.id,
554
- uid: mid,
555
- roomId,
556
- target,
557
- platform: session.event.platform,
558
- live: liveMsg,
559
- dynamic: dynamicMsg,
560
- });
561
- // 新增订阅展示到控制台
562
- this.updateSubNotifier();
563
- });
564
209
  biliCom
565
210
  .subcommand(".status <roomId:string>", "查询主播当前直播状态", {
566
211
  hidden: true,
@@ -630,7 +275,6 @@ class ComRegister {
630
275
  this.ctx.notifier.create({
631
276
  content: "您未配置私人机器人,将无法向您推送机器人状态!",
632
277
  });
633
- this.logger.error("您未配置私人机器人,将无法向您推送机器人状态!");
634
278
  }
635
279
  // 判断消息发送方式
636
280
  if (config.automaticResend) {
@@ -689,14 +333,12 @@ class ComRegister {
689
333
  }
690
334
  // 从配置获取订阅
691
335
  config.sub && (await this.loadSubFromConfig(config.sub));
692
- // 从数据库获取订阅
693
- await this.loadSubFromDatabase();
694
336
  // 检查是否需要动态监测
695
337
  this.checkIfDynamicDetectIsNeeded();
696
338
  // 在控制台中显示订阅对象
697
339
  this.updateSubNotifier();
698
- // Test
699
- const testTarget = [
340
+ /* // Test
341
+ const testTarget: Target = [
700
342
  {
701
343
  channelIdArr: [
702
344
  {
@@ -710,27 +352,9 @@ class ComRegister {
710
352
  platform: "qqguild",
711
353
  },
712
354
  ];
355
+
713
356
  const buffer = await this.ctx.gi.generateWordCloudImg();
714
- this.sendMsg(testTarget, koishi_1.h.image(buffer, "image/png"));
715
- }
716
- splitMultiPlatformStr(str) {
717
- return str
718
- .split(";")
719
- .map((cv) => cv.split("."))
720
- .map(([idStr, platform]) => {
721
- const channelIdArr = idStr.split(",").map((id) => {
722
- const atAll = /@$/.test(id); // 使用正则表达式检查 id 是否以 @ 结尾
723
- const channelId = atAll ? id.slice(0, -1) : id; // 去除末尾的 @
724
- return {
725
- channelId,
726
- dynamic: true,
727
- live: true,
728
- liveGuardBuy: false,
729
- atAll,
730
- };
731
- });
732
- return { channelIdArr, platform };
733
- });
357
+ this.sendMsg(testTarget, h.image(buffer, "image/png")); */
734
358
  }
735
359
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
736
360
  getBot(pf) {
@@ -1652,12 +1276,6 @@ class ComRegister {
1652
1276
  }
1653
1277
  // 构建消息处理函数
1654
1278
  const handler = {
1655
- onOpen: () => {
1656
- this.logger.info("直播间连接成功");
1657
- },
1658
- onClose: () => {
1659
- this.logger.info("直播间连接已断开");
1660
- },
1661
1279
  onIncomeDanmu: ({ body }) => {
1662
1280
  // 保存消息到数组
1663
1281
  currentLiveDanmakuArr.push(body.content);
@@ -1776,38 +1394,6 @@ class ComRegister {
1776
1394
  }
1777
1395
  return table ? table : "没有订阅任何UP";
1778
1396
  }
1779
- async checkIfNeedSub(liveSub, dynamicSub, session,
1780
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1781
- liveRoomData) {
1782
- // 定义方法:用户直播间是否存在
1783
- const liveRoom = async () => {
1784
- if (!liveRoomData) {
1785
- // 未开通直播间
1786
- await session.send("该用户未开通直播间,无法订阅直播");
1787
- // 返回false
1788
- return true;
1789
- }
1790
- return false;
1791
- };
1792
- // 如果两者都为true或者都为false则直接返回
1793
- if ((liveSub && dynamicSub) || (!liveSub && !dynamicSub)) {
1794
- // 判断是否存在直播间
1795
- if (await liveRoom())
1796
- return [false, true];
1797
- // 返回
1798
- return [true, true];
1799
- }
1800
- // 如果只订阅直播
1801
- if (liveSub) {
1802
- // 判断是否存在直播间
1803
- if (await liveRoom())
1804
- return [false, false];
1805
- // 返回
1806
- return [true, false];
1807
- }
1808
- // 只订阅动态
1809
- return [false, true];
1810
- }
1811
1397
  updateSubNotifier() {
1812
1398
  // 更新控制台提示
1813
1399
  if (this.subNotifier)
@@ -2027,147 +1613,6 @@ class ComRegister {
2027
1613
  });
2028
1614
  }
2029
1615
  }
2030
- async loadSubFromDatabase() {
2031
- // 从数据库中获取数据
2032
- const subData = await this.ctx.database.get("bilibili", { id: { $gt: 0 } });
2033
- // 定义变量:订阅直播数
2034
- let liveSubNum = 0;
2035
- // 循环遍历
2036
- for (const sub of subData) {
2037
- // 判断是否存在没有任何订阅的数据
2038
- if (!sub.dynamic && !sub.live) {
2039
- // 存在未订阅任何项目的数据
2040
- // 删除该条数据
2041
- this.ctx.database.remove("bilibili", { id: sub.id });
2042
- // log
2043
- this.logger.warn(`UID:${sub.uid} 该条数据没有任何订阅数据,自动取消订阅`);
2044
- // 跳过下面的步骤
2045
- continue;
2046
- }
2047
- // 判断用户是否在B站中订阅了
2048
- const subUserData = await this.subUserInBili(sub.uid);
2049
- // 判断是否订阅
2050
- if (!subUserData.flag) {
2051
- // log
2052
- this.logger.warn(`UID:${sub.uid} ${subUserData.msg},自动取消订阅`);
2053
- // 发送私聊消息
2054
- await this.sendPrivateMsg(`UID:${sub.uid} ${subUserData.msg},自动取消订阅`);
2055
- // 删除该条数据
2056
- await this.ctx.database.remove("bilibili", { id: sub.id });
2057
- // 跳过下面的步骤
2058
- continue;
2059
- }
2060
- // 获取推送目标数组
2061
- const target = JSON.parse(sub.target);
2062
- /* 判断数据库是否被篡改 */
2063
- // 获取用户信息
2064
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
2065
- let content;
2066
- const attempts = 3;
2067
- for (let i = 0; i < attempts; i++) {
2068
- try {
2069
- // 获取用户信息
2070
- content = await this.ctx.ba.getUserInfo(sub.uid);
2071
- // 成功则跳出循环
2072
- break;
2073
- }
2074
- catch (e) {
2075
- this.logger.error(`getSubFromDatabase() getUserInfo() 发生了错误,错误为:${e.message}`);
2076
- if (i === attempts - 1) {
2077
- // 已尝试三次
2078
- // 发送私聊消息并重启服务
2079
- return await this.sendPrivateMsgAndStopService();
2080
- }
2081
- }
2082
- }
2083
- // 获取data
2084
- const { data } = content;
2085
- // 定义函数删除数据和发送提示
2086
- const deleteSub = async () => {
2087
- // 从数据库删除该条数据
2088
- await this.ctx.database.remove("bilibili", { id: sub.id });
2089
- // 给用户发送提示
2090
- await this.sendPrivateMsg(`UID:${sub.uid} 数据库内容被篡改,已取消对该UP主的订阅`);
2091
- };
2092
- // 判断是否有其他问题
2093
- if (content.code !== 0) {
2094
- switch (content.code) {
2095
- case -352:
2096
- case -403: {
2097
- await this.sendPrivateMsg("你的登录信息已过期,请重新登录Bilibili");
2098
- return;
2099
- }
2100
- default: {
2101
- await deleteSub();
2102
- // PrivateMsg
2103
- await this.sendPrivateMsg(`UID:${sub.uid} 数据出现问题,自动取消订阅`);
2104
- // log
2105
- this.logger.info(`UID:${sub.uid} 数据出现问题,自动取消订阅`);
2106
- return;
2107
- }
2108
- }
2109
- }
2110
- // 检测房间号是否被篡改
2111
- if (sub.live &&
2112
- // biome-ignore lint/suspicious/noDoubleEquals: <explanation>
2113
- (!data.live_room || data.live_room.roomid != sub.room_id)) {
2114
- // 房间号被篡改,删除该订阅
2115
- await deleteSub();
2116
- // log
2117
- this.logger.info(`UID:${sub.uid} 房间号被篡改,自动取消订阅`);
2118
- // Send msg
2119
- await this.sendPrivateMsg(`UID:${sub.uid} 房间号被篡改,自动取消订阅`);
2120
- // 直接返回
2121
- return;
2122
- }
2123
- // 构建订阅对象
2124
- const subManagerItem = {
2125
- id: sub.id,
2126
- uid: sub.uid,
2127
- roomId: sub.room_id,
2128
- target,
2129
- platform: sub.platform,
2130
- live: sub.live === 1,
2131
- dynamic: sub.dynamic === 1,
2132
- liveDispose: null,
2133
- };
2134
- // 定义直播模式监测器
2135
- const liveDetectModeSelector = {
2136
- API: async () => {
2137
- // 判断是否已开启直播检测
2138
- if (!this.liveDispose) {
2139
- // 未开启直播检测
2140
- // 开启直播检测并保存销毁函数
2141
- this.liveDispose = await this.liveDetectWithAPI();
2142
- }
2143
- },
2144
- WS: async () => {
2145
- // 判断订阅直播数是否超过限制
2146
- if (!this.config.unlockSubLimits && liveSubNum >= 3) {
2147
- // 将live改为false
2148
- subManagerItem.live = false;
2149
- // log
2150
- this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
2151
- // 发送错误消息
2152
- await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
2153
- }
2154
- else {
2155
- // 直播订阅数+1
2156
- liveSubNum++;
2157
- // 订阅直播,开始循环检测
2158
- await this.liveDetectWithListener(sub.room_id, target);
2159
- }
2160
- },
2161
- };
2162
- // 判断是否订阅直播
2163
- if (sub.live) {
2164
- // 启动直播监测
2165
- await liveDetectModeSelector[this.config.liveDetectMode]();
2166
- }
2167
- // 保存新订阅对象
2168
- this.subManager.push(subManagerItem);
2169
- }
2170
- }
2171
1616
  checkIfDynamicDetectIsNeeded() {
2172
1617
  // 检查是否有订阅对象需要动态监测
2173
1618
  if (this.subManager.some((sub) => sub.dynamic))
@@ -2182,136 +1627,6 @@ class ComRegister {
2182
1627
  this.dynamicDispose = this.ctx.setInterval(this.dynamicDetect(), this.config.dynamicLoopTime * 1000);
2183
1628
  }
2184
1629
  }
2185
- unsubSingle(id /* UID或RoomId */, type /* 0取消Live订阅,1取消Dynamic订阅 */) {
2186
- // 定义返回消息
2187
- let msg;
2188
- // 定义方法:检查是否没有任何订阅
2189
- const checkIfNoSubExist = (sub) => !sub.dynamic && !sub.live;
2190
- // 定义方法:将订阅对象从订阅管理对象中移除
2191
- const removeSub = (index) => {
2192
- // 从管理对象中移除
2193
- this.subManager.splice(index, 1);
2194
- // 从数据库中删除
2195
- this.ctx.database.remove("bilibili", [this.subManager[index].id]);
2196
- // num--
2197
- this.num--;
2198
- // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
2199
- this.checkIfUserIsTheLastOneWhoSubDyn();
2200
- };
2201
- try {
2202
- switch (type) {
2203
- case 0: {
2204
- // 取消Live订阅
2205
- // 获取订阅对象所在的索引
2206
- const index = this.subManager.findIndex((sub) => sub.roomId === id);
2207
- // 获取订阅对象
2208
- const sub = this.subManager.find((sub) => sub.roomId === id);
2209
- // 判断是否存在订阅对象
2210
- if (!sub) {
2211
- msg = "未订阅该用户,无需取消订阅";
2212
- return msg;
2213
- }
2214
- // 取消订阅
2215
- sub.live = false;
2216
- // 判断直播检测方式
2217
- switch (this.config.liveDetectMode) {
2218
- case "API": {
2219
- msg = "请手动删除订阅,并重启插件";
2220
- break;
2221
- }
2222
- case "WS": {
2223
- // 取消直播监听
2224
- this.ctx.bl.closeListener(sub.roomId);
2225
- }
2226
- }
2227
- // 如果没有对这个UP的任何订阅,则移除
2228
- if (checkIfNoSubExist(sub)) {
2229
- // 从管理对象中移除
2230
- removeSub(index);
2231
- return "已取消订阅该用户";
2232
- }
2233
- // 更新数据库
2234
- this.ctx.database.upsert("bilibili", [
2235
- {
2236
- id: +`${sub.id}`,
2237
- live: 0,
2238
- },
2239
- ]);
2240
- return "已取消订阅Live";
2241
- }
2242
- case 1: {
2243
- // 取消Dynamic订阅
2244
- // 获取订阅对象所在的索引
2245
- const index = this.subManager.findIndex((sub) => sub.uid === id);
2246
- // 获取订阅对象
2247
- const sub = this.subManager.find((sub) => sub.uid === id);
2248
- // 判断是否存在订阅对象
2249
- if (!sub) {
2250
- msg = "未订阅该用户,无需取消订阅";
2251
- return msg;
2252
- }
2253
- // 取消订阅
2254
- this.subManager[index].dynamic = false;
2255
- // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
2256
- this.checkIfUserIsTheLastOneWhoSubDyn();
2257
- // 如果没有对这个UP的任何订阅,则移除
2258
- if (checkIfNoSubExist(sub)) {
2259
- // 从管理对象中移除
2260
- removeSub(index);
2261
- return "已取消订阅该用户";
2262
- }
2263
- // 更新数据库
2264
- this.ctx.database.upsert("bilibili", [
2265
- {
2266
- id: sub.id,
2267
- dynamic: 0,
2268
- },
2269
- ]);
2270
- return "已取消订阅Dynamic";
2271
- }
2272
- }
2273
- }
2274
- finally {
2275
- // 执行完该方法后,保证执行一次updateSubNotifier()
2276
- this.updateSubNotifier();
2277
- }
2278
- }
2279
- checkIfUserIsTheLastOneWhoSubDyn() {
2280
- if (this.dynamicDispose && !this.subManager.some((sub) => sub.dynamic)) {
2281
- // 停止动态监测
2282
- this.dynamicDispose();
2283
- this.dynamicDispose = null;
2284
- }
2285
- }
2286
- unsubAll(uid) {
2287
- this.subManager
2288
- .filter((sub) => sub.uid === uid)
2289
- .map(async (sub, i) => {
2290
- // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
2291
- this.checkIfUserIsTheLastOneWhoSubDyn();
2292
- switch (this.config.liveDetectMode) {
2293
- case "API": {
2294
- break;
2295
- }
2296
- case "WS": {
2297
- // 停止直播检测
2298
- this.ctx.bl.closeListener(sub.roomId);
2299
- }
2300
- }
2301
- // 从数据库中删除订阅
2302
- await this.ctx.database.remove("bilibili", {
2303
- uid: this.subManager[i].uid,
2304
- });
2305
- // 将该订阅对象从订阅管理对象中移除
2306
- this.subManager.splice(i, 1);
2307
- // id--
2308
- this.num--;
2309
- // 发送成功通知
2310
- this.sendPrivateMsg(`UID:${uid},已取消订阅该用户`);
2311
- // 更新控制台提示
2312
- this.updateSubNotifier();
2313
- });
2314
- }
2315
1630
  async checkIfIsLogin() {
2316
1631
  if ((await this.ctx.database.get("loginBili", 1)).length !== 0) {
2317
1632
  // 数据库中有数据
@@ -2349,7 +1664,6 @@ class ComRegister {
2349
1664
  masterAccount: koishi_1.Schema.string(),
2350
1665
  masterAccountGuildId: koishi_1.Schema.string(),
2351
1666
  }),
2352
- unlockSubLimits: koishi_1.Schema.boolean().required(),
2353
1667
  automaticResend: koishi_1.Schema.boolean().required(),
2354
1668
  liveDetectMode: koishi_1.Schema.union([
2355
1669
  koishi_1.Schema.const("API"),
package/lib/database.d.ts CHANGED
@@ -1,20 +1,9 @@
1
1
  import type { Context } from "koishi";
2
2
  declare module "koishi" {
3
3
  interface Tables {
4
- bilibili: Bilibili;
5
4
  loginBili: LoginBili;
6
5
  }
7
6
  }
8
- export interface Bilibili {
9
- id: number;
10
- uid: string;
11
- room_id: string;
12
- dynamic: number;
13
- live: number;
14
- target: string;
15
- platform: string;
16
- time: Date;
17
- }
18
7
  export interface LoginBili {
19
8
  id: number;
20
9
  bili_cookies: string;
package/lib/database.js CHANGED
@@ -4,17 +4,6 @@ exports.name = void 0;
4
4
  exports.apply = apply;
5
5
  exports.name = "Database";
6
6
  function apply(ctx) {
7
- // 新增Bilibili表
8
- ctx.model.extend("bilibili", {
9
- id: "unsigned",
10
- uid: "string",
11
- room_id: "string",
12
- dynamic: "unsigned",
13
- live: "unsigned",
14
- target: "string",
15
- platform: "string",
16
- time: "timestamp",
17
- }, { autoInc: true });
18
7
  // 新增LoginBili表
19
8
  ctx.model.extend("loginBili", {
20
9
  id: "unsigned",
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const koishi_1 = require("koishi");
4
+ const luxon_1 = require("luxon");
4
5
  const node_path_1 = require("node:path");
5
6
  const node_url_1 = require("node:url");
6
7
  // 动态类型
@@ -1487,22 +1488,39 @@ class GenerateImg extends koishi_1.Service {
1487
1488
  }
1488
1489
  async getTimeDifference(dateString) {
1489
1490
  // 将日期字符串转换为Date对象
1490
- const date = new Date(dateString);
1491
- // 获取Unix时间戳(以毫秒为单位)
1492
- const unixTime = date.getTime() / 1000;
1493
- // 获取当前Unix时间戳
1494
- const now = this.ctx.ba.getTimeOfUTC8();
1495
- // 计算时间差(以秒为单位)
1496
- const differenceInSeconds = Math.floor(now - unixTime);
1497
- // 获取yyyy:MM:dd HH:mm:ss
1498
- const days = Math.floor(differenceInSeconds / (24 * 60 * 60));
1499
- const hours = Math.floor((differenceInSeconds % (24 * 60 * 60)) / (60 * 60));
1500
- const minutes = Math.floor((differenceInSeconds % (60 * 60)) / 60);
1501
- const seconds = differenceInSeconds % 60;
1502
- // 返回格式化的字符串
1503
- return days
1504
- ? `${days}天${hours}小时${minutes.toString().padStart(2, "0")}分${seconds.toString().padStart(2, "0")}秒`
1505
- : `${hours}小时${minutes.toString().padStart(2, "0")}分${seconds.toString().padStart(2, "0")}秒`;
1491
+ const apiDateTime = luxon_1.DateTime.fromFormat(dateString, "yyyy-MM-dd HH:mm:ss", {
1492
+ zone: "UTC+8",
1493
+ });
1494
+ // 获取当前时间
1495
+ const currentDateTime = luxon_1.DateTime.now();
1496
+ // 计算时间差
1497
+ const diff = currentDateTime.diff(apiDateTime, [
1498
+ "years",
1499
+ "months",
1500
+ "days",
1501
+ "hours",
1502
+ "minutes",
1503
+ "seconds",
1504
+ ]);
1505
+ const { years, months, days, hours, minutes, seconds } = diff.toObject();
1506
+ // 按单位生成可读字符串(过滤零值)
1507
+ const parts = [];
1508
+ if (years !== 0)
1509
+ parts.push(`${Math.abs(years)}年`);
1510
+ if (months !== 0)
1511
+ parts.push(`${Math.abs(months)}个月`);
1512
+ if (days !== 0)
1513
+ parts.push(`${Math.abs(days)}天`);
1514
+ if (hours !== 0)
1515
+ parts.push(`${Math.abs(hours)}小时`);
1516
+ if (minutes !== 0)
1517
+ parts.push(`${Math.abs(minutes)}分`);
1518
+ if (seconds !== 0)
1519
+ parts.push(`${Math.round(Math.abs(seconds))}秒`);
1520
+ // 处理负值
1521
+ const sign = diff.as("seconds") < 0 ? "-" : "";
1522
+ // 组合结果(如果无差值返回"0秒")
1523
+ return parts.length > 0 ? `${sign}${parts.join("")}` : "0秒";
1506
1524
  }
1507
1525
  unixTimestampToString(timestamp) {
1508
1526
  const date = new Date(timestamp * 1000);
package/lib/index.d.ts CHANGED
@@ -22,7 +22,6 @@ export interface Config {
22
22
  key: string;
23
23
  master: {};
24
24
  basicSettings: {};
25
- unlockSubLimits: boolean;
26
25
  automaticResend: boolean;
27
26
  renderType: "render" | "page";
28
27
  userAgent: string;
package/lib/index.js CHANGED
@@ -162,7 +162,6 @@ class ServerManager extends koishi_1.Service {
162
162
  const cr = this.ctx.plugin(comRegister_1.default, {
163
163
  sub: globalConfig.sub,
164
164
  master: globalConfig.master,
165
- unlockSubLimits: globalConfig.unlockSubLimits,
166
165
  automaticResend: globalConfig.automaticResend,
167
166
  liveDetectMode: globalConfig.liveDetectMode,
168
167
  restartPush: globalConfig.restartPush,
@@ -232,19 +231,13 @@ function apply(ctx, config) {
232
231
  globalConfig = config;
233
232
  // 设置提示
234
233
  ctx.notifier.create({
235
- content: "从3.0.0-alpha.10以前版本更新需重新订阅",
234
+ type: 'danger',
235
+ content: "3.0.0-alpha.16 全面从指令订阅转移到配置订阅,以前使用指令的订阅需要全部重新填写到订阅配置中",
236
236
  });
237
237
  ctx.notifier.create({
238
+ type: 'warning',
238
239
  content: "请使用Auth插件创建超级管理员账号,没有权限将无法使用该插件提供的指令。",
239
240
  });
240
- if (config.unlockSubLimits) {
241
- // 用户允许订阅超过三个用户
242
- // 设置警告
243
- ctx.notifier.create({
244
- type: "danger",
245
- content: "过多的订阅可能会导致IP暂时被封禁!",
246
- });
247
- }
248
241
  // load database
249
242
  ctx.plugin(Database);
250
243
  // Register ServerManager
@@ -296,9 +289,6 @@ exports.Config = koishi_1.Schema.object({
296
289
  ]),
297
290
  ]),
298
291
  basicSettings: koishi_1.Schema.object({}).description("基本设置"),
299
- unlockSubLimits: koishi_1.Schema.boolean()
300
- .default(false)
301
- .description("解锁3个直播订阅限制,默认只允许订阅3位UP主。订阅过多用户可能有导致IP暂时被封禁的风险"),
302
292
  automaticResend: koishi_1.Schema.boolean()
303
293
  .default(true)
304
294
  .description("是否开启自动重发功能,默认开启。开启后,如果推送失败,将会自动重发,尝试三次。关闭后,推送失败将不会再重发,直到下一次推送"),
@@ -309,7 +299,7 @@ exports.Config = koishi_1.Schema.object({
309
299
  userAgent: koishi_1.Schema.string()
310
300
  .required()
311
301
  .description("设置请求头User-Agen,请求出现-352时可以尝试修改,UA获取方法可参考:https://blog.csdn.net/qq_44503987/article/details/104929111"),
312
- subTitle: koishi_1.Schema.object({}).description("手动订阅"),
302
+ subTitle: koishi_1.Schema.object({}).description("订阅配置"),
313
303
  sub: koishi_1.Schema.array(koishi_1.Schema.object({
314
304
  uid: koishi_1.Schema.string().description("订阅用户UID"),
315
305
  dynamic: koishi_1.Schema.boolean().description("是否订阅用户动态"),
@@ -321,12 +311,12 @@ exports.Config = koishi_1.Schema.object({
321
311
  live: koishi_1.Schema.boolean().description("该频道/群组是否推送直播通知"),
322
312
  liveGuardBuy: koishi_1.Schema.boolean().description("该频道/群组是否推送上舰消息"),
323
313
  atAll: koishi_1.Schema.boolean().description("推送开播通知时是否艾特全体成员"),
324
- })).description("频道/群组信息"),
314
+ })).description("需推送的频道/群组详细设置"),
325
315
  platform: koishi_1.Schema.string().description("推送平台"),
326
- })).description("订阅用户需要发送的频道/群组信息"),
316
+ })).description("订阅用户需要发送的平台和频道/群组信息(一个平台下可以推送多个频道/群组)"),
327
317
  }))
328
318
  .role("table")
329
- .description("手动输入订阅信息,方便自定义订阅内容,这里的订阅内容不会存入数据库。uid: 订阅用户UID,dynamic: 是否需要订阅动态,live: 是否需要订阅直播"),
319
+ .description("输入订阅信息,自定义订阅内容; uid: 订阅用户UID,dynamic: 是否需要订阅动态,live: 是否需要订阅直播"),
330
320
  dynamic: koishi_1.Schema.object({}).description("动态推送设置"),
331
321
  dynamicUrl: koishi_1.Schema.boolean()
332
322
  .default(false)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-bilibili-notify",
3
3
  "description": "Koishi bilibili notify plugin",
4
- "version": "3.0.0-alpha.14",
4
+ "version": "3.0.0-alpha.16",
5
5
  "contributors": [
6
6
  "Akokko <admin@akokko.com>"
7
7
  ],
package/readme.md CHANGED
@@ -53,43 +53,11 @@
53
53
 
54
54
  订阅UP主:订阅你想要推送的UP主
55
55
 
56
- - 使用指令 `bili sub <uid> [...groupId]` 订阅需要订阅的UP主
57
- - 参数说明:
58
- - `uid` 为必填参数,为 `up主` 的 `uid`
59
- - `groupId` 为可选参数,为需要推送的群号/频道号,可输入多个群号
60
- - 选项说明:`bili sub <uid>` 有四个选项:-l -d -m -a
61
- - `-l` 为订阅UP主直播间,包括直播开播通知,定时推送直播内容,下播通知
62
- - `-d` 为订阅UP主动态推送,目前实现推送的动态类型有:普通图文动态,转发动态,直播预约动态
63
- - `-m` 为多平台动态推送,格式为:群号/频道号,群号/频道号,群号/频道号.平台名;群号/频道号,群号/频道号.平台号。如果群号/频道号为 `all` 代表推送该平台下的所有群聊或/频道。在群号/频道号后加 `@` 则代表这个群聊/频道需要@全体成员。订阅TG群组时请使用 `bili sub xxx -m "xxxxxxx"` 这样的格式
64
- - `-a` 为是否艾特全体成员,对 `-m` 参数不生效
65
-
66
- 例如:
67
- `-m 3247293,324389,89874324.qq;EDBWIUBIU.qqguild;79324792,3247892.onebot` 代表推送QQ下3247293,324389,89874324这三个群聊,QQ频道下EDBWIUBIU这个频道,Onebot平台下79324792,3247892这两个群聊
68
- `-m 3247293,324389@,89874324.qq` 代表推送QQ下3247293,324389,89874324这三个群聊,其中群聊324389需要艾特全体成员
69
- 所有分隔符均为英文符号
70
-
71
- - 例如:
72
- - `bili sub 1194210119 ` 订阅UID为1194210119的UP主动态推送和直播间
73
- - `bili sub 1194210119 -d` 订阅UID为1194210119的UP主动态推送
74
- - `bili sub 1194210119 -l` 订阅UID为1194210119的UP主直播间
75
- - `bili sub 1194210119 -m 3247293,324389,89874324.qq;all.onebot;EHUIWDBUAWD.qqguild` 订阅UID为1194210119的UP主,向群号为3247293,324389,89874324的QQ群,所有onebot平台下的群聊,频道号为EHUIWDBUAWD的QQ频道平台进行推送
76
- - `bili sub 1194210119 -a` 订阅UID为1194210119的UP主动态推送和直播间并艾特全体成员
77
-
78
- 取消订阅UP主:取消订阅不需要推送的UP主
79
-
80
- - 使用指令 `bili unsub <uid>` 取消订阅不需要订阅的UP主
81
- - 参数说明:`uid` 为必填参数,为 `up主` 的 `uid`
82
- - 选项说明:`bili unsub <uid>` 有两个选项:-l 和 -d
83
- - `-l` 为取消订阅UP主直播间
84
- - `-d` 为取消订阅UP主动态
85
- - 例如:
86
- - `bili unsub 123456` 取消订阅UID为123456的UP主动态推送和直播间
87
- - `bili unsub 123456 -d` 取消订阅UID为123456的UP主动态推送
88
- - `bili unsub 123456 -dl` 取消订阅UID为123456的UP主动态推送和直播间
56
+ 在插件配置中配置需要订阅的UP主
89
57
 
90
58
  查看目前已订阅的UP主:
91
59
 
92
- - 使用指令 `bili show`
60
+ - 使用指令 `bili list`
93
61
 
94
62
  插件的启动、停止和重启
95
63
 
@@ -226,6 +194,8 @@
226
194
  - ver 3.0.0-alpha.12 修复:上一版本无法安装
227
195
  - ver 3.0.0-alpha.13 优化:将ESLint替换为Biome; 修复:增加弹幕词云功能产生的bug; 禁用:弹幕词云功能并不能正常运作,暂时将该功能禁用
228
196
  - ver 3.0.0-alpha.14 优化:移除不需要的服务
197
+ - ver 3.0.0-alpha.15 修复:启动插件提示发送群组消息失败、直播推送时间显示为负数(不用再特别设置系统时区为UTC+8)
198
+ - ver 3.0.0-alpha.16 重大更新:订阅不再依赖数据库,从指令订阅全面迁移到配置订阅; 修复:直播时长有误; 优化:`bili show` 指令更改为 `bili list`
229
199
 
230
200
  ## 交流群
231
201