koishi-plugin-bilibili-notify 3.3.4-alpha.4 → 3.3.6-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.
Files changed (4) hide show
  1. package/lib/index.js +101 -131
  2. package/lib/index.mjs +102 -131
  3. package/package.json +1 -1
  4. package/readme.md +0 -265
package/lib/index.js CHANGED
@@ -35,7 +35,6 @@ const cron = __toESM(require("cron"));
35
35
  const luxon = __toESM(require("luxon"));
36
36
  const __node_rs_jieba = __toESM(require("@node-rs/jieba"));
37
37
  const __node_rs_jieba_dict = __toESM(require("@node-rs/jieba/dict"));
38
- const __satorijs_element_jsx_runtime = __toESM(require("@satorijs/element/jsx-runtime"));
39
38
  require("koishi-plugin-puppeteer");
40
39
  const node_path = __toESM(require("node:path"));
41
40
  const node_url = __toESM(require("node:url"));
@@ -341,7 +340,7 @@ const stopwords = new Set([
341
340
  var stop_words_default = stopwords;
342
341
 
343
342
  //#endregion
344
- //#region src/command_register.tsx
343
+ //#region src/command_register.ts
345
344
  var ComRegister = class {
346
345
  static inject = [
347
346
  "bilibili-notify",
@@ -623,7 +622,7 @@ var ComRegister = class {
623
622
  ["田七", 25]
624
623
  ];
625
624
  const summary = this.config.liveSummary.join("\n").replace("-dmc", "114").replace("-mdn", "特工").replace("-dca", "514").replace("-un1", `${top5DanmakuMaker[0][0]}`).replace("-dc1", `${top5DanmakuMaker[0][1]}`).replace("-un2", `${top5DanmakuMaker[1][0]}`).replace("-dc2", `${top5DanmakuMaker[1][1]}`).replace("-un3", `${top5DanmakuMaker[2][0]}`).replace("-dc3", `${top5DanmakuMaker[2][1]}`).replace("-un4", `${top5DanmakuMaker[3][0]}`).replace("-dc4", `${top5DanmakuMaker[3][1]}`).replace("-un5", `${top5DanmakuMaker[4][0]}`).replace("-dc5", `${top5DanmakuMaker[4][1]}`).replaceAll("\\n", "\n");
626
- await session.send(/* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [img, summary] }));
625
+ await session.send((0, koishi.h)("message", [img, koishi.h.text(summary)]));
627
626
  });
628
627
  biliCom.subcommand(".cap").action(async ({ session }) => {
629
628
  const { code: userInfoCode, data: userInfoData } = await withRetry(async () => {
@@ -733,12 +732,12 @@ var ComRegister = class {
733
732
  }
734
733
  }
735
734
  initAllManager() {
736
- this.subManager = new Map();
737
- this.dynamicTimelineManager = new Map();
738
- this.liveAPIManager = new Map();
739
- this.liveWSManager = new Map();
740
- this.liveMsgManager = new Map();
741
- this.pushArrMap = new Map();
735
+ this.subManager = /* @__PURE__ */ new Map();
736
+ this.dynamicTimelineManager = /* @__PURE__ */ new Map();
737
+ this.liveAPIManager = /* @__PURE__ */ new Map();
738
+ this.liveWSManager = /* @__PURE__ */ new Map();
739
+ this.liveMsgManager = /* @__PURE__ */ new Map();
740
+ this.pushArrMap = /* @__PURE__ */ new Map();
742
741
  }
743
742
  configSubsToSubscription(sub) {
744
743
  const subs = {};
@@ -807,7 +806,6 @@ var ComRegister = class {
807
806
  await this.sendPrivateMsg("插件发生未知错误,请检查机器人状态后使用指令 bn start 启动插件");
808
807
  this.logger.error("插件发生未知错误,请检查机器人状态后使用指令 bn start 启动插件");
809
808
  await this.ctx["bilibili-notify"].disposePlugin();
810
- return;
811
809
  }
812
810
  async sendMessageWithRetry(bot, channelId, content) {
813
811
  withRetry(async () => await bot.sendMessage(channelId, content), 1).catch(async (e) => {
@@ -902,43 +900,35 @@ var ComRegister = class {
902
900
  }
903
901
  }
904
902
  async broadcastToTargets(uid, content, type) {
905
- this.logger.info(`本次推送对象:${uid},推送类型:${PushTypeMsg[type]}`);
906
903
  const record = this.pushArrMap.get(uid);
907
- this.logger.info("本次推送目标:");
908
- if (type === PushType.StartBroadcasting && record.liveAtAllArr?.length >= 1) {
909
- this.logger.info(record.liveAtAllArr);
904
+ if (!record) return;
905
+ 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);
906
+ if (!hasTargets) return;
907
+ this.logger.info(`本次推送对象:${uid},推送类型:${PushTypeMsg[type]}`);
908
+ if (type === PushType.StartBroadcasting && record.liveAtAllArr?.length > 0) {
909
+ this.logger.info("推送 @全体:", record.liveAtAllArr);
910
910
  const atAllArr = structuredClone(record.liveAtAllArr);
911
- await withRetry(async () => {
912
- return await this.pushMessage(atAllArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("at", { type: "all" }) }));
913
- }, 1);
911
+ await withRetry(() => this.pushMessage(atAllArr, koishi.h.at("all")), 1);
914
912
  }
915
- if (type === PushType.Dynamic && record.dynamicArr?.length >= 1) {
916
- if (record.dynamicAtAllArr?.length >= 1) {
917
- this.logger.info(record.dynamicAtAllArr);
913
+ if (type === PushType.Dynamic && record.dynamicArr?.length > 0) {
914
+ if (record.dynamicAtAllArr?.length > 0) {
915
+ this.logger.info("推送动态 @全体:", record.dynamicAtAllArr);
918
916
  const dynamicAtAllArr = structuredClone(record.dynamicAtAllArr);
919
- await withRetry(async () => {
920
- return await this.pushMessage(dynamicAtAllArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("at", { type: "all" }) }));
921
- }, 1);
917
+ await withRetry(() => this.pushMessage(dynamicAtAllArr, koishi.h.at("all")), 1);
922
918
  }
923
- this.logger.info(record.dynamicArr);
919
+ this.logger.info("推送动态:", record.dynamicArr);
924
920
  const dynamicArr = structuredClone(record.dynamicArr);
925
- await withRetry(async () => {
926
- return await this.pushMessage(dynamicArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", { children: content }));
927
- }, 1);
921
+ await withRetry(() => this.pushMessage(dynamicArr, (0, koishi.h)("message", content)), 1);
928
922
  }
929
- if ((type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length >= 1) {
930
- this.logger.info(record.liveArr);
923
+ if ((type === PushType.Live || type === PushType.StartBroadcasting) && record.liveArr?.length > 0) {
924
+ this.logger.info("推送直播:", record.liveArr);
931
925
  const liveArr = structuredClone(record.liveArr);
932
- await withRetry(async () => {
933
- return await this.pushMessage(liveArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", { children: content }));
934
- }, 1);
926
+ await withRetry(() => this.pushMessage(liveArr, (0, koishi.h)("message", content)), 1);
935
927
  }
936
- if (type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length >= 1) {
937
- this.logger.info(record.liveGuardBuyArr);
928
+ if (type === PushType.LiveGuardBuy && record.liveGuardBuyArr?.length > 0) {
929
+ this.logger.info("推送直播守护购买:", record.liveGuardBuyArr);
938
930
  const liveGuardBuyArr = structuredClone(record.liveGuardBuyArr);
939
- await withRetry(async () => {
940
- return await this.pushMessage(liveGuardBuyArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", { children: content }));
941
- }, 1);
931
+ await withRetry(() => this.pushMessage(liveGuardBuyArr, (0, koishi.h)(koishi.h.Fragment, (0, koishi.h)(content))), 1);
942
932
  }
943
933
  if (type === PushType.WordCloudAndLiveSummary) {
944
934
  const wordcloudArr = structuredClone(record.wordcloudArr);
@@ -947,25 +937,16 @@ var ComRegister = class {
947
937
  const wordcloudOnlyArr = wordcloudArr.filter((item) => !liveSummaryArr.includes(item));
948
938
  const liveSummaryOnlyArr = liveSummaryArr.filter((item) => !wordcloudArr.includes(item));
949
939
  if (wordcloudAndLiveSummaryArr.length > 0) {
950
- this.logger.info("词云和直播总结");
951
- this.logger.info(wordcloudAndLiveSummaryArr);
952
- await withRetry(async () => {
953
- return await this.pushMessage(wordcloudAndLiveSummaryArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [content[0], content[1]] }));
954
- }, 1);
940
+ this.logger.info("推送词云和直播总结:", wordcloudAndLiveSummaryArr);
941
+ await withRetry(() => this.pushMessage(wordcloudAndLiveSummaryArr, (0, koishi.h)("message", [content[0], content[1]])), 1);
955
942
  }
956
943
  if (wordcloudOnlyArr.length > 0) {
957
- this.logger.info("词云");
958
- this.logger.info(wordcloudOnlyArr);
959
- await withRetry(async () => {
960
- return await this.pushMessage(wordcloudOnlyArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", { children: content[0] }));
961
- }, 1);
944
+ this.logger.info("推送词云:", wordcloudOnlyArr);
945
+ await withRetry(() => this.pushMessage(wordcloudOnlyArr, (0, koishi.h)("message", [content[0]])), 1);
962
946
  }
963
947
  if (liveSummaryOnlyArr.length > 0) {
964
- this.logger.info("直播总结");
965
- this.logger.info(liveSummaryOnlyArr);
966
- await withRetry(async () => {
967
- return await this.pushMessage(liveSummaryOnlyArr, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", { children: content[1] }));
968
- }, 1);
948
+ this.logger.info("推送直播总结:", liveSummaryOnlyArr);
949
+ await withRetry(() => this.pushMessage(liveSummaryOnlyArr, (0, koishi.h)("message", [content[1]])), 1);
969
950
  }
970
951
  }
971
952
  }
@@ -979,24 +960,21 @@ var ComRegister = class {
979
960
  });
980
961
  if (!content) return;
981
962
  if (content.code !== 0) switch (content.code) {
982
- case -101: {
963
+ case -101:
983
964
  this.logger.error("账号未登录,插件已停止工作,请登录");
984
965
  await this.sendPrivateMsg("账号未登录,插件已停止工作,请登录");
985
966
  await this.ctx["bilibili-notify"].disposePlugin();
986
967
  break;
987
- }
988
- case -352: {
968
+ case -352:
989
969
  this.logger.error("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
990
970
  await this.sendPrivateMsg("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
991
971
  await this.ctx["bilibili-notify"].disposePlugin();
992
972
  break;
993
- }
994
- default: {
973
+ default:
995
974
  this.logger.error(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
996
975
  await this.sendPrivateMsg(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
997
976
  await this.ctx["bilibili-notify"].disposePlugin();
998
977
  break;
999
- }
1000
978
  }
1001
979
  const items = content.data.items;
1002
980
  for (const item of items) {
@@ -1013,15 +991,15 @@ var ComRegister = class {
1013
991
  }, 1).catch(async (e) => {
1014
992
  if (e.message === "直播开播动态,不做处理") return;
1015
993
  if (e.message === "出现关键词,屏蔽该动态") {
1016
- if (this.config.filter.notify) await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [name$2, "发布了一条含有屏蔽关键字的动态"] }), PushType.Dynamic);
994
+ if (this.config.filter.notify) await this.broadcastToTargets(uid, (0, koishi.h)("message", `${name$2}发布了一条含有屏蔽关键字的动态`), PushType.Dynamic);
1017
995
  return;
1018
996
  }
1019
997
  if (e.message === "已屏蔽转发动态") {
1020
- if (this.config.filter.notify) await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [name$2, "转发了一条动态,已屏蔽"] }), PushType.Dynamic);
998
+ if (this.config.filter.notify) await this.broadcastToTargets(uid, (0, koishi.h)("message", `${name$2}转发了一条动态,已屏蔽`), PushType.Dynamic);
1021
999
  return;
1022
1000
  }
1023
1001
  if (e.message === "已屏蔽专栏动态") {
1024
- if (this.config.filter.notify) await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [name$2, "投稿了一条专栏,已屏蔽"] }), PushType.Dynamic);
1002
+ if (this.config.filter.notify) await this.broadcastToTargets(uid, (0, koishi.h)("message", `${name$2}投稿了一条专栏,已屏蔽`), PushType.Dynamic);
1025
1003
  return;
1026
1004
  }
1027
1005
  this.logger.error(`dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:${e.message}`);
@@ -1035,18 +1013,12 @@ var ComRegister = class {
1035
1013
  } else dUrl = `${name$2}发布了新视频:https:${item.modules.module_dynamic.major.archive.jump_url}`;
1036
1014
  else dUrl = `${name$2}发布了一条动态:https://t.bilibili.com/${item.id_str}`;
1037
1015
  this.logger.info("推送动态中...");
1038
- await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [koishi.h.image(buffer, "image/jpeg"), dUrl] }), PushType.Dynamic);
1016
+ await this.broadcastToTargets(uid, (0, koishi.h)("message", [koishi.h.image(buffer, "image/jpeg"), koishi.h.text(dUrl)]), PushType.Dynamic);
1039
1017
  if (this.config.pushImgsInDynamic) {
1040
1018
  if (item.type === "DYNAMIC_TYPE_DRAW") {
1041
1019
  const pics = item.modules?.module_dynamic?.major?.opus?.pics;
1042
1020
  if (pics) {
1043
- const picsMsg = /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", {
1044
- forward: true,
1045
- children: pics.map((pic) => /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("img", {
1046
- src: pic.url,
1047
- alt: "动态图片"
1048
- }, pic.url))
1049
- });
1021
+ const picsMsg = (0, koishi.h)("message", { forward: true }, pics.map((pic) => koishi.h.img(pic.url)));
1050
1022
  await this.broadcastToTargets(uid, picsMsg, PushType.Dynamic);
1051
1023
  }
1052
1024
  }
@@ -1074,24 +1046,21 @@ var ComRegister = class {
1074
1046
  });
1075
1047
  if (!content) return;
1076
1048
  if (content.code !== 0) switch (content.code) {
1077
- case -101: {
1049
+ case -101:
1078
1050
  this.logger.error("账号未登录,插件已停止工作,请登录");
1079
1051
  await this.sendPrivateMsg("账号未登录,插件已停止工作,请登录");
1080
1052
  await this.ctx["bilibili-notify"].disposePlugin();
1081
1053
  break;
1082
- }
1083
- case -352: {
1054
+ case -352:
1084
1055
  this.logger.error("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
1085
1056
  await this.sendPrivateMsg("账号被风控,插件已停止工作,请输入指令 bili cap 根据提示解除风控");
1086
1057
  await this.ctx["bilibili-notify"].disposePlugin();
1087
1058
  break;
1088
- }
1089
- default: {
1059
+ default:
1090
1060
  this.logger.error(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
1091
1061
  await this.sendPrivateMsg(`获取动态信息错误,错误码为:${content.code},错误为:${content.message},请排除错误后输入指令 bn start 重启插件`);
1092
1062
  await this.ctx["bilibili-notify"].disposePlugin();
1093
1063
  break;
1094
- }
1095
1064
  }
1096
1065
  this.logger.info("获取动态信息成功!开始处理动态信息...");
1097
1066
  const items = content.data.items;
@@ -1114,15 +1083,15 @@ var ComRegister = class {
1114
1083
  }, 1).catch(async (e) => {
1115
1084
  if (e.message === "直播开播动态,不做处理") return;
1116
1085
  if (e.message === "出现关键词,屏蔽该动态") {
1117
- if (this.config.filter.notify) await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [name$2, "发布了一条含有屏蔽关键字的动态"] }), PushType.Dynamic);
1086
+ if (this.config.filter.notify) await this.broadcastToTargets(uid, (0, koishi.h)("message", `${name$2}发布了一条含有屏蔽关键字的动态`), PushType.Dynamic);
1118
1087
  return;
1119
1088
  }
1120
1089
  if (e.message === "已屏蔽转发动态") {
1121
- if (this.config.filter.notify) await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [name$2, "转发了一条动态,已屏蔽"] }), PushType.Dynamic);
1090
+ if (this.config.filter.notify) await this.broadcastToTargets(uid, (0, koishi.h)("message", `${name$2}转发了一条动态,已屏蔽`), PushType.Dynamic);
1122
1091
  return;
1123
1092
  }
1124
1093
  if (e.message === "已屏蔽专栏动态") {
1125
- if (this.config.filter.notify) await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [name$2, "投稿了一条专栏,已屏蔽"] }), PushType.Dynamic);
1094
+ if (this.config.filter.notify) await this.broadcastToTargets(uid, (0, koishi.h)("message", `${name$2}投稿了一条专栏,已屏蔽`), PushType.Dynamic);
1126
1095
  return;
1127
1096
  }
1128
1097
  this.logger.error(`dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:${e.message}`);
@@ -1141,19 +1110,13 @@ var ComRegister = class {
1141
1110
  this.logger.info("动态链接生成成功!");
1142
1111
  }
1143
1112
  this.logger.info("推送动态中...");
1144
- await this.broadcastToTargets(uid, /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [koishi.h.image(buffer, "image/jpeg"), dUrl] }), PushType.Dynamic);
1113
+ await this.broadcastToTargets(uid, (0, koishi.h)("message", [koishi.h.image(buffer, "image/jpeg"), koishi.h.text(dUrl)]), PushType.Dynamic);
1145
1114
  if (this.config.pushImgsInDynamic) {
1146
1115
  this.logger.info("需要发送动态中的图片,开始发送...");
1147
1116
  if (item.type === "DYNAMIC_TYPE_DRAW") {
1148
1117
  const pics = item.modules?.module_dynamic?.major?.opus?.pics;
1149
1118
  if (pics) {
1150
- const picsMsg = /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("message", {
1151
- forward: true,
1152
- children: pics.map((pic) => /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("img", {
1153
- src: pic.url,
1154
- alt: "动态图片"
1155
- }, pic.url))
1156
- });
1119
+ const picsMsg = (0, koishi.h)("message", { forward: true }, pics.map((pic) => koishi.h.img(pic.url)));
1157
1120
  await this.broadcastToTargets(uid, picsMsg, PushType.Dynamic);
1158
1121
  }
1159
1122
  }
@@ -1214,7 +1177,7 @@ var ComRegister = class {
1214
1177
  this.logger.error(`liveDetect generateLiveImg() 推送卡片生成失败,原因:${e.message}`);
1215
1178
  });
1216
1179
  if (!buffer) return await this.sendPrivateMsgAndStopService();
1217
- const msg = /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [koishi.h.image(buffer, "image/jpeg"), liveNotifyMsg || ""] });
1180
+ const msg = (0, koishi.h)("message", [koishi.h.image(buffer, "image/jpeg"), koishi.h.text(liveNotifyMsg || "")]);
1218
1181
  return await this.broadcastToTargets(uid, msg, liveType === LiveType.StartBroadcasting ? PushType.StartBroadcasting : PushType.Live);
1219
1182
  }
1220
1183
  async segmentDanmaku(danmaku, danmakuWeightRecord) {
@@ -1299,10 +1262,14 @@ var ComRegister = class {
1299
1262
  });
1300
1263
  return flag;
1301
1264
  };
1265
+ const LIVE_EVENT_COOLDOWN = 10 * 1e3;
1266
+ let lastLiveStart = 0;
1267
+ let lastLiveEnd = 0;
1302
1268
  const handler = {
1303
1269
  onError: async () => {
1304
1270
  liveStatus = false;
1305
1271
  pushAtTimeTimer?.();
1272
+ pushAtTimeTimer = null;
1306
1273
  this.ctx["bilibili-notify-live"].closeListener(sub.roomid);
1307
1274
  await this.sendPrivateMsg(`[${sub.roomid}]直播间连接发生错误!`);
1308
1275
  this.logger.error(`[${sub.roomid}]直播间连接发生错误!`);
@@ -1319,19 +1286,20 @@ var ComRegister = class {
1319
1286
  watchedNum = body.text_small;
1320
1287
  },
1321
1288
  onGuardBuy: ({ body }) => {
1322
- const content = /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [
1323
- "【",
1324
- masterInfo.username,
1325
- "的直播间】",
1326
- body.user.uname,
1327
- "加入了大航海(",
1328
- body.gift_name,
1329
- ")"
1330
- ] });
1289
+ const content = (0, koishi.h)("message", [koishi.h.text(`【${masterInfo.username}的直播间】${body.user.uname}加入了大航海(${body.gift_name})`)]);
1331
1290
  this.broadcastToTargets(sub.uid, content, PushType.LiveGuardBuy);
1332
1291
  },
1333
1292
  onLiveStart: async () => {
1334
- if (liveStatus) return;
1293
+ const now = Date.now();
1294
+ if (now - lastLiveStart < LIVE_EVENT_COOLDOWN) {
1295
+ this.logger.warn(`[${sub.roomid}] 开播事件冷却期内被忽略`);
1296
+ return;
1297
+ }
1298
+ lastLiveStart = now;
1299
+ if (liveStatus) {
1300
+ this.logger.warn(`[${sub.roomid}] 已是开播状态,忽略重复开播事件`);
1301
+ return;
1302
+ }
1335
1303
  liveStatus = true;
1336
1304
  if (!await useMasterAndLiveRoomInfo(LiveType.StartBroadcasting)) {
1337
1305
  liveStatus = false;
@@ -1352,6 +1320,16 @@ var ComRegister = class {
1352
1320
  }
1353
1321
  },
1354
1322
  onLiveEnd: async () => {
1323
+ const now = Date.now();
1324
+ if (now - lastLiveEnd < LIVE_EVENT_COOLDOWN) {
1325
+ this.logger.warn(`[${sub.roomid}] 下播事件冷却期内被忽略`);
1326
+ return;
1327
+ }
1328
+ lastLiveEnd = now;
1329
+ if (!liveStatus) {
1330
+ this.logger.warn(`[${sub.roomid}] 已是下播状态,忽略重复下播事件`);
1331
+ return;
1332
+ }
1355
1333
  liveStatus = false;
1356
1334
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast)) {
1357
1335
  await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
@@ -1360,8 +1338,8 @@ var ComRegister = class {
1360
1338
  liveRoomInfo.live_time = liveTime;
1361
1339
  const followerChange = (() => {
1362
1340
  const liveFollowerChangeNum = masterInfo.liveFollowerChange;
1363
- if (liveFollowerChangeNum > 0) return liveFollowerChangeNum >= 1e4 ? `+${liveFollowerChangeNum.toFixed(1)}万` : `+${liveFollowerChangeNum}`;
1364
- return liveFollowerChangeNum <= -1e4 ? `${liveFollowerChangeNum.toFixed(1)}万` : liveFollowerChangeNum.toString();
1341
+ if (liveFollowerChangeNum > 0) return liveFollowerChangeNum >= 1e4 ? `+${(liveFollowerChangeNum / 1e4).toFixed(1)}万` : `+${liveFollowerChangeNum}`;
1342
+ return liveFollowerChangeNum <= -1e4 ? `${(liveFollowerChangeNum / 1e4).toFixed(1)}万` : liveFollowerChangeNum.toString();
1365
1343
  })();
1366
1344
  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");
1367
1345
  await this.sendLiveNotifyCard(LiveType.StopBroadcast, followerChange, {
@@ -1369,8 +1347,11 @@ var ComRegister = class {
1369
1347
  masterInfo,
1370
1348
  cardStyle: sub.customCardStyle
1371
1349
  }, sub.uid, liveEndMsg);
1372
- pushAtTimeTimer();
1373
- pushAtTimeTimer = null;
1350
+ if (pushAtTimeTimer) {
1351
+ pushAtTimeTimer();
1352
+ pushAtTimeTimer = null;
1353
+ this.liveWSManager.delete(sub.roomid);
1354
+ }
1374
1355
  await sendDanmakuWordCloudAndLiveSummary(liveMsgObj.liveSummary);
1375
1356
  }
1376
1357
  };
@@ -1452,7 +1433,7 @@ var ComRegister = class {
1452
1433
  if (!sub) return;
1453
1434
  switch (item.live_status) {
1454
1435
  case 0:
1455
- case 2: {
1436
+ case 2:
1456
1437
  if (LiveAPIStatus.live === true) {
1457
1438
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast, LiveAPIStatus)) {
1458
1439
  await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
@@ -1476,8 +1457,7 @@ var ComRegister = class {
1476
1457
  LiveAPIStatus.live = false;
1477
1458
  }
1478
1459
  break;
1479
- }
1480
- case 1: {
1460
+ case 1:
1481
1461
  if (LiveAPIStatus.live === false) {
1482
1462
  if (!await useMasterAndLiveRoomInfo(LiveType.StopBroadcast, LiveAPIStatus)) {
1483
1463
  await this.sendPrivateMsg("获取直播间信息失败,推送直播开播卡片失败!");
@@ -1516,7 +1496,6 @@ var ComRegister = class {
1516
1496
  LiveAPIStatus.push = 0;
1517
1497
  }
1518
1498
  break;
1519
- }
1520
1499
  default: break;
1521
1500
  }
1522
1501
  }
@@ -1536,7 +1515,7 @@ var ComRegister = class {
1536
1515
  else {
1537
1516
  const subTableArray = subInfo.split("\n");
1538
1517
  subTableArray.splice(subTableArray.length - 1, 1);
1539
- table = /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)(__satorijs_element_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("p", { children: "当前订阅对象:" }), /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("ul", { children: subTableArray.map((str) => /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsx)("li", { children: str })) })] });
1518
+ table = (0, koishi.h)(koishi.h.Fragment, [(0, koishi.h)("p", "当前订阅对象:"), (0, koishi.h)("ul", subTableArray.map((str) => (0, koishi.h)("li", str)))]);
1540
1519
  }
1541
1520
  this.subNotifier = this.ctx.notifier.create(table);
1542
1521
  }
@@ -1775,7 +1754,7 @@ var ComRegister = class {
1775
1754
  }
1776
1755
  };
1777
1756
  (function(_ComRegister) {
1778
- const Config$1 = _ComRegister.Config = koishi.Schema.object({
1757
+ _ComRegister.Config = koishi.Schema.object({
1779
1758
  advancedSub: koishi.Schema.boolean(),
1780
1759
  subs: koishi.Schema.array(koishi.Schema.object({
1781
1760
  name: koishi.Schema.string().required().description("备注"),
@@ -2118,7 +2097,7 @@ var GenerateImg = class extends koishi.Service {
2118
2097
  switch (dynamic.type) {
2119
2098
  case DYNAMIC_TYPE_WORD:
2120
2099
  case DYNAMIC_TYPE_DRAW:
2121
- case DYNAMIC_TYPE_FORWARD: {
2100
+ case DYNAMIC_TYPE_FORWARD:
2122
2101
  basicDynamic();
2123
2102
  if (dynamic.type === DYNAMIC_TYPE_FORWARD) {
2124
2103
  if (this.giConfig.filter.enable && this.giConfig.filter.forward) throw new Error("已屏蔽转发动态");
@@ -2219,7 +2198,6 @@ var GenerateImg = class extends koishi.Service {
2219
2198
  }
2220
2199
  }
2221
2200
  break;
2222
- }
2223
2201
  case DYNAMIC_TYPE_AV: {
2224
2202
  basicDynamic();
2225
2203
  const archive = dynamic.modules.module_dynamic.major.archive;
@@ -2287,10 +2265,9 @@ var GenerateImg = class extends koishi.Service {
2287
2265
  case DYNAMIC_TYPE_LIVE: return [`${upName}发起了直播预约,我暂时无法渲染,请自行查看`];
2288
2266
  case DYNAMIC_TYPE_MEDIALIST: return [`${upName}分享了收藏夹,我暂时无法渲染,请自行查看`];
2289
2267
  case DYNAMIC_TYPE_PGC: return [`${upName}发布了剧集(番剧、电影、纪录片),我暂时无法渲染,请自行查看`];
2290
- case DYNAMIC_TYPE_ARTICLE: {
2268
+ case DYNAMIC_TYPE_ARTICLE:
2291
2269
  if (this.giConfig.filter.enable && this.giConfig.filter.article) throw new Error("已屏蔽专栏动态");
2292
2270
  return [`${upName}投稿了新专栏,我暂时无法渲染,请自行查看`];
2293
- }
2294
2271
  case DYNAMIC_TYPE_MUSIC: return [`${upName}发行了新歌,我暂时无法渲染,请自行查看`];
2295
2272
  case DYNAMIC_TYPE_COMMON_SQUARE: return [`${upName}发布了装扮|剧集|点评|普通分享,我暂时无法渲染,请自行查看`];
2296
2273
  case DYNAMIC_TYPE_COURSES_SEASON: return [`${upName}发布了新课程,我暂时无法渲染,请自行查看`];
@@ -3201,8 +3178,8 @@ var GenerateImg = class extends koishi.Service {
3201
3178
  </div>
3202
3179
  </div>
3203
3180
 
3204
- <script src="${wordcloudJS}"></script>
3205
- <script src="${renderFunc}"></script>
3181
+ <script src="${wordcloudJS}"><\/script>
3182
+ <script src="${renderFunc}"><\/script>
3206
3183
  <script>
3207
3184
  const canvas = document.getElementById('wordCloudCanvas');
3208
3185
  const ctx = canvas.getContext('2d');
@@ -3226,7 +3203,7 @@ var GenerateImg = class extends koishi.Service {
3226
3203
  densityTarget: 0.3,
3227
3204
  weightExponent: 0.4
3228
3205
  });
3229
- </script>
3206
+ <\/script>
3230
3207
  </body>
3231
3208
 
3232
3209
  </html>
@@ -3240,30 +3217,26 @@ var GenerateImg = class extends koishi.Service {
3240
3217
  let liveTime;
3241
3218
  let cover;
3242
3219
  switch (liveStatus) {
3243
- case 0: {
3220
+ case 0:
3244
3221
  titleStatus = "未直播";
3245
3222
  liveTime = "未开播";
3246
3223
  cover = true;
3247
3224
  break;
3248
- }
3249
- case 1: {
3225
+ case 1:
3250
3226
  titleStatus = "开播啦";
3251
3227
  liveTime = `开播时间:${time}`;
3252
3228
  cover = true;
3253
3229
  break;
3254
- }
3255
- case 2: {
3230
+ case 2:
3256
3231
  titleStatus = "正在直播";
3257
3232
  liveTime = `直播时长:${await this.getTimeDifference(time)}`;
3258
3233
  cover = false;
3259
3234
  break;
3260
- }
3261
- case 3: {
3235
+ case 3:
3262
3236
  titleStatus = "下播啦";
3263
3237
  liveTime = `开播时间:${time}`;
3264
3238
  cover = true;
3265
3239
  break;
3266
- }
3267
3240
  }
3268
3241
  return [
3269
3242
  titleStatus,
@@ -3294,7 +3267,7 @@ var GenerateImg = class extends koishi.Service {
3294
3267
  return parts.length > 0 ? `${sign}${parts.join("")}` : "0秒";
3295
3268
  }
3296
3269
  unixTimestampToString(timestamp) {
3297
- const date = new Date(timestamp * 1e3);
3270
+ const date = /* @__PURE__ */ new Date(timestamp * 1e3);
3298
3271
  const year = date.getFullYear();
3299
3272
  const month = `0${date.getMonth() + 1}`.slice(-2);
3300
3273
  const day = `0${date.getDate()}`.slice(-2);
@@ -3305,7 +3278,7 @@ var GenerateImg = class extends koishi.Service {
3305
3278
  }
3306
3279
  };
3307
3280
  (function(_GenerateImg) {
3308
- const Config$1 = _GenerateImg.Config = koishi.Schema.object({
3281
+ _GenerateImg.Config = koishi.Schema.object({
3309
3282
  filter: koishi.Schema.object({
3310
3283
  enable: koishi.Schema.boolean(),
3311
3284
  notify: koishi.Schema.boolean(),
@@ -4032,15 +4005,13 @@ var BiliAPI = class extends koishi.Service {
4032
4005
  }, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
4033
4006
  switch (refreshData.code) {
4034
4007
  case -101: return await this.createNewClient();
4035
- case -111: {
4008
+ case -111:
4036
4009
  await this.ctx.database.remove("loginBili", [1]);
4037
4010
  notifyAndError("csrf 校验错误,请重新登录");
4038
4011
  break;
4039
- }
4040
- case 86095: {
4012
+ case 86095:
4041
4013
  await this.ctx.database.remove("loginBili", [1]);
4042
4014
  notifyAndError("refresh_csrf 错误或 refresh_token 与 cookie 不匹配,请重新登录");
4043
- }
4044
4015
  }
4045
4016
  const encryptedCookies = this.encrypt(this.getCookies());
4046
4017
  const encryptedRefreshToken = this.encrypt(refreshData.data.refresh_token);
@@ -4057,11 +4028,10 @@ var BiliAPI = class extends koishi.Service {
4057
4028
  refresh_token: refreshToken
4058
4029
  }, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
4059
4030
  switch (aceeptData.code) {
4060
- case -111: {
4031
+ case -111:
4061
4032
  await this.ctx.database.remove("loginBili", [1]);
4062
4033
  notifyAndError("csrf 校验失败,请重新登录");
4063
4034
  break;
4064
- }
4065
4035
  case -400: throw new Error("请求错误");
4066
4036
  }
4067
4037
  }
@@ -4094,7 +4064,7 @@ var BiliAPI = class extends koishi.Service {
4094
4064
  }
4095
4065
  };
4096
4066
  (function(_BiliAPI) {
4097
- const Config$1 = _BiliAPI.Config = koishi.Schema.object({
4067
+ _BiliAPI.Config = koishi.Schema.object({
4098
4068
  userAgent: koishi.Schema.string(),
4099
4069
  key: koishi.Schema.string().pattern(/^[0-9a-f]{32}$/).required()
4100
4070
  });