koishi-plugin-bilibili-notify 3.0.0-alpha.0 → 3.0.0-alpha.10

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.
@@ -42,8 +42,10 @@ class ComRegister {
42
42
  loginDBData;
43
43
  // 机器人实例
44
44
  privateBot;
45
- // 动态销毁函数
45
+ // 动态检测销毁函数
46
46
  dynamicDispose;
47
+ // 直播检测销毁函数
48
+ liveDispose;
47
49
  // 发送消息方式
48
50
  sendMsgFunc;
49
51
  // 构造函数
@@ -163,6 +165,8 @@ class ComRegister {
163
165
  }]);
164
166
  // 销毁定时器
165
167
  this.loginTimer();
168
+ // 订阅手动订阅中的订阅
169
+ await this.loadSubFromConfig(config.sub);
166
170
  // 订阅之前的订阅
167
171
  await this.loadSubFromDatabase();
168
172
  // 清除控制台通知
@@ -173,7 +177,6 @@ class ComRegister {
173
177
  await session.execute('bili show');
174
178
  // 开启cookies刷新检测
175
179
  ctx.ba.enableRefreshCookiesDetect();
176
- return;
177
180
  }
178
181
  }
179
182
  finally {
@@ -437,10 +440,23 @@ class ComRegister {
437
440
  this.logger.error('bili sub指令 getMasterInfo() 发生了错误,错误为:' + e.message);
438
441
  return '订阅出错啦,请重试';
439
442
  }
443
+ const liveDetectModeSelector = {
444
+ API: async () => {
445
+ // 判断是否已开启直播检测
446
+ if (!this.liveDispose) { // 未开启直播检测
447
+ // 开启直播检测并保存销毁函数
448
+ this.liveDispose = await this.liveDetectWithAPI();
449
+ }
450
+ },
451
+ WS: async () => {
452
+ // 连接到服务器
453
+ await this.liveDetectWithListener(roomId, target);
454
+ }
455
+ };
440
456
  // 订阅直播
441
457
  if (liveMsg) {
442
- // 连接到服务器
443
- this.liveDetectWithListener(roomId, target);
458
+ // 判断直播订阅方式
459
+ await liveDetectModeSelector[this.config.liveDetectMode]();
444
460
  // 发送订阅消息通知
445
461
  await session.send(`订阅${userData.info.uname}直播通知`);
446
462
  }
@@ -448,6 +464,7 @@ class ComRegister {
448
464
  if (dynamicMsg) {
449
465
  // 判断是否开启动态监测
450
466
  if (!this.dynamicDispose) {
467
+ // 开启动态监测
451
468
  this.enableDynamicDetect();
452
469
  }
453
470
  // 发送订阅消息通知
@@ -583,6 +600,14 @@ class ComRegister {
583
600
  }
584
601
  // 检查登录数据库是否有数据
585
602
  this.loginDBData = (await this.ctx.database.get('loginBili', 1, ['dynamic_group_id']))[0];
603
+ // 判断登录信息是否已加载完毕
604
+ await this.checkIfLoginInfoIsLoaded();
605
+ // 如果未登录,则直接返回
606
+ if (!(await this.checkIfIsLogin())) {
607
+ // log
608
+ this.logger.info(`账号未登录,请登录`);
609
+ return;
610
+ }
586
611
  // 从配置获取订阅
587
612
  config.sub && await this.loadSubFromConfig(config.sub);
588
613
  // 从数据库获取订阅
@@ -705,8 +730,12 @@ class ComRegister {
705
730
  }
706
731
  }
707
732
  dynamicDetect() {
733
+ // 检测初始化变量
708
734
  let detectSetup = true;
735
+ // 更新基线
709
736
  let updateBaseline;
737
+ // 第一条动态的动态ID
738
+ let dynamicIdStr;
710
739
  // 相当于锁的作用,防止上一个循环没处理完
711
740
  let flag = true;
712
741
  // 返回一个闭包函数
@@ -803,14 +832,23 @@ class ComRegister {
803
832
  // 寻找关注的UP主的动态
804
833
  this.subManager.forEach(async (sub) => {
805
834
  // 判断是否是订阅的UP主
806
- if (sub.uid == upUID) {
807
- // 订阅该UP主,推送该动态
835
+ if (sub.dynamic && sub.uid == upUID) { // 订阅该UP主,推送该动态
836
+ // 判断更新动态是否为1条
837
+ if (updateNum === 1) {
838
+ // 判断dynamicIdStr是否有值,是否与当前动态ID一致
839
+ if (dynamicIdStr && dynamicIdStr === items[num].id_str) {
840
+ // 重复动态,不再推送,直接返回
841
+ return;
842
+ }
843
+ // 存储该动态ID
844
+ dynamicIdStr = items[num].id_str;
845
+ }
808
846
  // 定义变量
809
847
  let pic;
810
848
  let buffer;
811
849
  // 从动态数据中取出UP主名称和动态ID
812
- const upName = content.data.items[num].modules.module_author.name;
813
- const dynamicId = content.data.items[num].id_str;
850
+ const upName = items[num].modules.module_author.name;
851
+ const dynamicId = items[num].id_str;
814
852
  // 推送该条动态
815
853
  const attempts = 3;
816
854
  for (let i = 0; i < attempts; i++) {
@@ -875,8 +913,12 @@ class ComRegister {
875
913
  };
876
914
  }
877
915
  debug_dynamicDetect() {
916
+ // 检测初始化变量
878
917
  let detectSetup = true;
918
+ // 更新基线
879
919
  let updateBaseline;
920
+ // 第一条动态的动态ID
921
+ let dynamicIdStr;
880
922
  // 相当于锁的作用,防止上一个循环没处理完
881
923
  let flag = true;
882
924
  // 返回一个闭包函数
@@ -986,14 +1028,23 @@ class ComRegister {
986
1028
  this.subManager.forEach(async (sub) => {
987
1029
  console.log(`当前订阅UP主:${sub.uid}`);
988
1030
  // 判断是否是订阅的UP主
989
- if (sub.uid == upUID) {
990
- // 订阅该UP主,推送该动态
1031
+ if (sub.dynamic && sub.uid == upUID) { // 订阅该UP主,推送该动态
1032
+ // 判断更新动态是否为1条
1033
+ if (updateNum === 1) {
1034
+ // 判断dynamicIdStr是否有值,是否与当前动态ID一致
1035
+ if (dynamicIdStr && dynamicIdStr === items[num].id_str) {
1036
+ // 重复动态,不再推送,直接返回
1037
+ return;
1038
+ }
1039
+ // 存储该动态ID
1040
+ dynamicIdStr = items[num].id_str;
1041
+ }
991
1042
  // 定义变量
992
1043
  let pic;
993
1044
  let buffer;
994
1045
  // 从动态数据中取出UP主名称和动态ID
995
- const upName = content.data.items[num].modules.module_author.name;
996
- const dynamicId = content.data.items[num].id_str;
1046
+ const upName = items[num].modules.module_author.name;
1047
+ const dynamicId = items[num].id_str;
997
1048
  console.log(`UP主名称:${upName},动态ID:${dynamicId}`);
998
1049
  // 推送该条动态
999
1050
  const attempts = 3;
@@ -1130,21 +1181,13 @@ class ComRegister {
1130
1181
  }
1131
1182
  async liveDetectWithAPI() {
1132
1183
  // 定义变量:第一次订阅
1133
- let firstSubscription = true;
1184
+ let liveDetectSetup = true;
1134
1185
  // 定义变量:timer计时器
1135
1186
  let timer = 0;
1136
1187
  // 相当于锁的作用,防止上一个循环没处理完
1137
1188
  let flag = true;
1138
1189
  // 定义订阅对象Record 0未开播 1正在直播 2轮播中
1139
1190
  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
1191
  // 定义函数: 发送请求获取直播状态
1149
1192
  const useLiveStatus = async (roomId) => {
1150
1193
  let content;
@@ -1176,10 +1219,18 @@ class ComRegister {
1176
1219
  try {
1177
1220
  // 获取正在直播对象
1178
1221
  const liveUsers = await this.ctx.ba.getTheUserWhoIsLiveStreaming();
1179
- // 判断是否是第一次订阅
1180
- if (firstSubscription) {
1222
+ // 判断是否是初始化直播监测
1223
+ if (liveDetectSetup) {
1181
1224
  // 将第一次订阅置为false
1182
- firstSubscription = false;
1225
+ liveDetectSetup = false;
1226
+ // 初始化subRecord
1227
+ this.subManager.forEach(sub => {
1228
+ // 判断是否订阅直播
1229
+ if (sub.live) {
1230
+ // 将该订阅添加到subRecord中
1231
+ liveRecord[sub.uid] = { liveStatus: 0, liveTime: '', target: sub.target };
1232
+ }
1233
+ });
1183
1234
  // 先判断是否有UP主正在直播
1184
1235
  if (liveUsers.count > 0) {
1185
1236
  // 遍历liveUsers
@@ -1190,6 +1241,8 @@ class ComRegister {
1190
1241
  const data = await useLiveStatus(item.room_id.toString());
1191
1242
  // 设置开播时间
1192
1243
  liveRecord[item.mid].liveTime = data.live_time;
1244
+ // 改变开播状态
1245
+ liveRecord[item.mid].liveStatus = 1;
1193
1246
  // 设置直播中消息
1194
1247
  const liveMsg = this.config.customLive ? this.config.customLive
1195
1248
  .replace('-name', item.uname)
@@ -1203,8 +1256,6 @@ class ComRegister {
1203
1256
  target: liveRecord[item.mid].target,
1204
1257
  data
1205
1258
  }, LiveType.LiveBroadcast, liveMsg);
1206
- // 改变开播状态
1207
- liveRecord[item.mid].liveStatus = 1;
1208
1259
  }
1209
1260
  });
1210
1261
  }
@@ -1312,6 +1363,8 @@ class ComRegister {
1312
1363
  const masterInfo = await this.useMasterInfo(subUID);
1313
1364
  // 获取直播间消息
1314
1365
  const liveRoomInfo = await this.useLiveRoomInfo(masterInfo.roomId.toString());
1366
+ // 设置开播时间
1367
+ liveRoomInfo.live_time = liveRecord[subUID].liveTime;
1315
1368
  // 定义下播播通知语
1316
1369
  const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1317
1370
  .replace('-name', masterInfo.username)
@@ -1340,10 +1393,21 @@ class ComRegister {
1340
1393
  // 定义弹幕存放数组
1341
1394
  const currentLiveDanmakuArr = [];
1342
1395
  const temporaryLiveDanmakuArr = [];
1396
+ // 定义开播状态
1397
+ let liveStatus = false;
1343
1398
  // 处理target
1399
+ // 定义channelIdArr总长度
1400
+ let channelIdArrLen = 0;
1401
+ // 定义数据
1402
+ let liveRoomInfo;
1403
+ let masterInfo;
1344
1404
  // 找到频道/群组对应的
1345
- const newTarget = target.map(channel => {
1405
+ const danmakuPushTargetArr = target.map(channel => {
1406
+ // 获取符合条件的target
1346
1407
  const liveDanmakuArr = channel.channelIdArr.filter(channelId => channelId.liveDanmaku);
1408
+ // 将当前liveDanmakuArr的长度+到channelIdArrLen中
1409
+ channelIdArrLen += liveDanmakuArr.length;
1410
+ // 返回符合的target
1347
1411
  return {
1348
1412
  channelIdArr: liveDanmakuArr,
1349
1413
  platform: channel.platform
@@ -1351,11 +1415,14 @@ class ComRegister {
1351
1415
  });
1352
1416
  // 定义定时推送函数
1353
1417
  const pushAtTimeFunc = async () => {
1354
- // 获取直播间信息
1355
- const liveRoomInfo = await this.useLiveRoomInfo(roomId);
1356
- // 获取主播信息
1357
- const masterInfo = await this.useMasterInfo(liveRoomInfo.uid);
1358
- // 定义直播中通知消息
1418
+ // 判断是否信息是否获取成功
1419
+ if (!(await useMasterAndLiveRoomInfo())) {
1420
+ // 未获取成功,直接返回
1421
+ return this.sendPrivateMsg('获取直播间信息失败,推送直播卡片失败!');
1422
+ }
1423
+ // 设置开播时间
1424
+ liveTime = liveRoomInfo.live_time;
1425
+ // 设置直播中消息
1359
1426
  const liveMsg = this.config.customLive ? this.config.customLive
1360
1427
  .replace('-name', masterInfo.username)
1361
1428
  .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
@@ -1364,24 +1431,58 @@ class ComRegister {
1364
1431
  await this.sendLiveNotifyCard({
1365
1432
  username: masterInfo.username,
1366
1433
  userface: masterInfo.userface,
1367
- target: newTarget,
1434
+ target,
1368
1435
  data: liveRoomInfo
1369
1436
  }, LiveType.LiveBroadcast, liveMsg);
1370
1437
  };
1371
1438
  // 定义弹幕推送函数
1372
1439
  const danmakuPushFunc = () => {
1373
1440
  // 判断数组是否有内容
1374
- if (temporaryLiveDanmakuArr.length > 0) {
1441
+ if (channelIdArrLen > 0 && temporaryLiveDanmakuArr.length > 0) {
1375
1442
  // 发送消息
1376
- this.sendMsg(newTarget, temporaryLiveDanmakuArr.join('\n'));
1443
+ this.sendMsg(danmakuPushTargetArr, temporaryLiveDanmakuArr.join('\n'));
1377
1444
  // 将临时消息数组清空
1378
1445
  temporaryLiveDanmakuArr.length = 0;
1379
1446
  }
1380
1447
  };
1381
- // 获取直播间信息
1382
- const liveRoomInfo = await this.useLiveRoomInfo(roomId);
1383
- // 获取主播信息
1384
- const masterInfo = await this.useMasterInfo(liveRoomInfo.uid);
1448
+ // 定义直播间信息获取函数
1449
+ const useMasterAndLiveRoomInfo = async () => {
1450
+ // 定义flag
1451
+ let flag = true;
1452
+ // 判断是否已存在值
1453
+ if (liveRoomInfo && masterInfo && liveTime) {
1454
+ // 所有值均已存在,不需要再获取信息
1455
+ return flag;
1456
+ }
1457
+ // 获取直播间信息
1458
+ liveRoomInfo = await this.useLiveRoomInfo(roomId).catch(() => {
1459
+ // 设置flag为false
1460
+ flag = false;
1461
+ // 返回空
1462
+ return null;
1463
+ });
1464
+ // 判断是否成功获取信息
1465
+ if (!flag || !liveRoomInfo || !liveRoomInfo.uid) {
1466
+ // 上一步未成功
1467
+ flag = false;
1468
+ // 返回flag
1469
+ return flag;
1470
+ }
1471
+ // 获取主播信息(需要满足flag为true,liveRoomInfo.uid有值)
1472
+ masterInfo = await this.useMasterInfo(liveRoomInfo.uid).catch(() => {
1473
+ // 设置flag为false
1474
+ flag = false;
1475
+ // 返回空
1476
+ return null;
1477
+ });
1478
+ // 返回信息
1479
+ return flag;
1480
+ };
1481
+ // 判断是否信息是否获取成功
1482
+ if (!(await useMasterAndLiveRoomInfo())) {
1483
+ // 未获取成功,直接返回
1484
+ return this.sendPrivateMsg('获取直播间信息失败,启动直播间弹幕检测失败!');
1485
+ }
1385
1486
  // 构建消息处理函数
1386
1487
  const handler = {
1387
1488
  onOpen: () => {
@@ -1411,49 +1512,67 @@ class ComRegister {
1411
1512
  temporaryLiveDanmakuArr.push(content);
1412
1513
  },
1413
1514
  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
1515
+ // 判断是否已经开播
1516
+ if (liveStatus)
1517
+ return;
1518
+ // 设置开播状态为true
1519
+ liveStatus = true;
1520
+ // 判断是否信息是否获取成功
1521
+ if (!(await useMasterAndLiveRoomInfo())) {
1522
+ // 设置开播状态为false
1523
+ liveStatus = false;
1524
+ // 未获取成功,直接返回
1525
+ return await this.sendPrivateMsg('获取直播间信息失败,推送直播开播卡片失败!');
1526
+ }
1527
+ // 设置开播时间
1528
+ liveTime = liveRoomInfo.live_time;
1529
+ // 定义开播通知语
1530
+ const liveStartMsg = this.config.customLiveStart ? this.config.customLiveStart
1420
1531
  .replace('-name', masterInfo.username)
1421
- .replace('-time', await this.ctx.gi.getTimeDifference(liveTime)) : null;
1422
- // 更改直播时长
1423
- liveRoomInfo.live_time = liveTime;
1424
- // 推送下播通知
1532
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1533
+ .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1534
+ // 推送开播通知
1425
1535
  await this.sendLiveNotifyCard({
1426
1536
  username: masterInfo.username,
1427
1537
  userface: masterInfo.userface,
1428
- target: newTarget,
1538
+ target,
1429
1539
  data: liveRoomInfo
1430
- }, LiveType.StopBroadcast, liveEndMsg);
1540
+ }, LiveType.StartBroadcasting, liveStartMsg);
1541
+ // 判断定时器是否已开启
1542
+ if (!pushAtTimeTimer) {
1543
+ // 开始直播,开启定时器
1544
+ pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1545
+ }
1431
1546
  },
1432
1547
  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;
1548
+ // 判断是否信息是否获取成功
1549
+ if (!(await useMasterAndLiveRoomInfo())) {
1550
+ // 未获取成功,直接返回
1551
+ return this.sendPrivateMsg('获取直播间信息失败,推送直播下播卡片失败!');
1552
+ }
1553
+ // 更改直播时长
1554
+ liveRoomInfo.live_time = liveTime;
1441
1555
  // 定义下播播通知语
1442
1556
  const liveEndMsg = this.config.customLiveEnd ? this.config.customLiveEnd
1443
1557
  .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;
1558
+ .replace('-time', await this.ctx.gi.getTimeDifference(liveTime)) : null;
1446
1559
  // 推送通知卡片
1447
1560
  await this.sendLiveNotifyCard({
1448
1561
  username: masterInfo.username,
1449
1562
  userface: masterInfo.userface,
1450
- target: newTarget,
1563
+ target,
1451
1564
  data: liveRoomInfo
1452
- }, LiveType.StartBroadcasting, liveEndMsg);
1565
+ }, LiveType.StopBroadcast, liveEndMsg);
1566
+ // 关闭定时推送定时器
1567
+ pushAtTimeTimer();
1568
+ // 将推送定时器变量置空
1569
+ pushAtTimeTimer = null;
1570
+ // 将直播状态设置为false
1571
+ liveStatus = false;
1453
1572
  }
1454
1573
  };
1455
1574
  // 启动直播间弹幕监测
1456
- this.ctx.bl.startLiveRoomListener(roomId, handler, danmakuPushFunc);
1575
+ await this.ctx.bl.startLiveRoomListener(roomId, handler, danmakuPushFunc);
1457
1576
  // 判断直播状态
1458
1577
  if (liveRoomInfo.live_status === 1) {
1459
1578
  // 设置开播时间
@@ -1468,12 +1587,18 @@ class ComRegister {
1468
1587
  await this.sendLiveNotifyCard({
1469
1588
  username: masterInfo.username,
1470
1589
  userface: masterInfo.userface,
1471
- target: newTarget,
1590
+ target,
1472
1591
  data: liveRoomInfo
1473
1592
  }, LiveType.LiveBroadcast, liveMsg);
1474
1593
  }
1475
1594
  // 正在直播,开启定时器
1476
- pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1595
+ // 判断定时器是否已开启
1596
+ if (!pushAtTimeTimer) {
1597
+ // 开始直播,开启定时器
1598
+ pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1599
+ }
1600
+ // 设置直播状态为true
1601
+ liveStatus = true;
1477
1602
  }
1478
1603
  }
1479
1604
  subShow() {
@@ -1657,7 +1782,7 @@ class ComRegister {
1657
1782
  break;
1658
1783
  }
1659
1784
  catch (e) {
1660
- this.logger.error('getSubFromDatabase() getUserInfo() 发生了错误,错误为:' + e.message);
1785
+ this.logger.error('loadSubFromConfig() getUserInfo() 发生了错误,错误为:' + e.message);
1661
1786
  if (i === attempts - 1) { // 已尝试三次
1662
1787
  // 发送私聊消息并重启服务
1663
1788
  return await this.sendPrivateMsgAndStopService();
@@ -1673,10 +1798,24 @@ class ComRegister {
1673
1798
  // 发送提示
1674
1799
  this.logger.warn(`UID:${sub.uid} 用户没有开通直播间,无法订阅直播!`);
1675
1800
  }
1801
+ //
1802
+ const liveDetectModeSelector = {
1803
+ API: async () => {
1804
+ // 判断是否已开启直播检测
1805
+ if (!this.liveDispose) { // 未开启直播检测
1806
+ // 开启直播检测并保存销毁函数
1807
+ this.liveDispose = await this.liveDetectWithAPI();
1808
+ }
1809
+ },
1810
+ WS: async () => {
1811
+ // 连接到服务器
1812
+ await this.liveDetectWithListener(data.live_room.roomid, sub.target);
1813
+ }
1814
+ };
1676
1815
  // 判断是否订阅直播
1677
1816
  if (sub.live) {
1678
- // 订阅直播
1679
- this.liveDetectWithListener(data.live_room.roomid, sub.target);
1817
+ // 启动直播监测
1818
+ await liveDetectModeSelector[this.config.liveDetectMode]();
1680
1819
  }
1681
1820
  }
1682
1821
  // 在B站中订阅该对象
@@ -1697,17 +1836,6 @@ class ComRegister {
1697
1836
  }
1698
1837
  }
1699
1838
  async loadSubFromDatabase() {
1700
- // 判断登录信息是否已加载完毕
1701
- await this.checkIfLoginInfoIsLoaded();
1702
- // 如果未登录,则直接返回
1703
- if (!(await this.checkIfIsLogin())) {
1704
- // log
1705
- this.logger.info(`账号未登录,请登录`);
1706
- return;
1707
- }
1708
- // 已存在订阅管理对象,不再进行订阅操作
1709
- if (this.subManager.length !== 0)
1710
- return;
1711
1839
  // 从数据库中获取数据
1712
1840
  const subData = await this.ctx.database.get('bilibili', { id: { $gt: 0 } });
1713
1841
  // 定义变量:订阅直播数
@@ -1808,23 +1936,37 @@ class ComRegister {
1808
1936
  dynamic: sub.dynamic === 1 ? true : false,
1809
1937
  liveDispose: null
1810
1938
  };
1939
+ // 定义直播模式监测器
1940
+ const liveDetectModeSelector = {
1941
+ API: async () => {
1942
+ // 判断是否已开启直播检测
1943
+ if (!this.liveDispose) { // 未开启直播检测
1944
+ // 开启直播检测并保存销毁函数
1945
+ this.liveDispose = await this.liveDetectWithAPI();
1946
+ }
1947
+ },
1948
+ WS: async () => {
1949
+ // 判断订阅直播数是否超过限制
1950
+ if (!this.config.unlockSubLimits && liveSubNum >= 3) {
1951
+ // 将live改为false
1952
+ subManagerItem.live = false;
1953
+ // log
1954
+ this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1955
+ // 发送错误消息
1956
+ await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1957
+ }
1958
+ else {
1959
+ // 直播订阅数+1
1960
+ liveSubNum++;
1961
+ // 订阅直播,开始循环检测
1962
+ await this.liveDetectWithListener(sub.room_id, target);
1963
+ }
1964
+ }
1965
+ };
1811
1966
  // 判断是否订阅直播
1812
1967
  if (sub.live) {
1813
- // 判断订阅直播数是否超过限制
1814
- if (!this.config.unlockSubLimits && liveSubNum >= 3) {
1815
- // 将live改为false
1816
- subManagerItem.live = false;
1817
- // log
1818
- this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1819
- // 发送错误消息
1820
- await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1821
- }
1822
- else {
1823
- // 直播订阅数+1
1824
- liveSubNum++;
1825
- // 订阅直播,开始循环检测
1826
- this.liveDetectWithListener(sub.room_id, target);
1827
- }
1968
+ // 启动直播监测
1969
+ await liveDetectModeSelector[this.config.liveDetectMode]();
1828
1970
  }
1829
1971
  // 保存新订阅对象
1830
1972
  this.subManager.push(subManagerItem);
@@ -1874,6 +2016,17 @@ class ComRegister {
1874
2016
  }
1875
2017
  // 取消订阅
1876
2018
  sub.live = false;
2019
+ // 判断直播检测方式
2020
+ switch (this.config.liveDetectMode) {
2021
+ case 'API': {
2022
+ msg = '请手动删除订阅,并重启插件';
2023
+ break;
2024
+ }
2025
+ case 'WS': {
2026
+ // 取消直播监听
2027
+ this.ctx.bl.closeListener(sub.roomId);
2028
+ }
2029
+ }
1877
2030
  // 如果没有对这个UP的任何订阅,则移除
1878
2031
  if (checkIfNoSubExist(sub)) {
1879
2032
  // 从管理对象中移除
@@ -1932,6 +2085,15 @@ class ComRegister {
1932
2085
  this.subManager.filter(sub => sub.uid === uid).map(async (sub, i) => {
1933
2086
  // 判断是否还存在订阅了动态的对象,不存在则停止动态监测
1934
2087
  this.checkIfUserIsTheLastOneWhoSubDyn();
2088
+ switch (this.config.liveDetectMode) {
2089
+ case "API": {
2090
+ break;
2091
+ }
2092
+ case "WS": {
2093
+ // 停止直播检测
2094
+ this.ctx.bl.closeListener(sub.roomId);
2095
+ }
2096
+ }
1935
2097
  // 从数据库中删除订阅
1936
2098
  await this.ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
1937
2099
  // 将该订阅对象从订阅管理对象中移除
@@ -1979,6 +2141,10 @@ class ComRegister {
1979
2141
  }),
1980
2142
  unlockSubLimits: koishi_1.Schema.boolean().required(),
1981
2143
  automaticResend: koishi_1.Schema.boolean().required(),
2144
+ liveDetectMode: koishi_1.Schema.union([
2145
+ koishi_1.Schema.const('API'),
2146
+ koishi_1.Schema.const('WS')
2147
+ ]).required(),
1982
2148
  restartPush: koishi_1.Schema.boolean().required(),
1983
2149
  pushTime: koishi_1.Schema.number().required(),
1984
2150
  liveLoopTime: koishi_1.Schema.number().default(10),
@@ -176,7 +176,7 @@ class GenerateImg extends koishi_1.Service {
176
176
  </div>
177
177
  ${this.giConfig.hideDesc ? '' : `<p class="card-text">${data.description ? data.description : '这个主播很懒,什么都简介都没写'}</p>`}
178
178
  <p class="card-link">
179
- ${liveStatus !== 3 ? `<span>人气:${data.online > 10000 ? `${(data.online / 10000).toFixed(1)}万` : data.online}</span>` : ''}
179
+ <span>人气:${data.online > 10000 ? `${(data.online / 10000).toFixed(1)}万` : data.online}</span>
180
180
  <span>分区名称:${data.area_name}</span>
181
181
  </p>
182
182
  <p class="card-link">
@@ -1432,7 +1432,7 @@ class GenerateImg extends koishi_1.Service {
1432
1432
  }
1433
1433
  case 3: {
1434
1434
  titleStatus = '下播啦';
1435
- liveTime = `直播时长:${await this.getTimeDifference(time)}`;
1435
+ liveTime = `开播时间:${time}`;
1436
1436
  cover = true;
1437
1437
  break;
1438
1438
  }
@@ -1455,7 +1455,7 @@ class GenerateImg extends koishi_1.Service {
1455
1455
  const seconds = differenceInSeconds % 60;
1456
1456
  // 返回格式化的字符串
1457
1457
  return days ?
1458
- `${days} 天 ${hours}小时${minutes.toString().padStart(2, '0')}分${seconds.toString().padStart(2, '0')}秒` :
1458
+ `${days}天${hours}小时${minutes.toString().padStart(2, '0')}分${seconds.toString().padStart(2, '0')}秒` :
1459
1459
  `${hours}小时${minutes.toString().padStart(2, '0')}分${seconds.toString().padStart(2, '0')}秒`;
1460
1460
  }
1461
1461
  unixTimestampToString(timestamp) {
package/lib/index.d.ts CHANGED
@@ -6,6 +6,17 @@ declare module 'koishi' {
6
6
  sm: ServerManager;
7
7
  }
8
8
  }
9
+ declare class ServerManager extends Service {
10
+ servers: ForkScope[];
11
+ renderType: number;
12
+ dynamicLoopTime: number;
13
+ constructor(ctx: Context);
14
+ protected start(): void | Promise<void>;
15
+ registerPlugin: () => boolean;
16
+ disposePlugin: () => Promise<boolean>;
17
+ restartPlugin: () => Promise<boolean>;
18
+ }
19
+ export declare function apply(ctx: Context, config: Config): void;
9
20
  export interface Config {
10
21
  require: {};
11
22
  key: string;
@@ -36,6 +47,7 @@ export interface Config {
36
47
  dynamicCheckNumber: number;
37
48
  dynamicLoopTime: '1分钟' | '2分钟' | '3分钟' | '5分钟' | '10分钟' | '20分钟';
38
49
  live: {};
50
+ liveDetectMode: 'API' | 'WS';
39
51
  restartPush: boolean;
40
52
  pushTime: number;
41
53
  danmakuPushTime: number;
@@ -54,15 +66,4 @@ export interface Config {
54
66
  dynamicDebugMode: boolean;
55
67
  }
56
68
  export declare const Config: Schema<Config>;
57
- declare class ServerManager extends Service {
58
- servers: ForkScope[];
59
- renderType: number;
60
- dynamicLoopTime: number;
61
- constructor(ctx: Context);
62
- protected start(): void | Promise<void>;
63
- registerPlugin: () => boolean;
64
- disposePlugin: () => Promise<boolean>;
65
- restartPlugin: () => Promise<boolean>;
66
- }
67
- export declare function apply(ctx: Context, config: Config): void;
68
69
  export {};