koishi-plugin-bilibili-notify 2.0.0-alpha.8 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,14 +18,25 @@ var LiveType;
18
18
  LiveType[LiveType["StopBroadcast"] = 3] = "StopBroadcast";
19
19
  })(LiveType || (LiveType = {}));
20
20
  class ComRegister {
21
- static inject = ['ba', 'gi', 'database', 'sm'];
21
+ // 必须服务
22
+ static inject = ['ba', 'gi', 'database', 'bl', 'sm'];
23
+ // 定义数组:QQ相关bot
22
24
  qqRelatedBotList = ['qq', 'onebot', 'red', 'satori', 'chronocat'];
25
+ // logger
23
26
  logger;
27
+ // config
24
28
  config;
29
+ // 登录定时器
25
30
  loginTimer;
31
+ // 订阅数量
26
32
  num = 0;
33
+ // 重启次数
27
34
  rebootCount = 0;
35
+ // 订阅通知
28
36
  subNotifier;
37
+ // Context
38
+ ctx;
39
+ // 订阅管理器
29
40
  subManager = [];
30
41
  // 检查登录数据库是否有数据
31
42
  loginDBData;
@@ -37,56 +48,11 @@ class ComRegister {
37
48
  sendMsgFunc;
38
49
  // 构造函数
39
50
  constructor(ctx, config) {
40
- this.logger = ctx.logger('cr');
41
- this.config = config;
42
- // 拿到私人机器人实例
43
- this.privateBot = ctx.bots.find(bot => bot.platform === config.master.platform);
44
- if (!this.privateBot) {
45
- ctx.notifier.create({
46
- content: '您未配置私人机器人,将无法向您推送机器人状态!'
47
- });
48
- this.logger.error('您未配置私人机器人,将无法向您推送机器人状态!');
49
- }
50
- // 检查登录数据库是否有数据
51
- ctx.database.get('loginBili', 1, ['dynamic_group_id']).then(data => this.loginDBData = data[0]);
52
- // 从数据库获取订阅
53
- this.getSubFromDatabase(ctx);
54
- // 判断消息发送方式
55
- if (config.automaticResend) {
56
- this.sendMsgFunc = async (bot, guild, content) => {
57
- // 多次尝试发送消息
58
- const attempts = 3;
59
- for (let i = 0; i < attempts; i++) {
60
- try {
61
- // 发送消息
62
- await bot.sendMessage(guild, content);
63
- // 防止消息发送速度过快被忽略
64
- await ctx.sleep(500);
65
- // 成功发送消息,跳出循环
66
- break;
67
- }
68
- catch (e) {
69
- if (i === attempts - 1) { // 已尝试三次
70
- this.logger.error(`发送群组ID:${guild}消息失败!原因: ` + e.message);
71
- console.log(e);
72
- this.sendPrivateMsg(`发送群组ID:${guild}消息失败,请查看日志`);
73
- }
74
- }
75
- }
76
- };
77
- }
78
- else {
79
- this.sendMsgFunc = async (bot, guild, content) => {
80
- try {
81
- // 发送消息
82
- await bot.sendMessage(guild, content);
83
- }
84
- catch (e) {
85
- this.logger.error(`发送群组ID:${guild}消息失败!原因: ` + e.message);
86
- await this.sendPrivateMsg(`发送群组ID:${guild}消息失败,请查看日志`);
87
- }
88
- };
89
- }
51
+ // ctx赋值给类属性
52
+ this.ctx = ctx;
53
+ // 初始化
54
+ this.init(config);
55
+ // 注册指令
90
56
  const statusCom = ctx.command('status', '插件状态相关指令', { permissions: ['authority:5'] });
91
57
  statusCom.subcommand('.dyn', '查看动态监测运行状态')
92
58
  .usage('查看动态监测运行状态')
@@ -198,7 +164,7 @@ class ComRegister {
198
164
  // 销毁定时器
199
165
  this.loginTimer();
200
166
  // 订阅之前的订阅
201
- await this.getSubFromDatabase(ctx);
167
+ await this.loadSubFromDatabase();
202
168
  // 清除控制台通知
203
169
  ctx.ba.disposeNotifier();
204
170
  // 发送成功登录推送
@@ -236,17 +202,14 @@ class ComRegister {
236
202
  // 取消单个订阅
237
203
  if (options.live || options.dynamic) {
238
204
  if (options.live)
239
- await session.send(this.unsubSingle(ctx, sub.roomId, 0)); /* 0为取消订阅Live */
205
+ await session.send(this.unsubSingle(sub.roomId, 0)); /* 0为取消订阅Live */
240
206
  if (options.dynamic)
241
- await session.send(this.unsubSingle(ctx, sub.uid, 1)); /* 1为取消订阅Dynamic */
207
+ await session.send(this.unsubSingle(sub.uid, 1)); /* 1为取消订阅Dynamic */
242
208
  // 将存在flag设置为true
243
209
  exist = true;
244
210
  // 结束循环
245
211
  return;
246
212
  }
247
- // 取消全部订阅 执行dispose方法,销毁定时器
248
- if (sub.live)
249
- this.subManager[i].liveDispose();
250
213
  // 从数据库中删除订阅
251
214
  await ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
252
215
  // 将该订阅对象从订阅管理对象中移除
@@ -265,16 +228,11 @@ class ComRegister {
265
228
  // id--
266
229
  this.num--;
267
230
  // 判断是否还有动态订阅
268
- if (this.dynamicDispose && !this.subManager.find((sub) => sub.dynamic === true)) { // 没有动态订阅
269
- // 将动态检测关闭
270
- this.dynamicDispose();
271
- // 将动态监测置为空
272
- this.dynamicDispose = null;
273
- }
231
+ this.checkIfUserIsTheLastOneWhoSubDyn();
274
232
  // 发送成功通知
275
233
  await session.send('已取消订阅该用户');
276
234
  // 更新控制台提示
277
- this.updateSubNotifier(ctx);
235
+ this.updateSubNotifier();
278
236
  // 将存在flag设置为true
279
237
  exist = true;
280
238
  }
@@ -292,20 +250,21 @@ class ComRegister {
292
250
  return subTable;
293
251
  });
294
252
  biliCom
295
- .subcommand('.sub <mid:string>', '订阅用户动态和直播通知')
296
- .option('multiplatform', '-m <value:string>', { 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]+)*\.[A-Za-z0-9]+(?:,[A-Za-z0-9]+)*)*$/ })
253
+ .subcommand('.sub <mid:string> [...groupId:string]', '订阅用户动态和直播通知')
254
+ .option('multiplatform', '-m <value:string>', { 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]+))*$/ })
297
255
  .option('live', '-l')
298
256
  .option('dynamic', '-d')
299
- .usage('订阅用户动态和直播通知,若需要订阅直播请加上-l,需要订阅动态则加上-d。若没有加任何参数,之后会向你单独询问,尖括号中为必选参数,中括号为可选参数,目标群号若不填,则默认为当前群聊')
300
- .example('bili sub 1194210119 目标QQ群号(实验性) -l -d 订阅UID为1194210119的UP主的动态和直播')
301
- .action(async ({ session, options }, mid) => {
257
+ .option('atAll', '-a')
258
+ .usage('订阅用户动态和直播通知,若需要订阅直播请加上-l,需要订阅动态则加上-d')
259
+ .example('bili sub 1194210119 目标群号或频道号 -l -d 订阅UID为1194210119的UP主的动态和直播')
260
+ .action(async ({ session, options }, mid, ...groupId) => {
302
261
  this.logger.info('调用bili.sub指令');
303
262
  // 先判断是否订阅直播,再判断是否解锁订阅限制,最后判断直播订阅是否已超三个
304
263
  if (options.live && !this.config.unlockSubLimits && (this.subManager.reduce((acc, cur) => acc + (cur.live ? 1 : 0), 0) >= 3)) {
305
264
  return '直播订阅已达上限,请取消部分直播订阅后再进行订阅';
306
265
  }
307
266
  // 检查是否登录
308
- if (!(await this.checkIfIsLogin(ctx))) {
267
+ if (!(await this.checkIfIsLogin())) {
309
268
  // 未登录直接返回
310
269
  return '请使用指令bili login登录后再进行订阅操作';
311
270
  }
@@ -313,71 +272,103 @@ class ComRegister {
313
272
  if (!mid)
314
273
  return '请输入用户uid';
315
274
  // 订阅对象
316
- const subUserData = await this.subUserInBili(ctx, mid);
275
+ const subUserData = await this.subUserInBili(mid);
317
276
  // 判断是否订阅对象存在
318
277
  if (!subUserData.flag)
319
278
  return '订阅对象失败,请稍后重试!';
320
- let target;
321
- // 判断是否使用多平台功能
322
- if (options.multiplatform) {
323
- // 分割字符串,赋值给target
324
- target = this.splitMultiPlatformStr(options.multiplatform);
279
+ // 定义目标变量
280
+ let target = [];
281
+ // 判断是否使用了多群组推送
282
+ if (groupId.length > 0) {
283
+ // 定义channelIdArr
284
+ const channelIdArr = [];
285
+ // 遍历输入的群组
286
+ groupId.forEach(group => {
287
+ channelIdArr.push({
288
+ channelId: group,
289
+ dynamic: true,
290
+ live: true,
291
+ liveDanmaku: false,
292
+ atAll: options.atAll
293
+ });
294
+ });
295
+ target.push({
296
+ channelIdArr,
297
+ platform: session.event.platform
298
+ });
325
299
  }
326
- if (target) {
327
- target.forEach(async ({ idArr, platform }, index) => {
328
- if (idArr.length > 0) { // 输入了推送群号或频道号
329
- // 拿到对应的bot
330
- const bot = this.getBot(ctx, platform);
331
- // 判断是否配置了对应平台的机器人
332
- if (!ctx.bots.some(bot => bot.platform === platform)) {
333
- await session.send('您未配置对应平台的机器人,不能在该平台进行订阅操作');
334
- }
335
- // 判断是否需要加入的群全部推送
336
- if (idArr[0] !== 'all') {
337
- // 定义满足条件的群组数组
338
- const targetArr = [];
339
- // 获取机器人加入的群组
340
- const guildList = await bot.getGuildList();
341
- // 遍历群组
342
- for (const guild of guildList.data) {
343
- // 获取频道
344
- const channelList = await bot.getChannelList(guild.id);
345
- // 判断群号是否符合条件
346
- for (const id of idArr) {
347
- // 判断是否机器人加入了该群
348
- if (channelList.data.some(channel => channel.id === id)) { // 机器人加入了该群
349
- // 保存到数组
350
- targetArr.push(id);
351
- // 继续下一个循环
352
- continue;
300
+ else {
301
+ // 判断是否使用多平台功能
302
+ if (options.multiplatform) {
303
+ // 分割字符串,赋值给target
304
+ target = this.splitMultiPlatformStr(options.multiplatform);
305
+ }
306
+ // 判断是否使用了多平台
307
+ if (target.length > 0) {
308
+ for (const [index, { channelIdArr, platform }] of target.entries()) {
309
+ if (channelIdArr.length > 0) { // 输入了推送群号或频道号
310
+ // 拿到对应的bot
311
+ const bot = this.getBot(platform);
312
+ // 判断是否配置了对应平台的机器人
313
+ if (!ctx.bots.some(bot => bot.platform === platform)) {
314
+ // 发送提示消息
315
+ await session.send('您未配置对应平台的机器人,不能在该平台进行订阅操作');
316
+ // 直接返回
317
+ return;
318
+ }
319
+ // 判断是否需要加入的群全部推送
320
+ if (channelIdArr[0].channelId !== 'all') {
321
+ // 定义满足条件的群组数组
322
+ const targetArr = [];
323
+ // 获取机器人加入的群组
324
+ const guildList = await bot.getGuildList();
325
+ // 遍历target数组
326
+ for (const channelId of channelIdArr) {
327
+ // 定义是否加入群组标志
328
+ let flag = false;
329
+ // 遍历群组
330
+ for (const guild of guildList.data) {
331
+ // 获取频道列表
332
+ const channelList = await bot.getChannelList(guild.id);
333
+ // 判断机器人是否加入群聊或频道
334
+ if (channelList.data.some(channel => channel.id === channelId.channelId)) {
335
+ // 加入群聊或频道
336
+ targetArr.push(channelId);
337
+ // 设置标志位为true
338
+ flag = true;
339
+ // 结束循环
340
+ break;
341
+ }
342
+ }
343
+ if (!flag) {
344
+ // 不满足条件发送错误提示
345
+ await session.send(`您的机器未加入${channelId.channelId},无法对该群或频道进行推送`);
353
346
  }
354
- // 不满足条件发送错误提示
355
- await session.send(`您的机器未加入${id},无法对该群或频道进行推送`);
356
347
  }
348
+ // 判断targetArr是否为空
349
+ if (target.length === 0) {
350
+ // 为空则默认为当前环境
351
+ target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, liveDanmaku: false, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
352
+ // 没有满足条件的群组或频道
353
+ await session.send('没有满足条件的群组或频道,默认订阅到当前聊天环境');
354
+ }
355
+ // 将符合条件的群组添加到target中
356
+ target[index].channelIdArr = targetArr;
357
357
  }
358
- // 判断targetArr是否为空
359
- if (targetArr.length === 0) {
360
- // 为空则默认为当前环境
361
- target = [{ idArr: [session.event.channel.id], platform: session.event.platform }];
362
- // 没有满足条件的群组或频道
363
- await session.send('没有满足条件的群组或频道,默认订阅到当前聊天环境');
364
- }
365
- // 将符合条件的群组添加到target中
366
- target[index].idArr = targetArr;
358
+ // 如果为all则全部推送,不需要进行处理
359
+ }
360
+ else {
361
+ // 未填写群号或频道号,默认为当前环境
362
+ target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, liveDanmaku: false, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
363
+ // 发送提示消息
364
+ await session.send('没有填写群号或频道号,默认订阅到当前聊天环境');
367
365
  }
368
- // 如果为all则全部推送,不需要进行修改
369
- }
370
- else {
371
- // 未填写群号或频道号,默认为当前环境
372
- target = [{ idArr: [session.event.channel.id], platform: session.event.platform }];
373
- // 发送提示消息
374
- await session.send('没有填写群号或频道号,默认订阅到当前聊天环境');
375
366
  }
376
- });
377
- }
378
- else {
379
- // 用户直接订阅,将当前环境赋值给target
380
- target = [{ idArr: [session.event.channel.id], platform: session.event.platform }];
367
+ }
368
+ else {
369
+ // 用户直接订阅,将当前环境赋值给target
370
+ target = [{ channelIdArr: [{ channelId: session.event.channel.id, dynamic: true, live: true, liveDanmaku: false, atAll: options.atAll ? options.atAll : false }], platform: session.event.platform }];
371
+ }
381
372
  }
382
373
  // 定义外围变量
383
374
  let content;
@@ -446,12 +437,10 @@ class ComRegister {
446
437
  this.logger.error('bili sub指令 getMasterInfo() 发生了错误,错误为:' + e.message);
447
438
  return '订阅出错啦,请重试';
448
439
  }
449
- // 定义live销毁函数
450
- let liveDispose;
451
440
  // 订阅直播
452
441
  if (liveMsg) {
453
- // 开始循环检测
454
- liveDispose = ctx.setInterval(this.liveDetect(ctx, roomId, target), config.liveLoopTime * 1000);
442
+ // 连接到服务器
443
+ this.liveDetectWithListener(roomId, target);
455
444
  // 发送订阅消息通知
456
445
  await session.send(`订阅${userData.info.uname}直播通知`);
457
446
  }
@@ -459,13 +448,7 @@ class ComRegister {
459
448
  if (dynamicMsg) {
460
449
  // 判断是否开启动态监测
461
450
  if (!this.dynamicDispose) {
462
- // 开启动态监测
463
- if (this.config.dynamicDebugMode) {
464
- this.dynamicDispose = ctx.setInterval(this.debug_dynamicDetect(ctx), config.dynamicLoopTime * 1000);
465
- }
466
- else {
467
- this.dynamicDispose = ctx.setInterval(this.dynamicDetect(ctx), config.dynamicLoopTime * 1000);
468
- }
451
+ this.enableDynamicDetect();
469
452
  }
470
453
  // 发送订阅消息通知
471
454
  await session.send(`订阅${userData.info.uname}动态通知`);
@@ -475,7 +458,6 @@ class ComRegister {
475
458
  uid: mid,
476
459
  room_id: roomId,
477
460
  dynamic: dynamicMsg ? 1 : 0,
478
- video: 1,
479
461
  live: liveMsg ? 1 : 0,
480
462
  target: JSON.stringify(target),
481
463
  platform: session.event.platform,
@@ -492,28 +474,10 @@ class ComRegister {
492
474
  platform: session.event.platform,
493
475
  live: liveMsg,
494
476
  dynamic: dynamicMsg,
495
- liveDispose
496
477
  });
497
478
  // 新增订阅展示到控制台
498
- this.updateSubNotifier(ctx);
479
+ this.updateSubNotifier();
499
480
  });
500
- /* biliCom
501
- .subcommand('.live <roomId:string> <...guildId:string>', '订阅主播开播通知', { hidden: true })
502
- .usage('订阅主播开播通知')
503
- .example('bili live 26316137 订阅房间号为26316137的直播间')
504
- .action(async (_, roomId, ...guildId) => {
505
- this.logger.info('调用bili.live指令')
506
- // 如果room_id为空则返回
507
- if (!roomId) return `${roomId}非法调用 dynamic 指令` // 订阅主播房间号不能为空
508
- if (!guildId) return `${roomId}非法调用 dynamic 指令` // 目标群组或频道不能为空
509
- // 要订阅的对象不在订阅管理对象中,直接返回
510
- const index = this.subManager.findIndex(sub => sub.roomId === roomId)
511
- if (index === -1) return '请勿直接调用该指令'
512
- // 开始循环检测
513
- const dispose = ctx.setInterval(this.liveDetect(ctx, roomId, guildId, this.subManager[index].platform), config.liveLoopTime * 1000)
514
- // 保存销毁函数
515
- this.subManager[index].liveDispose = dispose
516
- }) */
517
481
  biliCom
518
482
  .subcommand('.status <roomId:string>', '查询主播当前直播状态', { hidden: true })
519
483
  .usage('查询主播当前直播状态')
@@ -568,14 +532,78 @@ class ComRegister {
568
532
  await session.send('已发送消息,如未收到则说明您的机器人不支持发送私聊消息或您的信息填写有误');
569
533
  });
570
534
  }
535
+ async init(config) {
536
+ // 设置logger
537
+ this.logger = this.ctx.logger('cr');
538
+ // 将config设置给类属性
539
+ this.config = config;
540
+ // 拿到私人机器人实例
541
+ this.privateBot = this.ctx.bots.find(bot => bot.platform === config.master.platform);
542
+ if (!this.privateBot) {
543
+ this.ctx.notifier.create({
544
+ content: '您未配置私人机器人,将无法向您推送机器人状态!'
545
+ });
546
+ this.logger.error('您未配置私人机器人,将无法向您推送机器人状态!');
547
+ }
548
+ // 判断消息发送方式
549
+ if (config.automaticResend) {
550
+ this.sendMsgFunc = async (bot, channelId, content) => {
551
+ // 多次尝试发送消息
552
+ const attempts = 3;
553
+ for (let i = 0; i < attempts; i++) {
554
+ try {
555
+ // 发送消息
556
+ await bot.sendMessage(channelId, content);
557
+ // 防止消息发送速度过快被忽略
558
+ await this.ctx.sleep(500);
559
+ // 成功发送消息,跳出循环
560
+ break;
561
+ }
562
+ catch (e) {
563
+ if (i === attempts - 1) { // 已尝试三次
564
+ this.logger.error(`发送群组ID:${channelId}消息失败!原因: ` + e.message);
565
+ console.log(e);
566
+ this.sendPrivateMsg(`发送群组ID:${channelId}消息失败,请查看日志`);
567
+ }
568
+ }
569
+ }
570
+ };
571
+ }
572
+ else {
573
+ this.sendMsgFunc = async (bot, guild, content) => {
574
+ try {
575
+ // 发送消息
576
+ await bot.sendMessage(guild, content);
577
+ }
578
+ catch (e) {
579
+ this.logger.error(`发送群组ID:${guild}消息失败!原因: ` + e.message);
580
+ await this.sendPrivateMsg(`发送群组ID:${guild}消息失败,请查看日志`);
581
+ }
582
+ };
583
+ }
584
+ // 检查登录数据库是否有数据
585
+ this.loginDBData = (await this.ctx.database.get('loginBili', 1, ['dynamic_group_id']))[0];
586
+ // 从配置获取订阅
587
+ config.sub && await this.loadSubFromConfig(config.sub);
588
+ // 从数据库获取订阅
589
+ await this.loadSubFromDatabase();
590
+ // 检查是否需要动态监测
591
+ this.checkIfDynamicDetectIsNeeded();
592
+ // 在控制台中显示订阅对象
593
+ this.updateSubNotifier();
594
+ }
571
595
  splitMultiPlatformStr(str) {
572
596
  return str.split(';').map(cv => cv.split('.')).map(([idStr, platform]) => {
573
- const idArr = idStr.split(',');
574
- return { idArr, platform };
597
+ const channelIdArr = idStr.split(',').map(id => {
598
+ const atAll = /@$/.test(id); // 使用正则表达式检查 id 是否以 @ 结尾
599
+ const channelId = atAll ? id.slice(0, -1) : id; // 去除末尾的 @
600
+ return { channelId, dynamic: true, live: true, liveDanmaku: false, atAll };
601
+ });
602
+ return { channelIdArr, platform };
575
603
  });
576
604
  }
577
- getBot(ctx, pf) {
578
- return ctx.bots.find(bot => bot.platform === pf);
605
+ getBot(pf) {
606
+ return this.ctx.bots.find(bot => bot.platform === pf);
579
607
  }
580
608
  async sendPrivateMsg(content) {
581
609
  if (this.config.master.enable) {
@@ -589,7 +617,7 @@ class ComRegister {
589
617
  }
590
618
  }
591
619
  }
592
- async sendPrivateMsgAndRebootService(ctx) {
620
+ async sendPrivateMsgAndRebootService() {
593
621
  // 判断重启次数是否超过三次
594
622
  if (this.rebootCount >= 3) {
595
623
  // logger
@@ -597,7 +625,7 @@ class ComRegister {
597
625
  // 重启失败,发送消息
598
626
  await this.sendPrivateMsg('已重启插件三次,请检查机器人状态后使用指令 sys start 启动插件');
599
627
  // 关闭插件
600
- await ctx.sm.disposePlugin();
628
+ await this.ctx.sm.disposePlugin();
601
629
  // 结束
602
630
  return;
603
631
  }
@@ -606,7 +634,7 @@ class ComRegister {
606
634
  // logger
607
635
  this.logger.info('插件出现未知错误,正在重启插件');
608
636
  // 重启插件
609
- const flag = await ctx.sm.restartPlugin();
637
+ const flag = await this.ctx.sm.restartPlugin();
610
638
  // 判断是否重启成功
611
639
  if (flag) {
612
640
  this.logger.info('重启插件成功');
@@ -617,42 +645,66 @@ class ComRegister {
617
645
  // 重启失败,发送消息
618
646
  await this.sendPrivateMsg('重启插件失败,请检查机器人状态后使用指令 sys start 启动插件');
619
647
  // 关闭插件
620
- await ctx.sm.disposePlugin();
648
+ await this.ctx.sm.disposePlugin();
621
649
  }
622
650
  }
623
- async sendPrivateMsgAndStopService(ctx) {
651
+ async sendPrivateMsgAndStopService() {
624
652
  // 发送消息
625
653
  await this.sendPrivateMsg('插件发生未知错误,请检查机器人状态后使用指令 sys start 启动插件');
626
654
  // logger
627
655
  this.logger.error('插件发生未知错误,请检查机器人状态后使用指令 sys start 启动插件');
628
656
  // 关闭插件
629
- await ctx.sm.disposePlugin();
657
+ await this.ctx.sm.disposePlugin();
630
658
  // 结束
631
659
  return;
632
660
  }
633
- async sendMsg(ctx, targets, content) {
661
+ async sendMsg(targets, content, live) {
634
662
  for (const target of targets) {
635
663
  // 获取机器人实例
636
- const bot = this.getBot(ctx, target.platform);
664
+ const bot = this.getBot(target.platform);
637
665
  // 定义需要发送的数组
638
666
  let sendArr = [];
639
667
  // 判断是否需要推送所有机器人加入的群
640
- if (target.idArr[0] === 'all') {
668
+ if (target.channelIdArr[0].channelId === 'all') {
641
669
  // 获取所有guild
642
670
  for (const guild of (await bot.getGuildList()).data) {
643
- sendArr.push(guild.id);
671
+ sendArr.push({
672
+ channelId: guild.id,
673
+ dynamic: target.channelIdArr[0].dynamic,
674
+ live: target.channelIdArr[0].live,
675
+ liveDanmaku: target.channelIdArr[0].liveDanmaku,
676
+ atAll: target.channelIdArr[0].atAll
677
+ });
644
678
  }
645
679
  }
646
680
  else {
647
- sendArr = target.idArr;
681
+ sendArr = target.channelIdArr;
682
+ }
683
+ // 判断是否是直播开播推送,如果是则需要进一步判断是否需要艾特群体成员
684
+ if (live) {
685
+ // 直播开播推送,判断是否需要艾特全体成员
686
+ for (const channel of sendArr) {
687
+ // 判断是否需要推送直播消息
688
+ if (channel.live) {
689
+ await this.sendMsgFunc(bot, channel.channelId, content);
690
+ }
691
+ // 判断是否需要艾特全体成员
692
+ if (channel.atAll) {
693
+ await this.sendMsgFunc(bot, channel.channelId, (0, jsx_runtime_1.jsx)("at", { type: "all" }));
694
+ }
695
+ }
648
696
  }
649
- // 循环给每个群组发送
650
- for (const guild of sendArr) {
651
- await this.sendMsgFunc(bot, guild, content);
697
+ else {
698
+ for (const channel of sendArr) {
699
+ // 判断是否需要推送动态消息和直播消息
700
+ if (channel.dynamic || channel.live) {
701
+ await this.sendMsgFunc(bot, channel.channelId, content);
702
+ }
703
+ }
652
704
  }
653
705
  }
654
706
  }
655
- dynamicDetect(ctx) {
707
+ dynamicDetect() {
656
708
  let detectSetup = true;
657
709
  let updateBaseline;
658
710
  // 相当于锁的作用,防止上一个循环没处理完
@@ -668,7 +720,7 @@ class ComRegister {
668
720
  // 检测启动初始化
669
721
  if (detectSetup) {
670
722
  // 获取动态信息
671
- const data = await ctx.ba.getAllDynamic();
723
+ const data = await this.ctx.ba.getAllDynamic();
672
724
  // 判断获取动态信息是否成功
673
725
  if (data.code !== 0)
674
726
  return;
@@ -684,13 +736,13 @@ class ComRegister {
684
736
  let content;
685
737
  try {
686
738
  // 查询是否有新动态
687
- const data = await ctx.ba.hasNewDynamic(updateBaseline);
739
+ const data = await this.ctx.ba.hasNewDynamic(updateBaseline);
688
740
  updateNum = data.data.update_num;
689
741
  // 没有新动态或获取动态信息失败直接返回
690
742
  if (updateNum <= 0 || data.code !== 0)
691
743
  return;
692
744
  // 获取动态内容
693
- content = await ctx.ba.getAllDynamic(updateBaseline);
745
+ content = await this.ctx.ba.getAllDynamic(updateBaseline);
694
746
  }
695
747
  catch (e) {
696
748
  return this.logger.error('dynamicDetect getUserSpaceDynamic() 发生了错误,错误为:' + e.message);
@@ -704,7 +756,7 @@ class ComRegister {
704
756
  // 发送私聊消息
705
757
  await this.sendPrivateMsg('账号未登录,插件已停止工作,请登录后,输入指令 sys start 启动插件');
706
758
  // 停止服务
707
- await ctx.sm.disposePlugin();
759
+ await this.ctx.sm.disposePlugin();
708
760
  // 结束循环
709
761
  break;
710
762
  }
@@ -714,7 +766,7 @@ class ComRegister {
714
766
  // 发送私聊消息
715
767
  await this.sendPrivateMsg('账号被风控,插件已停止工作,请确认风控解除后,输入指令 sys start 启动插件');
716
768
  // 停止服务
717
- await ctx.sm.disposePlugin();
769
+ await this.ctx.sm.disposePlugin();
718
770
  // 结束循环
719
771
  break;
720
772
  }
@@ -765,7 +817,7 @@ class ComRegister {
765
817
  // 获取动态推送图片
766
818
  try {
767
819
  // 渲染图片
768
- const { pic: gimgPic, buffer: gimgBuffer } = await ctx.gi.generateDynamicImg(items[num]);
820
+ const { pic: gimgPic, buffer: gimgBuffer } = await this.ctx.gi.generateDynamicImg(items[num]);
769
821
  // 赋值
770
822
  pic = gimgPic;
771
823
  buffer = gimgBuffer;
@@ -779,13 +831,13 @@ class ComRegister {
779
831
  if (e.message === '出现关键词,屏蔽该动态') {
780
832
  // 如果需要发送才发送
781
833
  if (this.config.filter.notify) {
782
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
834
+ await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
783
835
  }
784
836
  return;
785
837
  }
786
838
  if (e.message === '已屏蔽转发动态') {
787
839
  if (this.config.filter.notify) {
788
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条转发动态,已屏蔽`);
840
+ await this.sendMsg(sub.target, `${upName}发布了一条转发动态,已屏蔽`);
789
841
  }
790
842
  return;
791
843
  }
@@ -793,7 +845,7 @@ class ComRegister {
793
845
  if (i === attempts - 1) {
794
846
  this.logger.error('dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:' + e.message);
795
847
  // 发送私聊消息并重启服务
796
- return await this.sendPrivateMsgAndStopService(ctx);
848
+ return await this.sendPrivateMsgAndStopService();
797
849
  }
798
850
  }
799
851
  }
@@ -803,12 +855,12 @@ class ComRegister {
803
855
  if (pic) {
804
856
  this.logger.info('推送动态中,使用render模式');
805
857
  // pic存在,使用的是render模式
806
- await this.sendMsg(ctx, sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
858
+ await this.sendMsg(sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
807
859
  }
808
860
  else if (buffer) {
809
861
  this.logger.info('推送动态中,使用page模式');
810
862
  // pic不存在,说明使用的是page模式
811
- await this.sendMsg(ctx, sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
863
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
812
864
  }
813
865
  else {
814
866
  this.logger.info(items[num].modules.module_author.name + '发布了一条动态,但是推送失败');
@@ -822,7 +874,7 @@ class ComRegister {
822
874
  }
823
875
  };
824
876
  }
825
- debug_dynamicDetect(ctx) {
877
+ debug_dynamicDetect() {
826
878
  let detectSetup = true;
827
879
  let updateBaseline;
828
880
  // 相当于锁的作用,防止上一个循环没处理完
@@ -839,7 +891,7 @@ class ComRegister {
839
891
  // 检测启动初始化
840
892
  if (detectSetup) {
841
893
  // 获取动态信息
842
- const data = await ctx.ba.getAllDynamic();
894
+ const data = await this.ctx.ba.getAllDynamic();
843
895
  // 判断获取动态信息是否成功
844
896
  if (data.code !== 0)
845
897
  return;
@@ -856,7 +908,7 @@ class ComRegister {
856
908
  let content;
857
909
  try {
858
910
  // 查询是否有新动态
859
- const data = await ctx.ba.hasNewDynamic(updateBaseline);
911
+ const data = await this.ctx.ba.hasNewDynamic(updateBaseline);
860
912
  updateNum = data.data.update_num;
861
913
  console.log(`获取是否有新动态:`);
862
914
  console.log(data);
@@ -864,7 +916,7 @@ class ComRegister {
864
916
  if (updateNum <= 0 || data.code !== 0)
865
917
  return;
866
918
  // 获取动态内容
867
- content = await ctx.ba.getAllDynamic(updateBaseline);
919
+ content = await this.ctx.ba.getAllDynamic(updateBaseline);
868
920
  console.log('获取动态内容:');
869
921
  console.log(content.data.items[0]);
870
922
  }
@@ -880,7 +932,7 @@ class ComRegister {
880
932
  // 发送私聊消息
881
933
  await this.sendPrivateMsg('账号未登录,插件已停止工作,请登录后,输入指令 sys start 启动插件');
882
934
  // 停止服务
883
- await ctx.sm.disposePlugin();
935
+ await this.ctx.sm.disposePlugin();
884
936
  // 结束循环
885
937
  break;
886
938
  }
@@ -890,7 +942,7 @@ class ComRegister {
890
942
  // 发送私聊消息
891
943
  await this.sendPrivateMsg('账号被风控,插件已停止工作,请确认风控解除后,输入指令 sys start 启动插件');
892
944
  // 停止服务
893
- await ctx.sm.disposePlugin();
945
+ await this.ctx.sm.disposePlugin();
894
946
  // 结束循环
895
947
  break;
896
948
  }
@@ -949,7 +1001,7 @@ class ComRegister {
949
1001
  // 获取动态推送图片
950
1002
  try {
951
1003
  // 渲染图片
952
- const { pic: gimgPic, buffer: gimgBuffer } = await ctx.gi.generateDynamicImg(items[num]);
1004
+ const { pic: gimgPic, buffer: gimgBuffer } = await this.ctx.gi.generateDynamicImg(items[num]);
953
1005
  // 赋值
954
1006
  pic = gimgPic;
955
1007
  buffer = gimgBuffer;
@@ -963,13 +1015,13 @@ class ComRegister {
963
1015
  if (e.message === '出现关键词,屏蔽该动态') {
964
1016
  // 如果需要发送才发送
965
1017
  if (this.config.filter.notify) {
966
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
1018
+ await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
967
1019
  }
968
1020
  return;
969
1021
  }
970
1022
  if (e.message === '已屏蔽转发动态') {
971
1023
  if (this.config.filter.notify) {
972
- await this.sendMsg(ctx, sub.target, `${upName}发布了一条转发动态,已屏蔽`);
1024
+ await this.sendMsg(sub.target, `${upName}发布了一条转发动态,已屏蔽`);
973
1025
  }
974
1026
  return;
975
1027
  }
@@ -977,7 +1029,7 @@ class ComRegister {
977
1029
  if (i === attempts - 1) {
978
1030
  this.logger.error('dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:' + e.message);
979
1031
  // 发送私聊消息并重启服务
980
- return await this.sendPrivateMsgAndStopService(ctx);
1032
+ return await this.sendPrivateMsgAndStopService();
981
1033
  }
982
1034
  }
983
1035
  }
@@ -987,12 +1039,12 @@ class ComRegister {
987
1039
  if (pic) {
988
1040
  this.logger.info('推送动态中,使用render模式');
989
1041
  // pic存在,使用的是render模式
990
- await this.sendMsg(ctx, sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
1042
+ await this.sendMsg(sub.target, pic + (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: dUrl }));
991
1043
  }
992
1044
  else if (buffer) {
993
1045
  this.logger.info('推送动态中,使用page模式');
994
1046
  // pic不存在,说明使用的是page模式
995
- await this.sendMsg(ctx, sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
1047
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), dUrl] }));
996
1048
  }
997
1049
  else {
998
1050
  this.logger.info(items[num].modules.module_author.name + '发布了一条动态,但是推送失败');
@@ -1006,203 +1058,272 @@ class ComRegister {
1006
1058
  }
1007
1059
  };
1008
1060
  }
1009
- liveDetect(ctx, roomId, target) {
1061
+ // 定义发送直播通知卡片方法
1062
+ async sendLiveNotifyCard(info, liveType, liveNotifyMsg) {
1063
+ // 定义变量
1064
+ let pic;
1065
+ let buffer;
1066
+ // 多次尝试生成图片
1067
+ const attempts = 3;
1068
+ for (let i = 0; i < attempts; i++) {
1069
+ try {
1070
+ // 获取直播通知卡片
1071
+ const { pic: picv, buffer: bufferv } = await this.ctx.gi.generateLiveImg(info.data, info.username, info.userface, liveType);
1072
+ // 赋值
1073
+ pic = picv;
1074
+ buffer = bufferv;
1075
+ // 成功则跳出循环
1076
+ break;
1077
+ }
1078
+ catch (e) {
1079
+ if (i === attempts - 1) { // 已尝试三次
1080
+ this.logger.error('liveDetect generateLiveImg() 推送卡片生成失败,原因:' + e.message);
1081
+ // 发送私聊消息并重启服务
1082
+ return await this.sendPrivateMsgAndStopService();
1083
+ }
1084
+ }
1085
+ }
1086
+ // 推送直播信息
1087
+ // pic 存在,使用的是render模式
1088
+ if (pic) {
1089
+ // 只有在开播时才艾特全体成员
1090
+ if (liveType === LiveType.StartBroadcasting) {
1091
+ return await this.sendMsg(info.target, pic + (liveNotifyMsg ?? ''), true);
1092
+ }
1093
+ // 正常不需要艾特全体成员
1094
+ return await this.sendMsg(info.target, pic + (liveNotifyMsg ?? ''));
1095
+ }
1096
+ // pic不存在,说明使用的是page模式
1097
+ const msg = (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), liveNotifyMsg || ''] });
1098
+ // 只有在开播时才艾特全体成员
1099
+ if (liveType === LiveType.StartBroadcasting) {
1100
+ return await this.sendMsg(info.target, msg, true);
1101
+ }
1102
+ // 正常不需要艾特全体成员
1103
+ return await this.sendMsg(info.target, msg);
1104
+ }
1105
+ // 定义获取主播信息方法
1106
+ async useMasterInfo(uid) {
1107
+ const { data } = await this.ctx.ba.getMasterInfo(uid);
1108
+ return { username: data.info.uname, userface: data.info.face, roomId: data.room_id };
1109
+ }
1110
+ async useLiveRoomInfo(roomId) {
1111
+ // 发送请求获取直播间信息
1112
+ let content;
1113
+ const attempts = 3;
1114
+ for (let i = 0; i < attempts; i++) {
1115
+ try {
1116
+ // 发送请求获取room信息
1117
+ content = await this.ctx.ba.getLiveRoomInfo(roomId);
1118
+ // 成功则跳出循环
1119
+ break;
1120
+ }
1121
+ catch (e) {
1122
+ this.logger.error('liveDetect getLiveRoomInfo 发生了错误,错误为:' + e.message);
1123
+ if (i === attempts - 1) { // 已尝试三次
1124
+ // 发送私聊消息并重启服务
1125
+ return await this.sendPrivateMsgAndStopService();
1126
+ }
1127
+ }
1128
+ }
1129
+ return content.data;
1130
+ }
1131
+ async liveDetectWithAPI() {
1132
+ // 定义变量:第一次订阅
1010
1133
  let firstSubscription = true;
1134
+ // 定义变量:timer计时器
1011
1135
  let timer = 0;
1012
- let open = false;
1013
- let liveTime;
1014
- let username;
1015
- let userface;
1016
1136
  // 相当于锁的作用,防止上一个循环没处理完
1017
1137
  let flag = true;
1018
- // 定义发送直播通知卡片方法
1019
- const sendLiveNotifyCard = async (data, liveType, liveNotifyMsg, atAll) => {
1020
- // 定义变量
1021
- let pic;
1022
- let buffer;
1023
- // 多次尝试生成图片
1138
+ // 定义订阅对象Record 0未开播 1正在直播 2轮播中
1139
+ const liveRecord = {};
1140
+ // 初始化subRecord
1141
+ this.subManager.forEach(sub => {
1142
+ // 判断是否订阅直播
1143
+ if (sub.live) {
1144
+ // 将该订阅添加到subRecord中
1145
+ liveRecord[sub.uid] = { liveStatus: 0, liveTime: '', target: sub.target };
1146
+ }
1147
+ });
1148
+ // 定义函数: 发送请求获取直播状态
1149
+ const useLiveStatus = async (roomId) => {
1150
+ let content;
1024
1151
  const attempts = 3;
1025
1152
  for (let i = 0; i < attempts; i++) {
1026
1153
  try {
1027
- // 获取直播通知卡片
1028
- const { pic: picv, buffer: bufferv } = await ctx.gi.generateLiveImg(data, username, userface, liveType);
1029
- // 赋值
1030
- pic = picv;
1031
- buffer = bufferv;
1154
+ // 发送请求获取room信息
1155
+ content = await this.ctx.ba.getLiveRoomInfo(roomId);
1032
1156
  // 成功则跳出循环
1033
1157
  break;
1034
1158
  }
1035
1159
  catch (e) {
1160
+ this.logger.error('liveDetect getLiveRoomInfo 发生了错误,错误为:' + e.message);
1036
1161
  if (i === attempts - 1) { // 已尝试三次
1037
- this.logger.error('liveDetect generateLiveImg() 推送卡片生成失败,原因:' + e.message);
1038
1162
  // 发送私聊消息并重启服务
1039
- return await this.sendPrivateMsgAndStopService(ctx);
1163
+ return await this.sendPrivateMsgAndStopService();
1040
1164
  }
1041
1165
  }
1042
1166
  }
1043
- // 推送直播信息
1044
- // pic 存在,使用的是render模式
1045
- if (pic) {
1046
- const msg = (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [atAll && (0, jsx_runtime_1.jsx)("at", { type: "all" }), liveNotifyMsg && liveNotifyMsg] });
1047
- return await this.sendMsg(ctx, target, pic + msg);
1048
- }
1049
- // pic不存在,说明使用的是page模式
1050
- const msg = (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, 'image/png'), atAll && (0, jsx_runtime_1.jsx)("at", { type: "all" }), liveNotifyMsg && liveNotifyMsg] });
1051
- await this.sendMsg(ctx, target, pic + msg);
1167
+ // 返回data
1168
+ return content.data;
1052
1169
  };
1053
- // 定义获取主播信息方法
1054
- let useMasterInfo;
1055
- if (this.config.changeMasterInfoApi) {
1056
- useMasterInfo = async (uid) => {
1057
- const { data } = await ctx.ba.getUserInfo(uid);
1058
- username = data.name;
1059
- userface = data.face;
1060
- };
1061
- }
1062
- else {
1063
- useMasterInfo = async (uid) => {
1064
- const { data: { info } } = await ctx.ba.getMasterInfo(uid);
1065
- username = info.uname;
1066
- userface = info.face;
1067
- };
1068
- }
1069
1170
  return async () => {
1070
1171
  // 如果flag为false则说明前面的代码还未执行完,则直接返回
1071
1172
  if (!flag)
1072
1173
  return;
1174
+ // 将标志位置为false
1073
1175
  flag = false;
1074
- // 无论是否执行成功都要释放锁
1075
1176
  try {
1076
- // 发送请求检测直播状态
1077
- let content;
1078
- const attempts = 3;
1079
- for (let i = 0; i < attempts; i++) {
1080
- try {
1081
- // 发送请求获取room信息
1082
- content = await ctx.ba.getLiveRoomInfo(roomId);
1083
- // 成功则跳出循环
1084
- break;
1085
- }
1086
- catch (e) {
1087
- this.logger.error('liveDetect getLiveRoomInfo 发生了错误,错误为:' + e.message);
1088
- if (i === attempts - 1) { // 已尝试三次
1089
- // 发送私聊消息并重启服务
1090
- return await this.sendPrivateMsgAndStopService(ctx);
1091
- }
1092
- }
1093
- }
1094
- const { data } = content;
1177
+ // 获取正在直播对象
1178
+ const liveUsers = await this.ctx.ba.getTheUserWhoIsLiveStreaming();
1095
1179
  // 判断是否是第一次订阅
1096
1180
  if (firstSubscription) {
1181
+ // 将第一次订阅置为false
1097
1182
  firstSubscription = false;
1098
- // 获取主播信息
1099
- const attempts = 3;
1100
- for (let i = 0; i < attempts; i++) {
1101
- try {
1102
- // 发送请求获取主播信息
1103
- await useMasterInfo(data.uid);
1104
- // 成功则跳出循环
1105
- break;
1106
- }
1107
- catch (e) {
1108
- this.logger.error('liveDetect getMasterInfo() 发生了错误,错误为:' + e.message);
1109
- if (i === attempts - 1) { // 已尝试三次
1110
- // 发送私聊消息并重启服务
1111
- return await this.sendPrivateMsgAndStopService(ctx);
1183
+ // 先判断是否有UP主正在直播
1184
+ if (liveUsers.count > 0) {
1185
+ // 遍历liveUsers
1186
+ liveUsers.items.forEach(async (item) => {
1187
+ // 判断是否有订阅对象正在直播
1188
+ if (liveRecord[item.mid]) {
1189
+ // 获取当前用户直播间信息
1190
+ const data = await useLiveStatus(item.room_id.toString());
1191
+ // 设置开播时间
1192
+ liveRecord[item.mid].liveTime = data.live_time;
1193
+ // 设置直播中消息
1194
+ const liveMsg = this.config.customLive ? this.config.customLive
1195
+ .replace('-name', item.uname)
1196
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1197
+ .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null;
1198
+ // 发送直播通知卡片
1199
+ if (this.config.restartPush)
1200
+ this.sendLiveNotifyCard({
1201
+ username: item.uname,
1202
+ userface: item.face,
1203
+ target: liveRecord[item.mid].target,
1204
+ data
1205
+ }, LiveType.LiveBroadcast, liveMsg);
1206
+ // 改变开播状态
1207
+ liveRecord[item.mid].liveStatus = 1;
1112
1208
  }
1113
- }
1209
+ });
1114
1210
  }
1115
- // 判断直播状态
1116
- if (data.live_status === 1) { // 当前正在直播
1117
- // 设置开播时间
1118
- liveTime = data.live_time;
1119
- // 发送直播通知卡片
1120
- if (this.config.restartPush)
1121
- sendLiveNotifyCard(data, LiveType.LiveBroadcast);
1122
- // 改变开播状态
1123
- open = true;
1124
- } // 未开播,直接返回
1211
+ // 没有正在直播的订阅对象,直接返回
1125
1212
  return;
1126
1213
  }
1127
- // 检查直播状态
1128
- switch (data.live_status) {
1129
- case 0:
1130
- case 2: { // 状态 0 和 2 说明未开播
1131
- if (open) { // 之前开播,现在下播了
1132
- // 更改直播状态
1133
- open = false;
1134
- // 下播了将定时器清零
1135
- timer = 0;
1136
- // 定义下播通知消息
1137
- const liveEndMsg = this.config.customLiveEnd
1138
- .replace('-name', username)
1139
- .replace('-time', await ctx.gi.getTimeDifference(liveTime));
1140
- // 更改直播时长
1141
- data.live_time = liveTime;
1142
- // 发送@全体成员通知
1143
- await sendLiveNotifyCard(data, LiveType.StopBroadcast, liveEndMsg);
1144
- }
1145
- // 未进循环,还未开播,继续循环
1146
- break;
1147
- }
1148
- case 1: {
1149
- if (!open) { // 之前未开播,现在开播了
1150
- // 更改直播状态
1151
- open = true;
1152
- // 设置开播时间
1153
- liveTime = data.live_time;
1154
- // 获取主播信息
1155
- const attempts = 3;
1156
- for (let i = 0; i < attempts; i++) {
1157
- try {
1158
- // 主播信息不会变,开播时刷新一次即可
1159
- // 发送请求获取主播信息
1160
- await useMasterInfo(data.uid);
1161
- // 成功则跳出循环
1214
+ // 获取当前订阅直播的数量
1215
+ const currentLiveSubs = this.subManager.filter(sub => sub.live);
1216
+ // 获取当前liveRecord里的订阅数量
1217
+ const currentLiveRecordKeys = Object.keys(liveRecord);
1218
+ // 判断是否能匹配双方数量
1219
+ if (currentLiveRecordKeys.length < currentLiveSubs.length) {
1220
+ // 遍历currentLiveSubs
1221
+ for (const sub of currentLiveSubs) {
1222
+ // 判断liveRecord中缺少了哪些订阅
1223
+ if (!liveRecord[sub.uid]) {
1224
+ // 获取当前用户直播间信息
1225
+ const data = await useLiveStatus(sub.roomId.toString());
1226
+ switch (data.live_status) {
1227
+ case 0:
1228
+ case 2: { // 未开播
1229
+ // 添加到liveRecord中
1230
+ liveRecord[sub.uid] = { liveStatus: 0, liveTime: '', target: sub.target };
1231
+ // break
1162
1232
  break;
1163
1233
  }
1164
- catch (e) {
1165
- this.logger.error('liveDetect open getMasterInfo() 发生了错误,错误为:' + e.message);
1166
- if (i === attempts - 1) { // 已尝试三次
1167
- // 发送私聊消息并重启服务
1168
- return await this.sendPrivateMsgAndStopService(ctx);
1169
- }
1234
+ case 1: { //正在直播
1235
+ // 添加到liveRecord中
1236
+ liveRecord[sub.uid] = { liveStatus: 1, liveTime: data.live_time, target: sub.target };
1170
1237
  }
1171
1238
  }
1172
- // 定义开播通知语
1173
- const liveStartMsg = this.config.customLiveStart
1174
- .replace('-name', username)
1175
- .replace('-time', await ctx.gi.getTimeDifference(liveTime))
1176
- .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`);
1177
- // 判断是否需要@全体成员
1178
- if (this.config.liveStartAtAll) {
1179
- // 发送@全体成员通知
1180
- await sendLiveNotifyCard(data, LiveType.StartBroadcasting, liveStartMsg, true);
1181
- }
1182
- else {
1239
+ }
1240
+ }
1241
+ }
1242
+ if (currentLiveRecordKeys.length > currentLiveSubs.length) {
1243
+ // 创建Set
1244
+ const setCurrentLiveSubs = new Set(currentLiveSubs.map(sub => sub.uid));
1245
+ // 找出 currentLiveRecordKeys中比currentLiveSubs 多的元素
1246
+ const extraInCurrentLiveSubs = currentLiveRecordKeys.filter(key => !setCurrentLiveSubs.has(key));
1247
+ // 遍历 extraInCurrentLiveSubs
1248
+ for (const subUID of extraInCurrentLiveSubs) {
1249
+ // 删除记录
1250
+ delete liveRecord[subUID];
1251
+ }
1252
+ }
1253
+ // 数量没有差异,则不进行其他操作
1254
+ // 遍历liveUsers
1255
+ liveUsers.items.forEach(async (item) => {
1256
+ // 判断是否有正在直播的订阅对象
1257
+ if (liveRecord[item.mid]) { // 有正在直播的订阅对象
1258
+ // 获取当前用户直播间信息
1259
+ const data = await useLiveStatus(item.room_id.toString());
1260
+ // 判断开播状态
1261
+ switch (liveRecord[item.mid].liveStatus) {
1262
+ case 0: { // 之前未开播,现在开播了
1263
+ // 设置开播时间
1264
+ liveRecord[item.mid].liveTime = data.live_time;
1265
+ // 定义开播通知语
1266
+ const liveStartMsg = this.config.customLiveStart ? this.config.customLiveStart
1267
+ .replace('-name', item.uname)
1268
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1269
+ .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null;
1183
1270
  // 发送直播通知卡片
1184
- await sendLiveNotifyCard(data, LiveType.StartBroadcasting, liveStartMsg);
1271
+ await this.sendLiveNotifyCard({
1272
+ username: item.uname,
1273
+ userface: item.face,
1274
+ target: liveRecord[item.mid].target,
1275
+ data
1276
+ }, LiveType.LiveBroadcast, liveStartMsg);
1277
+ // 改变开播状态
1278
+ liveRecord[item.mid].liveStatus = 1;
1279
+ // 结束
1280
+ break;
1185
1281
  }
1186
- }
1187
- else { // 还在直播
1188
- if (this.config.pushTime > 0) {
1189
- timer++;
1190
- // 开始记录时间
1191
- if (timer >= (6 * 60 * this.config.pushTime)) { // 到时间推送直播消息
1192
- // 到时间重新计时
1193
- timer = 0;
1194
- // 定义直播中通知消息
1195
- const liveMsg = this.config.customLive ? this.config.customLive
1196
- .replace('-name', username)
1197
- .replace('-time', await ctx.gi.getTimeDifference(liveTime))
1198
- .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : '';
1199
- // 发送直播通知卡片
1200
- sendLiveNotifyCard(data, LiveType.LiveBroadcast, liveMsg);
1282
+ case 1: { // 仍在直播
1283
+ if (this.config.pushTime > 0) {
1284
+ timer++;
1285
+ // 开始记录时间
1286
+ if (timer >= (6 * 60 * this.config.pushTime)) { // 到时间推送直播消息
1287
+ // 到时间重新计时
1288
+ timer = 0;
1289
+ // 定义直播中通知消息
1290
+ const liveMsg = this.config.customLive ? this.config.customLive
1291
+ .replace('-name', item.uname)
1292
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
1293
+ .replace('-link', `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`) : null;
1294
+ // 发送直播通知卡片
1295
+ this.sendLiveNotifyCard({
1296
+ username: item.uname,
1297
+ userface: item.face,
1298
+ target: liveRecord[item.mid].target,
1299
+ data
1300
+ }, LiveType.LiveBroadcast, liveMsg);
1301
+ }
1201
1302
  }
1202
1303
  }
1203
- // 否则继续循环
1204
1304
  }
1205
1305
  }
1306
+ });
1307
+ // 找出liveRecord中liveStatus为1但liveUsers中没有的元素
1308
+ const extraInLiveRecord = currentLiveRecordKeys.filter(key => !liveUsers.items.some(item => item.mid === Number(key)));
1309
+ // 遍历 extraInLiveRecord
1310
+ for (const subUID of extraInLiveRecord) { // 下播的主播
1311
+ // 获取主播信息
1312
+ const masterInfo = await this.useMasterInfo(subUID);
1313
+ // 获取直播间消息
1314
+ const liveRoomInfo = await this.useLiveRoomInfo(masterInfo.roomId.toString());
1315
+ // 定义下播播通知语
1316
+ const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1317
+ .replace('-name', masterInfo.username)
1318
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveRecord[subUID].liveTime))
1319
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1320
+ // 发送下播通知
1321
+ this.sendLiveNotifyCard({
1322
+ username: masterInfo.username,
1323
+ userface: masterInfo.userface,
1324
+ target: liveRecord[subUID].target,
1325
+ data: liveRoomInfo
1326
+ }, LiveType.StopBroadcast, liveEndMsg);
1206
1327
  }
1207
1328
  }
1208
1329
  finally {
@@ -1211,6 +1332,150 @@ class ComRegister {
1211
1332
  }
1212
1333
  };
1213
1334
  }
1335
+ async liveDetectWithListener(roomId, target) {
1336
+ // 定义开播时间
1337
+ let liveTime;
1338
+ // 定义定时推送定时器
1339
+ let pushAtTimeTimer;
1340
+ // 定义弹幕存放数组
1341
+ const currentLiveDanmakuArr = [];
1342
+ const temporaryLiveDanmakuArr = [];
1343
+ // 处理target
1344
+ // 找到频道/群组对应的
1345
+ const newTarget = target.map(channel => {
1346
+ const liveDanmakuArr = channel.channelIdArr.filter(channelId => channelId.liveDanmaku);
1347
+ return {
1348
+ channelIdArr: liveDanmakuArr,
1349
+ platform: channel.platform
1350
+ };
1351
+ });
1352
+ // 定义定时推送函数
1353
+ const pushAtTimeFunc = async () => {
1354
+ // 获取直播间信息
1355
+ const liveRoomInfo = await this.useLiveRoomInfo(roomId);
1356
+ // 获取主播信息
1357
+ const masterInfo = await this.useMasterInfo(liveRoomInfo.uid);
1358
+ // 定义直播中通知消息
1359
+ const liveMsg = this.config.customLive ? this.config.customLive
1360
+ .replace('-name', masterInfo.username)
1361
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1362
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1363
+ // 发送直播通知卡片
1364
+ await this.sendLiveNotifyCard({
1365
+ username: masterInfo.username,
1366
+ userface: masterInfo.userface,
1367
+ target: newTarget,
1368
+ data: liveRoomInfo
1369
+ }, LiveType.LiveBroadcast, liveMsg);
1370
+ };
1371
+ // 定义弹幕推送函数
1372
+ const danmakuPushFunc = () => {
1373
+ // 判断数组是否有内容
1374
+ if (temporaryLiveDanmakuArr.length > 0) {
1375
+ // 发送消息
1376
+ this.sendMsg(newTarget, temporaryLiveDanmakuArr.join('\n'));
1377
+ // 将临时消息数组清空
1378
+ temporaryLiveDanmakuArr.length = 0;
1379
+ }
1380
+ };
1381
+ // 获取直播间信息
1382
+ const liveRoomInfo = await this.useLiveRoomInfo(roomId);
1383
+ // 获取主播信息
1384
+ const masterInfo = await this.useMasterInfo(liveRoomInfo.uid);
1385
+ // 构建消息处理函数
1386
+ const handler = {
1387
+ onOpen: () => {
1388
+ this.logger.info('直播间连接成功');
1389
+ },
1390
+ onClose: () => {
1391
+ this.logger.info('直播间连接已断开');
1392
+ },
1393
+ onIncomeDanmu: ({ body }) => {
1394
+ // 处理消息,只需要UP主名字和消息内容
1395
+ const content = `【${masterInfo.username}的直播间】${body.user.uname}:${body.content}`;
1396
+ // 保存消息到数组
1397
+ currentLiveDanmakuArr.push(body.content);
1398
+ temporaryLiveDanmakuArr.push(content);
1399
+ },
1400
+ onIncomeSuperChat: ({ body }) => {
1401
+ // 处理SC消息
1402
+ const content = `【${masterInfo.username}的直播间】${body.user.uname}发送了一条SC:${body.content}`;
1403
+ // 保存消息到数组
1404
+ currentLiveDanmakuArr.push(body.content);
1405
+ temporaryLiveDanmakuArr.push(content);
1406
+ },
1407
+ onGuardBuy: ({ body }) => {
1408
+ const content = `【${masterInfo.username}的直播间】${body.user.uname}加入了大航海(${body.gift_name})`;
1409
+ // 保存消息到数组
1410
+ currentLiveDanmakuArr.push(content);
1411
+ temporaryLiveDanmakuArr.push(content);
1412
+ },
1413
+ onLiveStart: async () => {
1414
+ // 获取直播间信息
1415
+ const liveRoomInfo = await this.useLiveRoomInfo(roomId);
1416
+ // 获取主播信息
1417
+ const masterInfo = await this.useMasterInfo(liveRoomInfo.uid);
1418
+ // 定义下播通知消息
1419
+ const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1420
+ .replace('-name', masterInfo.username)
1421
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime)) : null;
1422
+ // 更改直播时长
1423
+ liveRoomInfo.live_time = liveTime;
1424
+ // 推送下播通知
1425
+ await this.sendLiveNotifyCard({
1426
+ username: masterInfo.username,
1427
+ userface: masterInfo.userface,
1428
+ target: newTarget,
1429
+ data: liveRoomInfo
1430
+ }, LiveType.StopBroadcast, liveEndMsg);
1431
+ },
1432
+ onLiveEnd: async () => {
1433
+ // 获取直播间消息
1434
+ const liveRoomInfo = await this.useLiveRoomInfo(roomId);
1435
+ // 获取主播信息
1436
+ const masterInfo = await this.useMasterInfo(liveRoomInfo.uid);
1437
+ // 关闭定时推送定时器
1438
+ pushAtTimeTimer();
1439
+ // 将推送定时器变量置空
1440
+ pushAtTimeTimer = null;
1441
+ // 定义下播播通知语
1442
+ const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1443
+ .replace('-name', masterInfo.username)
1444
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1445
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1446
+ // 推送通知卡片
1447
+ await this.sendLiveNotifyCard({
1448
+ username: masterInfo.username,
1449
+ userface: masterInfo.userface,
1450
+ target: newTarget,
1451
+ data: liveRoomInfo
1452
+ }, LiveType.StartBroadcasting, liveEndMsg);
1453
+ }
1454
+ };
1455
+ // 启动直播间弹幕监测
1456
+ this.ctx.bl.startLiveRoomListener(roomId, handler, danmakuPushFunc);
1457
+ // 判断直播状态
1458
+ if (liveRoomInfo.live_status === 1) {
1459
+ // 设置开播时间
1460
+ liveTime = liveRoomInfo.live_time;
1461
+ // 定义直播中通知消息
1462
+ const liveMsg = this.config.customLive ? this.config.customLive
1463
+ .replace('-name', masterInfo.username)
1464
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1465
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1466
+ // 发送直播通知卡片
1467
+ if (this.config.restartPush) {
1468
+ await this.sendLiveNotifyCard({
1469
+ username: masterInfo.username,
1470
+ userface: masterInfo.userface,
1471
+ target: newTarget,
1472
+ data: liveRoomInfo
1473
+ }, LiveType.LiveBroadcast, liveMsg);
1474
+ }
1475
+ // 正在直播,开启定时器
1476
+ pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1477
+ }
1478
+ }
1214
1479
  subShow() {
1215
1480
  // 在控制台中显示订阅对象
1216
1481
  let table = ``;
@@ -1249,7 +1514,7 @@ class ComRegister {
1249
1514
  // 只订阅动态
1250
1515
  return [false, true];
1251
1516
  }
1252
- updateSubNotifier(ctx) {
1517
+ updateSubNotifier() {
1253
1518
  // 更新控制台提示
1254
1519
  if (this.subNotifier)
1255
1520
  this.subNotifier.dispose();
@@ -1268,13 +1533,13 @@ class ComRegister {
1268
1533
  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 }))) })] });
1269
1534
  }
1270
1535
  // 设置更新后的提示
1271
- this.subNotifier = ctx.notifier.create(table);
1536
+ this.subNotifier = this.ctx.notifier.create(table);
1272
1537
  }
1273
- async checkIfLoginInfoIsLoaded(ctx) {
1538
+ async checkIfLoginInfoIsLoaded() {
1274
1539
  return new Promise(resolve => {
1275
1540
  const check = () => {
1276
- if (!ctx.ba.getLoginInfoIsLoaded()) {
1277
- ctx.setTimeout(check, 500);
1541
+ if (!this.ctx.ba.getLoginInfoIsLoaded()) {
1542
+ this.ctx.setTimeout(check, 500);
1278
1543
  }
1279
1544
  else {
1280
1545
  resolve('success');
@@ -1283,17 +1548,17 @@ class ComRegister {
1283
1548
  check();
1284
1549
  });
1285
1550
  }
1286
- async subUserInBili(ctx, mid) {
1551
+ async subUserInBili(mid) {
1287
1552
  // 获取关注分组信息
1288
1553
  const checkGroupIsReady = async () => {
1289
1554
  // 判断是否有数据
1290
1555
  if (this.loginDBData.dynamic_group_id === '' || this.loginDBData.dynamic_group_id === null) {
1291
1556
  // 没有数据,没有创建分组,尝试创建分组
1292
- const createGroupData = await ctx.ba.createGroup("订阅");
1557
+ const createGroupData = await this.ctx.ba.createGroup("订阅");
1293
1558
  // 如果分组已创建,则获取分组id
1294
1559
  if (createGroupData.code === 22106) {
1295
1560
  // 分组已存在,拿到之前的分组id
1296
- const allGroupData = await ctx.ba.getAllGroup();
1561
+ const allGroupData = await this.ctx.ba.getAllGroup();
1297
1562
  // 遍历所有分组
1298
1563
  for (const group of allGroupData.data) {
1299
1564
  // 找到订阅分组
@@ -1311,7 +1576,7 @@ class ComRegister {
1311
1576
  return false;
1312
1577
  }
1313
1578
  // 创建成功,保存到数据库
1314
- ctx.database.set('loginBili', 1, { dynamic_group_id: this.loginDBData.dynamic_group_id });
1579
+ this.ctx.database.set('loginBili', 1, { dynamic_group_id: this.loginDBData.dynamic_group_id });
1315
1580
  // 创建成功
1316
1581
  return true;
1317
1582
  }
@@ -1325,7 +1590,7 @@ class ComRegister {
1325
1590
  return { flag: false, msg: '创建分组失败,请尝试重启插件' };
1326
1591
  }
1327
1592
  // 获取分组明细
1328
- const relationGroupDetailData = await ctx.ba.getRelationGroupDetail(this.loginDBData.dynamic_group_id);
1593
+ const relationGroupDetailData = await this.ctx.ba.getRelationGroupDetail(this.loginDBData.dynamic_group_id);
1329
1594
  // 判断分组信息是否获取成功
1330
1595
  if (relationGroupDetailData.code !== 0) {
1331
1596
  if (relationGroupDetailData.code === 22104) {
@@ -1350,7 +1615,7 @@ class ComRegister {
1350
1615
  }
1351
1616
  });
1352
1617
  // 订阅对象
1353
- const subUserData = await ctx.ba.follow(mid);
1618
+ const subUserData = await this.ctx.ba.follow(mid);
1354
1619
  // 判断是否订阅成功
1355
1620
  switch (subUserData.code) {
1356
1621
  case -101: return { flag: false, msg: '账号未登录,请使用指令bili login登录后再进行订阅操作' };
@@ -1363,7 +1628,7 @@ class ComRegister {
1363
1628
  case 22014: // 已关注订阅对象 无需再次关注
1364
1629
  case 0: { // 执行订阅成功
1365
1630
  // 把订阅对象添加到分组中
1366
- const copyUserToGroupData = await ctx.ba.copyUserToGroup(mid, this.loginDBData.dynamic_group_id);
1631
+ const copyUserToGroupData = await this.ctx.ba.copyUserToGroup(mid, this.loginDBData.dynamic_group_id);
1367
1632
  // 判断是否添加成功
1368
1633
  if (copyUserToGroupData.code !== 0) {
1369
1634
  // 添加失败
@@ -1374,11 +1639,68 @@ class ComRegister {
1374
1639
  // 订阅成功
1375
1640
  return { flag: true, msg: '用户订阅成功' };
1376
1641
  }
1377
- async getSubFromDatabase(ctx) {
1642
+ async loadSubFromConfig(subs) {
1643
+ for (const sub of subs) {
1644
+ // 定义Data
1645
+ let data;
1646
+ // 判断是否需要订阅直播
1647
+ if (sub.live) {
1648
+ // 获取用户信息
1649
+ let content;
1650
+ // 设置重试次数
1651
+ const attempts = 3;
1652
+ for (let i = 0; i < attempts; i++) {
1653
+ try {
1654
+ // 获取用户信息
1655
+ content = await this.ctx.ba.getUserInfo(sub.uid);
1656
+ // 成功则跳出循环
1657
+ break;
1658
+ }
1659
+ catch (e) {
1660
+ this.logger.error('getSubFromDatabase() getUserInfo() 发生了错误,错误为:' + e.message);
1661
+ if (i === attempts - 1) { // 已尝试三次
1662
+ // 发送私聊消息并重启服务
1663
+ return await this.sendPrivateMsgAndStopService();
1664
+ }
1665
+ }
1666
+ }
1667
+ // 获取data
1668
+ data = content.data;
1669
+ // 检查roomid是否存在
1670
+ if (!data.live_room) {
1671
+ // 用户没有开通直播间,无法订阅直播
1672
+ sub.live = false;
1673
+ // 发送提示
1674
+ this.logger.warn(`UID:${sub.uid} 用户没有开通直播间,无法订阅直播!`);
1675
+ }
1676
+ // 判断是否订阅直播
1677
+ if (sub.live) {
1678
+ // 订阅直播
1679
+ this.liveDetectWithListener(data.live_room.roomid, sub.target);
1680
+ }
1681
+ }
1682
+ // 在B站中订阅该对象
1683
+ const subInfo = await this.subUserInBili(sub.uid);
1684
+ // 判断订阅是否成功
1685
+ if (!subInfo.flag)
1686
+ this.logger.warn(subInfo.msg);
1687
+ // 将该订阅添加到sm中
1688
+ this.subManager.push({
1689
+ id: +sub.uid,
1690
+ uid: sub.uid,
1691
+ roomId: sub.live ? data.live_room.roomid : '',
1692
+ target: sub.target,
1693
+ platform: '',
1694
+ live: sub.live,
1695
+ dynamic: sub.dynamic
1696
+ });
1697
+ }
1698
+ }
1699
+ async loadSubFromDatabase() {
1378
1700
  // 判断登录信息是否已加载完毕
1379
- await this.checkIfLoginInfoIsLoaded(ctx);
1701
+ await this.checkIfLoginInfoIsLoaded();
1380
1702
  // 如果未登录,则直接返回
1381
- if (!(await this.checkIfIsLogin(ctx))) {
1703
+ if (!(await this.checkIfIsLogin())) {
1382
1704
  // log
1383
1705
  this.logger.info(`账号未登录,请登录`);
1384
1706
  return;
@@ -1387,7 +1709,7 @@ class ComRegister {
1387
1709
  if (this.subManager.length !== 0)
1388
1710
  return;
1389
1711
  // 从数据库中获取数据
1390
- const subData = await ctx.database.get('bilibili', { id: { $gt: 0 } });
1712
+ const subData = await this.ctx.database.get('bilibili', { id: { $gt: 0 } });
1391
1713
  // 定义变量:订阅直播数
1392
1714
  let liveSubNum = 0;
1393
1715
  // 循环遍历
@@ -1395,14 +1717,14 @@ class ComRegister {
1395
1717
  // 判断是否存在没有任何订阅的数据
1396
1718
  if (!sub.dynamic && !sub.live) { // 存在未订阅任何项目的数据
1397
1719
  // 删除该条数据
1398
- ctx.database.remove('bilibili', { id: sub.id });
1720
+ this.ctx.database.remove('bilibili', { id: sub.id });
1399
1721
  // log
1400
1722
  this.logger.warn(`UID:${sub.uid} 该条数据没有任何订阅数据,自动取消订阅`);
1401
1723
  // 跳过下面的步骤
1402
1724
  continue;
1403
1725
  }
1404
1726
  // 判断用户是否在B站中订阅了
1405
- const subUserData = await this.subUserInBili(ctx, sub.uid);
1727
+ const subUserData = await this.subUserInBili(sub.uid);
1406
1728
  // 判断是否订阅
1407
1729
  if (!subUserData.flag) {
1408
1730
  // log
@@ -1410,7 +1732,7 @@ class ComRegister {
1410
1732
  // 发送私聊消息
1411
1733
  await this.sendPrivateMsg(`UID:${sub.uid} ${subUserData.msg},自动取消订阅`);
1412
1734
  // 删除该条数据
1413
- await ctx.database.remove('bilibili', { id: sub.id });
1735
+ await this.ctx.database.remove('bilibili', { id: sub.id });
1414
1736
  // 跳过下面的步骤
1415
1737
  continue;
1416
1738
  }
@@ -1423,7 +1745,7 @@ class ComRegister {
1423
1745
  for (let i = 0; i < attempts; i++) {
1424
1746
  try {
1425
1747
  // 获取用户信息
1426
- content = await ctx.ba.getUserInfo(sub.uid);
1748
+ content = await this.ctx.ba.getUserInfo(sub.uid);
1427
1749
  // 成功则跳出循环
1428
1750
  break;
1429
1751
  }
@@ -1431,7 +1753,7 @@ class ComRegister {
1431
1753
  this.logger.error('getSubFromDatabase() getUserInfo() 发生了错误,错误为:' + e.message);
1432
1754
  if (i === attempts - 1) { // 已尝试三次
1433
1755
  // 发送私聊消息并重启服务
1434
- return await this.sendPrivateMsgAndStopService(ctx);
1756
+ return await this.sendPrivateMsgAndStopService();
1435
1757
  }
1436
1758
  }
1437
1759
  }
@@ -1440,7 +1762,7 @@ class ComRegister {
1440
1762
  // 定义函数删除数据和发送提示
1441
1763
  const deleteSub = async () => {
1442
1764
  // 从数据库删除该条数据
1443
- await ctx.database.remove('bilibili', { id: sub.id });
1765
+ await this.ctx.database.remove('bilibili', { id: sub.id });
1444
1766
  // 给用户发送提示
1445
1767
  await this.sendPrivateMsg(`UID:${sub.uid} 数据库内容被篡改,已取消对该UP主的订阅`);
1446
1768
  };
@@ -1472,6 +1794,7 @@ class ComRegister {
1472
1794
  this.logger.info(`UID:${sub.uid} 房间号被篡改,自动取消订阅`);
1473
1795
  // Send msg
1474
1796
  await this.sendPrivateMsg(`UID:${sub.uid} 房间号被篡改,自动取消订阅`);
1797
+ // 直接返回
1475
1798
  return;
1476
1799
  }
1477
1800
  // 构建订阅对象
@@ -1481,46 +1804,47 @@ class ComRegister {
1481
1804
  roomId: sub.room_id,
1482
1805
  target,
1483
1806
  platform: sub.platform,
1484
- live: +sub.live === 1 ? true : false,
1485
- dynamic: +sub.dynamic === 1 ? true : false,
1807
+ live: sub.live === 1 ? true : false,
1808
+ dynamic: sub.dynamic === 1 ? true : false,
1486
1809
  liveDispose: null
1487
1810
  };
1488
1811
  // 判断是否订阅直播
1489
1812
  if (sub.live) {
1490
1813
  // 判断订阅直播数是否超过限制
1491
1814
  if (!this.config.unlockSubLimits && liveSubNum >= 3) {
1815
+ // 将live改为false
1492
1816
  subManagerItem.live = false;
1493
1817
  // log
1494
1818
  this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1495
1819
  // 发送错误消息
1496
- this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1820
+ await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1497
1821
  }
1498
1822
  else {
1499
1823
  // 直播订阅数+1
1500
1824
  liveSubNum++;
1501
1825
  // 订阅直播,开始循环检测
1502
- const dispose = ctx.setInterval(this.liveDetect(ctx, sub.room_id, target), this.config.liveLoopTime * 1000);
1503
- // 保存销毁函数
1504
- subManagerItem.liveDispose = dispose;
1826
+ this.liveDetectWithListener(sub.room_id, target);
1505
1827
  }
1506
1828
  }
1507
1829
  // 保存新订阅对象
1508
1830
  this.subManager.push(subManagerItem);
1509
1831
  }
1832
+ }
1833
+ checkIfDynamicDetectIsNeeded() {
1510
1834
  // 检查是否有订阅对象需要动态监测
1511
- if (this.subManager.some(sub => sub.dynamic)) {
1512
- // 开始动态监测
1513
- if (this.config.dynamicDebugMode) {
1514
- this.dynamicDispose = ctx.setInterval(this.debug_dynamicDetect(ctx), 10000);
1515
- }
1516
- else {
1517
- this.dynamicDispose = ctx.setInterval(this.dynamicDetect(ctx), 10000 /* this.config.dynamicLoopTime * 1000 */);
1518
- }
1835
+ if (this.subManager.some(sub => sub.dynamic))
1836
+ this.enableDynamicDetect();
1837
+ }
1838
+ enableDynamicDetect() {
1839
+ // 开始动态监测
1840
+ if (this.config.dynamicDebugMode) {
1841
+ this.dynamicDispose = this.ctx.setInterval(this.debug_dynamicDetect(), this.config.dynamicLoopTime * 1000);
1842
+ }
1843
+ else {
1844
+ this.dynamicDispose = this.ctx.setInterval(this.dynamicDetect(), this.config.dynamicLoopTime * 1000);
1519
1845
  }
1520
- // 在控制台中显示订阅对象
1521
- this.updateSubNotifier(ctx);
1522
1846
  }
1523
- unsubSingle(ctx, id /* UID或RoomId */, type /* 0取消Live订阅,1取消Dynamic订阅 */) {
1847
+ unsubSingle(id /* UID或RoomId */, type /* 0取消Live订阅,1取消Dynamic订阅 */) {
1524
1848
  // 定义返回消息
1525
1849
  let msg;
1526
1850
  // 定义方法:检查是否没有任何订阅
@@ -1530,7 +1854,7 @@ class ComRegister {
1530
1854
  // 从管理对象中移除
1531
1855
  this.subManager.splice(index, 1);
1532
1856
  // 从数据库中删除
1533
- ctx.database.remove('bilibili', [this.subManager[index].id]);
1857
+ this.ctx.database.remove('bilibili', [this.subManager[index].id]);
1534
1858
  // num--
1535
1859
  this.num--;
1536
1860
  // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
@@ -1549,9 +1873,6 @@ class ComRegister {
1549
1873
  return msg;
1550
1874
  }
1551
1875
  // 取消订阅
1552
- if (sub.live)
1553
- sub.liveDispose();
1554
- sub.liveDispose = null;
1555
1876
  sub.live = false;
1556
1877
  // 如果没有对这个UP的任何订阅,则移除
1557
1878
  if (checkIfNoSubExist(sub)) {
@@ -1560,7 +1881,7 @@ class ComRegister {
1560
1881
  return '已取消订阅该用户';
1561
1882
  }
1562
1883
  // 更新数据库
1563
- ctx.database.upsert('bilibili', [{
1884
+ this.ctx.database.upsert('bilibili', [{
1564
1885
  id: +`${sub.id}`,
1565
1886
  live: 0
1566
1887
  }]);
@@ -1587,7 +1908,7 @@ class ComRegister {
1587
1908
  return '已取消订阅该用户';
1588
1909
  }
1589
1910
  // 更新数据库
1590
- ctx.database.upsert('bilibili', [{
1911
+ this.ctx.database.upsert('bilibili', [{
1591
1912
  id: sub.id,
1592
1913
  dynamic: 0
1593
1914
  }]);
@@ -1597,25 +1918,22 @@ class ComRegister {
1597
1918
  }
1598
1919
  finally {
1599
1920
  // 执行完该方法后,保证执行一次updateSubNotifier()
1600
- this.updateSubNotifier(ctx);
1921
+ this.updateSubNotifier();
1601
1922
  }
1602
1923
  }
1603
1924
  checkIfUserIsTheLastOneWhoSubDyn() {
1604
- if (this.subManager.some(sub => sub.dynamic)) {
1925
+ if (this.dynamicDispose && !this.subManager.some(sub => sub.dynamic)) {
1605
1926
  // 停止动态监测
1606
1927
  this.dynamicDispose();
1607
1928
  this.dynamicDispose = null;
1608
1929
  }
1609
1930
  }
1610
- unsubAll(ctx, uid) {
1931
+ unsubAll(uid) {
1611
1932
  this.subManager.filter(sub => sub.uid === uid).map(async (sub, i) => {
1612
- // 取消全部订阅 执行dispose方法,销毁定时器
1613
- if (sub.live)
1614
- await this.subManager[i].liveDispose();
1615
1933
  // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
1616
1934
  this.checkIfUserIsTheLastOneWhoSubDyn();
1617
1935
  // 从数据库中删除订阅
1618
- await ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
1936
+ await this.ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
1619
1937
  // 将该订阅对象从订阅管理对象中移除
1620
1938
  this.subManager.splice(i, 1);
1621
1939
  // id--
@@ -1623,13 +1941,13 @@ class ComRegister {
1623
1941
  // 发送成功通知
1624
1942
  this.sendPrivateMsg(`UID:${uid},已取消订阅该用户`);
1625
1943
  // 更新控制台提示
1626
- this.updateSubNotifier(ctx);
1944
+ this.updateSubNotifier();
1627
1945
  });
1628
1946
  }
1629
- async checkIfIsLogin(ctx) {
1630
- if ((await ctx.database.get('loginBili', 1)).length !== 0) { // 数据库中有数据
1947
+ async checkIfIsLogin() {
1948
+ if ((await this.ctx.database.get('loginBili', 1)).length !== 0) { // 数据库中有数据
1631
1949
  // 检查cookie中是否有值
1632
- if (ctx.ba.getCookies() !== '[]') { // 有值说明已登录
1950
+ if (this.ctx.ba.getCookies() !== '[]') { // 有值说明已登录
1633
1951
  return true;
1634
1952
  }
1635
1953
  }
@@ -1638,6 +1956,21 @@ class ComRegister {
1638
1956
  }
1639
1957
  (function (ComRegister) {
1640
1958
  ComRegister.Config = koishi_1.Schema.object({
1959
+ sub: koishi_1.Schema.array(koishi_1.Schema.object({
1960
+ uid: koishi_1.Schema.string().description('订阅用户UID'),
1961
+ dynamic: koishi_1.Schema.boolean().description('是否订阅用户动态'),
1962
+ live: koishi_1.Schema.boolean().description('是否订阅用户直播'),
1963
+ target: koishi_1.Schema.array(koishi_1.Schema.object({
1964
+ channelIdArr: koishi_1.Schema.array(koishi_1.Schema.object({
1965
+ channelId: koishi_1.Schema.string().description('频道/群组号'),
1966
+ dynamic: koishi_1.Schema.boolean().description('该频道/群组是否推送动态信息'),
1967
+ live: koishi_1.Schema.boolean().description('该频道/群组是否推送直播通知'),
1968
+ liveDanmaku: koishi_1.Schema.boolean().description('该频道/群组是否推送弹幕消息'),
1969
+ atAll: koishi_1.Schema.boolean().description('推送开播通知时是否艾特全体成员')
1970
+ })).description('频道/群组信息'),
1971
+ platform: koishi_1.Schema.string().description('推送平台')
1972
+ })).description('订阅用户需要发送的频道/群组信息')
1973
+ })).role('table').description('手动输入订阅信息,方便自定义订阅内容,这里的订阅内容不会存入数据库。uid: 订阅用户UID,dynamic: 是否需要订阅动态,live: 是否需要订阅直播'),
1641
1974
  master: koishi_1.Schema.object({
1642
1975
  enable: koishi_1.Schema.boolean(),
1643
1976
  platform: koishi_1.Schema.string(),
@@ -1646,8 +1979,6 @@ class ComRegister {
1646
1979
  }),
1647
1980
  unlockSubLimits: koishi_1.Schema.boolean().required(),
1648
1981
  automaticResend: koishi_1.Schema.boolean().required(),
1649
- changeMasterInfoApi: koishi_1.Schema.boolean().required(),
1650
- liveStartAtAll: koishi_1.Schema.boolean().required(),
1651
1982
  restartPush: koishi_1.Schema.boolean().required(),
1652
1983
  pushTime: koishi_1.Schema.number().required(),
1653
1984
  liveLoopTime: koishi_1.Schema.number().default(10),