koishi-plugin-bilibili-notify 3.3.5-alpha.0 → 3.3.6

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.
Files changed (4) hide show
  1. package/lib/index.js +105 -103
  2. package/lib/index.mjs +106 -103
  3. package/package.json +1 -1
  4. package/readme.md +0 -266
package/lib/index.js CHANGED
@@ -490,7 +490,8 @@ var ComRegister = class {
490
490
  });
491
491
  }
492
492
  let table = "";
493
- for (const user of subLiveUsers) table += `[UID:${user.uid}] 「${user.uname}」 ${user.onLive ? "正在直播" : "未开播"}\n`;
493
+ if (subLiveUsers.length === 0) table += "当前没有正在直播的订阅对象";
494
+ else for (const user of subLiveUsers) table += `[UID:${user.uid}] 「${user.uname}」 ${user.onLive ? "正在直播" : "未开播"}\n`;
494
495
  return table;
495
496
  });
496
497
  biliCom.subcommand(".dyn <uid:string> [index:number]", "手动推送一条动态信息", { hidden: true }).usage("手动推送一条动态信息").example("bili dyn 233 1 手动推送UID为233用户空间的第一条动态信息").action(async ({ session }, uid, index) => {
@@ -663,6 +664,7 @@ var ComRegister = class {
663
664
  return;
664
665
  }
665
666
  this.mergeStopWords(config.wordcloudStopWords);
667
+ this.initAllManager();
666
668
  this.registeringForEvents();
667
669
  if (config.advancedSub) {
668
670
  this.logger.info("开启高级订阅,等待加载订阅...");
@@ -693,7 +695,6 @@ var ComRegister = class {
693
695
  });
694
696
  }
695
697
  async initAsyncPart(subs) {
696
- this.initAllManager();
697
698
  this.logger.info("获取到订阅信息,开始加载订阅...");
698
699
  const { code, message } = await this.loadSubFromConfig(subs);
699
700
  if (code !== 0) {
@@ -702,7 +703,7 @@ var ComRegister = class {
702
703
  await this.sendPrivateMsg("订阅对象加载失败,插件初始化失败!");
703
704
  return;
704
705
  }
705
- this.initManager();
706
+ this.initManagerAfterLoadSub();
706
707
  this.checkIfDynamicDetectIsNeeded();
707
708
  this.checkIfLiveDetectIsNeeded();
708
709
  this.updateSubNotifier();
@@ -716,7 +717,7 @@ var ComRegister = class {
716
717
  const additionalStopWords = stopWordsStr.split(",").map((word) => word.trim()).filter((word) => word !== "");
717
718
  this.stopwords = new Set([...stop_words_default, ...additionalStopWords]);
718
719
  }
719
- initManager() {
720
+ initManagerAfterLoadSub() {
720
721
  for (const [uid, sub] of this.subManager) {
721
722
  if (sub.dynamic) this.dynamicTimelineManager.set(uid, Math.floor(luxon.DateTime.now().toSeconds()));
722
723
  if (sub.live) this.liveAPIManager.set(uid, {
@@ -732,12 +733,12 @@ var ComRegister = class {
732
733
  }
733
734
  }
734
735
  initAllManager() {
735
- this.subManager = new Map();
736
- this.dynamicTimelineManager = new Map();
737
- this.liveAPIManager = new Map();
738
- this.liveWSManager = new Map();
739
- this.liveMsgManager = new Map();
740
- this.pushArrMap = new Map();
736
+ this.subManager = /* @__PURE__ */ new Map();
737
+ this.dynamicTimelineManager = /* @__PURE__ */ new Map();
738
+ this.liveAPIManager = /* @__PURE__ */ new Map();
739
+ this.liveWSManager = /* @__PURE__ */ new Map();
740
+ this.liveMsgManager = /* @__PURE__ */ new Map();
741
+ this.pushArrMap = /* @__PURE__ */ new Map();
741
742
  }
742
743
  configSubsToSubscription(sub) {
743
744
  const subs = {};
@@ -806,7 +807,6 @@ var ComRegister = class {
806
807
  await this.sendPrivateMsg("插件发生未知错误,请检查机器人状态后使用指令 bn start 启动插件");
807
808
  this.logger.error("插件发生未知错误,请检查机器人状态后使用指令 bn start 启动插件");
808
809
  await this.ctx["bilibili-notify"].disposePlugin();
809
- return;
810
810
  }
811
811
  async sendMessageWithRetry(bot, channelId, content) {
812
812
  withRetry(async () => await bot.sendMessage(channelId, content), 1).catch(async (e) => {
@@ -901,43 +901,35 @@ var ComRegister = class {
901
901
  }
902
902
  }
903
903
  async broadcastToTargets(uid, content, type) {
904
- this.logger.info(`本次推送对象:${uid},推送类型:${PushTypeMsg[type]}`);
905
904
  const record = this.pushArrMap.get(uid);
906
- this.logger.info("本次推送目标:");
907
- if (type === PushType.StartBroadcasting && record.liveAtAllArr?.length >= 1) {
908
- this.logger.info(record.liveAtAllArr);
905
+ if (!record) return;
906
+ const hasTargets = type === PushType.StartBroadcasting && record.liveAtAllArr?.length > 0 || type === PushType.Dynamic && (record.dynamicArr?.length > 0 || record.dynamicAtAllArr?.length > 0) || (type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length > 0 || type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length > 0 || type === PushType.WordCloudAndLiveSummary && (record.wordcloudArr?.length > 0 || record.liveSummaryArr?.length > 0);
907
+ if (!hasTargets) return;
908
+ this.logger.info(`本次推送对象:${uid},推送类型:${PushTypeMsg[type]}`);
909
+ if (type === PushType.StartBroadcasting && record.liveAtAllArr?.length > 0) {
910
+ this.logger.info("推送 @全体:", record.liveAtAllArr);
909
911
  const atAllArr = structuredClone(record.liveAtAllArr);
910
- await withRetry(async () => {
911
- return await this.pushMessage(atAllArr, koishi.h.at("all"));
912
- }, 1);
912
+ await withRetry(() => this.pushMessage(atAllArr, koishi.h.at("all")), 1);
913
913
  }
914
- if (type === PushType.Dynamic && record.dynamicArr?.length >= 1) {
915
- if (record.dynamicAtAllArr?.length >= 1) {
916
- this.logger.info(record.dynamicAtAllArr);
914
+ if (type === PushType.Dynamic && record.dynamicArr?.length > 0) {
915
+ if (record.dynamicAtAllArr?.length > 0) {
916
+ this.logger.info("推送动态 @全体:", record.dynamicAtAllArr);
917
917
  const dynamicAtAllArr = structuredClone(record.dynamicAtAllArr);
918
- await withRetry(async () => {
919
- return await this.pushMessage(dynamicAtAllArr, koishi.h.at("all"));
920
- }, 1);
918
+ await withRetry(() => this.pushMessage(dynamicAtAllArr, koishi.h.at("all")), 1);
921
919
  }
922
- this.logger.info(record.dynamicArr);
920
+ this.logger.info("推送动态:", record.dynamicArr);
923
921
  const dynamicArr = structuredClone(record.dynamicArr);
924
- await withRetry(async () => {
925
- return await this.pushMessage(dynamicArr, (0, koishi.h)("message", content));
926
- }, 1);
922
+ await withRetry(() => this.pushMessage(dynamicArr, (0, koishi.h)("message", content)), 1);
927
923
  }
928
- if ((type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length >= 1) {
929
- this.logger.info(record.liveArr);
924
+ if ((type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length > 0) {
925
+ this.logger.info("推送直播:", record.liveArr);
930
926
  const liveArr = structuredClone(record.liveArr);
931
- await withRetry(async () => {
932
- return await this.pushMessage(liveArr, (0, koishi.h)("message", content));
933
- }, 1);
927
+ await withRetry(() => this.pushMessage(liveArr, (0, koishi.h)("message", content)), 1);
934
928
  }
935
- if (type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length >= 1) {
936
- this.logger.info(record.liveGuardBuyArr);
929
+ if (type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length > 0) {
930
+ this.logger.info("推送直播守护购买:", record.liveGuardBuyArr);
937
931
  const liveGuardBuyArr = structuredClone(record.liveGuardBuyArr);
938
- await withRetry(async () => {
939
- return await this.pushMessage(liveGuardBuyArr, (0, koishi.h)(koishi.h.Fragment, (0, koishi.h)(content)));
940
- }, 1);
932
+ await withRetry(() => this.pushMessage(liveGuardBuyArr, (0, koishi.h)(koishi.h.Fragment, (0, koishi.h)(content))), 1);
941
933
  }
942
934
  if (type === PushType.WordCloudAndLiveSummary) {
943
935
  const wordcloudArr = structuredClone(record.wordcloudArr);
@@ -946,25 +938,16 @@ var ComRegister = class {
946
938
  const wordcloudOnlyArr = wordcloudArr.filter((item) => !liveSummaryArr.includes(item));
947
939
  const liveSummaryOnlyArr = liveSummaryArr.filter((item) => !wordcloudArr.includes(item));
948
940
  if (wordcloudAndLiveSummaryArr.length > 0) {
949
- this.logger.info("词云和直播总结");
950
- this.logger.info(wordcloudAndLiveSummaryArr);
951
- await withRetry(async () => {
952
- return await this.pushMessage(wordcloudAndLiveSummaryArr, (0, koishi.h)("message", [content[0], content[1]]));
953
- }, 1);
941
+ this.logger.info("推送词云和直播总结:", wordcloudAndLiveSummaryArr);
942
+ await withRetry(() => this.pushMessage(wordcloudAndLiveSummaryArr, (0, koishi.h)("message", [content[0], content[1]])), 1);
954
943
  }
955
944
  if (wordcloudOnlyArr.length > 0) {
956
- this.logger.info("词云");
957
- this.logger.info(wordcloudOnlyArr);
958
- await withRetry(async () => {
959
- return await this.pushMessage(wordcloudOnlyArr, (0, koishi.h)("message", [content[0]]));
960
- }, 1);
945
+ this.logger.info("推送词云:", wordcloudOnlyArr);
946
+ await withRetry(() => this.pushMessage(wordcloudOnlyArr, (0, koishi.h)("message", [content[0]])), 1);
961
947
  }
962
948
  if (liveSummaryOnlyArr.length > 0) {
963
- this.logger.info("直播总结");
964
- this.logger.info(liveSummaryOnlyArr);
965
- await withRetry(async () => {
966
- return await this.pushMessage(liveSummaryOnlyArr, (0, koishi.h)("message", [content[1]]));
967
- }, 1);
949
+ this.logger.info("推送直播总结:", liveSummaryOnlyArr);
950
+ await withRetry(() => this.pushMessage(liveSummaryOnlyArr, (0, koishi.h)("message", [content[1]])), 1);
968
951
  }
969
952
  }
970
953
  }
@@ -978,24 +961,21 @@ var ComRegister = class {
978
961
  });
979
962
  if (!content) return;
980
963
  if (content.code !== 0) switch (content.code) {
981
- case -101: {
964
+ case -101:
982
965
  this.logger.error("账号未登录,插件已停止工作,请登录");
983
966
  await this.sendPrivateMsg("账号未登录,插件已停止工作,请登录");
984
967
  await this.ctx["bilibili-notify"].disposePlugin();
985
968
  break;
986
- }
987
- case -352: {
969
+ case -352:
988
970
  this.logger.error("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
989
971
  await this.sendPrivateMsg("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
990
972
  await this.ctx["bilibili-notify"].disposePlugin();
991
973
  break;
992
- }
993
- default: {
974
+ default:
994
975
  this.logger.error(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
995
976
  await this.sendPrivateMsg(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
996
977
  await this.ctx["bilibili-notify"].disposePlugin();
997
978
  break;
998
- }
999
979
  }
1000
980
  const items = content.data.items;
1001
981
  for (const item of items) {
@@ -1067,24 +1047,21 @@ var ComRegister = class {
1067
1047
  });
1068
1048
  if (!content) return;
1069
1049
  if (content.code !== 0) switch (content.code) {
1070
- case -101: {
1050
+ case -101:
1071
1051
  this.logger.error("账号未登录,插件已停止工作,请登录");
1072
1052
  await this.sendPrivateMsg("账号未登录,插件已停止工作,请登录");
1073
1053
  await this.ctx["bilibili-notify"].disposePlugin();
1074
1054
  break;
1075
- }
1076
- case -352: {
1055
+ case -352:
1077
1056
  this.logger.error("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
1078
1057
  await this.sendPrivateMsg("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
1079
1058
  await this.ctx["bilibili-notify"].disposePlugin();
1080
1059
  break;
1081
- }
1082
- default: {
1060
+ default:
1083
1061
  this.logger.error(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
1084
1062
  await this.sendPrivateMsg(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
1085
1063
  await this.ctx["bilibili-notify"].disposePlugin();
1086
1064
  break;
1087
- }
1088
1065
  }
1089
1066
  this.logger.info("获取动态信息成功!开始处理动态信息...");
1090
1067
  const items = content.data.items;
@@ -1286,10 +1263,14 @@ var ComRegister = class {
1286
1263
  });
1287
1264
  return flag;
1288
1265
  };
1266
+ const LIVE_EVENT_COOLDOWN = 10 * 1e3;
1267
+ let lastLiveStart = 0;
1268
+ let lastLiveEnd = 0;
1289
1269
  const handler = {
1290
1270
  onError: async () => {
1291
1271
  liveStatus = false;
1292
1272
  pushAtTimeTimer?.();
1273
+ pushAtTimeTimer = null;
1293
1274
  this.ctx["bilibili-notify-live"].closeListener(sub.roomid);
1294
1275
  await this.sendPrivateMsg(`[${sub.roomid}]直播间连接发生错误!`);
1295
1276
  this.logger.error(`[${sub.roomid}]直播间连接发生错误!`);
@@ -1310,16 +1291,30 @@ var ComRegister = class {
1310
1291
  this.broadcastToTargets(sub.uid, content, PushType.LiveGuardBuy);
1311
1292
  },
1312
1293
  onLiveStart: async () => {
1313
- if (liveStatus) return;
1294
+ const now = Date.now();
1295
+ if (now - lastLiveStart < LIVE_EVENT_COOLDOWN) {
1296
+ this.logger.warn(`[${sub.roomid}] 开播事件冷却期内被忽略`);
1297
+ if (!liveTime) {
1298
+ await useMasterAndLiveRoomInfo(LiveType.StartBroadcasting);
1299
+ liveTime = liveRoomInfo?.live_time || Date.now();
1300
+ }
1301
+ return;
1302
+ }
1303
+ lastLiveStart = now;
1304
+ if (liveStatus) {
1305
+ this.logger.warn(`[${sub.roomid}] 已是开播状态,忽略重复开播事件`);
1306
+ return;
1307
+ }
1314
1308
  liveStatus = true;
1315
1309
  if (!await useMasterAndLiveRoomInfo(LiveType.StartBroadcasting)) {
1316
1310
  liveStatus = false;
1317
1311
  await this.sendPrivateMsg("获取直播间信息失败,推送直播开播卡片失败!");
1318
1312
  return await this.sendPrivateMsgAndStopService();
1319
1313
  }
1320
- liveTime = liveRoomInfo.live_time;
1314
+ liveTime = liveRoomInfo?.live_time || Date.now();
1315
+ const diffTime = await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime);
1321
1316
  const follower = masterInfo.liveOpenFollowerNum >= 1e4 ? `${(masterInfo.liveOpenFollowerNum / 1e4).toFixed(1)}万` : masterInfo.liveOpenFollowerNum.toString();
1322
- const liveStartMsg = liveMsgObj.customLiveStart.replace("-name", masterInfo.username).replace("-time", await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime)).replace("-follower", follower).replaceAll("\\n", "\n").replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`);
1317
+ const liveStartMsg = liveMsgObj.customLiveStart.replace("-name", masterInfo.username).replace("-time", diffTime).replace("-follower", follower).replaceAll("\\n", "\n").replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`);
1323
1318
  await this.sendLiveNotifyCard(LiveType.StartBroadcasting, follower, {
1324
1319
  liveRoomInfo,
1325
1320
  masterInfo,
@@ -1331,25 +1326,43 @@ var ComRegister = class {
1331
1326
  }
1332
1327
  },
1333
1328
  onLiveEnd: async () => {
1329
+ const now = Date.now();
1330
+ if (now - lastLiveEnd < LIVE_EVENT_COOLDOWN) {
1331
+ this.logger.warn(`[${sub.roomid}] 下播事件冷却期内被忽略`);
1332
+ if (!liveTime) {
1333
+ await useMasterAndLiveRoomInfo(LiveType.StopBroadcast);
1334
+ liveTime = liveRoomInfo?.live_time || Date.now();
1335
+ }
1336
+ return;
1337
+ }
1338
+ lastLiveEnd = now;
1339
+ if (!liveStatus) {
1340
+ this.logger.warn(`[${sub.roomid}] 已是下播状态,忽略重复下播事件`);
1341
+ return;
1342
+ }
1334
1343
  liveStatus = false;
1335
1344
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast)) {
1336
1345
  await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
1337
1346
  return await this.sendPrivateMsgAndStopService();
1338
1347
  }
1339
- liveRoomInfo.live_time = liveTime;
1348
+ liveTime = liveTime || liveRoomInfo?.live_time || Date.now();
1349
+ const diffTime = await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime);
1340
1350
  const followerChange = (() => {
1341
1351
  const liveFollowerChangeNum = masterInfo.liveFollowerChange;
1342
- if (liveFollowerChangeNum > 0) return liveFollowerChangeNum >= 1e4 ? `+${liveFollowerChangeNum.toFixed(1)}万` : `+${liveFollowerChangeNum}`;
1343
- return liveFollowerChangeNum <= -1e4 ? `${liveFollowerChangeNum.toFixed(1)}万` : liveFollowerChangeNum.toString();
1352
+ if (liveFollowerChangeNum > 0) return liveFollowerChangeNum >= 1e4 ? `+${(liveFollowerChangeNum / 1e4).toFixed(1)}万` : `+${liveFollowerChangeNum}`;
1353
+ return liveFollowerChangeNum <= -1e4 ? `${(liveFollowerChangeNum / 1e4).toFixed(1)}万` : liveFollowerChangeNum.toString();
1344
1354
  })();
1345
- const liveEndMsg = liveMsgObj.customLiveEnd.replace("-name", masterInfo.username).replace("-time", await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime)).replace("-follower_change", followerChange).replaceAll("\\n", "\n");
1355
+ const liveEndMsg = liveMsgObj.customLiveEnd.replace("-name", masterInfo.username).replace("-time", diffTime).replace("-follower_change", followerChange).replaceAll("\\n", "\n");
1346
1356
  await this.sendLiveNotifyCard(LiveType.StopBroadcast, followerChange, {
1347
1357
  liveRoomInfo,
1348
1358
  masterInfo,
1349
1359
  cardStyle: sub.customCardStyle
1350
1360
  }, sub.uid, liveEndMsg);
1351
- pushAtTimeTimer();
1352
- pushAtTimeTimer = null;
1361
+ if (pushAtTimeTimer) {
1362
+ pushAtTimeTimer();
1363
+ pushAtTimeTimer = null;
1364
+ this.liveWSManager.delete(sub.roomid);
1365
+ }
1353
1366
  await sendDanmakuWordCloudAndLiveSummary(liveMsgObj.liveSummary);
1354
1367
  }
1355
1368
  };
@@ -1431,7 +1444,7 @@ var ComRegister = class {
1431
1444
  if (!sub) return;
1432
1445
  switch (item.live_status) {
1433
1446
  case 0:
1434
- case 2: {
1447
+ case 2:
1435
1448
  if (LiveAPIStatus.live === true) {
1436
1449
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast, LiveAPIStatus)) {
1437
1450
  await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
@@ -1455,8 +1468,7 @@ var ComRegister = class {
1455
1468
  LiveAPIStatus.live = false;
1456
1469
  }
1457
1470
  break;
1458
- }
1459
- case 1: {
1471
+ case 1:
1460
1472
  if (LiveAPIStatus.live === false) {
1461
1473
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast, LiveAPIStatus)) {
1462
1474
  await this.sendPrivateMsg("获取直播间信息失败,推送直播开播卡片失败!");
@@ -1495,7 +1507,6 @@ var ComRegister = class {
1495
1507
  LiveAPIStatus.push = 0;
1496
1508
  }
1497
1509
  break;
1498
- }
1499
1510
  default: break;
1500
1511
  }
1501
1512
  }
@@ -1754,7 +1765,7 @@ var ComRegister = class {
1754
1765
  }
1755
1766
  };
1756
1767
  (function(_ComRegister) {
1757
- const Config$1 = _ComRegister.Config = koishi.Schema.object({
1768
+ _ComRegister.Config = koishi.Schema.object({
1758
1769
  advancedSub: koishi.Schema.boolean(),
1759
1770
  subs: koishi.Schema.array(koishi.Schema.object({
1760
1771
  name: koishi.Schema.string().required().description("备注"),
@@ -2097,7 +2108,7 @@ var GenerateImg = class extends koishi.Service {
2097
2108
  switch (dynamic.type) {
2098
2109
  case DYNAMIC_TYPE_WORD:
2099
2110
  case DYNAMIC_TYPE_DRAW:
2100
- case DYNAMIC_TYPE_FORWARD: {
2111
+ case DYNAMIC_TYPE_FORWARD:
2101
2112
  basicDynamic();
2102
2113
  if (dynamic.type === DYNAMIC_TYPE_FORWARD) {
2103
2114
  if (this.giConfig.filter.enable && this.giConfig.filter.forward) throw new Error("已屏蔽转发动态");
@@ -2198,7 +2209,6 @@ var GenerateImg = class extends koishi.Service {
2198
2209
  }
2199
2210
  }
2200
2211
  break;
2201
- }
2202
2212
  case DYNAMIC_TYPE_AV: {
2203
2213
  basicDynamic();
2204
2214
  const archive = dynamic.modules.module_dynamic.major.archive;
@@ -2266,10 +2276,9 @@ var GenerateImg = class extends koishi.Service {
2266
2276
  case DYNAMIC_TYPE_LIVE: return [`${upName}发起了直播预约,我暂时无法渲染,请自行查看`];
2267
2277
  case DYNAMIC_TYPE_MEDIALIST: return [`${upName}分享了收藏夹,我暂时无法渲染,请自行查看`];
2268
2278
  case DYNAMIC_TYPE_PGC: return [`${upName}发布了剧集(番剧、电影、纪录片),我暂时无法渲染,请自行查看`];
2269
- case DYNAMIC_TYPE_ARTICLE: {
2279
+ case DYNAMIC_TYPE_ARTICLE:
2270
2280
  if (this.giConfig.filter.enable && this.giConfig.filter.article) throw new Error("已屏蔽专栏动态");
2271
2281
  return [`${upName}投稿了新专栏,我暂时无法渲染,请自行查看`];
2272
- }
2273
2282
  case DYNAMIC_TYPE_MUSIC: return [`${upName}发行了新歌,我暂时无法渲染,请自行查看`];
2274
2283
  case DYNAMIC_TYPE_COMMON_SQUARE: return [`${upName}发布了装扮|剧集|点评|普通分享,我暂时无法渲染,请自行查看`];
2275
2284
  case DYNAMIC_TYPE_COURSES_SEASON: return [`${upName}发布了新课程,我暂时无法渲染,请自行查看`];
@@ -3180,8 +3189,8 @@ var GenerateImg = class extends koishi.Service {
3180
3189
  </div>
3181
3190
  </div>
3182
3191
 
3183
- <script src="${wordcloudJS}"></script>
3184
- <script src="${renderFunc}"></script>
3192
+ <script src="${wordcloudJS}"><\/script>
3193
+ <script src="${renderFunc}"><\/script>
3185
3194
  <script>
3186
3195
  const canvas = document.getElementById('wordCloudCanvas');
3187
3196
  const ctx = canvas.getContext('2d');
@@ -3205,7 +3214,7 @@ var GenerateImg = class extends koishi.Service {
3205
3214
  densityTarget: 0.3,
3206
3215
  weightExponent: 0.4
3207
3216
  });
3208
- </script>
3217
+ <\/script>
3209
3218
  </body>
3210
3219
 
3211
3220
  </html>
@@ -3219,30 +3228,26 @@ var GenerateImg = class extends koishi.Service {
3219
3228
  let liveTime;
3220
3229
  let cover;
3221
3230
  switch (liveStatus) {
3222
- case 0: {
3231
+ case 0:
3223
3232
  titleStatus = "未直播";
3224
3233
  liveTime = "未开播";
3225
3234
  cover = true;
3226
3235
  break;
3227
- }
3228
- case 1: {
3236
+ case 1:
3229
3237
  titleStatus = "开播啦";
3230
3238
  liveTime = `开播时间:${time}`;
3231
3239
  cover = true;
3232
3240
  break;
3233
- }
3234
- case 2: {
3241
+ case 2:
3235
3242
  titleStatus = "正在直播";
3236
3243
  liveTime = `直播时长:${await this.getTimeDifference(time)}`;
3237
3244
  cover = false;
3238
3245
  break;
3239
- }
3240
- case 3: {
3246
+ case 3:
3241
3247
  titleStatus = "下播啦";
3242
3248
  liveTime = `开播时间:${time}`;
3243
3249
  cover = true;
3244
3250
  break;
3245
- }
3246
3251
  }
3247
3252
  return [
3248
3253
  titleStatus,
@@ -3273,7 +3278,7 @@ var GenerateImg = class extends koishi.Service {
3273
3278
  return parts.length > 0 ? `${sign}${parts.join("")}` : "0秒";
3274
3279
  }
3275
3280
  unixTimestampToString(timestamp) {
3276
- const date = new Date(timestamp * 1e3);
3281
+ const date = /* @__PURE__ */ new Date(timestamp * 1e3);
3277
3282
  const year = date.getFullYear();
3278
3283
  const month = `0${date.getMonth() + 1}`.slice(-2);
3279
3284
  const day = `0${date.getDate()}`.slice(-2);
@@ -3284,7 +3289,7 @@ var GenerateImg = class extends koishi.Service {
3284
3289
  }
3285
3290
  };
3286
3291
  (function(_GenerateImg) {
3287
- const Config$1 = _GenerateImg.Config = koishi.Schema.object({
3292
+ _GenerateImg.Config = koishi.Schema.object({
3288
3293
  filter: koishi.Schema.object({
3289
3294
  enable: koishi.Schema.boolean(),
3290
3295
  notify: koishi.Schema.boolean(),
@@ -4011,15 +4016,13 @@ var BiliAPI = class extends koishi.Service {
4011
4016
  }, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
4012
4017
  switch (refreshData.code) {
4013
4018
  case -101: return await this.createNewClient();
4014
- case -111: {
4019
+ case -111:
4015
4020
  await this.ctx.database.remove("loginBili", [1]);
4016
4021
  notifyAndError("csrf 校验错误,请重新登录");
4017
4022
  break;
4018
- }
4019
- case 86095: {
4023
+ case 86095:
4020
4024
  await this.ctx.database.remove("loginBili", [1]);
4021
4025
  notifyAndError("refresh_csrf 错误或 refresh_token 与 cookie 不匹配,请重新登录");
4022
- }
4023
4026
  }
4024
4027
  const encryptedCookies = this.encrypt(this.getCookies());
4025
4028
  const encryptedRefreshToken = this.encrypt(refreshData.data.refresh_token);
@@ -4036,11 +4039,10 @@ var BiliAPI = class extends koishi.Service {
4036
4039
  refresh_token: refreshToken
4037
4040
  }, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
4038
4041
  switch (aceeptData.code) {
4039
- case -111: {
4042
+ case -111:
4040
4043
  await this.ctx.database.remove("loginBili", [1]);
4041
4044
  notifyAndError("csrf 校验失败,请重新登录");
4042
4045
  break;
4043
- }
4044
4046
  case -400: throw new Error("请求错误");
4045
4047
  }
4046
4048
  }
@@ -4073,7 +4075,7 @@ var BiliAPI = class extends koishi.Service {
4073
4075
  }
4074
4076
  };
4075
4077
  (function(_BiliAPI) {
4076
- const Config$1 = _BiliAPI.Config = koishi.Schema.object({
4078
+ _BiliAPI.Config = koishi.Schema.object({
4077
4079
  userAgent: koishi.Schema.string(),
4078
4080
  key: koishi.Schema.string().pattern(/^[0-9a-f]{32}$/).required()
4079
4081
  });
package/lib/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import "node:module";
1
2
  import { Schema, Service, Universal, h } from "koishi";
2
3
  import "@koishijs/plugin-notifier";
3
4
  import "@koishijs/plugin-help";
@@ -471,7 +472,8 @@ var ComRegister = class {
471
472
  });
472
473
  }
473
474
  let table = "";
474
- for (const user of subLiveUsers) table += `[UID:${user.uid}] 「${user.uname}」 ${user.onLive ? "正在直播" : "未开播"}\n`;
475
+ if (subLiveUsers.length === 0) table += "当前没有正在直播的订阅对象";
476
+ else for (const user of subLiveUsers) table += `[UID:${user.uid}] 「${user.uname}」 ${user.onLive ? "正在直播" : "未开播"}\n`;
475
477
  return table;
476
478
  });
477
479
  biliCom.subcommand(".dyn <uid:string> [index:number]", "手动推送一条动态信息", { hidden: true }).usage("手动推送一条动态信息").example("bili dyn 233 1 手动推送UID为233用户空间的第一条动态信息").action(async ({ session }, uid, index) => {
@@ -644,6 +646,7 @@ var ComRegister = class {
644
646
  return;
645
647
  }
646
648
  this.mergeStopWords(config.wordcloudStopWords);
649
+ this.initAllManager();
647
650
  this.registeringForEvents();
648
651
  if (config.advancedSub) {
649
652
  this.logger.info("开启高级订阅,等待加载订阅...");
@@ -674,7 +677,6 @@ var ComRegister = class {
674
677
  });
675
678
  }
676
679
  async initAsyncPart(subs) {
677
- this.initAllManager();
678
680
  this.logger.info("获取到订阅信息,开始加载订阅...");
679
681
  const { code, message } = await this.loadSubFromConfig(subs);
680
682
  if (code !== 0) {
@@ -683,7 +685,7 @@ var ComRegister = class {
683
685
  await this.sendPrivateMsg("订阅对象加载失败,插件初始化失败!");
684
686
  return;
685
687
  }
686
- this.initManager();
688
+ this.initManagerAfterLoadSub();
687
689
  this.checkIfDynamicDetectIsNeeded();
688
690
  this.checkIfLiveDetectIsNeeded();
689
691
  this.updateSubNotifier();
@@ -697,7 +699,7 @@ var ComRegister = class {
697
699
  const additionalStopWords = stopWordsStr.split(",").map((word) => word.trim()).filter((word) => word !== "");
698
700
  this.stopwords = new Set([...stop_words_default, ...additionalStopWords]);
699
701
  }
700
- initManager() {
702
+ initManagerAfterLoadSub() {
701
703
  for (const [uid, sub] of this.subManager) {
702
704
  if (sub.dynamic) this.dynamicTimelineManager.set(uid, Math.floor(DateTime.now().toSeconds()));
703
705
  if (sub.live) this.liveAPIManager.set(uid, {
@@ -713,12 +715,12 @@ var ComRegister = class {
713
715
  }
714
716
  }
715
717
  initAllManager() {
716
- this.subManager = new Map();
717
- this.dynamicTimelineManager = new Map();
718
- this.liveAPIManager = new Map();
719
- this.liveWSManager = new Map();
720
- this.liveMsgManager = new Map();
721
- this.pushArrMap = new Map();
718
+ this.subManager = /* @__PURE__ */ new Map();
719
+ this.dynamicTimelineManager = /* @__PURE__ */ new Map();
720
+ this.liveAPIManager = /* @__PURE__ */ new Map();
721
+ this.liveWSManager = /* @__PURE__ */ new Map();
722
+ this.liveMsgManager = /* @__PURE__ */ new Map();
723
+ this.pushArrMap = /* @__PURE__ */ new Map();
722
724
  }
723
725
  configSubsToSubscription(sub) {
724
726
  const subs = {};
@@ -787,7 +789,6 @@ var ComRegister = class {
787
789
  await this.sendPrivateMsg("插件发生未知错误,请检查机器人状态后使用指令 bn start 启动插件");
788
790
  this.logger.error("插件发生未知错误,请检查机器人状态后使用指令 bn start 启动插件");
789
791
  await this.ctx["bilibili-notify"].disposePlugin();
790
- return;
791
792
  }
792
793
  async sendMessageWithRetry(bot, channelId, content) {
793
794
  withRetry(async () => await bot.sendMessage(channelId, content), 1).catch(async (e) => {
@@ -882,43 +883,35 @@ var ComRegister = class {
882
883
  }
883
884
  }
884
885
  async broadcastToTargets(uid, content, type) {
885
- this.logger.info(`本次推送对象:${uid},推送类型:${PushTypeMsg[type]}`);
886
886
  const record = this.pushArrMap.get(uid);
887
- this.logger.info("本次推送目标:");
888
- if (type === PushType.StartBroadcasting && record.liveAtAllArr?.length >= 1) {
889
- this.logger.info(record.liveAtAllArr);
887
+ if (!record) return;
888
+ const hasTargets = type === PushType.StartBroadcasting && record.liveAtAllArr?.length > 0 || type === PushType.Dynamic && (record.dynamicArr?.length > 0 || record.dynamicAtAllArr?.length > 0) || (type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length > 0 || type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length > 0 || type === PushType.WordCloudAndLiveSummary && (record.wordcloudArr?.length > 0 || record.liveSummaryArr?.length > 0);
889
+ if (!hasTargets) return;
890
+ this.logger.info(`本次推送对象:${uid},推送类型:${PushTypeMsg[type]}`);
891
+ if (type === PushType.StartBroadcasting && record.liveAtAllArr?.length > 0) {
892
+ this.logger.info("推送 @全体:", record.liveAtAllArr);
890
893
  const atAllArr = structuredClone(record.liveAtAllArr);
891
- await withRetry(async () => {
892
- return await this.pushMessage(atAllArr, h.at("all"));
893
- }, 1);
894
+ await withRetry(() => this.pushMessage(atAllArr, h.at("all")), 1);
894
895
  }
895
- if (type === PushType.Dynamic && record.dynamicArr?.length >= 1) {
896
- if (record.dynamicAtAllArr?.length >= 1) {
897
- this.logger.info(record.dynamicAtAllArr);
896
+ if (type === PushType.Dynamic && record.dynamicArr?.length > 0) {
897
+ if (record.dynamicAtAllArr?.length > 0) {
898
+ this.logger.info("推送动态 @全体:", record.dynamicAtAllArr);
898
899
  const dynamicAtAllArr = structuredClone(record.dynamicAtAllArr);
899
- await withRetry(async () => {
900
- return await this.pushMessage(dynamicAtAllArr, h.at("all"));
901
- }, 1);
900
+ await withRetry(() => this.pushMessage(dynamicAtAllArr, h.at("all")), 1);
902
901
  }
903
- this.logger.info(record.dynamicArr);
902
+ this.logger.info("推送动态:", record.dynamicArr);
904
903
  const dynamicArr = structuredClone(record.dynamicArr);
905
- await withRetry(async () => {
906
- return await this.pushMessage(dynamicArr, h("message", content));
907
- }, 1);
904
+ await withRetry(() => this.pushMessage(dynamicArr, h("message", content)), 1);
908
905
  }
909
- if ((type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length >= 1) {
910
- this.logger.info(record.liveArr);
906
+ if ((type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length > 0) {
907
+ this.logger.info("推送直播:", record.liveArr);
911
908
  const liveArr = structuredClone(record.liveArr);
912
- await withRetry(async () => {
913
- return await this.pushMessage(liveArr, h("message", content));
914
- }, 1);
909
+ await withRetry(() => this.pushMessage(liveArr, h("message", content)), 1);
915
910
  }
916
- if (type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length >= 1) {
917
- this.logger.info(record.liveGuardBuyArr);
911
+ if (type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length > 0) {
912
+ this.logger.info("推送直播守护购买:", record.liveGuardBuyArr);
918
913
  const liveGuardBuyArr = structuredClone(record.liveGuardBuyArr);
919
- await withRetry(async () => {
920
- return await this.pushMessage(liveGuardBuyArr, h(h.Fragment, h(content)));
921
- }, 1);
914
+ await withRetry(() => this.pushMessage(liveGuardBuyArr, h(h.Fragment, h(content))), 1);
922
915
  }
923
916
  if (type === PushType.WordCloudAndLiveSummary) {
924
917
  const wordcloudArr = structuredClone(record.wordcloudArr);
@@ -927,25 +920,16 @@ var ComRegister = class {
927
920
  const wordcloudOnlyArr = wordcloudArr.filter((item) => !liveSummaryArr.includes(item));
928
921
  const liveSummaryOnlyArr = liveSummaryArr.filter((item) => !wordcloudArr.includes(item));
929
922
  if (wordcloudAndLiveSummaryArr.length > 0) {
930
- this.logger.info("词云和直播总结");
931
- this.logger.info(wordcloudAndLiveSummaryArr);
932
- await withRetry(async () => {
933
- return await this.pushMessage(wordcloudAndLiveSummaryArr, h("message", [content[0], content[1]]));
934
- }, 1);
923
+ this.logger.info("推送词云和直播总结:", wordcloudAndLiveSummaryArr);
924
+ await withRetry(() => this.pushMessage(wordcloudAndLiveSummaryArr, h("message", [content[0], content[1]])), 1);
935
925
  }
936
926
  if (wordcloudOnlyArr.length > 0) {
937
- this.logger.info("词云");
938
- this.logger.info(wordcloudOnlyArr);
939
- await withRetry(async () => {
940
- return await this.pushMessage(wordcloudOnlyArr, h("message", [content[0]]));
941
- }, 1);
927
+ this.logger.info("推送词云:", wordcloudOnlyArr);
928
+ await withRetry(() => this.pushMessage(wordcloudOnlyArr, h("message", [content[0]])), 1);
942
929
  }
943
930
  if (liveSummaryOnlyArr.length > 0) {
944
- this.logger.info("直播总结");
945
- this.logger.info(liveSummaryOnlyArr);
946
- await withRetry(async () => {
947
- return await this.pushMessage(liveSummaryOnlyArr, h("message", [content[1]]));
948
- }, 1);
931
+ this.logger.info("推送直播总结:", liveSummaryOnlyArr);
932
+ await withRetry(() => this.pushMessage(liveSummaryOnlyArr, h("message", [content[1]])), 1);
949
933
  }
950
934
  }
951
935
  }
@@ -959,24 +943,21 @@ var ComRegister = class {
959
943
  });
960
944
  if (!content) return;
961
945
  if (content.code !== 0) switch (content.code) {
962
- case -101: {
946
+ case -101:
963
947
  this.logger.error("账号未登录,插件已停止工作,请登录");
964
948
  await this.sendPrivateMsg("账号未登录,插件已停止工作,请登录");
965
949
  await this.ctx["bilibili-notify"].disposePlugin();
966
950
  break;
967
- }
968
- case -352: {
951
+ case -352:
969
952
  this.logger.error("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
970
953
  await this.sendPrivateMsg("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
971
954
  await this.ctx["bilibili-notify"].disposePlugin();
972
955
  break;
973
- }
974
- default: {
956
+ default:
975
957
  this.logger.error(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
976
958
  await this.sendPrivateMsg(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
977
959
  await this.ctx["bilibili-notify"].disposePlugin();
978
960
  break;
979
- }
980
961
  }
981
962
  const items = content.data.items;
982
963
  for (const item of items) {
@@ -1048,24 +1029,21 @@ var ComRegister = class {
1048
1029
  });
1049
1030
  if (!content) return;
1050
1031
  if (content.code !== 0) switch (content.code) {
1051
- case -101: {
1032
+ case -101:
1052
1033
  this.logger.error("账号未登录,插件已停止工作,请登录");
1053
1034
  await this.sendPrivateMsg("账号未登录,插件已停止工作,请登录");
1054
1035
  await this.ctx["bilibili-notify"].disposePlugin();
1055
1036
  break;
1056
- }
1057
- case -352: {
1037
+ case -352:
1058
1038
  this.logger.error("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
1059
1039
  await this.sendPrivateMsg("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
1060
1040
  await this.ctx["bilibili-notify"].disposePlugin();
1061
1041
  break;
1062
- }
1063
- default: {
1042
+ default:
1064
1043
  this.logger.error(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
1065
1044
  await this.sendPrivateMsg(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
1066
1045
  await this.ctx["bilibili-notify"].disposePlugin();
1067
1046
  break;
1068
- }
1069
1047
  }
1070
1048
  this.logger.info("获取动态信息成功!开始处理动态信息...");
1071
1049
  const items = content.data.items;
@@ -1267,10 +1245,14 @@ var ComRegister = class {
1267
1245
  });
1268
1246
  return flag;
1269
1247
  };
1248
+ const LIVE_EVENT_COOLDOWN = 10 * 1e3;
1249
+ let lastLiveStart = 0;
1250
+ let lastLiveEnd = 0;
1270
1251
  const handler = {
1271
1252
  onError: async () => {
1272
1253
  liveStatus = false;
1273
1254
  pushAtTimeTimer?.();
1255
+ pushAtTimeTimer = null;
1274
1256
  this.ctx["bilibili-notify-live"].closeListener(sub.roomid);
1275
1257
  await this.sendPrivateMsg(`[${sub.roomid}]直播间连接发生错误!`);
1276
1258
  this.logger.error(`[${sub.roomid}]直播间连接发生错误!`);
@@ -1291,16 +1273,30 @@ var ComRegister = class {
1291
1273
  this.broadcastToTargets(sub.uid, content, PushType.LiveGuardBuy);
1292
1274
  },
1293
1275
  onLiveStart: async () => {
1294
- if (liveStatus) return;
1276
+ const now = Date.now();
1277
+ if (now - lastLiveStart < LIVE_EVENT_COOLDOWN) {
1278
+ this.logger.warn(`[${sub.roomid}] 开播事件冷却期内被忽略`);
1279
+ if (!liveTime) {
1280
+ await useMasterAndLiveRoomInfo(LiveType.StartBroadcasting);
1281
+ liveTime = liveRoomInfo?.live_time || Date.now();
1282
+ }
1283
+ return;
1284
+ }
1285
+ lastLiveStart = now;
1286
+ if (liveStatus) {
1287
+ this.logger.warn(`[${sub.roomid}] 已是开播状态,忽略重复开播事件`);
1288
+ return;
1289
+ }
1295
1290
  liveStatus = true;
1296
1291
  if (!await useMasterAndLiveRoomInfo(LiveType.StartBroadcasting)) {
1297
1292
  liveStatus = false;
1298
1293
  await this.sendPrivateMsg("获取直播间信息失败,推送直播开播卡片失败!");
1299
1294
  return await this.sendPrivateMsgAndStopService();
1300
1295
  }
1301
- liveTime = liveRoomInfo.live_time;
1296
+ liveTime = liveRoomInfo?.live_time || Date.now();
1297
+ const diffTime = await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime);
1302
1298
  const follower = masterInfo.liveOpenFollowerNum >= 1e4 ? `${(masterInfo.liveOpenFollowerNum / 1e4).toFixed(1)}万` : masterInfo.liveOpenFollowerNum.toString();
1303
- const liveStartMsg = liveMsgObj.customLiveStart.replace("-name", masterInfo.username).replace("-time", await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime)).replace("-follower", follower).replaceAll("\\n", "\n").replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`);
1299
+ const liveStartMsg = liveMsgObj.customLiveStart.replace("-name", masterInfo.username).replace("-time", diffTime).replace("-follower", follower).replaceAll("\\n", "\n").replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`);
1304
1300
  await this.sendLiveNotifyCard(LiveType.StartBroadcasting, follower, {
1305
1301
  liveRoomInfo,
1306
1302
  masterInfo,
@@ -1312,25 +1308,43 @@ var ComRegister = class {
1312
1308
  }
1313
1309
  },
1314
1310
  onLiveEnd: async () => {
1311
+ const now = Date.now();
1312
+ if (now - lastLiveEnd < LIVE_EVENT_COOLDOWN) {
1313
+ this.logger.warn(`[${sub.roomid}] 下播事件冷却期内被忽略`);
1314
+ if (!liveTime) {
1315
+ await useMasterAndLiveRoomInfo(LiveType.StopBroadcast);
1316
+ liveTime = liveRoomInfo?.live_time || Date.now();
1317
+ }
1318
+ return;
1319
+ }
1320
+ lastLiveEnd = now;
1321
+ if (!liveStatus) {
1322
+ this.logger.warn(`[${sub.roomid}] 已是下播状态,忽略重复下播事件`);
1323
+ return;
1324
+ }
1315
1325
  liveStatus = false;
1316
1326
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast)) {
1317
1327
  await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
1318
1328
  return await this.sendPrivateMsgAndStopService();
1319
1329
  }
1320
- liveRoomInfo.live_time = liveTime;
1330
+ liveTime = liveTime || liveRoomInfo?.live_time || Date.now();
1331
+ const diffTime = await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime);
1321
1332
  const followerChange = (() => {
1322
1333
  const liveFollowerChangeNum = masterInfo.liveFollowerChange;
1323
- if (liveFollowerChangeNum > 0) return liveFollowerChangeNum >= 1e4 ? `+${liveFollowerChangeNum.toFixed(1)}万` : `+${liveFollowerChangeNum}`;
1324
- return liveFollowerChangeNum <= -1e4 ? `${liveFollowerChangeNum.toFixed(1)}万` : liveFollowerChangeNum.toString();
1334
+ if (liveFollowerChangeNum > 0) return liveFollowerChangeNum >= 1e4 ? `+${(liveFollowerChangeNum / 1e4).toFixed(1)}万` : `+${liveFollowerChangeNum}`;
1335
+ return liveFollowerChangeNum <= -1e4 ? `${(liveFollowerChangeNum / 1e4).toFixed(1)}万` : liveFollowerChangeNum.toString();
1325
1336
  })();
1326
- const liveEndMsg = liveMsgObj.customLiveEnd.replace("-name", masterInfo.username).replace("-time", await this.ctx["bilibili-notify-generate-img"].getTimeDifference(liveTime)).replace("-follower_change", followerChange).replaceAll("\\n", "\n");
1337
+ const liveEndMsg = liveMsgObj.customLiveEnd.replace("-name", masterInfo.username).replace("-time", diffTime).replace("-follower_change", followerChange).replaceAll("\\n", "\n");
1327
1338
  await this.sendLiveNotifyCard(LiveType.StopBroadcast, followerChange, {
1328
1339
  liveRoomInfo,
1329
1340
  masterInfo,
1330
1341
  cardStyle: sub.customCardStyle
1331
1342
  }, sub.uid, liveEndMsg);
1332
- pushAtTimeTimer();
1333
- pushAtTimeTimer = null;
1343
+ if (pushAtTimeTimer) {
1344
+ pushAtTimeTimer();
1345
+ pushAtTimeTimer = null;
1346
+ this.liveWSManager.delete(sub.roomid);
1347
+ }
1334
1348
  await sendDanmakuWordCloudAndLiveSummary(liveMsgObj.liveSummary);
1335
1349
  }
1336
1350
  };
@@ -1412,7 +1426,7 @@ var ComRegister = class {
1412
1426
  if (!sub) return;
1413
1427
  switch (item.live_status) {
1414
1428
  case 0:
1415
- case 2: {
1429
+ case 2:
1416
1430
  if (LiveAPIStatus.live === true) {
1417
1431
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast, LiveAPIStatus)) {
1418
1432
  await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
@@ -1436,8 +1450,7 @@ var ComRegister = class {
1436
1450
  LiveAPIStatus.live = false;
1437
1451
  }
1438
1452
  break;
1439
- }
1440
- case 1: {
1453
+ case 1:
1441
1454
  if (LiveAPIStatus.live === false) {
1442
1455
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast, LiveAPIStatus)) {
1443
1456
  await this.sendPrivateMsg("获取直播间信息失败,推送直播开播卡片失败!");
@@ -1476,7 +1489,6 @@ var ComRegister = class {
1476
1489
  LiveAPIStatus.push = 0;
1477
1490
  }
1478
1491
  break;
1479
- }
1480
1492
  default: break;
1481
1493
  }
1482
1494
  }
@@ -1735,7 +1747,7 @@ var ComRegister = class {
1735
1747
  }
1736
1748
  };
1737
1749
  (function(_ComRegister) {
1738
- const Config$1 = _ComRegister.Config = Schema.object({
1750
+ _ComRegister.Config = Schema.object({
1739
1751
  advancedSub: Schema.boolean(),
1740
1752
  subs: Schema.array(Schema.object({
1741
1753
  name: Schema.string().required().description("备注"),
@@ -2078,7 +2090,7 @@ var GenerateImg = class extends Service {
2078
2090
  switch (dynamic.type) {
2079
2091
  case DYNAMIC_TYPE_WORD:
2080
2092
  case DYNAMIC_TYPE_DRAW:
2081
- case DYNAMIC_TYPE_FORWARD: {
2093
+ case DYNAMIC_TYPE_FORWARD:
2082
2094
  basicDynamic();
2083
2095
  if (dynamic.type === DYNAMIC_TYPE_FORWARD) {
2084
2096
  if (this.giConfig.filter.enable && this.giConfig.filter.forward) throw new Error("已屏蔽转发动态");
@@ -2179,7 +2191,6 @@ var GenerateImg = class extends Service {
2179
2191
  }
2180
2192
  }
2181
2193
  break;
2182
- }
2183
2194
  case DYNAMIC_TYPE_AV: {
2184
2195
  basicDynamic();
2185
2196
  const archive = dynamic.modules.module_dynamic.major.archive;
@@ -2247,10 +2258,9 @@ var GenerateImg = class extends Service {
2247
2258
  case DYNAMIC_TYPE_LIVE: return [`${upName}发起了直播预约,我暂时无法渲染,请自行查看`];
2248
2259
  case DYNAMIC_TYPE_MEDIALIST: return [`${upName}分享了收藏夹,我暂时无法渲染,请自行查看`];
2249
2260
  case DYNAMIC_TYPE_PGC: return [`${upName}发布了剧集(番剧、电影、纪录片),我暂时无法渲染,请自行查看`];
2250
- case DYNAMIC_TYPE_ARTICLE: {
2261
+ case DYNAMIC_TYPE_ARTICLE:
2251
2262
  if (this.giConfig.filter.enable && this.giConfig.filter.article) throw new Error("已屏蔽专栏动态");
2252
2263
  return [`${upName}投稿了新专栏,我暂时无法渲染,请自行查看`];
2253
- }
2254
2264
  case DYNAMIC_TYPE_MUSIC: return [`${upName}发行了新歌,我暂时无法渲染,请自行查看`];
2255
2265
  case DYNAMIC_TYPE_COMMON_SQUARE: return [`${upName}发布了装扮|剧集|点评|普通分享,我暂时无法渲染,请自行查看`];
2256
2266
  case DYNAMIC_TYPE_COURSES_SEASON: return [`${upName}发布了新课程,我暂时无法渲染,请自行查看`];
@@ -3161,8 +3171,8 @@ var GenerateImg = class extends Service {
3161
3171
  </div>
3162
3172
  </div>
3163
3173
 
3164
- <script src="${wordcloudJS}"></script>
3165
- <script src="${renderFunc}"></script>
3174
+ <script src="${wordcloudJS}"><\/script>
3175
+ <script src="${renderFunc}"><\/script>
3166
3176
  <script>
3167
3177
  const canvas = document.getElementById('wordCloudCanvas');
3168
3178
  const ctx = canvas.getContext('2d');
@@ -3186,7 +3196,7 @@ var GenerateImg = class extends Service {
3186
3196
  densityTarget: 0.3,
3187
3197
  weightExponent: 0.4
3188
3198
  });
3189
- </script>
3199
+ <\/script>
3190
3200
  </body>
3191
3201
 
3192
3202
  </html>
@@ -3200,30 +3210,26 @@ var GenerateImg = class extends Service {
3200
3210
  let liveTime;
3201
3211
  let cover;
3202
3212
  switch (liveStatus) {
3203
- case 0: {
3213
+ case 0:
3204
3214
  titleStatus = "未直播";
3205
3215
  liveTime = "未开播";
3206
3216
  cover = true;
3207
3217
  break;
3208
- }
3209
- case 1: {
3218
+ case 1:
3210
3219
  titleStatus = "开播啦";
3211
3220
  liveTime = `开播时间:${time}`;
3212
3221
  cover = true;
3213
3222
  break;
3214
- }
3215
- case 2: {
3223
+ case 2:
3216
3224
  titleStatus = "正在直播";
3217
3225
  liveTime = `直播时长:${await this.getTimeDifference(time)}`;
3218
3226
  cover = false;
3219
3227
  break;
3220
- }
3221
- case 3: {
3228
+ case 3:
3222
3229
  titleStatus = "下播啦";
3223
3230
  liveTime = `开播时间:${time}`;
3224
3231
  cover = true;
3225
3232
  break;
3226
- }
3227
3233
  }
3228
3234
  return [
3229
3235
  titleStatus,
@@ -3254,7 +3260,7 @@ var GenerateImg = class extends Service {
3254
3260
  return parts.length > 0 ? `${sign}${parts.join("")}` : "0秒";
3255
3261
  }
3256
3262
  unixTimestampToString(timestamp) {
3257
- const date = new Date(timestamp * 1e3);
3263
+ const date = /* @__PURE__ */ new Date(timestamp * 1e3);
3258
3264
  const year = date.getFullYear();
3259
3265
  const month = `0${date.getMonth() + 1}`.slice(-2);
3260
3266
  const day = `0${date.getDate()}`.slice(-2);
@@ -3265,7 +3271,7 @@ var GenerateImg = class extends Service {
3265
3271
  }
3266
3272
  };
3267
3273
  (function(_GenerateImg) {
3268
- const Config$1 = _GenerateImg.Config = Schema.object({
3274
+ _GenerateImg.Config = Schema.object({
3269
3275
  filter: Schema.object({
3270
3276
  enable: Schema.boolean(),
3271
3277
  notify: Schema.boolean(),
@@ -3992,15 +3998,13 @@ var BiliAPI = class extends Service {
3992
3998
  }, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
3993
3999
  switch (refreshData.code) {
3994
4000
  case -101: return await this.createNewClient();
3995
- case -111: {
4001
+ case -111:
3996
4002
  await this.ctx.database.remove("loginBili", [1]);
3997
4003
  notifyAndError("csrf 校验错误,请重新登录");
3998
4004
  break;
3999
- }
4000
- case 86095: {
4005
+ case 86095:
4001
4006
  await this.ctx.database.remove("loginBili", [1]);
4002
4007
  notifyAndError("refresh_csrf 错误或 refresh_token 与 cookie 不匹配,请重新登录");
4003
- }
4004
4008
  }
4005
4009
  const encryptedCookies = this.encrypt(this.getCookies());
4006
4010
  const encryptedRefreshToken = this.encrypt(refreshData.data.refresh_token);
@@ -4017,11 +4021,10 @@ var BiliAPI = class extends Service {
4017
4021
  refresh_token: refreshToken
4018
4022
  }, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
4019
4023
  switch (aceeptData.code) {
4020
- case -111: {
4024
+ case -111:
4021
4025
  await this.ctx.database.remove("loginBili", [1]);
4022
4026
  notifyAndError("csrf 校验失败,请重新登录");
4023
4027
  break;
4024
- }
4025
4028
  case -400: throw new Error("请求错误");
4026
4029
  }
4027
4030
  }
@@ -4054,7 +4057,7 @@ var BiliAPI = class extends Service {
4054
4057
  }
4055
4058
  };
4056
4059
  (function(_BiliAPI) {
4057
- const Config$1 = _BiliAPI.Config = Schema.object({
4060
+ _BiliAPI.Config = Schema.object({
4058
4061
  userAgent: Schema.string(),
4059
4062
  key: Schema.string().pattern(/^[0-9a-f]{32}$/).required()
4060
4063
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-bilibili-notify",
3
3
  "description": "Koishi bilibili notify plugin",
4
- "version": "3.3.5-alpha.0",
4
+ "version": "3.3.6",
5
5
  "main": "./lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/readme.md CHANGED
@@ -10,7 +10,6 @@
10
10
  - [注意事项](#注意事项)
11
11
  - [安装](#安装)
12
12
  - [使用方法](#使用方法)
13
- - [更新日志](#更新日志)
14
13
  - [交流群](#交流群)
15
14
  - [感谢](#感谢)
16
15
  - [License](#License)
@@ -76,271 +75,6 @@ uid为必填参数,为要推送的UP主的UID,index为可选参数,为要
76
75
  - 使用指令 `sys`
77
76
  - 子命令:`start`、`stop`、`restart` 分别代表插件的启动,停止和重启
78
77
 
79
- ## 更新日志
80
-
81
- > [!NOTE]
82
- > - ver 1.0.1 修复了一些bug,提供用户自己选择动态检测时间的选项
83
- > - ver 1.0.2 修复时间bug和字体乱码问题
84
- > - ver 1.0.3 修复了一些bug,提供用户自己选择推送卡片字体样式的选项
85
- > - ver 1.0.4 修复了重复推送的bug,提供用户选择推送卡片渲染方式的选项
86
- > - ver 1.0.5 修复了用户非法篡改数据库内容可能导致程序异常运行的bug,修复了UP主开播动态推> 送空白卡片的bug
87
- > - ver 1.0.6 修复了转发动态转发信息出现`undefined`的bug,修复了再次登录订阅显示错误的> bug,优化了动态推送的逻辑
88
- > - ver 1.0.7 修复了在已登录情况下,再次登录会导致重复订阅和提示用户未订阅任何UP主的提示> (实际上已订阅)的bug,新增了订阅对象在控制台的显示,优化了`bili show`指令的逻辑
89
- > - ver 1.0.8 修复了取消订阅的bug
90
- > - ver 1.0.9 更新请求客户端header信息。优化了动态推送卡片的页面布局,增加了字体大小。提供> 用户开放订阅数量限制的选项,提供用户移除推送卡片边框的选项。在控制台页面增加订阅信息提示
91
- > - ver 1.0.10 增加对`onebot`的支持,添加动态关键字屏蔽功能
92
- > - ver 1.0.11 修复了`render`渲染模式下,动态重复推送的问题,修复了没有订阅时,控制台空白> 提示的问题。优化了视频动态缩略图显示不全的问题,优化了部分逻辑。增强容错和增加错误提示
93
- > - ver 1.0.12 提供用户选择动态推送卡片字体增大的选项
94
- > - ver 1.0.13 修复了直播通知卡片连续发三次的bug,修复了多次调用指令 `bili login` 产生> 的bug
95
- > - ver 1.0.14 修复了获取二维码,二维码失效后会多次发送提示的bug,新增对`red`的支持,新增> 开播艾特全体成员功能,优化了部分逻辑
96
- > - ver 1.1.0-alpha.0 修复了直播订阅一段时间过后提示房间不存在的bug,修复了自动登录刷新> 错误的bug
97
- > - ver 1.1.0-beta.0 修复了一个bug(如果本身已经存在乱码问题的情况下,使用page模式仍然会> 乱码),修复了日志bug
98
- > - ver 1.1.0-rc.0 修复了订阅用户直播一段时间后提示用户直播间不存在并自动取消订阅的bug
99
- > - ver 1.1.0 移除了直播艾特全体成员选项实验性的标志,优化了直播房间号的获取逻辑,移除了部> 分测试代码
100
- > - ver 1.1.1 新增依赖axios
101
- > - ver 1.1.2 修复了对red协议支持的一个bug
102
- > - ver 1.2.0-alpha.0 对自动更新登录信息的功能做了提升,修复了一些bug
103
- > - ver 1.2.0-alpha.1 对推送进行了改进:在开启直播开播艾特全体成员的情况下,发送图片后才> 会艾特全体成员
104
- > - ver 1.2.0-alpha.2 支持QQ群多群推送(实验性),修复了一些bug
105
- > - ver 1.2.0-alpha.3 修复了指定QQ群订阅时的一个bug
106
- > - ver 1.2.0-alpha.4 对时间获取进行了优化,能够适应不同环境下的时间获取,修复了一些bug
107
- > - ver 1.2.0-alpha.5 修复了与PostgreSQL不兼容的问题,优化了图片推送,增强了推送容错
108
- > - ver 1.2.0-rc.0 现已支持自定义开播和下播提示语(实验性)
109
- > - ver 1.2.0-rc.1 现已支持Telegram平台(实验性)
110
- > - ver 1.2.0-rc.2 添加更多日志输出
111
- > - ver 1.2.0-rc.3 针对Telegram的bug测试版本
112
- > - ver 1.2.0-rc.4 修复了订阅指令的一个bug
113
- > - ver 1.2.0-rc.5 屏蔽动态设置新增是否发送动态被屏蔽消息的选项
114
- > - ver 1.2.0 添加屏蔽转发动态功能,添加发送动态卡片时附带文本信息和动态链接功能,支持订阅> 哔哩哔哩番剧出差
115
- > - ver 1.2.1 现已支持Satori平台(实验性)
116
- > - ver 1.2.2-alpha.0 bug测试
117
- > - ver 1.2.2-beta.0 修复重启koishi后,提示没有任何订阅的bug,新增对chronocat的支持> (实验性)
118
- > - ver 1.2.2-beta.1 现已支持直播开播发送链接(实验性)
119
- > - ver 1.2.2-beta.2 修复了动态推送时图片下方出现空行的情况
120
- > - ver 1.2.3-alpha.0 新增主人账号功能,开启后,会将插件的错误消息向主人账号发送(实验> 性)。修复订阅消息推送失败刷屏的bug
121
- > - ver 1.2.3-beta.0 优化错误推送逻辑,现在只有设置主人账号后才会推送错误消息
122
- > - ver 1.2.3-beta.1 新增指令 `bili private` 方便测试主人账号功能
123
- > - ver 1.2.3-beta.2 功能测试版本,请跳过该版本
124
- > - ver 1.2.3-rc.0 现已支持向机器人加入的所有群发送推送消息(仅支持Q群,实验性),修复预约> 动态无法正常推送的bug
125
- > - ver 1.2.3-rc.1 修复 `1.2.3-rc.0` 出现的重复推送bug
126
- > - ver 1.2.3-rc.2 bug测试版本,请跳过
127
- > - ver 1.2.3-rc.3 bug测试版本,请跳过
128
- > - ver 1.2.3-rc.4 bug测试版本,请跳过
129
- > - ver 1.2.3-rc.5 修复了第一次使用插件时,扫码登录后没有任何反应,并且仍提示没有登录的> bug
130
- > - ver 1.2.3-rc.6 bug测试版本,请跳过
131
- > - ver 1.2.3-rc.7 尝试修复多群推送时部分群未推送的bug
132
- > - ver 1.2.3-rc.8 修复在 `1.2.3-rc.7` 版本引入的连续推送三次的bug
133
- > - ver 1.2.3-rc.9 完善了插件出错时的日志输出
134
- > - ver 1.2.3-rc.10 修复不能移除边框的bug,对图片布局进行了调整,新增下播消息发送主播头像
135
- > - ver 1.2.3-rc.11 测试版本,请跳过
136
- > - ver 1.2.3 完善主播下播消息发送头像功能,优化控制台订阅信息显示
137
- > - ver 1.2.4 优化了下播消息发送头像图片的质量和插件重启提示
138
- > - ver 1.2.5 修复了在多群订阅的情况下,其中一个群推送失败会导致其余的群全部重新推送的> bug。更换图片处理依赖以解决在插件市场中被标记为不安全插件的问题
139
- > - ver 1.2.6 现在可以随机生成UA,并更新了UA
140
- > - ver 1.2.7 修复不论选择什么渲染模式都是render模式的bug,优化直播卡片推送逻辑
141
- > - ver 1.2.8 修复例如像UP主籽岷使用webp格式的头像,下播通知无法发出的bug
142
- > - ver 1.2.9-alpha.0 bug测试版本,请跳过
143
- > - ver 1.2.10 修复插件启动一段时间后一直报错的问题,更新了UA列表,新增了更多日志输出
144
- > - ver 1.2.11-alpha.0 新增自定义UA的设置。动态推送出错时,现在会直接取消订阅该UP主而不> 是取消订阅动态
145
- > - ver 1.2.11-alpha.1 修复报错 `app TypeError: Cannot read properties of > undefined (reading 'toString')`,添加更多日志输出
146
- > - ver 1.2.12-alpha.0 新增 `sys` 类指令,包括子命令:`start`、`stop`、`restart` > 分别为插件的启动、停止和重启,需要权限等级5才能使用。现在,账号出现某些问题后,不会再清除订> 阅信息,而是停止插件,在排除问题后需要使用指令 `sys start` 手动启动插件。修复一个动态推送> 的bug
147
- > - ver 1.2.12-alpha.1 删除直播推送时的多余空格
148
- > - ver 1.2.12-alpha.2 尝试修复版本 `1.2.12-alpha.0 账号出现某些问题后,不会再清除订> 阅信息` 仍然会清除订阅信息的bug
149
- > - ver 1.2.12-alpha.3 尝试修复订阅时使用 `all` 报错的bug
150
- > - ver 1.2.12 新增动态错误处理
151
- > - ver 1.2.13 现已支持调试模式,目前支持对动态的调试。需要调试模式可在控制台中开启
152
- > - ver 1.2.14 优化调试模式输出,直播推送卡片添加分区信息
153
- > - ver 1.2.15 新增直播推送卡片简介隐藏选项
154
- > - ver 1.2.16 当存储在数据库中的登录信息被篡改时,新增控制台提示
155
- > - ver 1.3.0-alpha.0 对直播推送逻辑进行小型重构,优化了性能。新增功能:定时推送直播卡片> 可选是否发送直播链接;在遇到getMasterInfo()错误时,可切换获取主播信息Api
156
- > - ver 1.3.0-alpha.1 修复bug:发送直播开播通知时,如果在开播语中加入链接,同时开启了推> 送直播卡片发送直播链接,则会发送两条链接
157
- > - ver 1.3.0-rc.0 修复bug:发送直播开播通知时,如果开启了开播发送链接,会在链接末尾添加> 一个false
158
- > - ver 1.3.0 修复bug:渲染动态时,过长的单图会导致渲染错误
159
- > - ver 1.3.1 优化过长单图的显示样式
160
- > - ver 1.3.2 增加对飞书平台的支持
161
- > - ver 1.3.3 新增直播推送人气信息展示
162
- > - ver 1.3.4 新增消息推送失败是否自动重发的选项,修复了一些潜在的bug
163
- > - ver 1.3.5 动态监测循环时间新增20分钟选项
164
- > - ver 1.3.6-alpha.0 修复bug:无限重复的报错提示
165
- > - ver 1.3.6-beta.0 取消出错自动重启插件功能
166
- > - ver 1.3.6-rc.0 修复重启或更新后提示未登录或订阅时提示请登录后再订阅的问题
167
- > - ver 1.3.6 现在基本设置中的userAgent选项为必填项,当因风控订阅失败时会提示更换UA,优> 化直播人气显示
168
- > - ver 1.3.7 新增设置项:插件重启后是否进行直播推送。优化直播人气显示
169
- >
170
- > - ver 2.0.0-alpha.0 重构:对动态订阅进行了重构,优化了订阅流程
171
- > - ver 2.0.0-alpha.1 修复:无法成功取消订阅自己、用户没有直播间订阅直播出错。对直播订阅> 进行了限制,继承自以前的unlockSubLimits配置项。优化了一些配置项
172
- > - ver 2.0.0-alpha.2 新增:支持Discord平台。优化了下播通知
173
- > - ver 2.0.0-alpha.3 修复:订阅和取消订阅的bug,下播通知的bug
174
- > - ver 2.0.0-alpha.4 修复:初次订阅后不推送动态的bug 优化:下播不再发送链接
175
- > - ver 2.0.0-alpha.5 移除:选项pushUrl,选项platform 新增:选项customLive,主人账> 号中platform选项。支持多平台,且可同时推送不同平台,单个UP主只能推送一个平台
176
- > - ver 2.0.0-alpha.6 修复:直播推送发送失败的bug
177
- > - ver 2.0.0-alpha.7 重构:现已支持同一UP多平台推送
178
- > - ver 2.0.0-alpha.8 新增:重新订阅提示
179
- > - ver 2.0.0-alpha.9 修复:订阅反复提示未加入群组的bug,实际已加入
180
- > - ver 2.0.0-alpha.10 新增:可对每个群聊针对性设置是否艾特全体成员 优化:直播下播通知
181
- > - ver 2.0.0-alpha.11 回档:订阅时可直接接收群号/频道号 修复:直播过程推送消息不成功的> bug
182
- > - ver 2.0.0-alpha.12 更改:开启艾特全体成员后,只有在开播时才艾特全体成员
183
- > - ver 2.0.0-alpha.13 修复:无法对TG群组的特殊频道号进行订阅处理;提示 `您未配置对应平> 台的机器人,不能在该平台进行订阅操作` 仍进行订阅操作
184
- > - ver 2.0.0-alpha.14 修复:订阅TG群组时提示输入无效
185
- > - ver 2.0.0-alpha.15 新增:手动订阅功能 修复:一些潜在的bug
186
- > - ver 2.0.0-alpha.16 优化:手动订阅功能
187
- > - ver 2.0.0-alpha.17 修复:直接订阅当前环境不会推送
188
- > - ver 2.0.0-alpha.18 修复:手动订阅无法推送直播通知;自定义直播中通知语不会发送
189
- > - ver 2.0.0-alpha.19 修复:开播通知后带false;下播通知卡片人气位置显示false
190
- > - ver 2.0.0-alpha.20 修复:直播推送失败 `Error with request send_group_msg`
191
- > - ver 2.0.0-alpha.21 修复:在某些场景下仍会出现 `2.0.0-alpha.19` 和 `2.0.> 0-alpha.20` 版本已修复的问题
192
- > - ver 2.0.0-alpha.22 移除:不需要的服务
193
- > - ver 2.0.0-alpha.23 优化:将艾特全体成员消息单独发送
194
- >
195
- > - ver 3.0.0-alpha.0 重构:直播 新增:直播弹幕推送到群
196
- > - ver 3.0.0-alpha.1 测试版本
197
- > - ver 3.0.0-alpha.2 修复:只订阅直播也会将该UP主的动态进行推送、推送过的动态过一段时间> 又会再次推送
198
- > - ver 3.0.0-alpha.3 修复:未开启弹幕推送也不会推送直播通知卡片
199
- > - ver 3.0.0-alpha.4 修复:使用了手动订阅,数据库中的订阅不会加载
200
- > - ver 3.0.0-alpha.5 修复:订阅的直播开播后,未开启弹幕推送会一直报错、主播开播推送下播> 卡片,直播时长显示NaN; 新增:直播检测模式选项; 优化:下播卡片内容
201
- > - ver 3.0.0-alpha.6 修复:连续发送两次直播中通知卡片; 优化:下播通知卡片
202
- > - ver 3.0.0-alpha.7 修复:`ver 3.0.0-alpha.5` 未能解决的bug; 优化:ba代码结构
203
- > - ver 3.0.0-alpha.8 修复:开播通知连续发送两次,登录后不会加载手动订阅中的订阅; 优化:> 网络请求报错
204
- > - ver 3.0.0-alpha.9 优化:加强直播推送对获取直播信息的错误处理
205
- > - ver 3.0.0-alpha.10 修复:连续推送两次开播通知
206
- > - ver 3.0.0-alpha.11 新增:直播结束后推送弹幕词云,直播推送上舰消息; 修复:直播推送都> 是同一张画面; 移除:直播推送弹幕消息
207
- > - ver 3.0.0-alpha.12 修复:上一版本无法安装
208
- > - ver 3.0.0-alpha.13 优化:将ESLint替换为Biome; 修复:增加弹幕词云功能产生的bug; > 禁用:弹幕词云功能并不能正常运作,暂时将该功能禁用
209
- > - ver 3.0.0-alpha.14 优化:移除不需要的服务
210
- > - ver 3.0.0-alpha.15 修复:启动插件提示发送群组消息失败、直播推送时间显示为负数(不用再> 特别设置系统时区为UTC+8)
211
- > - ver 3.0.0-alpha.16 重大更新:订阅不再依赖数据库,从指令订阅全面迁移到配置订阅; 修> 复:直播时长有误; 优化:`bili show` 指令更改为 `bili list`
212
- > - ver 3.0.0-alpha.17 新增:更多的提示语变量,开播,当前粉丝数。正在直播,累计观看人数。> 下播,粉丝数变化。选项,新增的提示语变量是否展示到推送卡片中
213
- > - ver 3.0.0-alpha.18 移除:直播检测API模式已被废弃; 优化:更多提示语数据显示优化
214
- > - ver 3.0.0-alpha.19 修复:开播提示语粉丝数单位错误; 优化:订阅配置中所有配置项改为必> 填项
215
- > - ver 3.0.0-alpha.20 优化:订阅配置中开关选项默认为关闭
216
- > - ver 3.0.0-alpha.21 优化:部分代码; 新增:更新插件后,由于机器人还未启动,已开始发送> 消息报错 `this._request is not a function` ,新增报错后自动重新发送消息的功能
217
- > - ver 3.0.0-alpha.22 优化:订阅配置展示优化
218
- > - ver 3.0.0-alpha.23 新增:指令 `bili ll` 可以查看当前订阅直播的UP主们的开播情况
219
- > - ver 3.0.0-alpha.24 新增:配置项,`cardBasePlateColor` 和 > `cardBasePlateBorder`,分别设置卡片底板颜色和底板边框宽度; 优化:部分代码结构
220
- > - ver 3.0.0-alpha.25 修复:输入指令 `bili ll` 时报错 `TypeError: Cannot read > properties of null (reading 'items')`,当某个订阅只订阅动态时无法成功订阅且后续订阅> 都无法加载; 优化:部分代码结构
221
- > - ver 3.0.0-beta.0 移除:配置项 `renderType`,推送卡片渲染模式 `render`,现默认为 > `page` 渲染模式; 优化:部分代码结构
222
- > - ver 3.0.0-beta.1 修复:使用动态屏蔽时,同时开启动态debug模式,当检测到屏蔽动态时会直> 接报错关闭插件; 新增:配置项 `pushImgsInDynamic` 是否推送动态中的图片,默认不开启。开> 启后会单独推送动态中的图片,上舰信息直播间提示
223
- > - ver 3.0.0-beta.2 新增:配置项 `sub.card`,能更改每个订阅的推送卡片样式,未更改的样> 式与全局样式保持一致
224
- > - ver 3.0.0 优化:配置项 `sub.card` 添加实验性标识
225
- > - ver 3.0.1-alpha.0 优化:动态推送逻辑
226
- > - ver 3.0.1-alpha.1 新增:直播提示语换行符,配置项 `sub.name` 为可选项; 修复:> debug模式下动态监测5S一次; 优化:加载订阅
227
- > - ver 3.0.1-alpha.2 优化:改进错误提示,改进订阅加载方式
228
- > - ver 3.0.1 修复:动态推送过程中,如果上一次请求的第一条动态被删除,可能导致动态重复推送> (本次修复并不能完全保障不重复推送,如果第一条和第二条都被删除则可能会出现重复推送); 新增:> 配置项 `subTimeout` 设置订阅超时时间
229
- > - ver 3.0.2 优化:动态监测,新增依赖服务 `cron`
230
- > - ver 3.0.3 移除:配置项 `dynamicLoopTime` ,动态循环时间将不再可选,默认为两分钟
231
- > - ver 3.0.4 优化:动态监测,增加时间判断,防止出现重复推送问题; 由于 `3.0.2` 动态监测> 定时器更换为cron定时任务,如果需要测试动态监测功能是否正常,可以通过控制台日志输出观察,打> 印 `动态监测初始化完毕!` 后,可进行测试
232
- > - ver 3.0.5-alpha.0 优化:推送卡片渲染,压缩图片; 新增:指令 `bili dyn` 可用于推送> 指定UP主指定动态
233
- > - ver 3.0.5-alpha.1 优化:推送卡片渲染,调整渲染图片格式为 `jpeg`
234
- > - ver 3.0.5-alpha.2 优化:移除多余依赖
235
- > - ver 3.1.0-alpha.0 修复:新插件在第一次订阅时提示 `订阅失败,错误信息:该分组已经存在> `; 移除:消息重发功能; 重构:将消息发送模式改为 `broadcast`
236
- > - ver 3.1.0-alpha.1 修复:无法发送 `@全体成员` 消息,将消息发送模式改回
237
- > - ver 3.1.0 修复:订阅某位UP主直播和动态后,某些群聊只开启推送直播也会推送动态
238
- > - ver 3.1.1-alpha.0 修复:稿件重投后,会将之前日期的动态一起推送; 优化:加强动态debug> 输出; 移除:不必要选项 `live.liveDetectMode`
239
- > - ver 3.1.2-alpha.0 重构:对消息发送模块进行小型重构,多群多平台推送将不再支持艾特全体> 成员,仅单平台单群聊支持; 移除:群聊 `all` 选项
240
- > - ver 3.1.3-alpha.0 移除:订阅超时; 新增:屏蔽专栏动态功能; 优化:改进了加载插件的错> 误提示;
241
- > - ver 3.1.4-alpha.0 修复:动态只推送视频; 优化:动态视频链接将直接发送为视频链接;
242
- > - ver 3.1.5-alpha.0 修复:潜在动态推送bug; 优化:现在动态监测无需等待,当插件初始化完> 成即开始监测、移除多余依赖、移除对 `cron` 服务的依赖、移除选项 `超时订阅`
243
- > - ver 3.1.5-alpha.1 修复:动态不推送的bug;
244
- > - ver 3.1.5-alpha.2 修复:潜在动态推送bug;
245
- > - ver 3.1.5-alpha.3 修复:动态推送时报错:dynamicDetect generateDynamicImg() 推> 送卡片发送失败,原因:Cannot read properties of undefined (reading 'card');
246
- > - ver 3.1.5 修复:非 `debug` 模式下动态推送,如果在一个监测周期内同一个订阅的up主发送> 多条动态,下一个监测周期会重复推送;
247
- > - ver 3.1.6 修复:视频类动态推送时,发送的视频链接有误;
248
- > - ver 3.1.7-alpha.0 修复:登录账号和订阅账号是同一个账号,动态不会推送,使用 `bili > dyn` 指令,纯文本动态会被跳过; 新增:动态标题;
249
- > - ver 3.1.7-alpha.1 修复:启用自定义卡片样式后取消仍是自定义样式;
250
- > - ver 3.1.7-alpha.2 修复:`liveDetect generateLiveImg() 推送卡片生成失败,原因:> Cannot read properties of undefined (reading 'cardColorStart')`;
251
- > - ver 3.1.7-alpha.3 修复:推送视频类动态报错;
252
- > - ver 3.1.7 修复:第一次使用插件报错 `TypeError: Cannot read properties of > undefined (reading 'dynamic_group_id')`
253
- > - ver 3.2.0-alpha.0 新增:直播检测 `API` 模式; 优化:提升直播检测 `WS` 模式使用体> 验;
254
- > - ver 3.2.0-alpha.1 修复:直播检测 `API` 模式,中途加入推送语无法正确显示直播时长;
255
- > - ver 3.2.0-alpha.2 修复:直播检测 `API` 模式,请求错误优化(防止不停向QQ发送消息);
256
- > - ver 3.2.0-alpha.3 优化:增加直播检测 `API` 模式轮询时间,防止被暂时风控;
257
- > - ver 3.2.0-alpha.4 修复:直播卡片推送时间会是设置的 `pushTime` 的两倍;
258
- > - ver 3.2.0-alpha.5 修复:直播检测 `WS` 模式下,直播中推送卡片 `累计观看人数` 位置错> 误显示为 `粉丝数变化` 、转发动态的留言文字不显示; 优化:直播检测 `API` 模式下,直播推送> 语 `-watched` 固定显示为 `API模式无法获取`;
259
- > - ver 3.2.0-alpha.6 优化:调整配置项;
260
- > - ver 3.2.0-alpha.7 修复:自 `3.1.7` 版本 `pushImgsInDynamic` 功能失效;
261
- > - ver 3.2.1-alpha.0 新增:多个相同平台bot可以选择某个群聊/频道指定机器人发送; 优化:> 直播检测 `WS` 模式下播后仍推送、添加依赖 `cacheable-lookup` 优化网络; 修复:打开 > `pushImgsInDynamic` 功能时,如果发送的动态里没有图片则会报错 `TypeError: Cannot > read properties of null (reading 'opus')`
262
- > - ver 3.2.1-alpha.1 调整:将项目构建产物调整为 `esm`;
263
- > - ver 3.2.1-alpha.2 调整:将项目构建产物调整回 `cjs` 、将依赖 `cacheable-lookup` > 导入方式更改为动态导入;
264
- > - ver 3.2.1-alpha.3 修复:直播检测 `WS` 初始化后自动断开连接;
265
- > - ver 3.2.1-alpha.4 优化:直播监听初始化没有提示;
266
- > - ver 3.2.1-alpha.4 - ver 3.2.1-alpha.8 `deprecate`
267
- > - ver 3.2.1-alpha.9 修复:`bugs`
268
- > - ver 3.2.1-alpha.10 修复:临时切换依赖 `blive-message-listener` 为 `@akokko/> blive-message-listener` 以解决直播检测模式 `WS` 掉线问题、第一次使用插件报错 > `TypeError: Cannot set properties of undefined (setting 'dynamic_group_id')> `;
269
- > - ver 3.2.1-alpha.11 WARNING:测试版本;
270
- > - ver 3.2.1 优化:移除不必要成员变量、创建自动上传npm `github actions`,添加相关开发> 依赖;
271
- > - ver 3.2.2 调整:修改 `github actions`;
272
- > - ver 3.2.3 优化:移除不必要的代码;
273
- > - ver 3.2.4-alpha.0 优化:选项 `pushImgsInDynamic` 发送多图会以转发消息的格式发> 送; 新增:选项 `dynamicVideoUrlToBV` 开启后将链接转换为bv号以用作特殊用途;
274
- > - ver 3.2.4 修复:第一次使用插件时,使用登录指令报错; 插件配置页新增和删除提示信息;
275
- > - ver 3.2.5-alpha.0 优化:新增 `DNS` 缓存,以减少DNS错误;
276
- > - ver 3.2.5-alpha.1 测试版本
277
- > - ver 3.2.5-alpha.2 测试版本
278
- > - ver 3.2.5-alpha.3 更新依赖版本
279
- > - ver 3.2.5-alpha.4 测试版本
280
- > - ver 3.2.5-alpha.5 测试版本
281
- > - ver 3.2.5-alpha.6 测试版本
282
- > - ver 3.2.5-alpha.7 测试版本
283
- > - ver 3.2.5-alpha.8 测试版本
284
- > - ver 3.2.5-alpha.9 测试版本
285
- > - ver 3.2.5-alpha.10 测试版本
286
- > - ver 3.2.5-alpha.11 测试版本
287
- > - ver 3.2.5-alpha.12 测试版本
288
- > - ver 3.2.5-alpha.13 测试版本
289
- > - ver 3.2.5 重构:消息推送逻辑; 新增:选项 `dynamicCron`;
290
- > - ver 3.2.6-alpha.0 优化:更新依赖; 修复:长图动态向下箭头无法显示的bug;
291
- > - ver 3.2.7-alpha.0 优化:将选项 `userAgent` 更改为可选项,在 `cookies` 中添加 `bili_ticket` 降低风控概率;
292
- > - ver 3.2.7-alpha.1 修复:加载 `bili_ticket` 失败会导致插件加载失败;
293
- > - ver 3.2.8-alpha.0 修复:插件重启报错 `RangeError: Invalid time value` ; 新增:选项 `sub.liveMsg` ,可自定义每个UP个性化的直播推送语;
294
- > - ver 3.2.8-alpha.1 修复:直播推送没有推送语;
295
- > - ver 3.2.8-alpha.2 优化:直播推送语中,会换行所有换行符而不是第一个,其余参数仍只会替换第一个
296
-
297
- > [!CAUTION]
298
- > - ver 3.2.9-alpha.0 新增:弹幕词云; 不建议更新,目前仅做测试用!
299
- > - ver 3.2.9-alpha.1 修复:弹幕词云显示问题,弹幕过多导致插件爆炸; 不建议更新,目前仅做测试用!
300
- > - ver 3.2.9-alpha.2 修复:`AxiosError: Request failed with status code 404 xxx at async BiliAPI.checkIfTokenNeedRefresh`、潜在cookie相关bug、弹幕词云bug `Error: 生成图片失败!错误: TimeoutError: Navigation timeout of 30000 ms exceeded`
301
- > - ver 3.2.9-alpha.3 修复:词云生成空白
302
- > - ver 3.2.9-alpha.4 修复:弹幕词云bug `Error: 生成图片失败!错误: TimeoutError: Navigation timeout of 30000 ms exceeded`
303
-
304
- > [!NOTE]
305
- > - ver 3.2.9-rc.0 优化:弹幕词云生成效果、选项 `pushTime` 设置为0时可关闭该功能; 新增:选项 `wordcloud` 可选择在直播结束后是否生成弹幕词云
306
- > - ver 3.2.9-rc.1 优化:弹幕词云生成效果;
307
- > - ver 3.2.9-rc.2 优化:弹幕词云生成效果;
308
- > - ver 3.2.9-rc.3 优化:弹幕词云生成效果; 新增:直播总结语,开启弹幕词云后自动发送、选项 `liveSummary` 可自定义直播总结语; 修复:一场直播完成后,如果插件中途没有被关闭过,会影响同一位up主下一次直播词云数据;
309
- > - ver 3.2.9-rc.4 优化:弹幕词云生成效果; 新增:直播总结 `-mdn` 变量,代表主播粉丝牌子名
310
- > - ver 3.2.10-alpha.0 新增:指令 `bili cap` 在遇到风控时,可以手动验证解除风控; 优化:错误消息提示;
311
- > - ver 3.2.10-alpha.1 优化:使用指令 `bili cap` 后将对应cookie保存到数据库中、 `bili cap` 提示信息;
312
-
313
- > [!CAUTION]
314
- > - ver 3.2.11-alpha.2 测试版本
315
- > - ver 3.2.11-alpha.3 测试版本
316
- > - ver 3.2.11-alpha.4 测试版本
317
- > - ver 3.2.11-alpha.5 测试版本
318
- > - ver 3.2.11-alpha.6 测试版本
319
- > - ver 3.2.11-alpha.7 测试版本
320
- > - ver 3.2.11-alpha.8 测试版本
321
- > - ver 3.2.11-alpha.9 测试版本
322
- > - ver 3.2.11-alpha.10 测试版本
323
- > - ver 3.2.11-alpha.11 测试版本
324
- > - ver 3.2.11-alpha.12 测试版本
325
-
326
- > [!NOTE]
327
- > - ver 3.3.0-rc.0 优化:将当前版本的订阅配置移到了新插件:`bilibili-notify-advanced-subscription` ,简化当前版本订阅配置; 新增:配置项 `advancedSub` ,开启后可通过下载插件 `bilibili-notify-advanced-subscription` 配置更自定义化的订阅配置、新增动态@全体成员功能;
328
- > - ver 3.3.1-alpha.0 新增:弹幕词云自定义停用词、UP主弹幕词云开关; 优化:`liveSummary` 排版方式更加直观;
329
- > - ver 3.3.1-alpha.1 优化:拆分 `wordcloud` 和 `liveSummary`,优化指令 `bili cap` 风控验证;
330
- > - ver 3.3.1-rc.0 优化:代码结构,部分设置; 修复:启用高级订阅时,多次重载高级订阅插件会产生多个重复订阅;
331
- > - ver 3.3.1-rc.1 优化:动态错误处理;
332
- > - ver 3.3.1-rc.2 新增:订阅UID项可填写roomid,在目前版本可以极大降低风控概率;
333
- > - ver 3.3.1-rc.3 修复:当订阅用户没有直播且勾选订阅直播间报错;
334
- > - ver 3.3.1 优化:如果不订阅UP主直播且未填写房间号不再请求用户接口;
335
- > - ver 3.3.2 修复:当插件因动态报错停止后,应使用指令 `bn start` 启动插件,而不是 `bn restart`;
336
- > - ver 3.3.3 优化:初始化logger输出; 修复:B站订阅操作bug;
337
- > - ver 3.3.4-alpha.0 优化:在错误消息向主人帐号推送前会先进行机器人状态判断; 重构:部分重构消息发送逻辑;
338
- > - ver 3.3.4-alpha.1 修复: CI错误;
339
- > - ver 3.3.4-alpha.2 修复: 推送消息时发送6000的bug;
340
- > - ver 3.3.4-alpha.3 修复: 相同平台多个机器人可能造成消息重复推送、错误信息推送机器人未初始化完毕推送时会报错;
341
- > - ver 3.3.4-alpha.4 优化:切换依赖 `blive-message-listener` 回官方版本;
342
- > - ver 3.3.5-alpha.0 重构:用h渲染函数代替jsx;
343
-
344
78
  ## 交流群
345
79
 
346
80
  > [!TIP]