koishi-plugin-bilibili-notify 3.0.0-alpha.16 → 3.0.0-alpha.18
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.
- package/lib/comRegister.d.ts +3 -35
- package/lib/comRegister.js +93 -341
- package/lib/generateImg.d.ts +2 -1
- package/lib/generateImg.js +29 -24
- package/lib/index.d.ts +1 -0
- package/lib/index.js +15 -9
- package/lib/type/index.d.ts +37 -0
- package/lib/type/index.js +11 -0
- package/package.json +1 -1
- package/readme.md +2 -0
package/lib/comRegister.d.ts
CHANGED
|
@@ -1,34 +1,7 @@
|
|
|
1
1
|
import { type Bot, type Context, type FlatPick, type Logger, Schema } from "koishi";
|
|
2
2
|
import type { Notifier } from "@koishijs/plugin-notifier";
|
|
3
3
|
import type { LoginBili } from "./database";
|
|
4
|
-
|
|
5
|
-
NotLiveBroadcast = 0,
|
|
6
|
-
StartBroadcasting = 1,
|
|
7
|
-
LiveBroadcast = 2,
|
|
8
|
-
StopBroadcast = 3
|
|
9
|
-
}
|
|
10
|
-
type ChannelIdArr = Array<{
|
|
11
|
-
channelId: string;
|
|
12
|
-
dynamic: boolean;
|
|
13
|
-
live: boolean;
|
|
14
|
-
liveGuardBuy: boolean;
|
|
15
|
-
atAll: boolean;
|
|
16
|
-
}>;
|
|
17
|
-
type TargetItem = {
|
|
18
|
-
channelIdArr: ChannelIdArr;
|
|
19
|
-
platform: string;
|
|
20
|
-
};
|
|
21
|
-
type Target = Array<TargetItem>;
|
|
22
|
-
type SubItem = {
|
|
23
|
-
id: number;
|
|
24
|
-
uid: string;
|
|
25
|
-
roomId: string;
|
|
26
|
-
target: Target;
|
|
27
|
-
platform: string;
|
|
28
|
-
live: boolean;
|
|
29
|
-
dynamic: boolean;
|
|
30
|
-
};
|
|
31
|
-
type SubManager = Array<SubItem>;
|
|
4
|
+
import { LiveType, type MasterInfo, type SubManager, type Target } from "./type";
|
|
32
5
|
declare class ComRegister {
|
|
33
6
|
static inject: string[];
|
|
34
7
|
qqRelatedBotList: Array<string>;
|
|
@@ -59,14 +32,9 @@ declare class ComRegister {
|
|
|
59
32
|
userface: string;
|
|
60
33
|
target: Target;
|
|
61
34
|
data: any;
|
|
62
|
-
}, liveType: LiveType, liveNotifyMsg?: string): Promise<void>;
|
|
63
|
-
useMasterInfo(uid: string): Promise<
|
|
64
|
-
username: string;
|
|
65
|
-
userface: string;
|
|
66
|
-
roomId: number;
|
|
67
|
-
}>;
|
|
35
|
+
}, liveType: LiveType, followerDisplay: string, liveNotifyMsg?: string): Promise<void>;
|
|
36
|
+
useMasterInfo(uid: string, masterInfo: MasterInfo, liveType: LiveType): Promise<MasterInfo>;
|
|
68
37
|
useLiveRoomInfo(roomId: string): Promise<any>;
|
|
69
|
-
liveDetectWithAPI(): Promise<() => Promise<void>>;
|
|
70
38
|
liveDetectWithListener(roomId: string, target: Target): Promise<void>;
|
|
71
39
|
subShow(): string;
|
|
72
40
|
updateSubNotifier(): void;
|
package/lib/comRegister.js
CHANGED
|
@@ -7,16 +7,10 @@ const jsx_runtime_1 = require("@satorijs/element/jsx-runtime");
|
|
|
7
7
|
const koishi_1 = require("koishi");
|
|
8
8
|
// 导入qrcode
|
|
9
9
|
const qrcode_1 = __importDefault(require("qrcode"));
|
|
10
|
+
const type_1 = require("./type");
|
|
10
11
|
// 弹幕词云
|
|
11
12
|
// TODO:WorlCloud
|
|
12
13
|
// import { Segment } from "segmentit";
|
|
13
|
-
var LiveType;
|
|
14
|
-
(function (LiveType) {
|
|
15
|
-
LiveType[LiveType["NotLiveBroadcast"] = 0] = "NotLiveBroadcast";
|
|
16
|
-
LiveType[LiveType["StartBroadcasting"] = 1] = "StartBroadcasting";
|
|
17
|
-
LiveType[LiveType["LiveBroadcast"] = 2] = "LiveBroadcast";
|
|
18
|
-
LiveType[LiveType["StopBroadcast"] = 3] = "StopBroadcast";
|
|
19
|
-
})(LiveType || (LiveType = {}));
|
|
20
14
|
class ComRegister {
|
|
21
15
|
// 必须服务
|
|
22
16
|
static inject = ["ba", "gi", "database", "bl", "sm"];
|
|
@@ -206,53 +200,6 @@ class ComRegister {
|
|
|
206
200
|
const subTable = this.subShow();
|
|
207
201
|
return subTable;
|
|
208
202
|
});
|
|
209
|
-
biliCom
|
|
210
|
-
.subcommand(".status <roomId:string>", "查询主播当前直播状态", {
|
|
211
|
-
hidden: true,
|
|
212
|
-
})
|
|
213
|
-
.usage("查询主播当前直播状态")
|
|
214
|
-
.example("bili status 732")
|
|
215
|
-
.action(async ({ session }, roomId) => {
|
|
216
|
-
this.logger.info("调用bili.status指令");
|
|
217
|
-
if (!roomId)
|
|
218
|
-
return session.send("请输入房间号!");
|
|
219
|
-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
220
|
-
let content;
|
|
221
|
-
try {
|
|
222
|
-
content = await ctx.ba.getLiveRoomInfo(roomId);
|
|
223
|
-
}
|
|
224
|
-
catch (e) {
|
|
225
|
-
return `bili status指令 getLiveRoomInfo() 发生了错误,错误为:${e.message}`;
|
|
226
|
-
}
|
|
227
|
-
const { data } = content;
|
|
228
|
-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
229
|
-
let userData;
|
|
230
|
-
try {
|
|
231
|
-
const { data: userInfo } = await ctx.ba.getMasterInfo(data.uid);
|
|
232
|
-
userData = userInfo;
|
|
233
|
-
}
|
|
234
|
-
catch (e) {
|
|
235
|
-
return `bili status指令 getMasterInfo() 发生了错误,错误为:${e.message}`;
|
|
236
|
-
}
|
|
237
|
-
// B站出问题了
|
|
238
|
-
if (content.code !== 0) {
|
|
239
|
-
if (content.msg === "未找到该房间") {
|
|
240
|
-
session.send("未找到该房间");
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
session.send(`未知错误,错误信息为:${content.message}`);
|
|
244
|
-
}
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
const { pic, buffer } = await ctx.gi.generateLiveImg(data, userData.info.uname, userData.info.face, data.live_status !== 1
|
|
248
|
-
? LiveType.NotLiveBroadcast
|
|
249
|
-
: LiveType.LiveBroadcast);
|
|
250
|
-
// pic 存在,使用的是render模式
|
|
251
|
-
if (pic)
|
|
252
|
-
return pic;
|
|
253
|
-
// pic不存在,说明使用的是page模式
|
|
254
|
-
await session.send(koishi_1.h.image(buffer, "image/png"));
|
|
255
|
-
});
|
|
256
203
|
biliCom
|
|
257
204
|
.subcommand(".private", "向主人账号发送一条测试消息", { hidden: true })
|
|
258
205
|
.usage("向主人账号发送一条测试消息")
|
|
@@ -860,7 +807,7 @@ class ComRegister {
|
|
|
860
807
|
};
|
|
861
808
|
}
|
|
862
809
|
// 定义发送直播通知卡片方法
|
|
863
|
-
async sendLiveNotifyCard(info, liveType, liveNotifyMsg) {
|
|
810
|
+
async sendLiveNotifyCard(info, liveType, followerDisplay, liveNotifyMsg) {
|
|
864
811
|
// 定义变量
|
|
865
812
|
let pic;
|
|
866
813
|
let buffer;
|
|
@@ -869,7 +816,7 @@ class ComRegister {
|
|
|
869
816
|
for (let i = 0; i < attempts; i++) {
|
|
870
817
|
try {
|
|
871
818
|
// 获取直播通知卡片
|
|
872
|
-
const { pic: picv, buffer: bufferv } = await this.ctx.gi.generateLiveImg(info.data, info.username, info.userface, liveType);
|
|
819
|
+
const { pic: picv, buffer: bufferv } = await this.ctx.gi.generateLiveImg(info.data, info.username, info.userface, followerDisplay, liveType);
|
|
873
820
|
// 赋值
|
|
874
821
|
pic = picv;
|
|
875
822
|
buffer = bufferv;
|
|
@@ -889,7 +836,7 @@ class ComRegister {
|
|
|
889
836
|
// pic 存在,使用的是render模式
|
|
890
837
|
if (pic) {
|
|
891
838
|
// 只有在开播时才艾特全体成员
|
|
892
|
-
if (liveType === LiveType.StartBroadcasting) {
|
|
839
|
+
if (liveType === type_1.LiveType.StartBroadcasting) {
|
|
893
840
|
return await this.sendMsg(info.target, pic + (liveNotifyMsg ?? ""), true);
|
|
894
841
|
}
|
|
895
842
|
// 正常不需要艾特全体成员
|
|
@@ -898,19 +845,47 @@ class ComRegister {
|
|
|
898
845
|
// pic不存在,说明使用的是page模式
|
|
899
846
|
const msg = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, "image/png"), liveNotifyMsg || ""] }));
|
|
900
847
|
// 只有在开播时才艾特全体成员
|
|
901
|
-
if (liveType === LiveType.StartBroadcasting) {
|
|
848
|
+
if (liveType === type_1.LiveType.StartBroadcasting) {
|
|
902
849
|
return await this.sendMsg(info.target, msg, true);
|
|
903
850
|
}
|
|
904
851
|
// 正常不需要艾特全体成员
|
|
905
852
|
return await this.sendMsg(info.target, msg);
|
|
906
853
|
}
|
|
907
854
|
// 定义获取主播信息方法
|
|
908
|
-
async useMasterInfo(uid) {
|
|
855
|
+
async useMasterInfo(uid, masterInfo, liveType) {
|
|
856
|
+
// 获取主播信息
|
|
909
857
|
const { data } = await this.ctx.ba.getMasterInfo(uid);
|
|
858
|
+
// 定义粉丝数变量
|
|
859
|
+
let liveOpenFollowerNum;
|
|
860
|
+
let liveEndFollowerNum;
|
|
861
|
+
let liveFollowerChange;
|
|
862
|
+
// 判断直播状态
|
|
863
|
+
if (liveType === type_1.LiveType.StartBroadcasting ||
|
|
864
|
+
liveType === type_1.LiveType.FirstLiveBroadcast) {
|
|
865
|
+
// 第一次启动或刚开播
|
|
866
|
+
// 将当前粉丝数赋值给liveOpenFollowerNum、liveEndFollowerNum
|
|
867
|
+
liveOpenFollowerNum = data.follower_num;
|
|
868
|
+
liveEndFollowerNum = data.follower_num;
|
|
869
|
+
// 将粉丝数变化赋值为0
|
|
870
|
+
liveFollowerChange = 0;
|
|
871
|
+
}
|
|
872
|
+
if (liveType === type_1.LiveType.StopBroadcast ||
|
|
873
|
+
liveType === type_1.LiveType.LiveBroadcast) {
|
|
874
|
+
// 将上一次的liveOpenFollowerNum赋值给本次的liveOpenFollowerNum
|
|
875
|
+
liveOpenFollowerNum = masterInfo.liveOpenFollowerNum;
|
|
876
|
+
// 将当前粉丝数赋值给liveEndFollowerNum
|
|
877
|
+
liveEndFollowerNum = data.follower_num;
|
|
878
|
+
// 计算粉丝数变化量
|
|
879
|
+
liveFollowerChange = liveEndFollowerNum - masterInfo.liveOpenFollowerNum;
|
|
880
|
+
}
|
|
881
|
+
// 返回值
|
|
910
882
|
return {
|
|
911
883
|
username: data.info.uname,
|
|
912
884
|
userface: data.info.face,
|
|
913
885
|
roomId: data.room_id,
|
|
886
|
+
liveOpenFollowerNum,
|
|
887
|
+
liveEndFollowerNum,
|
|
888
|
+
liveFollowerChange,
|
|
914
889
|
};
|
|
915
890
|
}
|
|
916
891
|
async useLiveRoomInfo(roomId) {
|
|
@@ -936,241 +911,24 @@ class ComRegister {
|
|
|
936
911
|
}
|
|
937
912
|
return content.data;
|
|
938
913
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
for (let i = 0; i < attempts; i++) {
|
|
954
|
-
try {
|
|
955
|
-
// 发送请求获取room信息
|
|
956
|
-
content = await this.ctx.ba.getLiveRoomInfo(roomId);
|
|
957
|
-
// 成功则跳出循环
|
|
958
|
-
break;
|
|
959
|
-
}
|
|
960
|
-
catch (e) {
|
|
961
|
-
this.logger.error(`liveDetect getLiveRoomInfo 发生了错误,错误为:${e.message}`);
|
|
962
|
-
if (i === attempts - 1) {
|
|
963
|
-
// 已尝试三次
|
|
964
|
-
// 发送私聊消息并重启服务
|
|
965
|
-
return await this.sendPrivateMsgAndStopService();
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
// 返回data
|
|
970
|
-
return content.data;
|
|
971
|
-
};
|
|
972
|
-
return async () => {
|
|
973
|
-
// 如果flag为false则说明前面的代码还未执行完,则直接返回
|
|
974
|
-
if (!flag)
|
|
975
|
-
return;
|
|
976
|
-
// 将标志位置为false
|
|
977
|
-
flag = false;
|
|
978
|
-
try {
|
|
979
|
-
// 获取正在直播对象
|
|
980
|
-
const liveUsers = await this.ctx.ba.getTheUserWhoIsLiveStreaming();
|
|
981
|
-
// 判断是否是初始化直播监测
|
|
982
|
-
if (liveDetectSetup) {
|
|
983
|
-
// 将第一次订阅置为false
|
|
984
|
-
liveDetectSetup = false;
|
|
985
|
-
// 初始化subRecord
|
|
986
|
-
for (const sub of this.subManager) {
|
|
987
|
-
// 判断是否订阅直播
|
|
988
|
-
if (sub.live) {
|
|
989
|
-
// 将该订阅添加到subRecord中
|
|
990
|
-
liveRecord[sub.uid] = {
|
|
991
|
-
liveStatus: 0,
|
|
992
|
-
liveTime: "",
|
|
993
|
-
target: sub.target,
|
|
994
|
-
};
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
// 先判断是否有UP主正在直播
|
|
998
|
-
if (liveUsers.count > 0) {
|
|
999
|
-
// 遍历liveUsers
|
|
1000
|
-
for (const item of liveUsers.items) {
|
|
1001
|
-
// 判断是否有订阅对象正在直播
|
|
1002
|
-
if (liveRecord[item.mid]) {
|
|
1003
|
-
// 获取当前用户直播间信息
|
|
1004
|
-
const data = await useLiveStatus(item.room_id.toString());
|
|
1005
|
-
// 设置开播时间
|
|
1006
|
-
liveRecord[item.mid].liveTime = data.live_time;
|
|
1007
|
-
// 改变开播状态
|
|
1008
|
-
liveRecord[item.mid].liveStatus = 1;
|
|
1009
|
-
// 设置直播中消息
|
|
1010
|
-
const liveMsg = this.config.customLive
|
|
1011
|
-
? this.config.customLive
|
|
1012
|
-
.replace("-name", item.uname)
|
|
1013
|
-
.replace("-time", await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
|
|
1014
|
-
.replace("-link", `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`)
|
|
1015
|
-
: null;
|
|
1016
|
-
// 发送直播通知卡片
|
|
1017
|
-
if (this.config.restartPush)
|
|
1018
|
-
this.sendLiveNotifyCard({
|
|
1019
|
-
username: item.uname,
|
|
1020
|
-
userface: item.face,
|
|
1021
|
-
target: liveRecord[item.mid].target,
|
|
1022
|
-
data,
|
|
1023
|
-
}, LiveType.LiveBroadcast, liveMsg);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
// 没有正在直播的订阅对象,直接返回
|
|
1028
|
-
return;
|
|
1029
|
-
}
|
|
1030
|
-
// 获取当前订阅直播的数量
|
|
1031
|
-
const currentLiveSubs = this.subManager.filter((sub) => sub.live);
|
|
1032
|
-
// 获取当前liveRecord里的订阅数量
|
|
1033
|
-
const currentLiveRecordKeys = Object.keys(liveRecord);
|
|
1034
|
-
// 判断是否能匹配双方数量
|
|
1035
|
-
if (currentLiveRecordKeys.length < currentLiveSubs.length) {
|
|
1036
|
-
// 遍历currentLiveSubs
|
|
1037
|
-
for (const sub of currentLiveSubs) {
|
|
1038
|
-
// 判断liveRecord中缺少了哪些订阅
|
|
1039
|
-
if (!liveRecord[sub.uid]) {
|
|
1040
|
-
// 获取当前用户直播间信息
|
|
1041
|
-
const data = await useLiveStatus(sub.roomId.toString());
|
|
1042
|
-
switch (data.live_status) {
|
|
1043
|
-
case 0:
|
|
1044
|
-
case 2: {
|
|
1045
|
-
// 未开播
|
|
1046
|
-
// 添加到liveRecord中
|
|
1047
|
-
liveRecord[sub.uid] = {
|
|
1048
|
-
liveStatus: 0,
|
|
1049
|
-
liveTime: "",
|
|
1050
|
-
target: sub.target,
|
|
1051
|
-
};
|
|
1052
|
-
// break
|
|
1053
|
-
break;
|
|
1054
|
-
}
|
|
1055
|
-
case 1: {
|
|
1056
|
-
//正在直播
|
|
1057
|
-
// 添加到liveRecord中
|
|
1058
|
-
liveRecord[sub.uid] = {
|
|
1059
|
-
liveStatus: 1,
|
|
1060
|
-
liveTime: data.live_time,
|
|
1061
|
-
target: sub.target,
|
|
1062
|
-
};
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
if (currentLiveRecordKeys.length > currentLiveSubs.length) {
|
|
1069
|
-
// 创建Set
|
|
1070
|
-
const setCurrentLiveSubs = new Set(currentLiveSubs.map((sub) => sub.uid));
|
|
1071
|
-
// 找出 currentLiveRecordKeys中比currentLiveSubs 多的元素
|
|
1072
|
-
const extraInCurrentLiveSubs = currentLiveRecordKeys.filter((key) => !setCurrentLiveSubs.has(key));
|
|
1073
|
-
// 遍历 extraInCurrentLiveSubs
|
|
1074
|
-
for (const subUID of extraInCurrentLiveSubs) {
|
|
1075
|
-
// 删除记录
|
|
1076
|
-
delete liveRecord[subUID];
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
// 数量没有差异,则不进行其他操作
|
|
1080
|
-
// 遍历liveUsers
|
|
1081
|
-
for (const item of liveUsers.items) {
|
|
1082
|
-
// 判断是否有正在直播的订阅对象
|
|
1083
|
-
if (liveRecord[item.mid]) {
|
|
1084
|
-
// 有正在直播的订阅对象
|
|
1085
|
-
// 获取当前用户直播间信息
|
|
1086
|
-
const data = await useLiveStatus(item.room_id.toString());
|
|
1087
|
-
// 判断开播状态
|
|
1088
|
-
switch (liveRecord[item.mid].liveStatus) {
|
|
1089
|
-
case 0: {
|
|
1090
|
-
// 之前未开播,现在开播了
|
|
1091
|
-
// 设置开播时间
|
|
1092
|
-
liveRecord[item.mid].liveTime = data.live_time;
|
|
1093
|
-
// 定义开播通知语
|
|
1094
|
-
const liveStartMsg = this.config.customLiveStart
|
|
1095
|
-
? this.config.customLiveStart
|
|
1096
|
-
.replace("-name", item.uname)
|
|
1097
|
-
.replace("-time", await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
|
|
1098
|
-
.replace("-link", `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`)
|
|
1099
|
-
: null;
|
|
1100
|
-
// 发送直播通知卡片
|
|
1101
|
-
await this.sendLiveNotifyCard({
|
|
1102
|
-
username: item.uname,
|
|
1103
|
-
userface: item.face,
|
|
1104
|
-
target: liveRecord[item.mid].target,
|
|
1105
|
-
data,
|
|
1106
|
-
}, LiveType.LiveBroadcast, liveStartMsg);
|
|
1107
|
-
// 改变开播状态
|
|
1108
|
-
liveRecord[item.mid].liveStatus = 1;
|
|
1109
|
-
// 结束
|
|
1110
|
-
break;
|
|
1111
|
-
}
|
|
1112
|
-
case 1: {
|
|
1113
|
-
// 仍在直播
|
|
1114
|
-
if (this.config.pushTime > 0) {
|
|
1115
|
-
timer++;
|
|
1116
|
-
// 开始记录时间
|
|
1117
|
-
if (timer >= 6 * 60 * this.config.pushTime) {
|
|
1118
|
-
// 到时间推送直播消息
|
|
1119
|
-
// 到时间重新计时
|
|
1120
|
-
timer = 0;
|
|
1121
|
-
// 定义直播中通知消息
|
|
1122
|
-
const liveMsg = this.config.customLive
|
|
1123
|
-
? this.config.customLive
|
|
1124
|
-
.replace("-name", item.uname)
|
|
1125
|
-
.replace("-time", await this.ctx.gi.getTimeDifference(liveRecord[item.mid].liveTime))
|
|
1126
|
-
.replace("-link", `https://live.bilibili.com/${data.short_id === 0 ? data.room_id : data.short_id}`)
|
|
1127
|
-
: null;
|
|
1128
|
-
// 发送直播通知卡片
|
|
1129
|
-
this.sendLiveNotifyCard({
|
|
1130
|
-
username: item.uname,
|
|
1131
|
-
userface: item.face,
|
|
1132
|
-
target: liveRecord[item.mid].target,
|
|
1133
|
-
data,
|
|
1134
|
-
}, LiveType.LiveBroadcast, liveMsg);
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
// 找出liveRecord中liveStatus为1但liveUsers中没有的元素
|
|
1142
|
-
const extraInLiveRecord = currentLiveRecordKeys.filter((key) => !liveUsers.items.some((item) => item.mid === Number(key)));
|
|
1143
|
-
// 遍历 extraInLiveRecord
|
|
1144
|
-
for (const subUID of extraInLiveRecord) {
|
|
1145
|
-
// 下播的主播
|
|
1146
|
-
// 获取主播信息
|
|
1147
|
-
const masterInfo = await this.useMasterInfo(subUID);
|
|
1148
|
-
// 获取直播间消息
|
|
1149
|
-
const liveRoomInfo = await this.useLiveRoomInfo(masterInfo.roomId.toString());
|
|
1150
|
-
// 设置开播时间
|
|
1151
|
-
liveRoomInfo.live_time = liveRecord[subUID].liveTime;
|
|
1152
|
-
// 定义下播播通知语
|
|
1153
|
-
const liveEndMsg = this.config.customLiveEnd
|
|
1154
|
-
? this.config.customLiveEnd
|
|
1155
|
-
.replace("-name", masterInfo.username)
|
|
1156
|
-
.replace("-time", await this.ctx.gi.getTimeDifference(liveRecord[subUID].liveTime))
|
|
1157
|
-
.replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`)
|
|
1158
|
-
: null;
|
|
1159
|
-
// 发送下播通知
|
|
1160
|
-
this.sendLiveNotifyCard({
|
|
1161
|
-
username: masterInfo.username,
|
|
1162
|
-
userface: masterInfo.userface,
|
|
1163
|
-
target: liveRecord[subUID].target,
|
|
1164
|
-
data: liveRoomInfo,
|
|
1165
|
-
}, LiveType.StopBroadcast, liveEndMsg);
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
finally {
|
|
1169
|
-
// 执行完方法体不论如何都把flag设置为true
|
|
1170
|
-
flag = true;
|
|
914
|
+
// TODO:WordCloud
|
|
915
|
+
/* // 定义获取弹幕权重Record函数
|
|
916
|
+
const getDanmakuWeightRecord = (): Record<string, number> => {
|
|
917
|
+
// 创建segmentit
|
|
918
|
+
const segmentit = useDefault(new Segment());
|
|
919
|
+
// 创建Record
|
|
920
|
+
const danmakuWeightRecord: Record<string, number> = {};
|
|
921
|
+
// 循环遍历currentLiveDanmakuArr
|
|
922
|
+
for (const danmaku of currentLiveDanmakuArr) {
|
|
923
|
+
// 遍历结果
|
|
924
|
+
segmentit.doSegment(danmaku).map((word: { w: string; p: number }) => {
|
|
925
|
+
// 定义权重
|
|
926
|
+
danmakuWeightRecord[word.w] = (danmakuWeightRecord[word.w] || 0) + 1;
|
|
927
|
+
});
|
|
1171
928
|
}
|
|
1172
|
-
|
|
1173
|
-
|
|
929
|
+
// 返回Record
|
|
930
|
+
return danmakuWeightRecord;
|
|
931
|
+
}; */
|
|
1174
932
|
async liveDetectWithListener(roomId, target) {
|
|
1175
933
|
// 定义开播时间
|
|
1176
934
|
let liveTime;
|
|
@@ -1187,6 +945,7 @@ class ComRegister {
|
|
|
1187
945
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
1188
946
|
let liveRoomInfo;
|
|
1189
947
|
let masterInfo;
|
|
948
|
+
let watchedNum;
|
|
1190
949
|
// 找到频道/群组对应的
|
|
1191
950
|
const liveGuardBuyPushTargetArr = target.map((channel) => {
|
|
1192
951
|
// 获取符合条件的target
|
|
@@ -1202,17 +961,20 @@ class ComRegister {
|
|
|
1202
961
|
// 定义定时推送函数
|
|
1203
962
|
const pushAtTimeFunc = async () => {
|
|
1204
963
|
// 判断是否信息是否获取成功
|
|
1205
|
-
if (!(await useMasterAndLiveRoomInfo())) {
|
|
964
|
+
if (!(await useMasterAndLiveRoomInfo(type_1.LiveType.LiveBroadcast))) {
|
|
1206
965
|
// 未获取成功,直接返回
|
|
1207
966
|
return this.sendPrivateMsg("获取直播间信息失败,推送直播卡片失败!");
|
|
1208
967
|
}
|
|
1209
968
|
// 设置开播时间
|
|
1210
969
|
liveTime = liveRoomInfo.live_time;
|
|
970
|
+
// 获取watched
|
|
971
|
+
const watched = watchedNum || "暂未获取到";
|
|
1211
972
|
// 设置直播中消息
|
|
1212
973
|
const liveMsg = this.config.customLive
|
|
1213
974
|
? this.config.customLive
|
|
1214
975
|
.replace("-name", masterInfo.username)
|
|
1215
976
|
.replace("-time", await this.ctx.gi.getTimeDifference(liveTime))
|
|
977
|
+
.replace("-watched", watched)
|
|
1216
978
|
.replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`)
|
|
1217
979
|
: null;
|
|
1218
980
|
// 发送直播通知卡片
|
|
@@ -1221,28 +983,10 @@ class ComRegister {
|
|
|
1221
983
|
userface: masterInfo.userface,
|
|
1222
984
|
target,
|
|
1223
985
|
data: liveRoomInfo,
|
|
1224
|
-
}, LiveType.LiveBroadcast, liveMsg);
|
|
986
|
+
}, type_1.LiveType.LiveBroadcast, watched, liveMsg);
|
|
1225
987
|
};
|
|
1226
|
-
// TODO:WordCloud
|
|
1227
|
-
/* // 定义获取弹幕权重Record函数
|
|
1228
|
-
const getDanmakuWeightRecord = (): Record<string, number> => {
|
|
1229
|
-
// 创建segmentit
|
|
1230
|
-
const segmentit = useDefault(new Segment());
|
|
1231
|
-
// 创建Record
|
|
1232
|
-
const danmakuWeightRecord: Record<string, number> = {};
|
|
1233
|
-
// 循环遍历currentLiveDanmakuArr
|
|
1234
|
-
for (const danmaku of currentLiveDanmakuArr) {
|
|
1235
|
-
// 遍历结果
|
|
1236
|
-
segmentit.doSegment(danmaku).map((word: { w: string; p: number }) => {
|
|
1237
|
-
// 定义权重
|
|
1238
|
-
danmakuWeightRecord[word.w] = (danmakuWeightRecord[word.w] || 0) + 1;
|
|
1239
|
-
});
|
|
1240
|
-
}
|
|
1241
|
-
// 返回Record
|
|
1242
|
-
return danmakuWeightRecord;
|
|
1243
|
-
}; */
|
|
1244
988
|
// 定义直播间信息获取函数
|
|
1245
|
-
const useMasterAndLiveRoomInfo = async () => {
|
|
989
|
+
const useMasterAndLiveRoomInfo = async (liveType) => {
|
|
1246
990
|
// 定义函数是否执行成功flag
|
|
1247
991
|
let flag = true;
|
|
1248
992
|
// 获取直播间信息
|
|
@@ -1260,7 +1004,7 @@ class ComRegister {
|
|
|
1260
1004
|
return flag;
|
|
1261
1005
|
}
|
|
1262
1006
|
// 获取主播信息(需要满足flag为true,liveRoomInfo.uid有值)
|
|
1263
|
-
masterInfo = await this.useMasterInfo(liveRoomInfo.uid).catch(() => {
|
|
1007
|
+
masterInfo = await this.useMasterInfo(liveRoomInfo.uid, masterInfo, liveType).catch(() => {
|
|
1264
1008
|
// 设置flag为false
|
|
1265
1009
|
flag = false;
|
|
1266
1010
|
// 返回空
|
|
@@ -1269,11 +1013,6 @@ class ComRegister {
|
|
|
1269
1013
|
// 返回信息
|
|
1270
1014
|
return flag;
|
|
1271
1015
|
};
|
|
1272
|
-
// 判断是否信息是否获取成功
|
|
1273
|
-
if (!(await useMasterAndLiveRoomInfo())) {
|
|
1274
|
-
// 未获取成功,直接返回
|
|
1275
|
-
return this.sendPrivateMsg("获取直播间信息失败,启动直播间弹幕检测失败!");
|
|
1276
|
-
}
|
|
1277
1016
|
// 构建消息处理函数
|
|
1278
1017
|
const handler = {
|
|
1279
1018
|
onIncomeDanmu: ({ body }) => {
|
|
@@ -1284,6 +1023,10 @@ class ComRegister {
|
|
|
1284
1023
|
// 保存消息到数组
|
|
1285
1024
|
currentLiveDanmakuArr.push(body.content);
|
|
1286
1025
|
},
|
|
1026
|
+
onWatchedChange: ({ body }) => {
|
|
1027
|
+
// 保存观看人数到变量
|
|
1028
|
+
watchedNum = body.text_small;
|
|
1029
|
+
},
|
|
1287
1030
|
onGuardBuy: ({ body }) => {
|
|
1288
1031
|
// 定义消息
|
|
1289
1032
|
const content = `${body.user.uname}加入了大航海(${body.gift_name})`;
|
|
@@ -1297,7 +1040,7 @@ class ComRegister {
|
|
|
1297
1040
|
// 设置开播状态为true
|
|
1298
1041
|
liveStatus = true;
|
|
1299
1042
|
// 判断是否信息是否获取成功
|
|
1300
|
-
if (!(await useMasterAndLiveRoomInfo())) {
|
|
1043
|
+
if (!(await useMasterAndLiveRoomInfo(type_1.LiveType.StartBroadcasting))) {
|
|
1301
1044
|
// 设置开播状态为false
|
|
1302
1045
|
liveStatus = false;
|
|
1303
1046
|
// 未获取成功,直接返回
|
|
@@ -1305,11 +1048,14 @@ class ComRegister {
|
|
|
1305
1048
|
}
|
|
1306
1049
|
// 设置开播时间
|
|
1307
1050
|
liveTime = liveRoomInfo.live_time;
|
|
1051
|
+
// 获取当前粉丝数
|
|
1052
|
+
const follower = masterInfo.liveOpenFollowerNum >= 10_000 ? `${masterInfo.liveOpenFollowerNum.toFixed(1)}万` : masterInfo.liveOpenFollowerNum.toString();
|
|
1308
1053
|
// 定义开播通知语
|
|
1309
1054
|
const liveStartMsg = this.config.customLiveStart
|
|
1310
1055
|
? this.config.customLiveStart
|
|
1311
1056
|
.replace("-name", masterInfo.username)
|
|
1312
1057
|
.replace("-time", await this.ctx.gi.getTimeDifference(liveTime))
|
|
1058
|
+
.replace("-follower", follower)
|
|
1313
1059
|
.replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`)
|
|
1314
1060
|
: null;
|
|
1315
1061
|
// 推送开播通知
|
|
@@ -1318,7 +1064,7 @@ class ComRegister {
|
|
|
1318
1064
|
userface: masterInfo.userface,
|
|
1319
1065
|
target,
|
|
1320
1066
|
data: liveRoomInfo,
|
|
1321
|
-
}, LiveType.StartBroadcasting, liveStartMsg);
|
|
1067
|
+
}, type_1.LiveType.StartBroadcasting, follower, liveStartMsg);
|
|
1322
1068
|
// 判断定时器是否已开启
|
|
1323
1069
|
if (!pushAtTimeTimer) {
|
|
1324
1070
|
// 开始直播,开启定时器
|
|
@@ -1329,17 +1075,30 @@ class ComRegister {
|
|
|
1329
1075
|
// 将直播状态设置为false
|
|
1330
1076
|
liveStatus = false;
|
|
1331
1077
|
// 判断是否信息是否获取成功
|
|
1332
|
-
if (!(await useMasterAndLiveRoomInfo())) {
|
|
1078
|
+
if (!(await useMasterAndLiveRoomInfo(type_1.LiveType.StopBroadcast))) {
|
|
1333
1079
|
// 未获取成功,直接返回
|
|
1334
1080
|
return this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
|
|
1335
1081
|
}
|
|
1336
1082
|
// 更改直播时长
|
|
1337
1083
|
liveRoomInfo.live_time = liveTime;
|
|
1084
|
+
// 获取粉丝数变化
|
|
1085
|
+
const followerChange = (() => {
|
|
1086
|
+
// 获取直播关注变化值
|
|
1087
|
+
const liveFollowerChangeNum = masterInfo.liveFollowerChange;
|
|
1088
|
+
// 判断是否大于0
|
|
1089
|
+
if (liveFollowerChangeNum > 0) {
|
|
1090
|
+
// 大于0则加+
|
|
1091
|
+
return liveFollowerChangeNum >= 10_000 ? `+${liveFollowerChangeNum.toFixed(1)}万` : `+${liveFollowerChangeNum}`;
|
|
1092
|
+
}
|
|
1093
|
+
// 小于0
|
|
1094
|
+
return liveFollowerChangeNum <= -10_000 ? `${liveFollowerChangeNum.toFixed(1)}万` : liveFollowerChangeNum.toString();
|
|
1095
|
+
})();
|
|
1338
1096
|
// 定义下播播通知语
|
|
1339
1097
|
const liveEndMsg = this.config.customLiveEnd
|
|
1340
1098
|
? this.config.customLiveEnd
|
|
1341
1099
|
.replace("-name", masterInfo.username)
|
|
1342
1100
|
.replace("-time", await this.ctx.gi.getTimeDifference(liveTime))
|
|
1101
|
+
.replace("-follower_change", followerChange)
|
|
1343
1102
|
: null;
|
|
1344
1103
|
// 推送通知卡片
|
|
1345
1104
|
await this.sendLiveNotifyCard({
|
|
@@ -1347,7 +1106,7 @@ class ComRegister {
|
|
|
1347
1106
|
userface: masterInfo.userface,
|
|
1348
1107
|
target,
|
|
1349
1108
|
data: liveRoomInfo,
|
|
1350
|
-
}, LiveType.StopBroadcast, liveEndMsg);
|
|
1109
|
+
}, type_1.LiveType.StopBroadcast, followerChange, liveEndMsg);
|
|
1351
1110
|
// 关闭定时推送定时器
|
|
1352
1111
|
pushAtTimeTimer();
|
|
1353
1112
|
// 将推送定时器变量置空
|
|
@@ -1356,15 +1115,23 @@ class ComRegister {
|
|
|
1356
1115
|
};
|
|
1357
1116
|
// 启动直播间弹幕监测
|
|
1358
1117
|
await this.ctx.bl.startLiveRoomListener(roomId, handler);
|
|
1118
|
+
// 第一次启动获取信息并判信息是否获取成功
|
|
1119
|
+
if (!(await useMasterAndLiveRoomInfo(type_1.LiveType.FirstLiveBroadcast))) {
|
|
1120
|
+
// 未获取成功,直接返回
|
|
1121
|
+
return this.sendPrivateMsg("获取直播间信息失败,启动直播间弹幕检测失败!");
|
|
1122
|
+
}
|
|
1359
1123
|
// 判断直播状态
|
|
1360
1124
|
if (liveRoomInfo.live_status === 1) {
|
|
1361
1125
|
// 设置开播时间
|
|
1362
1126
|
liveTime = liveRoomInfo.live_time;
|
|
1127
|
+
// 获取当前累计观看人数
|
|
1128
|
+
const watched = watchedNum || "暂未获取到";
|
|
1363
1129
|
// 定义直播中通知消息
|
|
1364
1130
|
const liveMsg = this.config.customLive
|
|
1365
1131
|
? this.config.customLive
|
|
1366
1132
|
.replace("-name", masterInfo.username)
|
|
1367
1133
|
.replace("-time", await this.ctx.gi.getTimeDifference(liveTime))
|
|
1134
|
+
.replace("-watched", watched)
|
|
1368
1135
|
.replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`)
|
|
1369
1136
|
: null;
|
|
1370
1137
|
// 发送直播通知卡片
|
|
@@ -1374,7 +1141,7 @@ class ComRegister {
|
|
|
1374
1141
|
userface: masterInfo.userface,
|
|
1375
1142
|
target,
|
|
1376
1143
|
data: liveRoomInfo,
|
|
1377
|
-
}, LiveType.LiveBroadcast, liveMsg);
|
|
1144
|
+
}, type_1.LiveType.LiveBroadcast, watched, liveMsg);
|
|
1378
1145
|
}
|
|
1379
1146
|
// 正在直播,开启定时器
|
|
1380
1147
|
// 判断定时器是否已开启
|
|
@@ -1575,25 +1342,10 @@ class ComRegister {
|
|
|
1575
1342
|
// 发送提示
|
|
1576
1343
|
this.logger.warn(`UID:${sub.uid} 用户没有开通直播间,无法订阅直播!`);
|
|
1577
1344
|
}
|
|
1578
|
-
//
|
|
1579
|
-
const liveDetectModeSelector = {
|
|
1580
|
-
API: async () => {
|
|
1581
|
-
// 判断是否已开启直播检测
|
|
1582
|
-
if (!this.liveDispose) {
|
|
1583
|
-
// 未开启直播检测
|
|
1584
|
-
// 开启直播检测并保存销毁函数
|
|
1585
|
-
this.liveDispose = await this.liveDetectWithAPI();
|
|
1586
|
-
}
|
|
1587
|
-
},
|
|
1588
|
-
WS: async () => {
|
|
1589
|
-
// 连接到服务器
|
|
1590
|
-
await this.liveDetectWithListener(data.live_room.roomid, sub.target);
|
|
1591
|
-
},
|
|
1592
|
-
};
|
|
1593
1345
|
// 判断是否订阅直播
|
|
1594
1346
|
if (sub.live) {
|
|
1595
1347
|
// 启动直播监测
|
|
1596
|
-
await
|
|
1348
|
+
await this.liveDetectWithListener(data.live_room.roomid, sub.target);
|
|
1597
1349
|
}
|
|
1598
1350
|
}
|
|
1599
1351
|
// 在B站中订阅该对象
|
package/lib/generateImg.d.ts
CHANGED
|
@@ -8,7 +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
|
-
generateLiveImg(data: any, username: string, userface: string, liveStatus: number): Promise<{
|
|
11
|
+
generateLiveImg(data: any, username: string, userface: string, followerDisplay: string, liveStatus: number): Promise<{
|
|
12
12
|
buffer: Buffer<ArrayBufferLike>;
|
|
13
13
|
pic?: undefined;
|
|
14
14
|
} | {
|
|
@@ -45,6 +45,7 @@ declare namespace GenerateImg {
|
|
|
45
45
|
enableLargeFont: boolean;
|
|
46
46
|
font: string;
|
|
47
47
|
hideDesc: boolean;
|
|
48
|
+
followerDisplay: boolean;
|
|
48
49
|
}
|
|
49
50
|
const Config: Schema<Config>;
|
|
50
51
|
}
|
package/lib/generateImg.js
CHANGED
|
@@ -9,24 +9,16 @@ const DYNAMIC_TYPE_NONE = "DYNAMIC_TYPE_NONE";
|
|
|
9
9
|
const DYNAMIC_TYPE_FORWARD = "DYNAMIC_TYPE_FORWARD";
|
|
10
10
|
const DYNAMIC_TYPE_AV = "DYNAMIC_TYPE_AV";
|
|
11
11
|
const DYNAMIC_TYPE_PGC = "DYNAMIC_TYPE_PGC";
|
|
12
|
-
const DYNAMIC_TYPE_COURSES = "DYNAMIC_TYPE_COURSES";
|
|
13
12
|
const DYNAMIC_TYPE_WORD = "DYNAMIC_TYPE_WORD";
|
|
14
13
|
const DYNAMIC_TYPE_DRAW = "DYNAMIC_TYPE_DRAW";
|
|
15
14
|
const DYNAMIC_TYPE_ARTICLE = "DYNAMIC_TYPE_ARTICLE";
|
|
16
15
|
const DYNAMIC_TYPE_MUSIC = "DYNAMIC_TYPE_MUSIC";
|
|
17
16
|
const DYNAMIC_TYPE_COMMON_SQUARE = "DYNAMIC_TYPE_COMMON_SQUARE";
|
|
18
|
-
const DYNAMIC_TYPE_COMMON_VERTICAL = "DYNAMIC_TYPE_COMMON_VERTICAL";
|
|
19
17
|
const DYNAMIC_TYPE_LIVE = "DYNAMIC_TYPE_LIVE";
|
|
20
18
|
const DYNAMIC_TYPE_MEDIALIST = "DYNAMIC_TYPE_MEDIALIST";
|
|
21
19
|
const DYNAMIC_TYPE_COURSES_SEASON = "DYNAMIC_TYPE_COURSES_SEASON";
|
|
22
|
-
const DYNAMIC_TYPE_COURSES_BATCH = "DYNAMIC_TYPE_COURSES_BATCH";
|
|
23
|
-
const DYNAMIC_TYPE_AD = "DYNAMIC_TYPE_AD";
|
|
24
|
-
const DYNAMIC_TYPE_APPLET = "DYNAMIC_TYPE_APPLET";
|
|
25
|
-
const DYNAMIC_TYPE_SUBSCRIPTION = "DYNAMIC_TYPE_SUBSCRIPTION";
|
|
26
20
|
const DYNAMIC_TYPE_LIVE_RCMD = "DYNAMIC_TYPE_LIVE_RCMD";
|
|
27
|
-
const DYNAMIC_TYPE_BANNER = "DYNAMIC_TYPE_BANNER";
|
|
28
21
|
const DYNAMIC_TYPE_UGC_SEASON = "DYNAMIC_TYPE_UGC_SEASON";
|
|
29
|
-
const DYNAMIC_TYPE_SUBSCRIPTION_NEW = "DYNAMIC_TYPE_SUBSCRIPTION_NEW";
|
|
30
22
|
// 内容卡片类型
|
|
31
23
|
const ADDITIONAL_TYPE_RESERVE = "ADDITIONAL_TYPE_RESERVE";
|
|
32
24
|
class GenerateImg extends koishi_1.Service {
|
|
@@ -38,12 +30,12 @@ class GenerateImg extends koishi_1.Service {
|
|
|
38
30
|
}
|
|
39
31
|
async generateLiveImg(
|
|
40
32
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
41
|
-
data, username, userface, liveStatus /*0未开播 1刚开播 2已开播 3停止直播*/) {
|
|
33
|
+
data, username, userface, followerDisplay, liveStatus /*0未开播 1刚开播 2已开播 3停止直播*/) {
|
|
42
34
|
const [titleStatus, liveTime, cover] = await this.getLiveStatus(data.live_time, liveStatus);
|
|
43
35
|
// 加载字体
|
|
44
36
|
const fontURL = (0, node_url_1.pathToFileURL)((0, node_path_1.resolve)(__dirname, "font/HYZhengYuan-75W.ttf"));
|
|
45
37
|
// 卡片内容
|
|
46
|
-
const html = `
|
|
38
|
+
const html = /* html */ `
|
|
47
39
|
<!DOCTYPE html>
|
|
48
40
|
<html>
|
|
49
41
|
<head>
|
|
@@ -175,6 +167,18 @@ class GenerateImg extends koishi_1.Service {
|
|
|
175
167
|
</p>
|
|
176
168
|
<p class="card-link">
|
|
177
169
|
<span>${liveTime}</span>
|
|
170
|
+
${this.giConfig.followerDisplay
|
|
171
|
+
? /* html */ `
|
|
172
|
+
<span>
|
|
173
|
+
${liveStatus === 1
|
|
174
|
+
? `当前粉丝数:${followerDisplay}`
|
|
175
|
+
: liveStatus === 2
|
|
176
|
+
? `累计观看人数:${followerDisplay}`
|
|
177
|
+
: liveStatus === 3
|
|
178
|
+
? `粉丝数变化:${followerDisplay}`
|
|
179
|
+
: ""}
|
|
180
|
+
</span>`
|
|
181
|
+
: ""}
|
|
178
182
|
</p>
|
|
179
183
|
</div>
|
|
180
184
|
</div>
|
|
@@ -260,7 +264,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
260
264
|
if (module_dynamic.desc) {
|
|
261
265
|
const richText = module_dynamic.desc.rich_text_nodes.reduce((accumulator, currentValue) => {
|
|
262
266
|
if (currentValue.emoji) {
|
|
263
|
-
return `${accumulator}<img style="width:28px; height:28px;" src="${currentValue.emoji.icon_url}"/>`;
|
|
267
|
+
return /* html */ `${accumulator}<img style="width:28px; height:28px;" src="${currentValue.emoji.icon_url}"/>`;
|
|
264
268
|
}
|
|
265
269
|
return accumulator + currentValue.text;
|
|
266
270
|
}, "");
|
|
@@ -282,7 +286,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
282
286
|
const text = richText.replace(/\n/g, "<br>");
|
|
283
287
|
// 拼接字符串
|
|
284
288
|
if (text) {
|
|
285
|
-
main += `
|
|
289
|
+
main += /* html */ `
|
|
286
290
|
<div class="card-details">
|
|
287
291
|
${text}
|
|
288
292
|
</div>
|
|
@@ -297,7 +301,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
297
301
|
const height = module_dynamic.major.draw.items[0].height;
|
|
298
302
|
console.log(height);
|
|
299
303
|
if (height > 3000) {
|
|
300
|
-
major += `
|
|
304
|
+
major += /* html */ `
|
|
301
305
|
<div class="single-photo-container">
|
|
302
306
|
<img class="single-photo-item" src="${module_dynamic.major.draw.items[0].src}"/>
|
|
303
307
|
<div class="single-photo-mask">
|
|
@@ -308,7 +312,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
308
312
|
`;
|
|
309
313
|
}
|
|
310
314
|
else {
|
|
311
|
-
major += `
|
|
315
|
+
major += /* html */ `
|
|
312
316
|
<div class="single-photo-container">
|
|
313
317
|
<img class="single-photo-item" src="${module_dynamic.major.draw.items[0].src}"/>
|
|
314
318
|
</div>
|
|
@@ -317,15 +321,15 @@ class GenerateImg extends koishi_1.Service {
|
|
|
317
321
|
}
|
|
318
322
|
else if (module_dynamic.major.draw.items.length === 4) {
|
|
319
323
|
major += module_dynamic.major.draw.items.reduce((acc, cV) => {
|
|
320
|
-
return `${acc}<img class="four-photo-item" src="${cV.src}"/>`;
|
|
324
|
+
return /* html */ `${acc}<img class="four-photo-item" src="${cV.src}"/>`;
|
|
321
325
|
}, "");
|
|
322
326
|
}
|
|
323
327
|
else {
|
|
324
328
|
major += module_dynamic.major.draw.items.reduce((acc, cV) => {
|
|
325
|
-
return `${acc}<img class="photo-item" src="${cV.src}"/>`;
|
|
329
|
+
return /* html */ `${acc}<img class="photo-item" src="${cV.src}"/>`;
|
|
326
330
|
}, "");
|
|
327
331
|
}
|
|
328
|
-
main += `
|
|
332
|
+
main += /* html */ `
|
|
329
333
|
<div class="card-major">
|
|
330
334
|
${major}
|
|
331
335
|
</div>
|
|
@@ -353,7 +357,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
353
357
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
354
358
|
const [forwardMain, _, forwardInfo] = await getDynamicMajor(dynamicMajorData.orig, true);
|
|
355
359
|
// 拼接main
|
|
356
|
-
main += `
|
|
360
|
+
main += /* html */ `
|
|
357
361
|
<div class="card-forward">
|
|
358
362
|
<div class="forward-userinfo">
|
|
359
363
|
<img class="forward-avatar" src="${forwardUserAvatarUrl}" alt="avatar">
|
|
@@ -377,14 +381,14 @@ class GenerateImg extends koishi_1.Service {
|
|
|
377
381
|
let button;
|
|
378
382
|
// 判断按钮类型
|
|
379
383
|
if (reserve.button.uncheck.text === "已结束") {
|
|
380
|
-
button = `
|
|
384
|
+
button = /* html */ `
|
|
381
385
|
<button class="reserve-button-end">
|
|
382
386
|
<span>${reserve.button.uncheck.text}</span>
|
|
383
387
|
</button>
|
|
384
388
|
`;
|
|
385
389
|
}
|
|
386
390
|
else {
|
|
387
|
-
button = `
|
|
391
|
+
button = /* html */ `
|
|
388
392
|
<button class="reserve-button-ing">
|
|
389
393
|
<svg class="bili-dyn-card-reserve__action__icon" style="width: 16px; height: 16px;"
|
|
390
394
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
@@ -403,7 +407,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
403
407
|
</button>
|
|
404
408
|
`;
|
|
405
409
|
}
|
|
406
|
-
main += `
|
|
410
|
+
main += /* html */ `
|
|
407
411
|
<div class="card-reserve">
|
|
408
412
|
<div class="reserve-main">
|
|
409
413
|
<div class="reserve-title">
|
|
@@ -472,7 +476,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
472
476
|
pubTime = `${pubTime} · 投稿了视频`;
|
|
473
477
|
}
|
|
474
478
|
}
|
|
475
|
-
main += `
|
|
479
|
+
main += /* html */ `
|
|
476
480
|
<div class="card-video">
|
|
477
481
|
<div class="video-cover">
|
|
478
482
|
<img src="${archive.cover}"
|
|
@@ -1302,7 +1306,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
1302
1306
|
`;
|
|
1303
1307
|
}
|
|
1304
1308
|
// 定义卡片内容
|
|
1305
|
-
const html = `
|
|
1309
|
+
const html = /* html */ `
|
|
1306
1310
|
<!DOCTYPE html>
|
|
1307
1311
|
<html>
|
|
1308
1312
|
<head>
|
|
@@ -1428,7 +1432,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
1428
1432
|
async generateWordCloudImg() {
|
|
1429
1433
|
const page = await this.ctx.puppeteer.page();
|
|
1430
1434
|
// 创建HTML内容
|
|
1431
|
-
const htmlContent = `
|
|
1435
|
+
const htmlContent = /* html */ `
|
|
1432
1436
|
<!DOCTYPE html>
|
|
1433
1437
|
<html>
|
|
1434
1438
|
<head>
|
|
@@ -1549,6 +1553,7 @@ class GenerateImg extends koishi_1.Service {
|
|
|
1549
1553
|
enableLargeFont: koishi_1.Schema.boolean(),
|
|
1550
1554
|
font: koishi_1.Schema.string(),
|
|
1551
1555
|
hideDesc: koishi_1.Schema.boolean(),
|
|
1556
|
+
followerDisplay: koishi_1.Schema.boolean(),
|
|
1552
1557
|
});
|
|
1553
1558
|
})(GenerateImg || (GenerateImg = {}));
|
|
1554
1559
|
exports.default = GenerateImg;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -157,6 +157,7 @@ class ServerManager extends koishi_1.Service {
|
|
|
157
157
|
hideDesc: globalConfig.hideDesc,
|
|
158
158
|
enableLargeFont: globalConfig.enableLargeFont,
|
|
159
159
|
font: globalConfig.font,
|
|
160
|
+
followerDisplay: globalConfig.followerDisplay
|
|
160
161
|
});
|
|
161
162
|
// CR = ComRegister
|
|
162
163
|
const cr = this.ctx.plugin(comRegister_1.default, {
|
|
@@ -231,11 +232,11 @@ function apply(ctx, config) {
|
|
|
231
232
|
globalConfig = config;
|
|
232
233
|
// 设置提示
|
|
233
234
|
ctx.notifier.create({
|
|
234
|
-
type:
|
|
235
|
-
content: "3.0.0-alpha.16
|
|
235
|
+
type: "danger",
|
|
236
|
+
content: "3.0.0-alpha.16 全面从指令订阅迁移到配置订阅,以前使用指令的订阅需要全部重新填写到订阅配置中",
|
|
236
237
|
});
|
|
237
238
|
ctx.notifier.create({
|
|
238
|
-
type:
|
|
239
|
+
type: "warning",
|
|
239
240
|
content: "请使用Auth插件创建超级管理员账号,没有权限将无法使用该插件提供的指令。",
|
|
240
241
|
});
|
|
241
242
|
// load database
|
|
@@ -337,7 +338,7 @@ exports.Config = koishi_1.Schema.object({
|
|
|
337
338
|
koishi_1.Schema.const("WS").description("WebSocket模式:连接到对应的直播间,可推送弹幕消息,开播下播响应最快,但对订阅数有限制"),
|
|
338
339
|
koishi_1.Schema.const("API")
|
|
339
340
|
.description("API模式:请求对应直播间API,无法获取弹幕消息,开播下播响应慢,理论可无限订阅")
|
|
340
|
-
.
|
|
341
|
+
.deprecated(),
|
|
341
342
|
])
|
|
342
343
|
.role("radio")
|
|
343
344
|
.description("直播检测模式")
|
|
@@ -352,12 +353,17 @@ exports.Config = koishi_1.Schema.object({
|
|
|
352
353
|
.default(1)
|
|
353
354
|
.description("设定间隔多长时间推送一次直播状态,单位为小时,默认为一小时"),
|
|
354
355
|
customLiveStart: koishi_1.Schema.string()
|
|
355
|
-
.default("-name
|
|
356
|
-
.description("自定义开播提示语,-name代表UP昵称,-link代表直播间链接(如果使用的是QQ官方机器人,请不要使用)。例如-name开播啦,会发送为xxxUP开播啦"),
|
|
357
|
-
customLive: koishi_1.Schema.string()
|
|
356
|
+
.default("-name开播啦,当前粉丝数为-follower -link")
|
|
357
|
+
.description("自定义开播提示语,-name代表UP昵称,-follower代表当前粉丝数,-link代表直播间链接(如果使用的是QQ官方机器人,请不要使用)。例如-name开播啦,会发送为xxxUP开播啦"),
|
|
358
|
+
customLive: koishi_1.Schema.string()
|
|
359
|
+
.default("-name正在直播,目前已播-time。累计看过人数:-watched,-link")
|
|
360
|
+
.description("自定义直播中提示语,-name代表UP昵称,-time代表开播时长,-watched代表累计看过人数,-link代表直播间链接(如果使用的是QQ官方机器人,请不要使用)。例如-name正在直播,会发送为xxxUP正在直播xxx"),
|
|
358
361
|
customLiveEnd: koishi_1.Schema.string()
|
|
359
|
-
.default("-name下播啦,本次直播了-time")
|
|
360
|
-
.description("自定义下播提示语,-name代表UP昵称,-time代表开播时长。例如-name下播啦,本次直播了-time,会发送为xxxUP下播啦,直播时长为xx小时xx分钟xx秒"),
|
|
362
|
+
.default("-name下播啦,本次直播了-time。粉丝数变化-follower_change")
|
|
363
|
+
.description("自定义下播提示语,-name代表UP昵称,-follower_change代表本场直播粉丝数变,-time代表开播时长。例如-name下播啦,本次直播了-time,会发送为xxxUP下播啦,直播时长为xx小时xx分钟xx秒"),
|
|
364
|
+
followerDisplay: koishi_1.Schema.boolean()
|
|
365
|
+
.default(true)
|
|
366
|
+
.description("粉丝数变化和看过本场直播的人数是否显示在推送卡片中"),
|
|
361
367
|
hideDesc: koishi_1.Schema.boolean()
|
|
362
368
|
.default(false)
|
|
363
369
|
.description("是否隐藏UP主直播间简介,开启后推送的直播卡片将不再展示简介"),
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare enum LiveType {
|
|
2
|
+
NotLiveBroadcast = 0,
|
|
3
|
+
StartBroadcasting = 1,
|
|
4
|
+
LiveBroadcast = 2,
|
|
5
|
+
StopBroadcast = 3,
|
|
6
|
+
FirstLiveBroadcast = 4
|
|
7
|
+
}
|
|
8
|
+
export type ChannelIdArr = Array<{
|
|
9
|
+
channelId: string;
|
|
10
|
+
dynamic: boolean;
|
|
11
|
+
live: boolean;
|
|
12
|
+
liveGuardBuy: boolean;
|
|
13
|
+
atAll: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
export type TargetItem = {
|
|
16
|
+
channelIdArr: ChannelIdArr;
|
|
17
|
+
platform: string;
|
|
18
|
+
};
|
|
19
|
+
export type Target = Array<TargetItem>;
|
|
20
|
+
export type SubItem = {
|
|
21
|
+
id: number;
|
|
22
|
+
uid: string;
|
|
23
|
+
roomId: string;
|
|
24
|
+
target: Target;
|
|
25
|
+
platform: string;
|
|
26
|
+
live: boolean;
|
|
27
|
+
dynamic: boolean;
|
|
28
|
+
};
|
|
29
|
+
export type SubManager = Array<SubItem>;
|
|
30
|
+
export type MasterInfo = {
|
|
31
|
+
username: string;
|
|
32
|
+
userface: string;
|
|
33
|
+
roomId: number;
|
|
34
|
+
liveOpenFollowerNum: number;
|
|
35
|
+
liveEndFollowerNum: number;
|
|
36
|
+
liveFollowerChange: number;
|
|
37
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LiveType = void 0;
|
|
4
|
+
var LiveType;
|
|
5
|
+
(function (LiveType) {
|
|
6
|
+
LiveType[LiveType["NotLiveBroadcast"] = 0] = "NotLiveBroadcast";
|
|
7
|
+
LiveType[LiveType["StartBroadcasting"] = 1] = "StartBroadcasting";
|
|
8
|
+
LiveType[LiveType["LiveBroadcast"] = 2] = "LiveBroadcast";
|
|
9
|
+
LiveType[LiveType["StopBroadcast"] = 3] = "StopBroadcast";
|
|
10
|
+
LiveType[LiveType["FirstLiveBroadcast"] = 4] = "FirstLiveBroadcast";
|
|
11
|
+
})(LiveType || (exports.LiveType = LiveType = {}));
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -196,6 +196,8 @@
|
|
|
196
196
|
- ver 3.0.0-alpha.14 优化:移除不需要的服务
|
|
197
197
|
- ver 3.0.0-alpha.15 修复:启动插件提示发送群组消息失败、直播推送时间显示为负数(不用再特别设置系统时区为UTC+8)
|
|
198
198
|
- ver 3.0.0-alpha.16 重大更新:订阅不再依赖数据库,从指令订阅全面迁移到配置订阅; 修复:直播时长有误; 优化:`bili show` 指令更改为 `bili list`
|
|
199
|
+
- ver 3.0.0-alpha.17 新增:更多的提示语变量,开播,当前粉丝数。正在直播,累计观看人数。下播,粉丝数变化。选项,新增的提示语变量是否展示到推送卡片中
|
|
200
|
+
- ver 3.0.0-alpha.18 移除:直播检测API模式已被废弃; 优化:更多提示语数据显示优化
|
|
199
201
|
|
|
200
202
|
## 交流群
|
|
201
203
|
|