koishi-plugin-bilibili-notify 3.0.0-alpha.1 → 3.0.0-alpha.11

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.
@@ -10,6 +10,10 @@ const jsx_runtime_1 = require("@satorijs/element/jsx-runtime");
10
10
  const koishi_1 = require("koishi");
11
11
  // 导入qrcode
12
12
  const qrcode_1 = __importDefault(require("qrcode"));
13
+ // 弹幕词云
14
+ const segmentit_1 = require("segmentit");
15
+ const canvas_1 = require("canvas");
16
+ const d3_cloud_1 = __importDefault(require("d3-cloud"));
13
17
  var LiveType;
14
18
  (function (LiveType) {
15
19
  LiveType[LiveType["NotLiveBroadcast"] = 0] = "NotLiveBroadcast";
@@ -18,27 +22,42 @@ var LiveType;
18
22
  LiveType[LiveType["StopBroadcast"] = 3] = "StopBroadcast";
19
23
  })(LiveType || (LiveType = {}));
20
24
  class ComRegister {
25
+ // 必须服务
21
26
  static inject = ['ba', 'gi', 'database', 'bl', 'sm'];
27
+ // 定义数组:QQ相关bot
22
28
  qqRelatedBotList = ['qq', 'onebot', 'red', 'satori', 'chronocat'];
29
+ // logger
23
30
  logger;
31
+ // config
24
32
  config;
33
+ // 登录定时器
25
34
  loginTimer;
35
+ // 订阅数量
26
36
  num = 0;
37
+ // 重启次数
27
38
  rebootCount = 0;
39
+ // 订阅通知
28
40
  subNotifier;
41
+ // Context
42
+ ctx;
43
+ // 订阅管理器
29
44
  subManager = [];
30
45
  // 检查登录数据库是否有数据
31
46
  loginDBData;
32
47
  // 机器人实例
33
48
  privateBot;
34
- // 动态销毁函数
49
+ // 动态检测销毁函数
35
50
  dynamicDispose;
51
+ // 直播检测销毁函数
52
+ liveDispose;
36
53
  // 发送消息方式
37
54
  sendMsgFunc;
38
55
  // 构造函数
39
56
  constructor(ctx, config) {
57
+ // 将ctx赋值给类属性
58
+ this.ctx = ctx;
40
59
  // 初始化
41
- this.init(ctx, config);
60
+ this.init(config);
42
61
  // 注册指令
43
62
  const statusCom = ctx.command('status', '插件状态相关指令', { permissions: ['authority:5'] });
44
63
  statusCom.subcommand('.dyn', '查看动态监测运行状态')
@@ -150,8 +169,10 @@ class ComRegister {
150
169
  }]);
151
170
  // 销毁定时器
152
171
  this.loginTimer();
172
+ // 订阅手动订阅中的订阅
173
+ await this.loadSubFromConfig(config.sub);
153
174
  // 订阅之前的订阅
154
- await this.loadSubFromDatabase(ctx);
175
+ await this.loadSubFromDatabase();
155
176
  // 清除控制台通知
156
177
  ctx.ba.disposeNotifier();
157
178
  // 发送成功登录推送
@@ -160,7 +181,6 @@ class ComRegister {
160
181
  await session.execute('bili show');
161
182
  // 开启cookies刷新检测
162
183
  ctx.ba.enableRefreshCookiesDetect();
163
- return;
164
184
  }
165
185
  }
166
186
  finally {
@@ -189,17 +209,14 @@ class ComRegister {
189
209
  // 取消单个订阅
190
210
  if (options.live || options.dynamic) {
191
211
  if (options.live)
192
- await session.send(this.unsubSingle(ctx, sub.roomId, 0)); /* 0为取消订阅Live */
212
+ await session.send(this.unsubSingle(sub.roomId, 0)); /* 0为取消订阅Live */
193
213
  if (options.dynamic)
194
- await session.send(this.unsubSingle(ctx, sub.uid, 1)); /* 1为取消订阅Dynamic */
214
+ await session.send(this.unsubSingle(sub.uid, 1)); /* 1为取消订阅Dynamic */
195
215
  // 将存在flag设置为true
196
216
  exist = true;
197
217
  // 结束循环
198
218
  return;
199
219
  }
200
- // 取消全部订阅 执行dispose方法,销毁定时器
201
- if (sub.live)
202
- this.subManager[i].liveDispose();
203
220
  // 从数据库中删除订阅
204
221
  await ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
205
222
  // 将该订阅对象从订阅管理对象中移除
@@ -222,7 +239,7 @@ class ComRegister {
222
239
  // 发送成功通知
223
240
  await session.send('已取消订阅该用户');
224
241
  // 更新控制台提示
225
- this.updateSubNotifier(ctx);
242
+ this.updateSubNotifier();
226
243
  // 将存在flag设置为true
227
244
  exist = true;
228
245
  }
@@ -254,7 +271,7 @@ class ComRegister {
254
271
  return '直播订阅已达上限,请取消部分直播订阅后再进行订阅';
255
272
  }
256
273
  // 检查是否登录
257
- if (!(await this.checkIfIsLogin(ctx))) {
274
+ if (!(await this.checkIfIsLogin())) {
258
275
  // 未登录直接返回
259
276
  return '请使用指令bili login登录后再进行订阅操作';
260
277
  }
@@ -262,7 +279,7 @@ class ComRegister {
262
279
  if (!mid)
263
280
  return '请输入用户uid';
264
281
  // 订阅对象
265
- const subUserData = await this.subUserInBili(ctx, mid);
282
+ const subUserData = await this.subUserInBili(mid);
266
283
  // 判断是否订阅对象存在
267
284
  if (!subUserData.flag)
268
285
  return '订阅对象失败,请稍后重试!';
@@ -278,6 +295,7 @@ class ComRegister {
278
295
  channelId: group,
279
296
  dynamic: true,
280
297
  live: true,
298
+ liveGuardBuy: false,
281
299
  atAll: options.atAll
282
300
  });
283
301
  });
@@ -297,7 +315,7 @@ class ComRegister {
297
315
  for (const [index, { channelIdArr, platform }] of target.entries()) {
298
316
  if (channelIdArr.length > 0) { // 输入了推送群号或频道号
299
317
  // 拿到对应的bot
300
- const bot = this.getBot(ctx, platform);
318
+ const bot = this.getBot(platform);
301
319
  // 判断是否配置了对应平台的机器人
302
320
  if (!ctx.bots.some(bot => bot.platform === platform)) {
303
321
  // 发送提示消息
@@ -337,7 +355,7 @@ class ComRegister {
337
355
  // 判断targetArr是否为空
338
356
  if (target.length === 0) {
339
357
  // 为空则默认为当前环境
340
- target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
358
+ target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, liveGuardBuy: false, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
341
359
  // 没有满足条件的群组或频道
342
360
  await session.send('没有满足条件的群组或频道,默认订阅到当前聊天环境');
343
361
  }
@@ -348,7 +366,7 @@ class ComRegister {
348
366
  }
349
367
  else {
350
368
  // 未填写群号或频道号,默认为当前环境
351
- target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
369
+ target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, liveGuardBuy: false, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
352
370
  // 发送提示消息
353
371
  await session.send('没有填写群号或频道号,默认订阅到当前聊天环境');
354
372
  }
@@ -356,7 +374,7 @@ class ComRegister {
356
374
  }
357
375
  else {
358
376
  // 用户直接订阅,将当前环境赋值给target
359
- target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
377
+ target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, liveGuardBuy: false, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
360
378
  }
361
379
  }
362
380
  // 定义外围变量
@@ -426,12 +444,23 @@ class ComRegister {
426
444
  this.logger.error('bili sub指令 getMasterInfo() 发生了错误,错误为:' + e.message);
427
445
  return '订阅出错啦,请重试';
428
446
  }
429
- // 定义live销毁函数
430
- let liveDispose;
447
+ const liveDetectModeSelector = {
448
+ API: async () => {
449
+ // 判断是否已开启直播检测
450
+ if (!this.liveDispose) { // 未开启直播检测
451
+ // 开启直播检测并保存销毁函数
452
+ this.liveDispose = await this.liveDetectWithAPI();
453
+ }
454
+ },
455
+ WS: async () => {
456
+ // 连接到服务器
457
+ await this.liveDetectWithListener(roomId, target);
458
+ }
459
+ };
431
460
  // 订阅直播
432
461
  if (liveMsg) {
433
- // 连接到服务器
434
- this.liveDetectWithListener(ctx, roomId, target);
462
+ // 判断直播订阅方式
463
+ await liveDetectModeSelector[this.config.liveDetectMode]();
435
464
  // 发送订阅消息通知
436
465
  await session.send(`订阅${userData.info.uname}直播通知`);
437
466
  }
@@ -439,7 +468,8 @@ class ComRegister {
439
468
  if (dynamicMsg) {
440
469
  // 判断是否开启动态监测
441
470
  if (!this.dynamicDispose) {
442
- this.enableDynamicDetect(ctx);
471
+ // 开启动态监测
472
+ this.enableDynamicDetect();
443
473
  }
444
474
  // 发送订阅消息通知
445
475
  await session.send(`订阅${userData.info.uname}动态通知`);
@@ -465,10 +495,9 @@ class ComRegister {
465
495
  platform: session.event.platform,
466
496
  live: liveMsg,
467
497
  dynamic: dynamicMsg,
468
- liveDispose
469
498
  });
470
499
  // 新增订阅展示到控制台
471
- this.updateSubNotifier(ctx);
500
+ this.updateSubNotifier();
472
501
  });
473
502
  biliCom
474
503
  .subcommand('.status <roomId:string>', '查询主播当前直播状态', { hidden: true })
@@ -524,25 +553,19 @@ class ComRegister {
524
553
  await session.send('已发送消息,如未收到则说明您的机器人不支持发送私聊消息或您的信息填写有误');
525
554
  });
526
555
  }
527
- async init(ctx, config) {
556
+ async init(config) {
528
557
  // 设置logger
529
- this.logger = ctx.logger('cr');
558
+ this.logger = this.ctx.logger('cr');
530
559
  // 将config设置给类属性
531
560
  this.config = config;
532
561
  // 拿到私人机器人实例
533
- this.privateBot = ctx.bots.find(bot => bot.platform === config.master.platform);
562
+ this.privateBot = this.ctx.bots.find(bot => bot.platform === config.master.platform);
534
563
  if (!this.privateBot) {
535
- ctx.notifier.create({
564
+ this.ctx.notifier.create({
536
565
  content: '您未配置私人机器人,将无法向您推送机器人状态!'
537
566
  });
538
567
  this.logger.error('您未配置私人机器人,将无法向您推送机器人状态!');
539
568
  }
540
- // 检查登录数据库是否有数据
541
- this.loginDBData = (await ctx.database.get('loginBili', 1, ['dynamic_group_id']))[0];
542
- // 从配置获取订阅
543
- config.sub && await this.loadSubFromConfig(ctx, config.sub);
544
- // 从数据库获取订阅
545
- await this.loadSubFromDatabase(ctx);
546
569
  // 判断消息发送方式
547
570
  if (config.automaticResend) {
548
571
  this.sendMsgFunc = async (bot, channelId, content) => {
@@ -553,7 +576,7 @@ class ComRegister {
553
576
  // 发送消息
554
577
  await bot.sendMessage(channelId, content);
555
578
  // 防止消息发送速度过快被忽略
556
- await ctx.sleep(500);
579
+ await this.ctx.sleep(500);
557
580
  // 成功发送消息,跳出循环
558
581
  break;
559
582
  }
@@ -579,23 +602,37 @@ class ComRegister {
579
602
  }
580
603
  };
581
604
  }
605
+ // 检查登录数据库是否有数据
606
+ this.loginDBData = (await this.ctx.database.get('loginBili', 1, ['dynamic_group_id']))[0];
607
+ // 判断登录信息是否已加载完毕
608
+ await this.checkIfLoginInfoIsLoaded();
609
+ // 如果未登录,则直接返回
610
+ if (!(await this.checkIfIsLogin())) {
611
+ // log
612
+ this.logger.info(`账号未登录,请登录`);
613
+ return;
614
+ }
615
+ // 从配置获取订阅
616
+ config.sub && await this.loadSubFromConfig(config.sub);
617
+ // 从数据库获取订阅
618
+ await this.loadSubFromDatabase();
582
619
  // 检查是否需要动态监测
583
- this.checkIfDynamicDetectIsNeeded(ctx);
620
+ this.checkIfDynamicDetectIsNeeded();
584
621
  // 在控制台中显示订阅对象
585
- this.updateSubNotifier(ctx);
622
+ this.updateSubNotifier();
586
623
  }
587
624
  splitMultiPlatformStr(str) {
588
625
  return str.split(';').map(cv => cv.split('.')).map(([idStr, platform]) => {
589
626
  const channelIdArr = idStr.split(',').map(id => {
590
627
  const atAll = /@$/.test(id); // 使用正则表达式检查 id 是否以 @ 结尾
591
628
  const channelId = atAll ? id.slice(0, -1) : id; // 去除末尾的 @
592
- return { channelId, dynamic: true, live: true, atAll };
629
+ return { channelId, dynamic: true, live: true, liveGuardBuy: false, atAll };
593
630
  });
594
631
  return { channelIdArr, platform };
595
632
  });
596
633
  }
597
- getBot(ctx, pf) {
598
- return ctx.bots.find(bot => bot.platform === pf);
634
+ getBot(pf) {
635
+ return this.ctx.bots.find(bot => bot.platform === pf);
599
636
  }
600
637
  async sendPrivateMsg(content) {
601
638
  if (this.config.master.enable) {
@@ -609,7 +646,7 @@ class ComRegister {
609
646
  }
610
647
  }
611
648
  }
612
- async sendPrivateMsgAndRebootService(ctx) {
649
+ async sendPrivateMsgAndRebootService() {
613
650
  // 判断重启次数是否超过三次
614
651
  if (this.rebootCount >= 3) {
615
652
  // logger
@@ -617,7 +654,7 @@ class ComRegister {
617
654
  // 重启失败,发送消息
618
655
  await this.sendPrivateMsg('已重启插件三次,请检查机器人状态后使用指令 sys start 启动插件');
619
656
  // 关闭插件
620
- await ctx.sm.disposePlugin();
657
+ await this.ctx.sm.disposePlugin();
621
658
  // 结束
622
659
  return;
623
660
  }
@@ -626,7 +663,7 @@ class ComRegister {
626
663
  // logger
627
664
  this.logger.info('插件出现未知错误,正在重启插件');
628
665
  // 重启插件
629
- const flag = await ctx.sm.restartPlugin();
666
+ const flag = await this.ctx.sm.restartPlugin();
630
667
  // 判断是否重启成功
631
668
  if (flag) {
632
669
  this.logger.info('重启插件成功');
@@ -637,23 +674,23 @@ class ComRegister {
637
674
  // 重启失败,发送消息
638
675
  await this.sendPrivateMsg('重启插件失败,请检查机器人状态后使用指令 sys start 启动插件');
639
676
  // 关闭插件
640
- await ctx.sm.disposePlugin();
677
+ await this.ctx.sm.disposePlugin();
641
678
  }
642
679
  }
643
- async sendPrivateMsgAndStopService(ctx) {
680
+ async sendPrivateMsgAndStopService() {
644
681
  // 发送消息
645
682
  await this.sendPrivateMsg('插件发生未知错误,请检查机器人状态后使用指令 sys start 启动插件');
646
683
  // logger
647
684
  this.logger.error('插件发生未知错误,请检查机器人状态后使用指令 sys start 启动插件');
648
685
  // 关闭插件
649
- await ctx.sm.disposePlugin();
686
+ await this.ctx.sm.disposePlugin();
650
687
  // 结束
651
688
  return;
652
689
  }
653
- async sendMsg(ctx, targets, content, live) {
690
+ async sendMsg(targets, content, live) {
654
691
  for (const target of targets) {
655
692
  // 获取机器人实例
656
- const bot = this.getBot(ctx, target.platform);
693
+ const bot = this.getBot(target.platform);
657
694
  // 定义需要发送的数组
658
695
  let sendArr = [];
659
696
  // 判断是否需要推送所有机器人加入的群
@@ -664,6 +701,7 @@ class ComRegister {
664
701
  channelId: guild.id,
665
702
  dynamic: target.channelIdArr[0].dynamic,
666
703
  live: target.channelIdArr[0].live,
704
+ liveGuardBuy: target.channelIdArr[0].liveGuardBuy,
667
705
  atAll: target.channelIdArr[0].atAll
668
706
  });
669
707
  }
@@ -695,7 +733,7 @@ class ComRegister {
695
733
  }
696
734
  }
697
735
  }
698
- dynamicDetect(ctx) {
736
+ dynamicDetect() {
699
737
  // 检测初始化变量
700
738
  let detectSetup = true;
701
739
  // 更新基线
@@ -715,7 +753,7 @@ class ComRegister {
715
753
  // 检测启动初始化
716
754
  if (detectSetup) {
717
755
  // 获取动态信息
718
- const data = await ctx.ba.getAllDynamic();
756
+ const data = await this.ctx.ba.getAllDynamic();
719
757
  // 判断获取动态信息是否成功
720
758
  if (data.code !== 0)
721
759
  return;
@@ -731,13 +769,13 @@ class ComRegister {
731
769
  let content;
732
770
  try {
733
771
  // 查询是否有新动态
734
- const data = await ctx.ba.hasNewDynamic(updateBaseline);
772
+ const data = await this.ctx.ba.hasNewDynamic(updateBaseline);
735
773
  updateNum = data.data.update_num;
736
774
  // 没有新动态或获取动态信息失败直接返回
737
775
  if (updateNum <= 0 || data.code !== 0)
738
776
  return;
739
777
  // 获取动态内容
740
- content = await ctx.ba.getAllDynamic(updateBaseline);
778
+ content = await this.ctx.ba.getAllDynamic(updateBaseline);
741
779
  }
742
780
  catch (e) {
743
781
  return this.logger.error('dynamicDetect getUserSpaceDynamic() 发生了错误,错误为:' + e.message);
@@ -751,7 +789,7 @@ class ComRegister {
751
789
  // 发送私聊消息
752
790
  await this.sendPrivateMsg('账号未登录,插件已停止工作,请登录后,输入指令 sys start 启动插件');
753
791
  // 停止服务
754
- await ctx.sm.disposePlugin();
792
+ await this.ctx.sm.disposePlugin();
755
793
  // 结束循环
756
794
  break;
757
795
  }
@@ -761,7 +799,7 @@ class ComRegister {
761
799
  // 发送私聊消息
762
800
  await this.sendPrivateMsg('账号被风控,插件已停止工作,请确认风控解除后,输入指令 sys start 启动插件');
763
801
  // 停止服务
764
- await ctx.sm.disposePlugin();
802
+ await this.ctx.sm.disposePlugin();
765
803
  // 结束循环
766
804
  break;
767
805
  }
@@ -821,7 +859,7 @@ class ComRegister {
821
859
  // 获取动态推送图片
822
860
  try {
823
861
  // 渲染图片
824
- const { pic: gimgPic, buffer: gimgBuffer } = await ctx.gi.generateDynamicImg(items[num]);
862
+ const { pic: gimgPic, buffer: gimgBuffer } = await this.ctx.gi.generateDynamicImg(items[num]);
825
863
  // 赋值
826
864
  pic = gimgPic;
827
865
  buffer = gimgBuffer;
@@ -835,13 +873,13 @@ class ComRegister {
835
873
  if (e.message === '出现关键词,屏蔽该动态') {
836
874
  // 如果需要发送才发送
837
875
  if (this.config.filter.notify) {
838
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
876
+ await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
839
877
  }
840
878
  return;
841
879
  }
842
880
  if (e.message === '已屏蔽转发动态') {
843
881
  if (this.config.filter.notify) {
844
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条转发动态,已屏蔽`);
882
+ await this.sendMsg(sub.target, `${upName}发布了一条转发动态,已屏蔽`);
845
883
  }
846
884
  return;
847
885
  }
@@ -849,7 +887,7 @@ class ComRegister {
849
887
  if (i === attempts - 1) {
850
888
  this.logger.error('dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:' + e.message);
851
889
  // 发送私聊消息并重启服务
852
- return await this.sendPrivateMsgAndStopService(ctx);
890
+ return await this.sendPrivateMsgAndStopService();
853
891
  }
854
892
  }
855
893
  }
@@ -859,12 +897,12 @@ class ComRegister {
859
897
  if (pic) {
860
898
  this.logger.info('推送动态中,使用render模式');
861
899
  // pic存在,使用的是render模式
862
- await this.sendMsg(ctx, sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
900
+ await this.sendMsg(sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
863
901
  }
864
902
  else if (buffer) {
865
903
  this.logger.info('推送动态中,使用page模式');
866
904
  // pic不存在,说明使用的是page模式
867
- await this.sendMsg(ctx, sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
905
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
868
906
  }
869
907
  else {
870
908
  this.logger.info(items[num].modules.module_author.name + '发布了一条动态,但是推送失败');
@@ -878,7 +916,7 @@ class ComRegister {
878
916
  }
879
917
  };
880
918
  }
881
- debug_dynamicDetect(ctx) {
919
+ debug_dynamicDetect() {
882
920
  // 检测初始化变量
883
921
  let detectSetup = true;
884
922
  // 更新基线
@@ -899,7 +937,7 @@ class ComRegister {
899
937
  // 检测启动初始化
900
938
  if (detectSetup) {
901
939
  // 获取动态信息
902
- const data = await ctx.ba.getAllDynamic();
940
+ const data = await this.ctx.ba.getAllDynamic();
903
941
  // 判断获取动态信息是否成功
904
942
  if (data.code !== 0)
905
943
  return;
@@ -916,7 +954,7 @@ class ComRegister {
916
954
  let content;
917
955
  try {
918
956
  // 查询是否有新动态
919
- const data = await ctx.ba.hasNewDynamic(updateBaseline);
957
+ const data = await this.ctx.ba.hasNewDynamic(updateBaseline);
920
958
  updateNum = data.data.update_num;
921
959
  console.log(`获取是否有新动态:`);
922
960
  console.log(data);
@@ -924,7 +962,7 @@ class ComRegister {
924
962
  if (updateNum <= 0 || data.code !== 0)
925
963
  return;
926
964
  // 获取动态内容
927
- content = await ctx.ba.getAllDynamic(updateBaseline);
965
+ content = await this.ctx.ba.getAllDynamic(updateBaseline);
928
966
  console.log('获取动态内容:');
929
967
  console.log(content.data.items[0]);
930
968
  }
@@ -940,7 +978,7 @@ class ComRegister {
940
978
  // 发送私聊消息
941
979
  await this.sendPrivateMsg('账号未登录,插件已停止工作,请登录后,输入指令 sys start 启动插件');
942
980
  // 停止服务
943
- await ctx.sm.disposePlugin();
981
+ await this.ctx.sm.disposePlugin();
944
982
  // 结束循环
945
983
  break;
946
984
  }
@@ -950,7 +988,7 @@ class ComRegister {
950
988
  // 发送私聊消息
951
989
  await this.sendPrivateMsg('账号被风控,插件已停止工作,请确认风控解除后,输入指令 sys start 启动插件');
952
990
  // 停止服务
953
- await ctx.sm.disposePlugin();
991
+ await this.ctx.sm.disposePlugin();
954
992
  // 结束循环
955
993
  break;
956
994
  }
@@ -1018,7 +1056,7 @@ class ComRegister {
1018
1056
  // 获取动态推送图片
1019
1057
  try {
1020
1058
  // 渲染图片
1021
- const { pic: gimgPic, buffer: gimgBuffer } = await ctx.gi.generateDynamicImg(items[num]);
1059
+ const { pic: gimgPic, buffer: gimgBuffer } = await this.ctx.gi.generateDynamicImg(items[num]);
1022
1060
  // 赋值
1023
1061
  pic = gimgPic;
1024
1062
  buffer = gimgBuffer;
@@ -1032,13 +1070,13 @@ class ComRegister {
1032
1070
  if (e.message === '出现关键词,屏蔽该动态') {
1033
1071
  // 如果需要发送才发送
1034
1072
  if (this.config.filter.notify) {
1035
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
1073
+ await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
1036
1074
  }
1037
1075
  return;
1038
1076
  }
1039
1077
  if (e.message === '已屏蔽转发动态') {
1040
1078
  if (this.config.filter.notify) {
1041
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条转发动态,已屏蔽`);
1079
+ await this.sendMsg(sub.target, `${upName}发布了一条转发动态,已屏蔽`);
1042
1080
  }
1043
1081
  return;
1044
1082
  }
@@ -1046,7 +1084,7 @@ class ComRegister {
1046
1084
  if (i === attempts - 1) {
1047
1085
  this.logger.error('dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:' + e.message);
1048
1086
  // 发送私聊消息并重启服务
1049
- return await this.sendPrivateMsgAndStopService(ctx);
1087
+ return await this.sendPrivateMsgAndStopService();
1050
1088
  }
1051
1089
  }
1052
1090
  }
@@ -1056,12 +1094,12 @@ class ComRegister {
1056
1094
  if (pic) {
1057
1095
  this.logger.info('推送动态中,使用render模式');
1058
1096
  // pic存在,使用的是render模式
1059
- await this.sendMsg(ctx, sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
1097
+ await this.sendMsg(sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
1060
1098
  }
1061
1099
  else if (buffer) {
1062
1100
  this.logger.info('推送动态中,使用page模式');
1063
1101
  // pic不存在,说明使用的是page模式
1064
- await this.sendMsg(ctx, sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
1102
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
1065
1103
  }
1066
1104
  else {
1067
1105
  this.logger.info(items[num].modules.module_author.name + '发布了一条动态,但是推送失败');
@@ -1076,7 +1114,7 @@ class ComRegister {
1076
1114
  };
1077
1115
  }
1078
1116
  // 定义发送直播通知卡片方法
1079
- async sendLiveNotifyCard(ctx, info, liveType, liveNotifyMsg) {
1117
+ async sendLiveNotifyCard(info, liveType, liveNotifyMsg) {
1080
1118
  // 定义变量
1081
1119
  let pic;
1082
1120
  let buffer;
@@ -1085,7 +1123,7 @@ class ComRegister {
1085
1123
  for (let i = 0; i < attempts; i++) {
1086
1124
  try {
1087
1125
  // 获取直播通知卡片
1088
- const { pic: picv, buffer: bufferv } = await ctx.gi.generateLiveImg(info.data, info.username, info.userface, liveType);
1126
+ const { pic: picv, buffer: bufferv } = await this.ctx.gi.generateLiveImg(info.data, info.username, info.userface, liveType);
1089
1127
  // 赋值
1090
1128
  pic = picv;
1091
1129
  buffer = bufferv;
@@ -1096,7 +1134,7 @@ class ComRegister {
1096
1134
  if (i === attempts - 1) { // 已尝试三次
1097
1135
  this.logger.error('liveDetect generateLiveImg() 推送卡片生成失败,原因:' + e.message);
1098
1136
  // 发送私聊消息并重启服务
1099
- return await this.sendPrivateMsgAndStopService(ctx);
1137
+ return await this.sendPrivateMsgAndStopService();
1100
1138
  }
1101
1139
  }
1102
1140
  }
@@ -1105,33 +1143,33 @@ class ComRegister {
1105
1143
  if (pic) {
1106
1144
  // 只有在开播时才艾特全体成员
1107
1145
  if (liveType === LiveType.StartBroadcasting) {
1108
- return await this.sendMsg(ctx, info.target, pic + (liveNotifyMsg ?? ''), true);
1146
+ return await this.sendMsg(info.target, pic + (liveNotifyMsg ?? ''), true);
1109
1147
  }
1110
1148
  // 正常不需要艾特全体成员
1111
- return await this.sendMsg(ctx, info.target, pic + (liveNotifyMsg ?? ''));
1149
+ return await this.sendMsg(info.target, pic + (liveNotifyMsg ?? ''));
1112
1150
  }
1113
1151
  // pic不存在,说明使用的是page模式
1114
1152
  const msg = (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), liveNotifyMsg || ''] });
1115
1153
  // 只有在开播时才艾特全体成员
1116
1154
  if (liveType === LiveType.StartBroadcasting) {
1117
- return await this.sendMsg(ctx, info.target, msg, true);
1155
+ return await this.sendMsg(info.target, msg, true);
1118
1156
  }
1119
1157
  // 正常不需要艾特全体成员
1120
- return await this.sendMsg(ctx, info.target, msg);
1158
+ return await this.sendMsg(info.target, msg);
1121
1159
  }
1122
1160
  // 定义获取主播信息方法
1123
- async useMasterInfo(ctx, uid) {
1124
- const { data: { info } } = await ctx.ba.getMasterInfo(uid);
1125
- return { username: info.name, userface: info.face };
1161
+ async useMasterInfo(uid) {
1162
+ const { data } = await this.ctx.ba.getMasterInfo(uid);
1163
+ return { username: data.info.uname, userface: data.info.face, roomId: data.room_id };
1126
1164
  }
1127
- async useLiveRoomInfo(ctx, roomId) {
1165
+ async useLiveRoomInfo(roomId) {
1128
1166
  // 发送请求获取直播间信息
1129
1167
  let content;
1130
1168
  const attempts = 3;
1131
1169
  for (let i = 0; i < attempts; i++) {
1132
1170
  try {
1133
1171
  // 发送请求获取room信息
1134
- content = await ctx.ba.getLiveRoomInfo(roomId);
1172
+ content = await this.ctx.ba.getLiveRoomInfo(roomId);
1135
1173
  // 成功则跳出循环
1136
1174
  break;
1137
1175
  }
@@ -1139,180 +1177,21 @@ class ComRegister {
1139
1177
  this.logger.error('liveDetect getLiveRoomInfo 发生了错误,错误为:' + e.message);
1140
1178
  if (i === attempts - 1) { // 已尝试三次
1141
1179
  // 发送私聊消息并重启服务
1142
- return await this.sendPrivateMsgAndStopService(ctx);
1180
+ return await this.sendPrivateMsgAndStopService();
1143
1181
  }
1144
1182
  }
1145
1183
  }
1146
1184
  return content.data;
1147
1185
  }
1148
- /* liveDetect(
1149
- ctx: Context,
1150
- roomId: string,
1151
- target: Target
1152
- ) {
1153
- let firstSubscription: boolean = true;
1154
- let timer: number = 0;
1155
- let open: boolean = false;
1156
- let liveTime: string;
1157
- let username: string
1158
- let userface: string
1159
- // 相当于锁的作用,防止上一个循环没处理完
1160
- let flag: boolean = true
1161
-
1162
- return async () => {
1163
- // 如果flag为false则说明前面的代码还未执行完,则直接返回
1164
- if (!flag) return
1165
- flag = false
1166
- // 无论是否执行成功都要释放锁
1167
- try {
1168
- // 发送请求检测直播状态
1169
- let content: any
1170
- const attempts = 3
1171
- for (let i = 0; i < attempts; i++) {
1172
- try {
1173
- // 发送请求获取room信息
1174
- content = await ctx.ba.getLiveRoomInfo(roomId)
1175
- // 成功则跳出循环
1176
- break
1177
- } catch (e) {
1178
- this.logger.error('liveDetect getLiveRoomInfo 发生了错误,错误为:' + e.message)
1179
- if (i === attempts - 1) { // 已尝试三次
1180
- // 发送私聊消息并重启服务
1181
- return await this.sendPrivateMsgAndStopService(ctx)
1182
- }
1183
- }
1184
- }
1185
- const { data } = content
1186
- // 判断是否是第一次订阅
1187
- if (firstSubscription) {
1188
- firstSubscription = false
1189
- // 获取主播信息
1190
- const attempts = 3
1191
- for (let i = 0; i < attempts; i++) {
1192
- try {
1193
- // 发送请求获取主播信息
1194
- await useMasterInfo(data.uid)
1195
- // 成功则跳出循环
1196
- break
1197
- } catch (e) {
1198
- this.logger.error('liveDetect getMasterInfo() 发生了错误,错误为:' + e.message)
1199
- if (i === attempts - 1) { // 已尝试三次
1200
- // 发送私聊消息并重启服务
1201
- return await this.sendPrivateMsgAndStopService(ctx)
1202
- }
1203
- }
1204
- }
1205
- // 判断直播状态
1206
- if (data.live_status === 1) { // 当前正在直播
1207
- // 设置开播时间
1208
- liveTime = data.live_time
1209
- // 设置直播中消息
1210
- const liveMsg = this.config.customLive ? this.config.customLive
1211
- .replace('-name', username)
1212
- .replace('-time', await ctx.gi.getTimeDifference(liveTime))
1213
- .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null
1214
- // 发送直播通知卡片
1215
- if (this.config.restartPush) sendLiveNotifyCard(data, LiveType.LiveBroadcast, liveMsg)
1216
- // 改变开播状态
1217
- open = true
1218
- } // 未开播,直接返回
1219
- return
1220
- }
1221
- // 检查直播状态
1222
- switch (data.live_status) {
1223
- case 0:
1224
- case 2: { // 状态 0 和 2 说明未开播
1225
- if (open) { // 之前开播,现在下播了
1226
- // 更改直播状态
1227
- open = false
1228
- // 下播了将定时器清零
1229
- timer = 0
1230
- // 定义下播通知消息
1231
- const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1232
- .replace('-name', username)
1233
- .replace('-time', await ctx.gi.getTimeDifference(liveTime)) : null
1234
- // 更改直播时长
1235
- data.live_time = liveTime
1236
- // 推送下播通知
1237
- await sendLiveNotifyCard(data, LiveType.StopBroadcast, liveEndMsg)
1238
- }
1239
- // 未进循环,还未开播,继续循环
1240
- break
1241
- }
1242
- case 1: {
1243
- if (!open) { // 之前未开播,现在开播了
1244
- // 更改直播状态
1245
- open = true
1246
- // 设置开播时间
1247
- liveTime = data.live_time
1248
- // 获取主播信息
1249
- const attempts = 3
1250
- for (let i = 0; i < attempts; i++) {
1251
- try {
1252
- // 主播信息不会变,开播时刷新一次即可
1253
- // 发送请求获取主播信息
1254
- await useMasterInfo(data.uid)
1255
- // 成功则跳出循环
1256
- break
1257
- } catch (e) {
1258
- this.logger.error('liveDetect open getMasterInfo() 发生了错误,错误为:' + e.message)
1259
- if (i === attempts - 1) { // 已尝试三次
1260
- // 发送私聊消息并重启服务
1261
- return await this.sendPrivateMsgAndStopService(ctx)
1262
- }
1263
- }
1264
- }
1265
- // 定义开播通知语
1266
- const liveStartMsg = this.config.customLiveStart ? this.config.customLiveStart
1267
- .replace('-name', username)
1268
- .replace('-time', await ctx.gi.getTimeDifference(liveTime))
1269
- .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null
1270
- // 发送消息
1271
- await sendLiveNotifyCard(data, LiveType.StartBroadcasting, liveStartMsg)
1272
- } else { // 还在直播
1273
- if (this.config.pushTime > 0) {
1274
- timer++
1275
- // 开始记录时间
1276
- if (timer >= (6 * 60 * this.config.pushTime)) { // 到时间推送直播消息
1277
- // 到时间重新计时
1278
- timer = 0
1279
- // 定义直播中通知消息
1280
- const liveMsg = this.config.customLive ? this.config.customLive
1281
- .replace('-name', username)
1282
- .replace('-time', await ctx.gi.getTimeDifference(liveTime))
1283
- .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null
1284
- // 发送直播通知卡片
1285
- sendLiveNotifyCard(data, LiveType.LiveBroadcast, liveMsg)
1286
- }
1287
- }
1288
- // 否则继续循环
1289
- }
1290
- }
1291
- }
1292
- }
1293
- finally {
1294
- // 执行完方法体不论如何都把flag设置为true
1295
- flag = true
1296
- }
1297
- }
1298
- } */
1299
- async liveDetectWithAPI(ctx) {
1186
+ async liveDetectWithAPI() {
1300
1187
  // 定义变量:第一次订阅
1301
- let firstSubscription = true;
1188
+ let liveDetectSetup = true;
1302
1189
  // 定义变量:timer计时器
1303
1190
  let timer = 0;
1304
1191
  // 相当于锁的作用,防止上一个循环没处理完
1305
1192
  let flag = true;
1306
1193
  // 定义订阅对象Record 0未开播 1正在直播 2轮播中
1307
1194
  const liveRecord = {};
1308
- // 初始化subRecord
1309
- this.subManager.forEach(sub => {
1310
- // 判断是否订阅直播
1311
- if (sub.live) {
1312
- // 将该订阅添加到subRecord中
1313
- liveRecord[sub.uid] = { liveStatus: 0, liveTime: '', target: sub.target };
1314
- }
1315
- });
1316
1195
  // 定义函数: 发送请求获取直播状态
1317
1196
  const useLiveStatus = async (roomId) => {
1318
1197
  let content;
@@ -1320,7 +1199,7 @@ class ComRegister {
1320
1199
  for (let i = 0; i < attempts; i++) {
1321
1200
  try {
1322
1201
  // 发送请求获取room信息
1323
- content = await ctx.ba.getLiveRoomInfo(roomId);
1202
+ content = await this.ctx.ba.getLiveRoomInfo(roomId);
1324
1203
  // 成功则跳出循环
1325
1204
  break;
1326
1205
  }
@@ -1328,7 +1207,7 @@ class ComRegister {
1328
1207
  this.logger.error('liveDetect getLiveRoomInfo 发生了错误,错误为:' + e.message);
1329
1208
  if (i === attempts - 1) { // 已尝试三次
1330
1209
  // 发送私聊消息并重启服务
1331
- return await this.sendPrivateMsgAndStopService(ctx);
1210
+ return await this.sendPrivateMsgAndStopService();
1332
1211
  }
1333
1212
  }
1334
1213
  }
@@ -1343,11 +1222,19 @@ class ComRegister {
1343
1222
  flag = false;
1344
1223
  try {
1345
1224
  // 获取正在直播对象
1346
- const liveUsers = await ctx.ba.getTheUserWhoIsLiveStreaming();
1347
- // 判断是否是第一次订阅
1348
- if (firstSubscription) {
1225
+ const liveUsers = await this.ctx.ba.getTheUserWhoIsLiveStreaming();
1226
+ // 判断是否是初始化直播监测
1227
+ if (liveDetectSetup) {
1349
1228
  // 将第一次订阅置为false
1350
- firstSubscription = false;
1229
+ liveDetectSetup = false;
1230
+ // 初始化subRecord
1231
+ this.subManager.forEach(sub => {
1232
+ // 判断是否订阅直播
1233
+ if (sub.live) {
1234
+ // 将该订阅添加到subRecord中
1235
+ liveRecord[sub.uid] = { liveStatus: 0, liveTime: '', target: sub.target };
1236
+ }
1237
+ });
1351
1238
  // 先判断是否有UP主正在直播
1352
1239
  if (liveUsers.count > 0) {
1353
1240
  // 遍历liveUsers
@@ -1358,21 +1245,21 @@ class ComRegister {
1358
1245
  const data = await useLiveStatus(item.room_id.toString());
1359
1246
  // 设置开播时间
1360
1247
  liveRecord[item.mid].liveTime = data.live_time;
1248
+ // 改变开播状态
1249
+ liveRecord[item.mid].liveStatus = 1;
1361
1250
  // 设置直播中消息
1362
1251
  const liveMsg = this.config.customLive ? this.config.customLive
1363
1252
  .replace('-name', item.uname)
1364
- .replace('-time', await ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1253
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1365
1254
  .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null;
1366
1255
  // 发送直播通知卡片
1367
1256
  if (this.config.restartPush)
1368
- this.sendLiveNotifyCard(ctx, {
1257
+ this.sendLiveNotifyCard({
1369
1258
  username: item.uname,
1370
1259
  userface: item.face,
1371
1260
  target: liveRecord[item.mid].target,
1372
1261
  data
1373
1262
  }, LiveType.LiveBroadcast, liveMsg);
1374
- // 改变开播状态
1375
- liveRecord[item.mid].liveStatus = 1;
1376
1263
  }
1377
1264
  });
1378
1265
  }
@@ -1418,6 +1305,7 @@ class ComRegister {
1418
1305
  delete liveRecord[subUID];
1419
1306
  }
1420
1307
  }
1308
+ // 数量没有差异,则不进行其他操作
1421
1309
  // 遍历liveUsers
1422
1310
  liveUsers.items.forEach(async (item) => {
1423
1311
  // 判断是否有正在直播的订阅对象
@@ -1432,16 +1320,15 @@ class ComRegister {
1432
1320
  // 定义开播通知语
1433
1321
  const liveStartMsg = this.config.customLiveStart ? this.config.customLiveStart
1434
1322
  .replace('-name', item.uname)
1435
- .replace('-time', await ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1323
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1436
1324
  .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null;
1437
1325
  // 发送直播通知卡片
1438
- if (this.config.restartPush)
1439
- this.sendLiveNotifyCard(ctx, {
1440
- username: item.uname,
1441
- userface: item.face,
1442
- target: liveRecord[item.mid].target,
1443
- data
1444
- }, LiveType.LiveBroadcast, liveStartMsg);
1326
+ await this.sendLiveNotifyCard({
1327
+ username: item.uname,
1328
+ userface: item.face,
1329
+ target: liveRecord[item.mid].target,
1330
+ data
1331
+ }, LiveType.LiveBroadcast, liveStartMsg);
1445
1332
  // 改变开播状态
1446
1333
  liveRecord[item.mid].liveStatus = 1;
1447
1334
  // 结束
@@ -1457,10 +1344,10 @@ class ComRegister {
1457
1344
  // 定义直播中通知消息
1458
1345
  const liveMsg = this.config.customLive ? this.config.customLive
1459
1346
  .replace('-name', item.uname)
1460
- .replace('-time', await ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1347
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1461
1348
  .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null;
1462
1349
  // 发送直播通知卡片
1463
- this.sendLiveNotifyCard(ctx, {
1350
+ this.sendLiveNotifyCard({
1464
1351
  username: item.uname,
1465
1352
  userface: item.face,
1466
1353
  target: liveRecord[item.mid].target,
@@ -1472,6 +1359,29 @@ class ComRegister {
1472
1359
  }
1473
1360
  }
1474
1361
  });
1362
+ // 找出liveRecord中liveStatus为1但liveUsers中没有的元素
1363
+ const extraInLiveRecord = currentLiveRecordKeys.filter(key => !liveUsers.items.some(item => item.mid === Number(key)));
1364
+ // 遍历 extraInLiveRecord
1365
+ for (const subUID of extraInLiveRecord) { // 下播的主播
1366
+ // 获取主播信息
1367
+ const masterInfo = await this.useMasterInfo(subUID);
1368
+ // 获取直播间消息
1369
+ const liveRoomInfo = await this.useLiveRoomInfo(masterInfo.roomId.toString());
1370
+ // 设置开播时间
1371
+ liveRoomInfo.live_time = liveRecord[subUID].liveTime;
1372
+ // 定义下播播通知语
1373
+ const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1374
+ .replace('-name', masterInfo.username)
1375
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[subUID].liveTime))
1376
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1377
+ // 发送下播通知
1378
+ this.sendLiveNotifyCard({
1379
+ username: masterInfo.username,
1380
+ userface: masterInfo.userface,
1381
+ target: liveRecord[subUID].target,
1382
+ data: liveRoomInfo
1383
+ }, LiveType.StopBroadcast, liveEndMsg);
1384
+ }
1475
1385
  }
1476
1386
  finally {
1477
1387
  // 执行完方法体不论如何都把flag设置为true
@@ -1479,43 +1389,140 @@ class ComRegister {
1479
1389
  }
1480
1390
  };
1481
1391
  }
1482
- liveDetectWithListener(ctx, roomId, target) {
1392
+ async liveDetectWithListener(roomId, target) {
1483
1393
  // 定义开播时间
1484
1394
  let liveTime;
1485
1395
  // 定义定时推送定时器
1486
1396
  let pushAtTimeTimer;
1487
1397
  // 定义弹幕存放数组
1488
1398
  const currentLiveDanmakuArr = [];
1489
- const temporaryLiveDanmakuArr = [];
1399
+ // 定义开播状态
1400
+ let liveStatus = false;
1401
+ // 处理target
1402
+ // 定义channelIdArr总长度
1403
+ let channelIdArrLen = 0;
1404
+ // 定义数据
1405
+ let liveRoomInfo;
1406
+ let masterInfo;
1407
+ // 找到频道/群组对应的
1408
+ const liveGuardBuyPushTargetArr = target.map(channel => {
1409
+ // 获取符合条件的target
1410
+ const liveGuardBuyArr = channel.channelIdArr.filter(channelId => channelId.liveGuardBuy);
1411
+ // 将当前liveDanmakuArr的长度+到channelIdArrLen中
1412
+ channelIdArrLen += liveGuardBuyArr.length;
1413
+ // 返回符合的target
1414
+ return {
1415
+ channelIdArr: liveGuardBuyArr,
1416
+ platform: channel.platform
1417
+ };
1418
+ });
1490
1419
  // 定义定时推送函数
1491
- const pushAtTime = async () => {
1492
- // 获取直播间信息
1493
- const liveRoomInfo = await this.useLiveRoomInfo(ctx, roomId);
1494
- // 获取主播信息
1495
- const masterInfo = await this.useMasterInfo(ctx, liveRoomInfo.uid);
1496
- // 定义直播中通知消息
1420
+ const pushAtTimeFunc = async () => {
1421
+ // 判断是否信息是否获取成功
1422
+ if (!(await useMasterAndLiveRoomInfo())) {
1423
+ // 未获取成功,直接返回
1424
+ return this.sendPrivateMsg('获取直播间信息失败,推送直播卡片失败!');
1425
+ }
1426
+ // 设置开播时间
1427
+ liveTime = liveRoomInfo.live_time;
1428
+ // 设置直播中消息
1497
1429
  const liveMsg = this.config.customLive ? this.config.customLive
1498
1430
  .replace('-name', masterInfo.username)
1499
- .replace('-time', await ctx.gi.getTimeDifference(liveTime))
1431
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1500
1432
  .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1501
1433
  // 发送直播通知卡片
1502
- await this.sendLiveNotifyCard(liveRoomInfo, {
1434
+ await this.sendLiveNotifyCard({
1503
1435
  username: masterInfo.username,
1504
1436
  userface: masterInfo.userface,
1505
1437
  target,
1506
1438
  data: liveRoomInfo
1507
1439
  }, LiveType.LiveBroadcast, liveMsg);
1508
1440
  };
1509
- // 定义10秒推送函数
1510
- const pushOnceEveryTenS = () => {
1511
- // 判断数组是否有内容
1512
- if (temporaryLiveDanmakuArr.length > 0) {
1441
+ // 定义获取弹幕权重Record函数
1442
+ const getDanmakuWeightRecord = () => {
1443
+ // 创建segmentit
1444
+ const segmentit = (0, segmentit_1.useDefault)(new segmentit_1.Segment());
1445
+ // 创建Record
1446
+ const danmakuWeightRecord = {};
1447
+ // 循环遍历currentLiveDanmakuArr
1448
+ for (const danmaku of currentLiveDanmakuArr) {
1449
+ // 遍历结果
1450
+ segmentit.doSegment(danmaku).map((word) => {
1451
+ // 定义权重
1452
+ danmakuWeightRecord[word.w] = (danmakuWeightRecord[word.w] || 0) + 1;
1453
+ });
1454
+ }
1455
+ // 返回Record
1456
+ return danmakuWeightRecord;
1457
+ };
1458
+ // 定义获取弹幕词云函数
1459
+ const sendDanmakuWordCloud = (danmakuWeightRecord) => {
1460
+ // 准备词云数据
1461
+ const wordList = Object.keys(danmakuWeightRecord).map(word => ({ text: word, value: danmakuWeightRecord[word] }));
1462
+ // 创建画布
1463
+ const width = 800;
1464
+ const height = 600;
1465
+ const canvas = (0, canvas_1.createCanvas)(width, height);
1466
+ const context = canvas.getContext('2d');
1467
+ // 定义绘制函数
1468
+ const draw = (words) => {
1469
+ context.clearRect(0, 0, width, height);
1470
+ context.fillStyle = '#fff';
1471
+ context.fillRect(0, 0, width, height);
1472
+ words.forEach(function (d) {
1473
+ context.font = `${d.size}px Arial`;
1474
+ context.fillStyle = '#000';
1475
+ context.fillText(d.text, d.x, d.y);
1476
+ });
1477
+ // 保存画布为buffer
1478
+ const buffer = canvas.toBuffer('image/png');
1513
1479
  // 发送消息
1514
- this.sendMsg(ctx, target, temporaryLiveDanmakuArr.join('\n'));
1515
- // 将临时消息数组清空
1516
- temporaryLiveDanmakuArr.length = 0;
1480
+ this.sendMsg(target, koishi_1.h.image(buffer, 'image/png'));
1481
+ };
1482
+ // 配置词云
1483
+ const layout = (0, d3_cloud_1.default)()
1484
+ .size([width, height])
1485
+ .words(wordList.map(d => ({ text: d.text, size: d.value })))
1486
+ .padding(5)
1487
+ .font('Arial')
1488
+ .fontSize(d => d.size)
1489
+ .on('end', draw);
1490
+ // 生成词云
1491
+ layout.start();
1492
+ };
1493
+ // 定义直播间信息获取函数
1494
+ const useMasterAndLiveRoomInfo = async () => {
1495
+ // 定义函数是否执行成功flag
1496
+ let flag = true;
1497
+ // 获取直播间信息
1498
+ liveRoomInfo = await this.useLiveRoomInfo(roomId).catch(() => {
1499
+ // 设置flag为false
1500
+ flag = false;
1501
+ // 返回空
1502
+ return null;
1503
+ });
1504
+ // 判断是否成功获取信息
1505
+ if (!flag || !liveRoomInfo || !liveRoomInfo.uid) {
1506
+ // 上一步未成功
1507
+ flag = false;
1508
+ // 返回flag
1509
+ return flag;
1517
1510
  }
1511
+ // 获取主播信息(需要满足flag为true,liveRoomInfo.uid有值)
1512
+ masterInfo = await this.useMasterInfo(liveRoomInfo.uid).catch(() => {
1513
+ // 设置flag为false
1514
+ flag = false;
1515
+ // 返回空
1516
+ return null;
1517
+ });
1518
+ // 返回信息
1519
+ return flag;
1518
1520
  };
1521
+ // 判断是否信息是否获取成功
1522
+ if (!(await useMasterAndLiveRoomInfo())) {
1523
+ // 未获取成功,直接返回
1524
+ return this.sendPrivateMsg('获取直播间信息失败,启动直播间弹幕检测失败!');
1525
+ }
1519
1526
  // 构建消息处理函数
1520
1527
  const handler = {
1521
1528
  onOpen: () => {
@@ -1525,63 +1532,110 @@ class ComRegister {
1525
1532
  this.logger.info('直播间连接已断开');
1526
1533
  },
1527
1534
  onIncomeDanmu: ({ body }) => {
1528
- // 处理消息,只需要UP主名字和消息内容
1529
- const content = `${body.user.uname}:${body.content}`;
1530
1535
  // 保存消息到数组
1531
- currentLiveDanmakuArr.push(content);
1532
- temporaryLiveDanmakuArr.push(content);
1536
+ currentLiveDanmakuArr.push(body.content);
1533
1537
  },
1534
- onIncomeSuperChat: (msg) => {
1535
- console.log(msg.id, msg.body);
1538
+ onIncomeSuperChat: ({ body }) => {
1539
+ // 保存消息到数组
1540
+ currentLiveDanmakuArr.push(body.content);
1541
+ },
1542
+ onGuardBuy: ({ body }) => {
1543
+ // 定义消息
1544
+ const content = `${body.user.uname}加入了大航海(${body.gift_name})`;
1545
+ // 直接发送消息
1546
+ channelIdArrLen > 0 && this.sendMsg(liveGuardBuyPushTargetArr, content);
1536
1547
  },
1537
1548
  onLiveStart: async () => {
1538
- // 获取直播间信息
1539
- const liveRoomInfo = await this.useLiveRoomInfo(ctx, roomId);
1540
- // 获取主播信息
1541
- const masterInfo = await this.useMasterInfo(ctx, liveRoomInfo.uid);
1542
- // 定义下播通知消息
1543
- const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1549
+ // 判断是否已经开播
1550
+ if (liveStatus)
1551
+ return;
1552
+ // 设置开播状态为true
1553
+ liveStatus = true;
1554
+ // 判断是否信息是否获取成功
1555
+ if (!(await useMasterAndLiveRoomInfo())) {
1556
+ // 设置开播状态为false
1557
+ liveStatus = false;
1558
+ // 未获取成功,直接返回
1559
+ return await this.sendPrivateMsg('获取直播间信息失败,推送直播开播卡片失败!');
1560
+ }
1561
+ // 设置开播时间
1562
+ liveTime = liveRoomInfo.live_time;
1563
+ // 定义开播通知语
1564
+ const liveStartMsg = this.config.customLiveStart ? this.config.customLiveStart
1544
1565
  .replace('-name', masterInfo.username)
1545
- .replace('-time', await ctx.gi.getTimeDifference(liveTime)) : null;
1546
- // 更改直播时长
1547
- liveRoomInfo.live_time = liveTime;
1548
- // 推送下播通知
1549
- await this.sendLiveNotifyCard(liveRoomInfo, {
1566
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1567
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1568
+ // 推送开播通知
1569
+ await this.sendLiveNotifyCard({
1550
1570
  username: masterInfo.username,
1551
1571
  userface: masterInfo.userface,
1552
1572
  target,
1553
1573
  data: liveRoomInfo
1554
- }, LiveType.StopBroadcast, liveEndMsg);
1555
- // 关闭定时器
1556
- pushAtTimeTimer();
1557
- // 定时器变量置空
1558
- pushAtTimeTimer = null;
1574
+ }, LiveType.StartBroadcasting, liveStartMsg);
1575
+ // 判断定时器是否已开启
1576
+ if (!pushAtTimeTimer) {
1577
+ // 开始直播,开启定时器
1578
+ pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1579
+ }
1559
1580
  },
1560
1581
  onLiveEnd: async () => {
1561
- // 获取直播间消息
1562
- const liveRoomInfo = await this.useLiveRoomInfo(ctx, roomId);
1563
- // 获取主播信息
1564
- const masterInfo = await this.useMasterInfo(ctx, liveRoomInfo.uid);
1565
- // 设置开播时间
1566
- liveTime = liveRoomInfo.live_time;
1567
- // 开启推送定时器
1568
- pushAtTimeTimer = ctx.setInterval(pushAtTime, 3600 * 1000);
1569
- // 定义开播通知语
1570
- const liveStartMsg = this.config.customLiveStart ? this.config.customLiveStart
1582
+ // 判断是否信息是否获取成功
1583
+ if (!(await useMasterAndLiveRoomInfo())) {
1584
+ // 未获取成功,直接返回
1585
+ return this.sendPrivateMsg('获取直播间信息失败,推送直播下播卡片失败!');
1586
+ }
1587
+ // 更改直播时长
1588
+ liveRoomInfo.live_time = liveTime;
1589
+ // 定义下播播通知语
1590
+ const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1571
1591
  .replace('-name', masterInfo.username)
1572
- .replace('-time', await ctx.gi.getTimeDifference(liveTime))
1573
- .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1592
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime)) : null;
1574
1593
  // 推送通知卡片
1575
- await this.sendLiveNotifyCard(ctx, {
1594
+ await this.sendLiveNotifyCard({
1576
1595
  username: masterInfo.username,
1577
1596
  userface: masterInfo.userface,
1578
1597
  target,
1579
1598
  data: liveRoomInfo
1580
- }, LiveType.StartBroadcasting, liveStartMsg);
1599
+ }, LiveType.StopBroadcast, liveEndMsg);
1600
+ // 关闭定时推送定时器
1601
+ pushAtTimeTimer();
1602
+ // 将推送定时器变量置空
1603
+ pushAtTimeTimer = null;
1604
+ // 发送弹幕词云
1605
+ sendDanmakuWordCloud(getDanmakuWeightRecord());
1606
+ // 将直播状态设置为false
1607
+ liveStatus = false;
1581
1608
  }
1582
1609
  };
1583
1610
  // 启动直播间弹幕监测
1584
- ctx.bl.startLiveRoomListener(roomId, handler, pushOnceEveryTenS);
1611
+ await this.ctx.bl.startLiveRoomListener(roomId, handler);
1612
+ // 判断直播状态
1613
+ if (liveRoomInfo.live_status === 1) {
1614
+ // 设置开播时间
1615
+ liveTime = liveRoomInfo.live_time;
1616
+ // 定义直播中通知消息
1617
+ const liveMsg = this.config.customLive ? this.config.customLive
1618
+ .replace('-name', masterInfo.username)
1619
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1620
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1621
+ // 发送直播通知卡片
1622
+ if (this.config.restartPush) {
1623
+ await this.sendLiveNotifyCard({
1624
+ username: masterInfo.username,
1625
+ userface: masterInfo.userface,
1626
+ target,
1627
+ data: liveRoomInfo
1628
+ }, LiveType.LiveBroadcast, liveMsg);
1629
+ }
1630
+ // 正在直播,开启定时器
1631
+ // 判断定时器是否已开启
1632
+ if (!pushAtTimeTimer) {
1633
+ // 开始直播,开启定时器
1634
+ pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1635
+ }
1636
+ // 设置直播状态为true
1637
+ liveStatus = true;
1638
+ }
1585
1639
  }
1586
1640
  subShow() {
1587
1641
  // 在控制台中显示订阅对象
@@ -1621,7 +1675,7 @@ class ComRegister {
1621
1675
  // 只订阅动态
1622
1676
  return [false, true];
1623
1677
  }
1624
- updateSubNotifier(ctx) {
1678
+ updateSubNotifier() {
1625
1679
  // 更新控制台提示
1626
1680
  if (this.subNotifier)
1627
1681
  this.subNotifier.dispose();
@@ -1640,13 +1694,13 @@ class ComRegister {
1640
1694
  table = (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("p", { children: "\u5F53\u524D\u8BA2\u9605\u5BF9\u8C61\uFF1A" }), (0, jsx_runtime_1.jsx)("ul", { children: subTableArray.map(str => ((0, jsx_runtime_1.jsx)("li", { children: str }))) })] });
1641
1695
  }
1642
1696
  // 设置更新后的提示
1643
- this.subNotifier = ctx.notifier.create(table);
1697
+ this.subNotifier = this.ctx.notifier.create(table);
1644
1698
  }
1645
- async checkIfLoginInfoIsLoaded(ctx) {
1699
+ async checkIfLoginInfoIsLoaded() {
1646
1700
  return new Promise(resolve => {
1647
1701
  const check = () => {
1648
- if (!ctx.ba.getLoginInfoIsLoaded()) {
1649
- ctx.setTimeout(check, 500);
1702
+ if (!this.ctx.ba.getLoginInfoIsLoaded()) {
1703
+ this.ctx.setTimeout(check, 500);
1650
1704
  }
1651
1705
  else {
1652
1706
  resolve('success');
@@ -1655,17 +1709,17 @@ class ComRegister {
1655
1709
  check();
1656
1710
  });
1657
1711
  }
1658
- async subUserInBili(ctx, mid) {
1712
+ async subUserInBili(mid) {
1659
1713
  // 获取关注分组信息
1660
1714
  const checkGroupIsReady = async () => {
1661
1715
  // 判断是否有数据
1662
1716
  if (this.loginDBData.dynamic_group_id === '' || this.loginDBData.dynamic_group_id === null) {
1663
1717
  // 没有数据,没有创建分组,尝试创建分组
1664
- const createGroupData = await ctx.ba.createGroup("订阅");
1718
+ const createGroupData = await this.ctx.ba.createGroup("订阅");
1665
1719
  // 如果分组已创建,则获取分组id
1666
1720
  if (createGroupData.code === 22106) {
1667
1721
  // 分组已存在,拿到之前的分组id
1668
- const allGroupData = await ctx.ba.getAllGroup();
1722
+ const allGroupData = await this.ctx.ba.getAllGroup();
1669
1723
  // 遍历所有分组
1670
1724
  for (const group of allGroupData.data) {
1671
1725
  // 找到订阅分组
@@ -1683,7 +1737,7 @@ class ComRegister {
1683
1737
  return false;
1684
1738
  }
1685
1739
  // 创建成功,保存到数据库
1686
- ctx.database.set('loginBili', 1, { dynamic_group_id: this.loginDBData.dynamic_group_id });
1740
+ this.ctx.database.set('loginBili', 1, { dynamic_group_id: this.loginDBData.dynamic_group_id });
1687
1741
  // 创建成功
1688
1742
  return true;
1689
1743
  }
@@ -1697,7 +1751,7 @@ class ComRegister {
1697
1751
  return { flag: false, msg: '创建分组失败,请尝试重启插件' };
1698
1752
  }
1699
1753
  // 获取分组明细
1700
- const relationGroupDetailData = await ctx.ba.getRelationGroupDetail(this.loginDBData.dynamic_group_id);
1754
+ const relationGroupDetailData = await this.ctx.ba.getRelationGroupDetail(this.loginDBData.dynamic_group_id);
1701
1755
  // 判断分组信息是否获取成功
1702
1756
  if (relationGroupDetailData.code !== 0) {
1703
1757
  if (relationGroupDetailData.code === 22104) {
@@ -1722,7 +1776,7 @@ class ComRegister {
1722
1776
  }
1723
1777
  });
1724
1778
  // 订阅对象
1725
- const subUserData = await ctx.ba.follow(mid);
1779
+ const subUserData = await this.ctx.ba.follow(mid);
1726
1780
  // 判断是否订阅成功
1727
1781
  switch (subUserData.code) {
1728
1782
  case -101: return { flag: false, msg: '账号未登录,请使用指令bili login登录后再进行订阅操作' };
@@ -1735,7 +1789,7 @@ class ComRegister {
1735
1789
  case 22014: // 已关注订阅对象 无需再次关注
1736
1790
  case 0: { // 执行订阅成功
1737
1791
  // 把订阅对象添加到分组中
1738
- const copyUserToGroupData = await ctx.ba.copyUserToGroup(mid, this.loginDBData.dynamic_group_id);
1792
+ const copyUserToGroupData = await this.ctx.ba.copyUserToGroup(mid, this.loginDBData.dynamic_group_id);
1739
1793
  // 判断是否添加成功
1740
1794
  if (copyUserToGroupData.code !== 0) {
1741
1795
  // 添加失败
@@ -1746,12 +1800,10 @@ class ComRegister {
1746
1800
  // 订阅成功
1747
1801
  return { flag: true, msg: '用户订阅成功' };
1748
1802
  }
1749
- async loadSubFromConfig(ctx, subs) {
1803
+ async loadSubFromConfig(subs) {
1750
1804
  for (const sub of subs) {
1751
1805
  // 定义Data
1752
1806
  let data;
1753
- // 定义直播销毁函数
1754
- let liveDispose;
1755
1807
  // 判断是否需要订阅直播
1756
1808
  if (sub.live) {
1757
1809
  // 获取用户信息
@@ -1761,15 +1813,15 @@ class ComRegister {
1761
1813
  for (let i = 0; i < attempts; i++) {
1762
1814
  try {
1763
1815
  // 获取用户信息
1764
- content = await ctx.ba.getUserInfo(sub.uid);
1816
+ content = await this.ctx.ba.getUserInfo(sub.uid);
1765
1817
  // 成功则跳出循环
1766
1818
  break;
1767
1819
  }
1768
1820
  catch (e) {
1769
- this.logger.error('getSubFromDatabase() getUserInfo() 发生了错误,错误为:' + e.message);
1821
+ this.logger.error('loadSubFromConfig() getUserInfo() 发生了错误,错误为:' + e.message);
1770
1822
  if (i === attempts - 1) { // 已尝试三次
1771
1823
  // 发送私聊消息并重启服务
1772
- return await this.sendPrivateMsgAndStopService(ctx);
1824
+ return await this.sendPrivateMsgAndStopService();
1773
1825
  }
1774
1826
  }
1775
1827
  }
@@ -1782,14 +1834,28 @@ class ComRegister {
1782
1834
  // 发送提示
1783
1835
  this.logger.warn(`UID:${sub.uid} 用户没有开通直播间,无法订阅直播!`);
1784
1836
  }
1837
+ //
1838
+ const liveDetectModeSelector = {
1839
+ API: async () => {
1840
+ // 判断是否已开启直播检测
1841
+ if (!this.liveDispose) { // 未开启直播检测
1842
+ // 开启直播检测并保存销毁函数
1843
+ this.liveDispose = await this.liveDetectWithAPI();
1844
+ }
1845
+ },
1846
+ WS: async () => {
1847
+ // 连接到服务器
1848
+ await this.liveDetectWithListener(data.live_room.roomid, sub.target);
1849
+ }
1850
+ };
1785
1851
  // 判断是否订阅直播
1786
1852
  if (sub.live) {
1787
- // 订阅直播
1788
- this.liveDetectWithListener(ctx, data.live_room.roomid, sub.target);
1853
+ // 启动直播监测
1854
+ await liveDetectModeSelector[this.config.liveDetectMode]();
1789
1855
  }
1790
1856
  }
1791
1857
  // 在B站中订阅该对象
1792
- const subInfo = await this.subUserInBili(ctx, sub.uid);
1858
+ const subInfo = await this.subUserInBili(sub.uid);
1793
1859
  // 判断订阅是否成功
1794
1860
  if (!subInfo.flag)
1795
1861
  this.logger.warn(subInfo.msg);
@@ -1801,25 +1867,13 @@ class ComRegister {
1801
1867
  target: sub.target,
1802
1868
  platform: '',
1803
1869
  live: sub.live,
1804
- dynamic: sub.dynamic,
1805
- liveDispose
1870
+ dynamic: sub.dynamic
1806
1871
  });
1807
1872
  }
1808
1873
  }
1809
- async loadSubFromDatabase(ctx) {
1810
- // 判断登录信息是否已加载完毕
1811
- await this.checkIfLoginInfoIsLoaded(ctx);
1812
- // 如果未登录,则直接返回
1813
- if (!(await this.checkIfIsLogin(ctx))) {
1814
- // log
1815
- this.logger.info(`账号未登录,请登录`);
1816
- return;
1817
- }
1818
- // 已存在订阅管理对象,不再进行订阅操作
1819
- if (this.subManager.length !== 0)
1820
- return;
1874
+ async loadSubFromDatabase() {
1821
1875
  // 从数据库中获取数据
1822
- const subData = await ctx.database.get('bilibili', { id: { $gt: 0 } });
1876
+ const subData = await this.ctx.database.get('bilibili', { id: { $gt: 0 } });
1823
1877
  // 定义变量:订阅直播数
1824
1878
  let liveSubNum = 0;
1825
1879
  // 循环遍历
@@ -1827,14 +1881,14 @@ class ComRegister {
1827
1881
  // 判断是否存在没有任何订阅的数据
1828
1882
  if (!sub.dynamic && !sub.live) { // 存在未订阅任何项目的数据
1829
1883
  // 删除该条数据
1830
- ctx.database.remove('bilibili', { id: sub.id });
1884
+ this.ctx.database.remove('bilibili', { id: sub.id });
1831
1885
  // log
1832
1886
  this.logger.warn(`UID:${sub.uid} 该条数据没有任何订阅数据,自动取消订阅`);
1833
1887
  // 跳过下面的步骤
1834
1888
  continue;
1835
1889
  }
1836
1890
  // 判断用户是否在B站中订阅了
1837
- const subUserData = await this.subUserInBili(ctx, sub.uid);
1891
+ const subUserData = await this.subUserInBili(sub.uid);
1838
1892
  // 判断是否订阅
1839
1893
  if (!subUserData.flag) {
1840
1894
  // log
@@ -1842,7 +1896,7 @@ class ComRegister {
1842
1896
  // 发送私聊消息
1843
1897
  await this.sendPrivateMsg(`UID:${sub.uid} ${subUserData.msg},自动取消订阅`);
1844
1898
  // 删除该条数据
1845
- await ctx.database.remove('bilibili', { id: sub.id });
1899
+ await this.ctx.database.remove('bilibili', { id: sub.id });
1846
1900
  // 跳过下面的步骤
1847
1901
  continue;
1848
1902
  }
@@ -1855,7 +1909,7 @@ class ComRegister {
1855
1909
  for (let i = 0; i < attempts; i++) {
1856
1910
  try {
1857
1911
  // 获取用户信息
1858
- content = await ctx.ba.getUserInfo(sub.uid);
1912
+ content = await this.ctx.ba.getUserInfo(sub.uid);
1859
1913
  // 成功则跳出循环
1860
1914
  break;
1861
1915
  }
@@ -1863,7 +1917,7 @@ class ComRegister {
1863
1917
  this.logger.error('getSubFromDatabase() getUserInfo() 发生了错误,错误为:' + e.message);
1864
1918
  if (i === attempts - 1) { // 已尝试三次
1865
1919
  // 发送私聊消息并重启服务
1866
- return await this.sendPrivateMsgAndStopService(ctx);
1920
+ return await this.sendPrivateMsgAndStopService();
1867
1921
  }
1868
1922
  }
1869
1923
  }
@@ -1872,7 +1926,7 @@ class ComRegister {
1872
1926
  // 定义函数删除数据和发送提示
1873
1927
  const deleteSub = async () => {
1874
1928
  // 从数据库删除该条数据
1875
- await ctx.database.remove('bilibili', { id: sub.id });
1929
+ await this.ctx.database.remove('bilibili', { id: sub.id });
1876
1930
  // 给用户发送提示
1877
1931
  await this.sendPrivateMsg(`UID:${sub.uid} 数据库内容被篡改,已取消对该UP主的订阅`);
1878
1932
  };
@@ -1918,43 +1972,57 @@ class ComRegister {
1918
1972
  dynamic: sub.dynamic === 1 ? true : false,
1919
1973
  liveDispose: null
1920
1974
  };
1975
+ // 定义直播模式监测器
1976
+ const liveDetectModeSelector = {
1977
+ API: async () => {
1978
+ // 判断是否已开启直播检测
1979
+ if (!this.liveDispose) { // 未开启直播检测
1980
+ // 开启直播检测并保存销毁函数
1981
+ this.liveDispose = await this.liveDetectWithAPI();
1982
+ }
1983
+ },
1984
+ WS: async () => {
1985
+ // 判断订阅直播数是否超过限制
1986
+ if (!this.config.unlockSubLimits && liveSubNum >= 3) {
1987
+ // 将live改为false
1988
+ subManagerItem.live = false;
1989
+ // log
1990
+ this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1991
+ // 发送错误消息
1992
+ await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1993
+ }
1994
+ else {
1995
+ // 直播订阅数+1
1996
+ liveSubNum++;
1997
+ // 订阅直播,开始循环检测
1998
+ await this.liveDetectWithListener(sub.room_id, target);
1999
+ }
2000
+ }
2001
+ };
1921
2002
  // 判断是否订阅直播
1922
2003
  if (sub.live) {
1923
- // 判断订阅直播数是否超过限制
1924
- if (!this.config.unlockSubLimits && liveSubNum >= 3) {
1925
- // 将live改为false
1926
- subManagerItem.live = false;
1927
- // log
1928
- this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1929
- // 发送错误消息
1930
- await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1931
- }
1932
- else {
1933
- // 直播订阅数+1
1934
- liveSubNum++;
1935
- // 订阅直播,开始循环检测
1936
- this.liveDetectWithListener(ctx, sub.room_id, target);
1937
- }
2004
+ // 启动直播监测
2005
+ await liveDetectModeSelector[this.config.liveDetectMode]();
1938
2006
  }
1939
2007
  // 保存新订阅对象
1940
2008
  this.subManager.push(subManagerItem);
1941
2009
  }
1942
2010
  }
1943
- checkIfDynamicDetectIsNeeded(ctx) {
2011
+ checkIfDynamicDetectIsNeeded() {
1944
2012
  // 检查是否有订阅对象需要动态监测
1945
2013
  if (this.subManager.some(sub => sub.dynamic))
1946
- this.enableDynamicDetect(ctx);
2014
+ this.enableDynamicDetect();
1947
2015
  }
1948
- enableDynamicDetect(ctx) {
2016
+ enableDynamicDetect() {
1949
2017
  // 开始动态监测
1950
2018
  if (this.config.dynamicDebugMode) {
1951
- this.dynamicDispose = ctx.setInterval(this.debug_dynamicDetect(ctx), this.config.dynamicLoopTime * 1000);
2019
+ this.dynamicDispose = this.ctx.setInterval(this.debug_dynamicDetect(), this.config.dynamicLoopTime * 1000);
1952
2020
  }
1953
2021
  else {
1954
- this.dynamicDispose = ctx.setInterval(this.dynamicDetect(ctx), this.config.dynamicLoopTime * 1000);
2022
+ this.dynamicDispose = this.ctx.setInterval(this.dynamicDetect(), this.config.dynamicLoopTime * 1000);
1955
2023
  }
1956
2024
  }
1957
- unsubSingle(ctx, id /* UID或RoomId */, type /* 0取消Live订阅,1取消Dynamic订阅 */) {
2025
+ unsubSingle(id /* UID或RoomId */, type /* 0取消Live订阅,1取消Dynamic订阅 */) {
1958
2026
  // 定义返回消息
1959
2027
  let msg;
1960
2028
  // 定义方法:检查是否没有任何订阅
@@ -1964,7 +2032,7 @@ class ComRegister {
1964
2032
  // 从管理对象中移除
1965
2033
  this.subManager.splice(index, 1);
1966
2034
  // 从数据库中删除
1967
- ctx.database.remove('bilibili', [this.subManager[index].id]);
2035
+ this.ctx.database.remove('bilibili', [this.subManager[index].id]);
1968
2036
  // num--
1969
2037
  this.num--;
1970
2038
  // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
@@ -1983,10 +2051,18 @@ class ComRegister {
1983
2051
  return msg;
1984
2052
  }
1985
2053
  // 取消订阅
1986
- if (sub.live)
1987
- sub.liveDispose();
1988
- sub.liveDispose = null;
1989
2054
  sub.live = false;
2055
+ // 判断直播检测方式
2056
+ switch (this.config.liveDetectMode) {
2057
+ case 'API': {
2058
+ msg = '请手动删除订阅,并重启插件';
2059
+ break;
2060
+ }
2061
+ case 'WS': {
2062
+ // 取消直播监听
2063
+ this.ctx.bl.closeListener(sub.roomId);
2064
+ }
2065
+ }
1990
2066
  // 如果没有对这个UP的任何订阅,则移除
1991
2067
  if (checkIfNoSubExist(sub)) {
1992
2068
  // 从管理对象中移除
@@ -1994,7 +2070,7 @@ class ComRegister {
1994
2070
  return '已取消订阅该用户';
1995
2071
  }
1996
2072
  // 更新数据库
1997
- ctx.database.upsert('bilibili', [{
2073
+ this.ctx.database.upsert('bilibili', [{
1998
2074
  id: +`${sub.id}`,
1999
2075
  live: 0
2000
2076
  }]);
@@ -2021,7 +2097,7 @@ class ComRegister {
2021
2097
  return '已取消订阅该用户';
2022
2098
  }
2023
2099
  // 更新数据库
2024
- ctx.database.upsert('bilibili', [{
2100
+ this.ctx.database.upsert('bilibili', [{
2025
2101
  id: sub.id,
2026
2102
  dynamic: 0
2027
2103
  }]);
@@ -2031,7 +2107,7 @@ class ComRegister {
2031
2107
  }
2032
2108
  finally {
2033
2109
  // 执行完该方法后,保证执行一次updateSubNotifier()
2034
- this.updateSubNotifier(ctx);
2110
+ this.updateSubNotifier();
2035
2111
  }
2036
2112
  }
2037
2113
  checkIfUserIsTheLastOneWhoSubDyn() {
@@ -2041,15 +2117,21 @@ class ComRegister {
2041
2117
  this.dynamicDispose = null;
2042
2118
  }
2043
2119
  }
2044
- unsubAll(ctx, uid) {
2120
+ unsubAll(uid) {
2045
2121
  this.subManager.filter(sub => sub.uid === uid).map(async (sub, i) => {
2046
- // 取消全部订阅 执行dispose方法,销毁定时器
2047
- if (sub.live)
2048
- await this.subManager[i].liveDispose();
2049
2122
  // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
2050
2123
  this.checkIfUserIsTheLastOneWhoSubDyn();
2124
+ switch (this.config.liveDetectMode) {
2125
+ case "API": {
2126
+ break;
2127
+ }
2128
+ case "WS": {
2129
+ // 停止直播检测
2130
+ this.ctx.bl.closeListener(sub.roomId);
2131
+ }
2132
+ }
2051
2133
  // 从数据库中删除订阅
2052
- await ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
2134
+ await this.ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
2053
2135
  // 将该订阅对象从订阅管理对象中移除
2054
2136
  this.subManager.splice(i, 1);
2055
2137
  // id--
@@ -2057,13 +2139,13 @@ class ComRegister {
2057
2139
  // 发送成功通知
2058
2140
  this.sendPrivateMsg(`UID:${uid},已取消订阅该用户`);
2059
2141
  // 更新控制台提示
2060
- this.updateSubNotifier(ctx);
2142
+ this.updateSubNotifier();
2061
2143
  });
2062
2144
  }
2063
- async checkIfIsLogin(ctx) {
2064
- if ((await ctx.database.get('loginBili', 1)).length !== 0) { // 数据库中有数据
2145
+ async checkIfIsLogin() {
2146
+ if ((await this.ctx.database.get('loginBili', 1)).length !== 0) { // 数据库中有数据
2065
2147
  // 检查cookie中是否有值
2066
- if (ctx.ba.getCookies() !== '[]') { // 有值说明已登录
2148
+ if (this.ctx.ba.getCookies() !== '[]') { // 有值说明已登录
2067
2149
  return true;
2068
2150
  }
2069
2151
  }
@@ -2081,6 +2163,7 @@ class ComRegister {
2081
2163
  channelId: koishi_1.Schema.string().description('频道/群组号'),
2082
2164
  dynamic: koishi_1.Schema.boolean().description('该频道/群组是否推送动态信息'),
2083
2165
  live: koishi_1.Schema.boolean().description('该频道/群组是否推送直播通知'),
2166
+ liveGuardBuy: koishi_1.Schema.boolean().description('该频道/群组是否推送弹幕消息'),
2084
2167
  atAll: koishi_1.Schema.boolean().description('推送开播通知时是否艾特全体成员')
2085
2168
  })).description('频道/群组信息'),
2086
2169
  platform: koishi_1.Schema.string().description('推送平台')
@@ -2094,7 +2177,10 @@ class ComRegister {
2094
2177
  }),
2095
2178
  unlockSubLimits: koishi_1.Schema.boolean().required(),
2096
2179
  automaticResend: koishi_1.Schema.boolean().required(),
2097
- changeMasterInfoApi: koishi_1.Schema.boolean().required(),
2180
+ liveDetectMode: koishi_1.Schema.union([
2181
+ koishi_1.Schema.const('API'),
2182
+ koishi_1.Schema.const('WS')
2183
+ ]).required(),
2098
2184
  restartPush: koishi_1.Schema.boolean().required(),
2099
2185
  pushTime: koishi_1.Schema.number().required(),
2100
2186
  liveLoopTime: koishi_1.Schema.number().default(10),
@@ -2103,7 +2189,6 @@ class ComRegister {
2103
2189
  customLiveEnd: koishi_1.Schema.string().required(),
2104
2190
  dynamicUrl: koishi_1.Schema.boolean().required(),
2105
2191
  dynamicLoopTime: koishi_1.Schema.number().default(60),
2106
- dynamicCheckNumber: koishi_1.Schema.number().required(),
2107
2192
  filter: koishi_1.Schema.object({
2108
2193
  enable: koishi_1.Schema.boolean(),
2109
2194
  notify: koishi_1.Schema.boolean(),