koishi-plugin-bilibili-notify 3.0.3 → 3.0.5-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.
@@ -12,6 +12,7 @@ const qrcode_1 = __importDefault(require("qrcode"));
12
12
  const utils_1 = require("./utils");
13
13
  // Types
14
14
  const type_1 = require("./type");
15
+ const luxon_1 = require("luxon");
15
16
  // TODO:WorlCloud
16
17
  // import { Segment, useDefault } from "segmentit";
17
18
  class ComRegister {
@@ -252,6 +253,24 @@ class ComRegister {
252
253
  }
253
254
  return table;
254
255
  });
256
+ biliCom
257
+ .subcommand(".dyn <uid:string> [index:number]", "手动推送一条动态信息", {
258
+ hidden: true,
259
+ })
260
+ .usage("手动推送一条动态信息")
261
+ .example("bili dyn 233 1 手动推送UID为233用户空间的第一条动态信息")
262
+ .action(async ({ session }, uid, index) => {
263
+ // 获取index
264
+ const i = (index && index - 1) || 0;
265
+ // 获取动态
266
+ const content = await this.ctx.ba.getUserSpaceDynamic(uid);
267
+ // 获取动态内容
268
+ const item = content.data.items[i];
269
+ // 生成图片
270
+ const buffer = await this.ctx.gi.generateDynamicImg(item);
271
+ // 发送图片
272
+ await session.send(koishi_1.h.image(buffer, "image/png"));
273
+ });
255
274
  }
256
275
  async init(config) {
257
276
  // 设置logger
@@ -481,16 +500,16 @@ class ComRegister {
481
500
  dynamicDetect() {
482
501
  // 检测初始化变量
483
502
  let detectSetup = true;
484
- // 更新基线
485
- let updateBaseline;
503
+ // 时间线
504
+ let timeline;
486
505
  // 第一条动态的动态ID
487
506
  let dynamicIdStr1st;
488
- // 第二条动态的动态ID
489
- let dynamicIdStr2nd;
490
507
  // 定义handler
491
508
  const handler = async () => {
492
- // 检测启动初始化
509
+ // 动态监测启动初始化
493
510
  if (detectSetup) {
511
+ // logger
512
+ this.logger.info("动态监测初始化中...");
494
513
  // 使用withRetry函数进行重试
495
514
  const content = await (0, utils_1.withRetry)(async () => {
496
515
  // 获取动态内容
@@ -505,24 +524,23 @@ class ComRegister {
505
524
  // 判断获取动态信息是否成功
506
525
  if (content.code !== 0)
507
526
  return;
508
- // 设置更新基线
509
- updateBaseline = content.data.update_baseline;
510
527
  // 设置第一条动态的动态ID
511
528
  dynamicIdStr1st = content.data?.items[0]?.id_str || "0";
512
- // 判断第二条动态是否存在
513
- if (content.data?.items[1]) {
514
- // 设置第二条动态的动态ID
515
- dynamicIdStr2nd = content.data.items[1].id_str;
516
- }
529
+ // 设置时间线
530
+ timeline =
531
+ content.data?.items[0]?.modules.module_author.pub_ts ||
532
+ luxon_1.DateTime.now().toSeconds();
517
533
  // 设置初始化为false
518
534
  detectSetup = false;
535
+ // logger
536
+ this.logger.info("动态监测初始化完毕!");
519
537
  // 初始化完成
520
538
  return;
521
539
  }
522
540
  // 使用withRetry函数进行重试
523
541
  const content = await (0, utils_1.withRetry)(async () => {
524
542
  // 获取动态内容
525
- return (await this.ctx.ba.getAllDynamic(updateBaseline));
543
+ return (await this.ctx.ba.getAllDynamic());
526
544
  }, 1).catch((e) => {
527
545
  // logger
528
546
  this.logger.error(`dynamicDetect getAllDynamic() 发生了错误,错误为:${e.message}`);
@@ -574,87 +592,86 @@ class ComRegister {
574
592
  }
575
593
  }
576
594
  }
577
- // 获取数据内容
578
- const data = content.data;
579
- // 更新基线
580
- updateBaseline = data.update_baseline;
581
- // 有新动态内容
582
- const items = data.items;
595
+ const items = content.data.items;
583
596
  // 检查更新的动态
584
597
  for (const item of items) {
585
- // 动态ID如果一致则结束循环
586
- if (item.id_str === dynamicIdStr1st)
587
- break;
588
- if (item.id_str === dynamicIdStr2nd)
589
- break;
590
598
  // 没有动态内容则直接跳过
591
599
  if (!item)
592
600
  continue;
593
- // 从动态数据中取出UP主名称、UID和动态ID
594
- const upUID = item.modules.module_author.mid.toString();
595
- const upName = item.modules.module_author.name;
601
+ // 获取动态ID
596
602
  const dynamicId = item.id_str;
597
- // 寻找关注的UP主的动态
598
- for (const sub of this.subManager) {
599
- // 判断是否是订阅的UP主
600
- if (sub.dynamic && sub.uid === upUID) {
601
- // 订阅该UP主,推送该动态
602
- // 推送该条动态
603
- const buffer = await (0, utils_1.withRetry)(async () => {
604
- // 渲染图片
605
- return await this.ctx.gi.generateDynamicImg(item, sub.card);
606
- }, 1).catch(async (e) => {
607
- // 直播开播动态,不做处理
608
- if (e.message === "直播开播动态,不做处理")
609
- return;
610
- if (e.message === "出现关键词,屏蔽该动态") {
611
- // 如果需要发送才发送
612
- if (this.config.filter.notify) {
613
- await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
603
+ // 动态ID如果一致则结束循环
604
+ if (dynamicId === dynamicIdStr1st)
605
+ break;
606
+ // 判断动态时间戳是否大于时间线
607
+ if (item.modules.module_author.pub_ts > timeline) {
608
+ // 从动态数据中取出UP主名称、UID
609
+ const upUID = item.modules.module_author.mid.toString();
610
+ const upName = item.modules.module_author.name;
611
+ // 寻找关注的UP主的动态
612
+ for (const sub of this.subManager) {
613
+ // 判断是否是订阅的UP主
614
+ if (sub.dynamic && sub.uid === upUID) {
615
+ // 订阅该UP主,推送该动态
616
+ // 推送该条动态
617
+ const buffer = await (0, utils_1.withRetry)(async () => {
618
+ // 渲染图片
619
+ return await this.ctx.gi.generateDynamicImg(item, sub.card);
620
+ }, 1).catch(async (e) => {
621
+ // 直播开播动态,不做处理
622
+ if (e.message === "直播开播动态,不做处理")
623
+ return;
624
+ if (e.message === "出现关键词,屏蔽该动态") {
625
+ // 如果需要发送才发送
626
+ if (this.config.filter.notify) {
627
+ await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
628
+ }
629
+ return;
614
630
  }
615
- return;
616
- }
617
- if (e.message === "已屏蔽转发动态") {
618
- if (this.config.filter.notify) {
619
- await this.sendMsg(sub.target, `${upName}转发了一条动态,已屏蔽`);
631
+ if (e.message === "已屏蔽转发动态") {
632
+ if (this.config.filter.notify) {
633
+ await this.sendMsg(sub.target, `${upName}转发了一条动态,已屏蔽`);
634
+ }
635
+ return;
620
636
  }
621
- return;
622
- }
623
- // 未知错误
624
- this.logger.error(`dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:${e.message}`);
625
- // 发送私聊消息并重启服务
626
- await this.sendPrivateMsgAndStopService();
627
- });
628
- // 判断是否执行成功,未执行成功直接返回
629
- if (!buffer)
630
- continue;
631
- // 判断是否需要发送URL
632
- const dUrl = this.config.dynamicUrl
633
- ? `${upName}发布了一条动态:https://t.bilibili.com/${dynamicId}`
634
- : "";
635
- // logger
636
- this.logger.info("推送动态中...");
637
- // 发送推送卡片
638
- await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, "image/png"), dUrl] }));
639
- // 判断是否需要发送动态中的图片
640
- if (this.config.pushImgsInDynamic) {
641
- // 判断是否为图文动态,且存在draw
642
- if (item.type === "DYNAMIC_TYPE_DRAW" &&
643
- item.modules.module_dynamic.major?.draw) {
644
- for (const img of item.modules.module_dynamic.major.draw
645
- .items) {
646
- await this.sendMsg(sub.target, (0, jsx_runtime_1.jsx)("img", { src: img.src, alt: "\u52A8\u6001\u56FE\u7247" }));
637
+ // 未知错误
638
+ this.logger.error(`dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:${e.message}`);
639
+ // 发送私聊消息并重启服务
640
+ await this.sendPrivateMsgAndStopService();
641
+ });
642
+ // 判断是否执行成功,未执行成功直接返回
643
+ if (!buffer)
644
+ continue;
645
+ // 判断是否需要发送URL
646
+ const dUrl = this.config.dynamicUrl
647
+ ? `${upName}发布了一条动态:https://t.bilibili.com/${dynamicId}`
648
+ : "";
649
+ // logger
650
+ this.logger.info("推送动态中...");
651
+ // 发送推送卡片
652
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, "image/png"), dUrl] }));
653
+ // 判断是否需要发送动态中的图片
654
+ if (this.config.pushImgsInDynamic) {
655
+ // 判断是否为图文动态,且存在draw
656
+ if (item.type === "DYNAMIC_TYPE_DRAW" &&
657
+ item.modules.module_dynamic.major?.draw) {
658
+ for (const img of item.modules.module_dynamic.major.draw
659
+ .items) {
660
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsx)("img", { src: img.src, alt: "\u52A8\u6001\u56FE\u7247" }));
661
+ }
647
662
  }
648
663
  }
664
+ // logger
665
+ this.logger.info("动态推送完毕!");
649
666
  }
650
- // logger
651
- this.logger.info("动态推送完毕!");
652
667
  }
653
668
  }
654
669
  }
655
670
  // 更新本次请求第一条动态的动态ID
656
- dynamicIdStr1st = items[0]?.id_str || "0";
657
- dynamicIdStr2nd = items[1]?.id_str || "0";
671
+ dynamicIdStr1st = items[0].id_str;
672
+ // 更新时间线
673
+ timeline =
674
+ items[0].modules.module_author.pub_ts || luxon_1.DateTime.now().toSeconds();
658
675
  };
659
676
  // 返回一个闭包函数
660
677
  return (0, utils_1.withLock)(handler);
@@ -662,16 +679,18 @@ class ComRegister {
662
679
  debug_dynamicDetect() {
663
680
  // 检测初始化变量
664
681
  let detectSetup = true;
665
- // 更新基线
666
- let updateBaseline;
682
+ // 时间线
683
+ let timeline;
667
684
  // 第一条动态的动态ID
668
685
  let dynamicIdStr1st;
669
- let dynamicIdStr2nd;
670
686
  // 定义handler
671
687
  const handler = async () => {
672
- this.logger.info(`初始化状态:${detectSetup}`);
673
- // 检测启动初始化
688
+ // 动态监测启动初始化
674
689
  if (detectSetup) {
690
+ // logger
691
+ this.logger.info("动态监测初始化中...");
692
+ // logger
693
+ this.logger.info("正在获取动态信息...");
675
694
  // 使用withRetry函数进行重试
676
695
  const content = await (0, utils_1.withRetry)(async () => {
677
696
  // 获取动态内容
@@ -681,40 +700,48 @@ class ComRegister {
681
700
  this.logger.error(`dynamicDetect getAllDynamic() 发生了错误,错误为:${e.message}`);
682
701
  });
683
702
  // content不存在则直接返回
684
- if (!content)
703
+ if (!content) {
704
+ // logger
705
+ this.logger.info("获取动态信息失败!");
685
706
  return;
707
+ }
686
708
  // 判断获取动态信息是否成功
687
- if (content.code !== 0)
709
+ if (content.code !== 0) {
710
+ // logger
711
+ this.logger.info("获取动态信息失败!");
688
712
  return;
689
- // 设置更新基线
690
- updateBaseline = content.data.update_baseline;
691
- this.logger.info(`更新基线:${updateBaseline}`);
713
+ }
692
714
  // 设置第一条动态的动态ID
693
- dynamicIdStr1st = content.data.items[0]?.id_str || "0";
694
- dynamicIdStr2nd = content.data.items[1]?.id_str || "0";
695
- this.logger.info(`第一条动态ID:${dynamicIdStr1st}`);
696
- this.logger.info(`第二条动态ID:${dynamicIdStr2nd}`);
715
+ dynamicIdStr1st = content.data?.items[0]?.id_str || "0";
716
+ // logger
717
+ this.logger.info(`获取到第一条动态ID:${dynamicIdStr1st}`);
718
+ // 设置时间线
719
+ timeline =
720
+ content.data?.items[0]?.modules.module_author.pub_ts ||
721
+ luxon_1.DateTime.now().toSeconds();
722
+ // logger
723
+ this.logger.info(`获取到时间线信息:${timeline}`);
697
724
  // 设置初始化为false
698
725
  detectSetup = false;
726
+ // logger
727
+ this.logger.info("动态监测初始化完毕!");
699
728
  // 初始化完成
700
- this.logger.info("动态检测初始化完成");
701
729
  return;
702
730
  }
703
- this.logger.info(`更新基线:${updateBaseline}`);
704
- this.logger.info(`第一条动态ID:${dynamicIdStr1st}`);
705
- this.logger.info(`第二条动态ID:${dynamicIdStr2nd}`);
706
- this.logger.info("获取动态内容中...");
731
+ // logger
732
+ this.logger.info("正在获取动态信息...");
707
733
  // 使用withRetry函数进行重试
708
734
  const content = await (0, utils_1.withRetry)(async () => {
709
735
  // 获取动态内容
710
- return (await this.ctx.ba.getAllDynamic(updateBaseline));
736
+ return (await this.ctx.ba.getAllDynamic());
711
737
  }, 1).catch((e) => {
712
738
  // logger
713
739
  this.logger.error(`dynamicDetect getAllDynamic() 发生了错误,错误为:${e.message}`);
714
740
  });
715
741
  // content不存在则直接返回
716
742
  if (!content) {
717
- this.logger.error("获取动态内容失败");
743
+ // logger
744
+ this.logger.info("获取动态信息失败!");
718
745
  return;
719
746
  }
720
747
  // 判断获取动态内容是否成功
@@ -761,100 +788,127 @@ class ComRegister {
761
788
  }
762
789
  }
763
790
  }
764
- this.logger.error("获取动态内容成功,开始检测动态");
765
- // 获取数据内容
766
- const data = content.data;
767
- // 更新基线
768
- updateBaseline = data.update_baseline;
769
- this.logger.info(`更新基线:${updateBaseline}`);
770
- // 有新动态内容
771
- const items = data.items;
791
+ // logger
792
+ this.logger.info("成功获取动态信息!开始检查更新的动态...");
793
+ // 获取动态内容
794
+ const items = content.data.items;
772
795
  // 检查更新的动态
773
796
  for (const item of items) {
797
+ // 没有动态内容则直接跳过
798
+ if (!item) {
799
+ // logger
800
+ this.logger.info("动态内容为空,跳过该动态");
801
+ continue;
802
+ }
803
+ // 获取动态ID
804
+ const dynamicId = item.id_str;
805
+ // logger
806
+ this.logger.info(`当前动态ID:${dynamicId}`);
807
+ this.logger.info(`上一次获取到第一条动态ID:${dynamicId}`);
774
808
  // 动态ID如果一致则结束循环
775
- if (item.id_str === dynamicIdStr1st ||
776
- item.id_str === dynamicIdStr2nd) {
809
+ if (dynamicId === dynamicIdStr1st) {
777
810
  // logger
778
- this.logger.info("动态ID与上次检测第一条一致,结束循环");
779
- this.logger.info("动态检测结束");
780
- // 结束循环
811
+ this.logger.info("动态ID与上一次获取第一条一致,结束循环");
781
812
  break;
782
813
  }
783
- // 没有动态内容则直接跳过
784
- if (!item)
785
- continue;
786
- // 从动态数据中取出UP主名称、UID和动态ID
787
- const upUID = item.modules.module_author.mid.toString();
788
- const upName = item.modules.module_author.name;
789
- const dynamicId = item.id_str;
790
- // 寻找关注的UP主的动态
791
- for (const sub of this.subManager) {
792
- // 判断是否是订阅的UP主
793
- if (sub.dynamic && sub.uid === upUID) {
794
- // 订阅该UP主,推送该动态
795
- this.logger.info(`寻找到需要推送的动态,订阅的UP主:${upName}(${upUID}),动态ID:${dynamicId}`);
796
- this.logger.info("渲染推送卡片中...");
797
- // 推送该条动态
798
- const buffer = await (0, utils_1.withRetry)(async () => {
799
- // 渲染图片
800
- return await this.ctx.gi.generateDynamicImg(item, sub.card);
801
- }, 1).catch(async (e) => {
802
- // 直播开播动态,不做处理
803
- if (e.message === "直播开播动态,不做处理")
804
- return;
805
- if (e.message === "出现关键词,屏蔽该动态") {
806
- // 如果需要发送才发送
807
- if (this.config.filter.notify) {
808
- await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
814
+ // logger
815
+ this.logger.info(`当前动态时间线:${item.modules.module_author.pub_ts}`);
816
+ this.logger.info(`上一次获取到第一条动态时间线:${timeline}`);
817
+ // 判断动态时间戳是否大于时间线
818
+ if (item.modules.module_author.pub_ts > timeline) {
819
+ // logger
820
+ this.logger.info("动态时间线大于上一次获取到第一条动态时间线,开始判断是否是订阅的UP主...");
821
+ // 从动态数据中取出UP主名称、UID
822
+ const upUID = item.modules.module_author.mid.toString();
823
+ const upName = item.modules.module_author.name;
824
+ // logger
825
+ this.logger.info(`当前动态UP主UID:${upUID},UP主名称:${upName}`);
826
+ // 寻找关注的UP主的动态
827
+ for (const sub of this.subManager) {
828
+ // 判断是否是订阅的UP主
829
+ if (sub.dynamic && sub.uid === upUID) {
830
+ // logger:订阅该UP主,推送该动态
831
+ this.logger.info("订阅该UP主,开始推送该动态...");
832
+ // logger
833
+ this.logger.info("开始生成推送卡片...");
834
+ // 推送该条动态
835
+ const buffer = await (0, utils_1.withRetry)(async () => {
836
+ // 渲染图片
837
+ return await this.ctx.gi.generateDynamicImg(item, sub.card);
838
+ }, 1).catch(async (e) => {
839
+ // 直播开播动态,不做处理
840
+ if (e.message === "直播开播动态,不做处理")
841
+ return;
842
+ if (e.message === "出现关键词,屏蔽该动态") {
843
+ // 如果需要发送才发送
844
+ if (this.config.filter.notify) {
845
+ await this.sendMsg(sub.target, `${upName}发布了一条含有屏蔽关键字的动态`);
846
+ }
847
+ return;
809
848
  }
810
- return;
811
- }
812
- if (e.message === "已屏蔽转发动态") {
813
- if (this.config.filter.notify) {
814
- await this.sendMsg(sub.target, `${upName}转发了一条动态,已屏蔽`);
849
+ if (e.message === "已屏蔽转发动态") {
850
+ if (this.config.filter.notify) {
851
+ await this.sendMsg(sub.target, `${upName}转发了一条动态,已屏蔽`);
852
+ }
853
+ return;
815
854
  }
816
- return;
855
+ // 未知错误
856
+ this.logger.error(`dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:${e.message}`);
857
+ // 发送私聊消息并重启服务
858
+ await this.sendPrivateMsgAndStopService();
859
+ });
860
+ // 判断是否执行成功,未执行成功直接返回
861
+ if (!buffer) {
862
+ // logger
863
+ this.logger.info("推送卡片生成失败,或该动态为屏蔽动态,跳过该动态!");
864
+ // 结束循环
865
+ continue;
817
866
  }
818
- // 未知错误
819
- this.logger.error(`dynamicDetect generateDynamicImg() 推送卡片发送失败,原因:${e.message}`);
820
- // 发送私聊消息并重启服务
821
- await this.sendPrivateMsgAndStopService();
822
- });
823
- // 判断是否执行成功,未执行成功直接返回
824
- if (!buffer) {
825
- this.logger.error("渲染推送卡片失败");
826
- // 下一条
827
- continue;
828
- }
829
- // 判断是否需要发送URL
830
- const dUrl = this.config.dynamicUrl
831
- ? `${upName}发布了一条动态:https://t.bilibili.com/${dynamicId}`
832
- : "";
833
- // logger
834
- this.logger.info("推送动态中...");
835
- // 发送推送卡片
836
- await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, "image/png"), dUrl] }));
837
- // 判断是否需要发送动态中的图片
838
- if (this.config.pushImgsInDynamic) {
839
- // 判断是否为图文动态,且存在draw
840
- if (item.type === "DYNAMIC_TYPE_DRAW" &&
841
- item.modules.module_dynamic.major?.draw) {
842
- this.logger.info("推送动态图片中...");
843
- for (const img of item.modules.module_dynamic.major.draw
844
- .items) {
845
- await this.sendMsg(sub.target, (0, jsx_runtime_1.jsx)("img", { src: img.src, alt: "\u52A8\u6001\u56FE\u7247" }));
867
+ // 定义动态链接
868
+ let dUrl = "";
869
+ // 判断是否需要发送URL
870
+ if (this.config.dynamicUrl) {
871
+ // logger
872
+ this.logger.info("生成动态链接中...");
873
+ // 生成动态链接
874
+ dUrl = `${upName}发布了一条动态:https://t.bilibili.com/${dynamicId}`;
875
+ }
876
+ // logger
877
+ this.logger.info("推送动态中...");
878
+ // 发送推送卡片
879
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, "image/png"), dUrl] }));
880
+ // logger
881
+ this.logger.info("动态推送完毕!");
882
+ // 判断是否需要发送动态中的图片
883
+ if (this.config.pushImgsInDynamic) {
884
+ // logger
885
+ this.logger.info("开始推送动态中的图片...");
886
+ // 判断是否为图文动态,且存在draw
887
+ if (item.type === "DYNAMIC_TYPE_DRAW" &&
888
+ item.modules.module_dynamic.major?.draw) {
889
+ for (const img of item.modules.module_dynamic.major.draw
890
+ .items) {
891
+ await this.sendMsg(sub.target, (0, jsx_runtime_1.jsx)("img", { src: img.src, alt: "\u52A8\u6001\u56FE\u7247" }));
892
+ }
846
893
  }
847
- this.logger.info("动态图片推送完毕!");
894
+ // logger
895
+ this.logger.info("图片推送完毕!");
848
896
  }
897
+ // logger
898
+ this.logger.info("动态推送完毕!");
849
899
  }
850
- // logger
851
- this.logger.info("动态推送完毕!");
852
900
  }
853
901
  }
854
902
  }
855
903
  // 更新本次请求第一条动态的动态ID
856
- dynamicIdStr1st = items[0]?.id_str || "0";
857
- dynamicIdStr2nd = items[1]?.id_str || "0";
904
+ dynamicIdStr1st = items[0].id_str;
905
+ // logger
906
+ this.logger.info(`更新本次请求第一条动态的动态ID:${dynamicIdStr1st}`);
907
+ // 更新时间线
908
+ timeline =
909
+ items[0].modules.module_author.pub_ts || luxon_1.DateTime.now().toSeconds();
910
+ // logger
911
+ this.logger.info(`更新时间线:${timeline}`);
858
912
  };
859
913
  // 返回一个闭包函数
860
914
  return (0, utils_1.withLock)(handler);
@@ -8,6 +8,7 @@ declare class GenerateImg extends Service {
8
8
  static inject: string[];
9
9
  giConfig: GenerateImg.Config;
10
10
  constructor(ctx: Context, config: GenerateImg.Config);
11
+ compressImage(buffer: Buffer): Promise<Buffer>;
11
12
  imgHandler(html: string): Promise<Buffer<ArrayBufferLike>>;
12
13
  generateLiveImg(data: any, username: string, userface: string, followerDisplay: string, liveStatus: number, { cardColorStart, cardColorEnd, cardBasePlateColor, cardBasePlateBorder, }: {
13
14
  cardColorStart?: string;
@@ -15,7 +16,7 @@ declare class GenerateImg extends Service {
15
16
  cardBasePlateColor?: string;
16
17
  cardBasePlateBorder?: string;
17
18
  }): Promise<Buffer<ArrayBufferLike>>;
18
- generateDynamicImg(data: any, { cardColorStart, cardColorEnd, cardBasePlateColor, cardBasePlateBorder, }: {
19
+ generateDynamicImg(data: any, { cardColorStart, cardColorEnd, cardBasePlateColor, cardBasePlateBorder, }?: {
19
20
  cardColorStart?: string;
20
21
  cardColorEnd?: string;
21
22
  cardBasePlateColor?: string;
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  const koishi_1 = require("koishi");
4
7
  const luxon_1 = require("luxon");
8
+ const imagemin_1 = __importDefault(require("imagemin"));
9
+ const imagemin_pngquant_1 = __importDefault(require("imagemin-pngquant"));
5
10
  const node_path_1 = require("node:path");
6
11
  const node_url_1 = require("node:url");
7
12
  const utils_1 = require("./utils");
@@ -29,6 +34,25 @@ class GenerateImg extends koishi_1.Service {
29
34
  super(ctx, "gi");
30
35
  this.giConfig = config;
31
36
  }
37
+ async compressImage(buffer) {
38
+ return await (0, utils_1.withRetry)(async () => {
39
+ const compressedBuffer = await imagemin_1.default.buffer(buffer, {
40
+ plugins: [
41
+ (0, imagemin_pngquant_1.default)({
42
+ quality: [0.6, 0.8],
43
+ speed: 4,
44
+ }),
45
+ ],
46
+ });
47
+ if (compressedBuffer.length >= buffer.length) {
48
+ return buffer;
49
+ }
50
+ return Buffer.from(compressedBuffer);
51
+ }, 1).catch((e) => {
52
+ this.ctx.logger.error(`压缩图片失败: ${e.message}`);
53
+ return buffer;
54
+ });
55
+ }
32
56
  async imgHandler(html) {
33
57
  const htmlPath = `file://${__dirname.replaceAll("\\", "/")}/page/0.html`;
34
58
  const page = await this.ctx.puppeteer.page();
@@ -47,7 +71,7 @@ class GenerateImg extends koishi_1.Service {
47
71
  });
48
72
  await elementHandle.dispose();
49
73
  await page.close();
50
- return buffer;
74
+ return this.compressImage(buffer);
51
75
  }
52
76
  async generateLiveImg(
53
77
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
@@ -216,7 +240,7 @@ class GenerateImg extends koishi_1.Service {
216
240
  }
217
241
  async generateDynamicImg(
218
242
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
219
- data, { cardColorStart = this.giConfig.cardColorStart, cardColorEnd = this.giConfig.cardColorEnd, cardBasePlateColor = this.giConfig.cardBasePlateColor, cardBasePlateBorder = this.giConfig.cardBasePlateBorder, }) {
243
+ data, { cardColorStart = this.giConfig.cardColorStart, cardColorEnd = this.giConfig.cardColorEnd, cardBasePlateColor = this.giConfig.cardBasePlateColor, cardBasePlateBorder = this.giConfig.cardBasePlateBorder, } = {}) {
220
244
  // module_author
221
245
  const module_author = data.modules.module_author;
222
246
  const avatarUrl = module_author.face;
@@ -70,6 +70,7 @@ export type AllDynamicInfo = {
70
70
  mid: number;
71
71
  name: string;
72
72
  face: string;
73
+ pub_ts: number;
73
74
  };
74
75
  module_dynamic: {
75
76
  major: {
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.0.3",
4
+ "version": "3.0.5-alpha.0",
5
5
  "contributors": [
6
6
  "Akokko <admin@akokko.com>"
7
7
  ],
@@ -30,6 +30,8 @@
30
30
  "axios": "^1.7.9",
31
31
  "axios-cookiejar-support": "^5.0.5",
32
32
  "blive-message-listener": "^0.5.0",
33
+ "imagemin": "^9.0.1",
34
+ "imagemin-pngquant": "^10.0.0",
33
35
  "jsdom": "^24.1.3",
34
36
  "luxon": "^3.5.0",
35
37
  "md5": "^2.3.0",
@@ -39,6 +41,7 @@
39
41
  },
40
42
  "devDependencies": {
41
43
  "@biomejs/biome": "1.9.4",
44
+ "@types/imagemin": "^9",
42
45
  "@types/luxon": "^3.4.2",
43
46
  "@types/md5": "^2.3.5",
44
47
  "@types/qrcode": "^1.5.5",
package/readme.md CHANGED
@@ -27,7 +27,7 @@
27
27
 
28
28
  ## 注意事项
29
29
 
30
- 0. 动态监测,当您订阅之后,会在您设置的dynamicLoopTime(默认为2分钟)之后才会开启监测。如果您需要测试则需要等待您设置的dynamicLoopTime的时间之后再发送测试动态
30
+ 0. 由于 `3.0.2` 动态监测定时器更换为cron定时任务,如果需要测试动态监测功能是否正常,可以通过控制台日志输出观察,打印 `动态监测初始化完毕!` 后,可进行测试
31
31
 
32
32
  1. 此插件依赖于 `database` 和 `puppeteer` 服务,同时受权限控制,需要具备 `authority:3` 及以上的权限才能使用本插件提供的指令,你可以参考下方配置登录插件中的方法得到一个超级管理员账号(具有 `authority:5` 的最高权限)
33
33
 
@@ -38,6 +38,7 @@
38
38
  [权限管理](https://koishi.chat/zh-CN/manual/usage/customize.html)
39
39
 
40
40
  3. 指令使用方法请参考 `help bili`,子命令使用方法请加 `-h` ,例如 `bili login -h`
41
+
41
42
  4. 登录方式为二维码,输入命令 `bili login` 之后扫码登录,您的登录凭证将存储在您的本地数据库,并由您自己填写的密钥加密,所以请保管好你的密钥
42
43
 
43
44
  ## 安装
@@ -63,6 +64,12 @@
63
64
 
64
65
  - 使用指令 `bili ll`
65
66
 
67
+ 推送指定UP主指定动态:
68
+
69
+ - 使用指令 `bili dyn <uid> [index]`
70
+
71
+ uid为必填参数,为要推送的UP主的UID,index为可选参数,为要推送的动态排序,不应超过15,不填默认第一条。例如要推送UID为 `233` 的UP主的第九条动态 `bili dyn 233 9`
72
+
66
73
  插件的启动、停止和重启
67
74
 
68
75
  - 使用指令 `sys`
@@ -219,6 +226,8 @@
219
226
  - ver 3.0.1 修复:动态推送过程中,如果上一次请求的第一条动态被删除,可能导致动态重复推送(本次修复并不能完全保障不重复推送,如果第一条和第二条都被删除则可能会出现重复推送); 新增:配置项 `subTimeout` 设置订阅超时时间
220
227
  - ver 3.0.2 优化:动态监测,新增依赖服务 `cron`
221
228
  - ver 3.0.3 移除:配置项 `dynamicLoopTime` ,动态循环时间将不再可选,默认为两分钟
229
+ - ver 3.0.4 优化:动态监测,增加时间判断,防止出现重复推送问题; 由于 `3.0.2` 动态监测定时器更换为cron定时任务,如果需要测试动态监测功能是否正常,可以通过控制台日志输出观察,打印 `动态监测初始化完毕!` 后,可进行测试
230
+ - ver 3.0.5-alpha.0 优化:推送卡片渲染,压缩图片; 新增:指令 `bili dyn` 可用于推送指定UP主指定动态
222
231
 
223
232
  ## 交流群
224
233
 
@@ -227,7 +236,9 @@
227
236
  ## 感谢
228
237
 
229
238
  [koishijs](https://github.com/koishijs/koishi) 感谢官方提供的插件开发框架, 以及技术指导
239
+
230
240
  [blive-message-listener](https://github.com/ddiu8081/blive-message-listener) 感谢 `ddiu8081` 提供简单方便的B站直播监听依赖
241
+
231
242
  [bilibili-API-collect](https://github.com/SocialSisterYi/bilibili-API-collect) 感谢 `SocialSisterYi` 提供B站API参考
232
243
 
233
244
  ## License