koishi-plugin-bilibili-notify 3.1.7-alpha.3 → 3.2.0-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.
- package/lib/biliAPI.d.ts +1 -0
- package/lib/biliAPI.js +17 -0
- package/lib/comRegister.d.ts +13 -2
- package/lib/comRegister.js +324 -31
- package/lib/index.d.ts +1 -0
- package/lib/index.js +5 -0
- package/lib/type/index.d.ts +41 -0
- package/package.json +1 -1
- package/readme.md +2 -0
package/lib/biliAPI.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ declare class BiliAPI extends Service {
|
|
|
28
28
|
decrypt(text: string): string;
|
|
29
29
|
getTheUserWhoIsLiveStreaming(): Promise<any>;
|
|
30
30
|
getLiveRoomInfoStreamKey(roomId: string): Promise<any>;
|
|
31
|
+
getLiveRoomInfoByUids(uids: string[]): Promise<any>;
|
|
31
32
|
getServerUTCTime(): Promise<number>;
|
|
32
33
|
getTimeNow(): Promise<any>;
|
|
33
34
|
getAllGroup(): Promise<any>;
|
package/lib/biliAPI.js
CHANGED
|
@@ -48,6 +48,7 @@ const COPY_USER_TO_GROUP = "https://api.bilibili.com/x/relation/tags/copyUsers";
|
|
|
48
48
|
const GET_RELATION_GROUP_DETAIL = "https://api.bilibili.com/x/relation/tag";
|
|
49
49
|
// 直播
|
|
50
50
|
const GET_LIVE_ROOM_INFO_STREAM_KEY = "https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo";
|
|
51
|
+
const GET_LIVE_ROOMS_INFO = "https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids";
|
|
51
52
|
class BiliAPI extends koishi_1.Service {
|
|
52
53
|
static inject = ["database", "notifier"];
|
|
53
54
|
jar;
|
|
@@ -130,6 +131,14 @@ class BiliAPI extends koishi_1.Service {
|
|
|
130
131
|
// 返回data
|
|
131
132
|
return data;
|
|
132
133
|
}
|
|
134
|
+
async getLiveRoomInfoByUids(uids) {
|
|
135
|
+
// 构建查询参数
|
|
136
|
+
const params = uids.map((uid) => `uids[]=${uid}`).join("&");
|
|
137
|
+
// 获取直播间信息
|
|
138
|
+
const { data } = await this.client.get(`${GET_LIVE_ROOMS_INFO}?${params}`);
|
|
139
|
+
// 返回数据
|
|
140
|
+
return data;
|
|
141
|
+
}
|
|
133
142
|
async getServerUTCTime() {
|
|
134
143
|
const { data } = await this.client.get(GET_SERVER_UTC_TIME);
|
|
135
144
|
const regex = /Date\.UTC\((.*?)\)/;
|
|
@@ -581,6 +590,14 @@ __decorate([
|
|
|
581
590
|
},
|
|
582
591
|
})
|
|
583
592
|
], BiliAPI.prototype, "getLiveRoomInfoStreamKey", null);
|
|
593
|
+
__decorate([
|
|
594
|
+
(0, utils_1.Retry)({
|
|
595
|
+
attempts: 3,
|
|
596
|
+
onFailure(error, attempts) {
|
|
597
|
+
this.logger.error(`getLiveRoomInfoByUids() 第${attempts}次失败: ${error.message}`);
|
|
598
|
+
},
|
|
599
|
+
})
|
|
600
|
+
], BiliAPI.prototype, "getLiveRoomInfoByUids", null);
|
|
584
601
|
__decorate([
|
|
585
602
|
(0, utils_1.Retry)({
|
|
586
603
|
attempts: 3,
|
package/lib/comRegister.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type Bot, type Context, type FlatPick, type Logger, Schema } from "kois
|
|
|
2
2
|
import type { Notifier } from "@koishijs/plugin-notifier";
|
|
3
3
|
import type { LoginBili } from "./database";
|
|
4
4
|
import { CronJob } from "cron";
|
|
5
|
-
import { LiveType, type MasterInfo, PushType, type Result, type SubItem, type SubManager, type Target } from "./type";
|
|
5
|
+
import { type LiveStatus, LiveType, type MasterInfo, PushType, type Result, type SubItem, type SubManager, type Target } from "./type";
|
|
6
6
|
declare class ComRegister {
|
|
7
7
|
static inject: string[];
|
|
8
8
|
qqRelatedBotList: Array<string>;
|
|
@@ -15,12 +15,14 @@ declare class ComRegister {
|
|
|
15
15
|
ctx: Context;
|
|
16
16
|
subManager: SubManager;
|
|
17
17
|
dynamicTimelineManager: Map<string, number>;
|
|
18
|
+
liveStatusManager: Map<string, LiveStatus>;
|
|
18
19
|
loginDBData: FlatPick<LoginBili, "dynamic_group_id">;
|
|
19
20
|
privateBot: Bot<Context>;
|
|
20
21
|
dynamicJob: CronJob;
|
|
22
|
+
liveJob: CronJob;
|
|
21
23
|
constructor(ctx: Context, config: ComRegister.Config);
|
|
22
24
|
init(config: ComRegister.Config): Promise<void>;
|
|
23
|
-
|
|
25
|
+
initManager(): void;
|
|
24
26
|
getBot(pf: string): Bot<Context, any>;
|
|
25
27
|
sendPrivateMsg(content: string): Promise<void>;
|
|
26
28
|
sendPrivateMsgAndRebootService(): Promise<void>;
|
|
@@ -32,14 +34,22 @@ declare class ComRegister {
|
|
|
32
34
|
debug_dynamicDetect(): (...args: any[]) => void;
|
|
33
35
|
useMasterInfo(uid: string, masterInfo: MasterInfo, liveType: LiveType): Promise<MasterInfo>;
|
|
34
36
|
useLiveRoomInfo(roomId: string): Promise<any>;
|
|
37
|
+
sendLiveNotifyCard(liveType: LiveType, followerDisplay: string, liveInfo: {
|
|
38
|
+
liveRoomInfo: any;
|
|
39
|
+
masterInfo: MasterInfo;
|
|
40
|
+
cardStyle: SubItem["card"];
|
|
41
|
+
}, target: Target, liveNotifyMsg: string): Promise<void>;
|
|
35
42
|
liveDetectWithListener(roomId: string, target: Target, cardStyle: SubItem["card"]): Promise<void>;
|
|
43
|
+
liveDetectWithAPI(): Promise<(...args: any[]) => void>;
|
|
36
44
|
subShow(): string;
|
|
37
45
|
updateSubNotifier(): void;
|
|
38
46
|
checkIfLoginInfoIsLoaded(): Promise<unknown>;
|
|
39
47
|
subUserInBili(mid: string): Promise<Result>;
|
|
40
48
|
loadSubFromConfig(subs: ComRegister.Config["sub"]): Promise<Result>;
|
|
41
49
|
checkIfDynamicDetectIsNeeded(): void;
|
|
50
|
+
checkIfLiveDetectIsNeeded(): void;
|
|
42
51
|
enableDynamicDetect(): void;
|
|
52
|
+
enableLiveDetect(): Promise<void>;
|
|
43
53
|
checkIfIsLogin(): Promise<boolean>;
|
|
44
54
|
}
|
|
45
55
|
declare namespace ComRegister {
|
|
@@ -72,6 +82,7 @@ declare namespace ComRegister {
|
|
|
72
82
|
masterAccount: string;
|
|
73
83
|
masterAccountGuildId: string;
|
|
74
84
|
};
|
|
85
|
+
liveDetectType: string;
|
|
75
86
|
restartPush: boolean;
|
|
76
87
|
pushTime: number;
|
|
77
88
|
pushImgsInDynamic: boolean;
|
package/lib/comRegister.js
CHANGED
|
@@ -43,12 +43,16 @@ class ComRegister {
|
|
|
43
43
|
subManager = [];
|
|
44
44
|
// 动态时间线管理器
|
|
45
45
|
dynamicTimelineManager = new Map();
|
|
46
|
+
// 直播状态管理器
|
|
47
|
+
liveStatusManager = new Map();
|
|
46
48
|
// 检查登录数据库是否有数据
|
|
47
49
|
loginDBData;
|
|
48
50
|
// 机器人实例
|
|
49
51
|
privateBot;
|
|
50
52
|
// 动态检测销毁函数
|
|
51
53
|
dynamicJob;
|
|
54
|
+
// 直播检测销毁函数
|
|
55
|
+
liveJob;
|
|
52
56
|
// 构造函数
|
|
53
57
|
constructor(ctx, config) {
|
|
54
58
|
// 将ctx赋值给类属性
|
|
@@ -310,10 +314,12 @@ class ComRegister {
|
|
|
310
314
|
return;
|
|
311
315
|
}
|
|
312
316
|
}
|
|
313
|
-
//
|
|
314
|
-
this.
|
|
317
|
+
// 初始化管理器
|
|
318
|
+
this.initManager();
|
|
315
319
|
// 检查是否需要动态监测
|
|
316
320
|
this.checkIfDynamicDetectIsNeeded();
|
|
321
|
+
// 检查是否需要直播监测(仅API模式)
|
|
322
|
+
this.checkIfLiveDetectIsNeeded();
|
|
317
323
|
// 在控制台中显示订阅对象
|
|
318
324
|
this.updateSubNotifier();
|
|
319
325
|
// 注册插件销毁函数
|
|
@@ -324,15 +330,30 @@ class ComRegister {
|
|
|
324
330
|
// 销毁动态监测
|
|
325
331
|
if (this.dynamicJob)
|
|
326
332
|
this.dynamicJob.stop();
|
|
333
|
+
// 销毁直播监测
|
|
334
|
+
if (this.liveJob)
|
|
335
|
+
this.liveJob.stop();
|
|
327
336
|
});
|
|
328
337
|
// logger
|
|
329
338
|
this.logger.info("插件初始化完毕!");
|
|
330
339
|
}
|
|
331
|
-
|
|
340
|
+
initManager() {
|
|
332
341
|
for (const sub of this.subManager) {
|
|
333
342
|
if (sub.dynamic) {
|
|
334
343
|
this.dynamicTimelineManager.set(sub.uid, Math.floor(luxon_1.DateTime.now().toSeconds()));
|
|
335
344
|
}
|
|
345
|
+
if (sub.live) {
|
|
346
|
+
this.liveStatusManager.set(sub.uid, {
|
|
347
|
+
roomId: sub.roomId,
|
|
348
|
+
live: false,
|
|
349
|
+
liveRoomInfo: undefined,
|
|
350
|
+
masterInfo: undefined,
|
|
351
|
+
watchedNum: "0",
|
|
352
|
+
liveStartTime: "",
|
|
353
|
+
liveStartTimeInit: false,
|
|
354
|
+
push: 0,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
336
357
|
}
|
|
337
358
|
}
|
|
338
359
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
@@ -574,7 +595,7 @@ class ComRegister {
|
|
|
574
595
|
// 判断动态发布时间是否大于时间线
|
|
575
596
|
if (timeline < postTime) {
|
|
576
597
|
// 获取订阅对象
|
|
577
|
-
const sub = this.subManager.find(sub => sub.uid === uid);
|
|
598
|
+
const sub = this.subManager.find((sub) => sub.uid === uid);
|
|
578
599
|
// 推送该条动态
|
|
579
600
|
const buffer = await (0, utils_1.withRetry)(async () => {
|
|
580
601
|
// 渲染图片
|
|
@@ -749,7 +770,7 @@ class ComRegister {
|
|
|
749
770
|
// logger
|
|
750
771
|
this.logger.info("需要推送该条动态,开始推送...");
|
|
751
772
|
// 获取订阅对象
|
|
752
|
-
const sub = this.subManager.find(sub => sub.uid === uid);
|
|
773
|
+
const sub = this.subManager.find((sub) => sub.uid === uid);
|
|
753
774
|
// logger
|
|
754
775
|
this.logger.info("开始渲染推送卡片...");
|
|
755
776
|
// 推送该条动态
|
|
@@ -904,6 +925,24 @@ class ComRegister {
|
|
|
904
925
|
// 返回
|
|
905
926
|
return data;
|
|
906
927
|
}
|
|
928
|
+
async sendLiveNotifyCard(liveType, followerDisplay, liveInfo, target, liveNotifyMsg) {
|
|
929
|
+
// 生成图片
|
|
930
|
+
const buffer = await (0, utils_1.withRetry)(async () => {
|
|
931
|
+
// 获取直播通知卡片
|
|
932
|
+
return await this.ctx.gi.generateLiveImg(liveInfo.liveRoomInfo, liveInfo.masterInfo.username, liveInfo.masterInfo.userface, followerDisplay, liveType, liveInfo.cardStyle.enable ? liveInfo.cardStyle : undefined);
|
|
933
|
+
}, 1).catch((e) => {
|
|
934
|
+
this.logger.error(`liveDetect generateLiveImg() 推送卡片生成失败,原因:${e.message}`);
|
|
935
|
+
});
|
|
936
|
+
// 发送私聊消息并重启服务
|
|
937
|
+
if (!buffer)
|
|
938
|
+
return await this.sendPrivateMsgAndStopService();
|
|
939
|
+
// 推送直播信息
|
|
940
|
+
const msg = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, "image/jpeg"), liveNotifyMsg || ""] }));
|
|
941
|
+
// 只有在开播时才艾特全体成员
|
|
942
|
+
return await this.broadcastToTargets(target, msg, liveType === type_1.LiveType.StartBroadcasting
|
|
943
|
+
? type_1.PushType.StartBroadcasting
|
|
944
|
+
: type_1.PushType.Live);
|
|
945
|
+
}
|
|
907
946
|
async liveDetectWithListener(roomId, target, cardStyle) {
|
|
908
947
|
// 定义开播时间
|
|
909
948
|
let liveTime;
|
|
@@ -922,24 +961,6 @@ class ComRegister {
|
|
|
922
961
|
let masterInfo;
|
|
923
962
|
let watchedNum;
|
|
924
963
|
// 定义发送直播通知卡片方法
|
|
925
|
-
const sendLiveNotifyCard = async (liveType, followerDisplay, liveNotifyMsg) => {
|
|
926
|
-
// 生成图片
|
|
927
|
-
const buffer = await (0, utils_1.withRetry)(async () => {
|
|
928
|
-
// 获取直播通知卡片
|
|
929
|
-
return await this.ctx.gi.generateLiveImg(liveRoomInfo, masterInfo.username, masterInfo.userface, followerDisplay, liveType, cardStyle.enable ? cardStyle : undefined);
|
|
930
|
-
}, 1).catch((e) => {
|
|
931
|
-
this.logger.error(`liveDetect generateLiveImg() 推送卡片生成失败,原因:${e.message}`);
|
|
932
|
-
});
|
|
933
|
-
// 发送私聊消息并重启服务
|
|
934
|
-
if (!buffer)
|
|
935
|
-
return await this.sendPrivateMsgAndStopService();
|
|
936
|
-
// 推送直播信息
|
|
937
|
-
const msg = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [koishi_1.h.image(buffer, "image/jpeg"), liveNotifyMsg || ""] }));
|
|
938
|
-
// 只有在开播时才艾特全体成员
|
|
939
|
-
return await this.broadcastToTargets(target, msg, liveType === type_1.LiveType.StartBroadcasting
|
|
940
|
-
? type_1.PushType.StartBroadcasting
|
|
941
|
-
: type_1.PushType.Live);
|
|
942
|
-
};
|
|
943
964
|
// 找到频道/群组对应的
|
|
944
965
|
const liveGuardBuyPushTargetArr = target.map((channel) => {
|
|
945
966
|
// 获取符合条件的target
|
|
@@ -959,6 +980,15 @@ class ComRegister {
|
|
|
959
980
|
// 未获取成功,直接返回
|
|
960
981
|
return this.sendPrivateMsg("获取直播间信息失败,推送直播卡片失败!");
|
|
961
982
|
}
|
|
983
|
+
// 判断是否已经下播
|
|
984
|
+
if (liveRoomInfo.live_status === 0) {
|
|
985
|
+
// 设置开播状态为false
|
|
986
|
+
liveStatus = false;
|
|
987
|
+
// 清除定时器
|
|
988
|
+
pushAtTimeTimer?.();
|
|
989
|
+
// 发送私聊消息
|
|
990
|
+
await this.sendPrivateMsg("直播间已下播,定时推送已停止!与直播间的连接可能已断开,请使用指令 sys restart 重启插件");
|
|
991
|
+
}
|
|
962
992
|
// 设置开播时间
|
|
963
993
|
liveTime = liveRoomInfo.live_time;
|
|
964
994
|
// 获取watched
|
|
@@ -973,7 +1003,11 @@ class ComRegister {
|
|
|
973
1003
|
.replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`)
|
|
974
1004
|
: null;
|
|
975
1005
|
// 发送直播通知卡片
|
|
976
|
-
await sendLiveNotifyCard(type_1.LiveType.LiveBroadcast, watched,
|
|
1006
|
+
await this.sendLiveNotifyCard(type_1.LiveType.LiveBroadcast, watched, {
|
|
1007
|
+
liveRoomInfo,
|
|
1008
|
+
masterInfo,
|
|
1009
|
+
cardStyle,
|
|
1010
|
+
}, target, liveMsg);
|
|
977
1011
|
};
|
|
978
1012
|
// 定义直播间信息获取函数
|
|
979
1013
|
const useMasterAndLiveRoomInfo = async (liveType) => {
|
|
@@ -1053,7 +1087,11 @@ class ComRegister {
|
|
|
1053
1087
|
.replace("-link", `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`)
|
|
1054
1088
|
: null;
|
|
1055
1089
|
// 推送开播通知
|
|
1056
|
-
await sendLiveNotifyCard(type_1.LiveType.StartBroadcasting, follower,
|
|
1090
|
+
await this.sendLiveNotifyCard(type_1.LiveType.StartBroadcasting, follower, {
|
|
1091
|
+
liveRoomInfo,
|
|
1092
|
+
masterInfo,
|
|
1093
|
+
cardStyle,
|
|
1094
|
+
}, target, liveStartMsg);
|
|
1057
1095
|
// 判断定时器是否已开启
|
|
1058
1096
|
if (!pushAtTimeTimer) {
|
|
1059
1097
|
// 开始直播,开启定时器
|
|
@@ -1095,7 +1133,11 @@ class ComRegister {
|
|
|
1095
1133
|
.replace("\\n", "\n")
|
|
1096
1134
|
: null;
|
|
1097
1135
|
// 推送通知卡片
|
|
1098
|
-
await sendLiveNotifyCard(type_1.LiveType.StopBroadcast, followerChange,
|
|
1136
|
+
await this.sendLiveNotifyCard(type_1.LiveType.StopBroadcast, followerChange, {
|
|
1137
|
+
liveRoomInfo,
|
|
1138
|
+
masterInfo,
|
|
1139
|
+
cardStyle,
|
|
1140
|
+
}, target, liveEndMsg);
|
|
1099
1141
|
// 关闭定时推送定时器
|
|
1100
1142
|
pushAtTimeTimer();
|
|
1101
1143
|
// 将推送定时器变量置空
|
|
@@ -1126,7 +1168,11 @@ class ComRegister {
|
|
|
1126
1168
|
: null;
|
|
1127
1169
|
// 发送直播通知卡片
|
|
1128
1170
|
if (this.config.restartPush) {
|
|
1129
|
-
await sendLiveNotifyCard(type_1.LiveType.LiveBroadcast, watched,
|
|
1171
|
+
await this.sendLiveNotifyCard(type_1.LiveType.LiveBroadcast, watched, {
|
|
1172
|
+
liveRoomInfo,
|
|
1173
|
+
masterInfo,
|
|
1174
|
+
cardStyle,
|
|
1175
|
+
}, target, liveMsg);
|
|
1130
1176
|
}
|
|
1131
1177
|
// 正在直播,开启定时器,判断定时器是否已开启
|
|
1132
1178
|
if (!pushAtTimeTimer) {
|
|
@@ -1137,6 +1183,231 @@ class ComRegister {
|
|
|
1137
1183
|
liveStatus = true;
|
|
1138
1184
|
}
|
|
1139
1185
|
}
|
|
1186
|
+
async liveDetectWithAPI() {
|
|
1187
|
+
// 定义直播间信息获取函数
|
|
1188
|
+
const useMasterAndLiveRoomInfo = async (liveType, liveStatus) => {
|
|
1189
|
+
// 定义函数是否执行成功flag
|
|
1190
|
+
let flag = true;
|
|
1191
|
+
// 获取直播间信息
|
|
1192
|
+
liveStatus.liveRoomInfo = await this.useLiveRoomInfo(liveStatus.roomId).catch(() => {
|
|
1193
|
+
// 设置flag为false
|
|
1194
|
+
flag = false;
|
|
1195
|
+
// 返回空
|
|
1196
|
+
return null;
|
|
1197
|
+
});
|
|
1198
|
+
// 判断是否成功获取信息
|
|
1199
|
+
if (!flag || !liveStatus.liveRoomInfo?.uid) {
|
|
1200
|
+
// 上一步未成功
|
|
1201
|
+
flag = false;
|
|
1202
|
+
// 返回flag
|
|
1203
|
+
return flag;
|
|
1204
|
+
}
|
|
1205
|
+
// 获取主播信息(需要满足flag为true,liveRoomInfo.uid有值)
|
|
1206
|
+
liveStatus.masterInfo = await this.useMasterInfo(liveStatus.liveRoomInfo.uid, liveStatus.masterInfo, liveType).catch(() => {
|
|
1207
|
+
// 设置flag为false
|
|
1208
|
+
flag = false;
|
|
1209
|
+
// 返回空
|
|
1210
|
+
return null;
|
|
1211
|
+
});
|
|
1212
|
+
// 返回信息
|
|
1213
|
+
return flag;
|
|
1214
|
+
};
|
|
1215
|
+
const uids = [];
|
|
1216
|
+
for (const [uid] of this.liveStatusManager.entries()) {
|
|
1217
|
+
uids.push(uid);
|
|
1218
|
+
}
|
|
1219
|
+
// 初始化
|
|
1220
|
+
// 发送请求
|
|
1221
|
+
const { data } = (await this.ctx.ba.getLiveRoomInfoByUids(uids));
|
|
1222
|
+
for (const item of Object.values(data)) {
|
|
1223
|
+
// 将用户uid转换为string
|
|
1224
|
+
const uid = item.uid.toString();
|
|
1225
|
+
// 获取用户直播状态
|
|
1226
|
+
const liveStatus = this.liveStatusManager.get(uid);
|
|
1227
|
+
// 获取用户sub
|
|
1228
|
+
const sub = this.subManager.find((sub) => sub.uid === uid);
|
|
1229
|
+
// 判断直播状态
|
|
1230
|
+
if (item.live_status === 1) {
|
|
1231
|
+
// 将直播状态改为true
|
|
1232
|
+
liveStatus.live = true;
|
|
1233
|
+
// 初始化主播和直播间信息
|
|
1234
|
+
await useMasterAndLiveRoomInfo(type_1.LiveType.FirstLiveBroadcast, liveStatus);
|
|
1235
|
+
// 设置直播中消息
|
|
1236
|
+
const liveMsg = this.config.customLive
|
|
1237
|
+
? this.config.customLive
|
|
1238
|
+
.replace("-name", liveStatus.masterInfo.username)
|
|
1239
|
+
.replace("-time", await this.ctx.gi.getTimeDifference(liveStatus.liveStartTime))
|
|
1240
|
+
.replace("-watched", "暂未获取到")
|
|
1241
|
+
.replace("\\n", "\n")
|
|
1242
|
+
.replace("-link", `https://live.bilibili.com/${liveStatus.liveRoomInfo.short_id === 0 ? liveStatus.liveRoomInfo.room_id : liveStatus.liveRoomInfo.short_id}`)
|
|
1243
|
+
: null;
|
|
1244
|
+
// 发送直播通知卡片
|
|
1245
|
+
await this.sendLiveNotifyCard(type_1.LiveType.LiveBroadcast, "暂未获取到", {
|
|
1246
|
+
liveRoomInfo: liveStatus.liveRoomInfo,
|
|
1247
|
+
masterInfo: liveStatus.masterInfo,
|
|
1248
|
+
cardStyle: sub.card,
|
|
1249
|
+
}, sub.target, liveMsg);
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
useMasterAndLiveRoomInfo(type_1.LiveType.NotLiveBroadcast, liveStatus);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
// 定义函数
|
|
1256
|
+
const handler = async () => {
|
|
1257
|
+
// 发送请求
|
|
1258
|
+
const { data } = (await this.ctx.ba.getLiveRoomInfoByUids(uids));
|
|
1259
|
+
// 进行处理
|
|
1260
|
+
for (const item of Object.values(data)) {
|
|
1261
|
+
// 将用户uid转换为string
|
|
1262
|
+
const uid = item.uid.toString();
|
|
1263
|
+
// 获取用户直播状态
|
|
1264
|
+
const liveStatus = this.liveStatusManager.get(uid);
|
|
1265
|
+
// 获取sub
|
|
1266
|
+
const sub = this.subManager.find((sub) => sub.uid === uid);
|
|
1267
|
+
// 如果未找到sub直接返回
|
|
1268
|
+
if (!sub)
|
|
1269
|
+
return;
|
|
1270
|
+
// 判断当前状态和之前状态是否相同
|
|
1271
|
+
switch (item.live_status) {
|
|
1272
|
+
case 0:
|
|
1273
|
+
case 2: {
|
|
1274
|
+
// 未开播状态
|
|
1275
|
+
if (liveStatus.live === true) {
|
|
1276
|
+
// 现在下播了,发送下播通知
|
|
1277
|
+
// 判断信息是否获取成功
|
|
1278
|
+
if (!(await useMasterAndLiveRoomInfo(type_1.LiveType.StopBroadcast, liveStatus))) {
|
|
1279
|
+
// 未获取成功,直接返回
|
|
1280
|
+
return await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
|
|
1281
|
+
}
|
|
1282
|
+
// 更改直播时长
|
|
1283
|
+
if (liveStatus.liveStartTimeInit) {
|
|
1284
|
+
// 设置直播时长
|
|
1285
|
+
liveStatus.liveRoomInfo.live_time = liveStatus.liveStartTime;
|
|
1286
|
+
// 直播时间初始化改为false
|
|
1287
|
+
liveStatus.liveStartTimeInit = false;
|
|
1288
|
+
}
|
|
1289
|
+
// 获取粉丝数变化
|
|
1290
|
+
const followerChange = (() => {
|
|
1291
|
+
// 获取直播关注变化值
|
|
1292
|
+
const liveFollowerChangeNum = liveStatus.masterInfo.liveFollowerChange;
|
|
1293
|
+
// 判断是否大于0
|
|
1294
|
+
if (liveFollowerChangeNum > 0) {
|
|
1295
|
+
// 大于0则加+
|
|
1296
|
+
return liveFollowerChangeNum >= 10_000
|
|
1297
|
+
? `+${liveFollowerChangeNum.toFixed(1)}万`
|
|
1298
|
+
: `+${liveFollowerChangeNum}`;
|
|
1299
|
+
}
|
|
1300
|
+
// 小于0
|
|
1301
|
+
return liveFollowerChangeNum <= -10_000
|
|
1302
|
+
? `${liveFollowerChangeNum.toFixed(1)}万`
|
|
1303
|
+
: liveFollowerChangeNum.toString();
|
|
1304
|
+
})();
|
|
1305
|
+
// 定义下播播通知语
|
|
1306
|
+
const liveEndMsg = this.config.customLiveEnd
|
|
1307
|
+
? this.config.customLiveEnd
|
|
1308
|
+
.replace("-name", liveStatus.masterInfo.username)
|
|
1309
|
+
.replace("-time", await this.ctx.gi.getTimeDifference(liveStatus.liveStartTime))
|
|
1310
|
+
.replace("-follower_change", followerChange)
|
|
1311
|
+
.replace("\\n", "\n")
|
|
1312
|
+
: null;
|
|
1313
|
+
// 推送通知卡片
|
|
1314
|
+
await this.sendLiveNotifyCard(type_1.LiveType.StopBroadcast, followerChange, {
|
|
1315
|
+
liveRoomInfo: liveStatus.liveRoomInfo,
|
|
1316
|
+
masterInfo: liveStatus.masterInfo,
|
|
1317
|
+
cardStyle: sub.card,
|
|
1318
|
+
}, sub.target, liveEndMsg);
|
|
1319
|
+
// 更改直播状态
|
|
1320
|
+
liveStatus.live = false;
|
|
1321
|
+
}
|
|
1322
|
+
// 还未开播
|
|
1323
|
+
break;
|
|
1324
|
+
}
|
|
1325
|
+
case 1: {
|
|
1326
|
+
// 开播状态
|
|
1327
|
+
if (liveStatus.live === false) {
|
|
1328
|
+
// 开播了
|
|
1329
|
+
// 判断信息是否获取成功
|
|
1330
|
+
if (!(await useMasterAndLiveRoomInfo(type_1.LiveType.StopBroadcast, liveStatus))) {
|
|
1331
|
+
// 未获取成功,直接返回
|
|
1332
|
+
return await this.sendPrivateMsg("获取直播间信息失败,推送直播下播卡片失败!");
|
|
1333
|
+
}
|
|
1334
|
+
// 设置开播时间
|
|
1335
|
+
liveStatus.liveStartTime = liveStatus.liveRoomInfo.live_time;
|
|
1336
|
+
// 设置开播时间初始化状态
|
|
1337
|
+
liveStatus.liveStartTimeInit = true;
|
|
1338
|
+
// 获取当前粉丝数
|
|
1339
|
+
const follower = liveStatus.masterInfo.liveOpenFollowerNum >= 10_000
|
|
1340
|
+
? `${(liveStatus.masterInfo.liveOpenFollowerNum / 10000).toFixed(1)}万`
|
|
1341
|
+
: liveStatus.masterInfo.liveOpenFollowerNum.toString();
|
|
1342
|
+
// 定义开播通知语
|
|
1343
|
+
const liveStartMsg = this.config.customLiveStart
|
|
1344
|
+
? this.config.customLiveStart
|
|
1345
|
+
.replace("-name", liveStatus.masterInfo.username)
|
|
1346
|
+
.replace("-time", await this.ctx.gi.getTimeDifference(liveStatus.liveStartTime))
|
|
1347
|
+
.replace("-follower", follower)
|
|
1348
|
+
.replace("\\n", "\n")
|
|
1349
|
+
.replace("-link", `https://live.bilibili.com/${liveStatus.liveRoomInfo.short_id === 0 ? liveStatus.liveRoomInfo.room_id : liveStatus.liveRoomInfo.short_id}`)
|
|
1350
|
+
: null;
|
|
1351
|
+
// 推送开播通知
|
|
1352
|
+
await this.sendLiveNotifyCard(type_1.LiveType.StartBroadcasting, follower, {
|
|
1353
|
+
liveRoomInfo: liveStatus.liveRoomInfo,
|
|
1354
|
+
masterInfo: liveStatus.masterInfo,
|
|
1355
|
+
cardStyle: sub.card,
|
|
1356
|
+
}, sub.target, liveStartMsg);
|
|
1357
|
+
// 设置开播状态为true
|
|
1358
|
+
liveStatus.live = true;
|
|
1359
|
+
}
|
|
1360
|
+
if (liveStatus.live === true) {
|
|
1361
|
+
// 还在直播
|
|
1362
|
+
if (liveStatus.push < (this.config.pushTime * 60 * 60) / 10) {
|
|
1363
|
+
// push++
|
|
1364
|
+
liveStatus.push++;
|
|
1365
|
+
// 结束本次循环
|
|
1366
|
+
break;
|
|
1367
|
+
}
|
|
1368
|
+
// 判断是否信息是否获取成功
|
|
1369
|
+
if (!(await useMasterAndLiveRoomInfo(type_1.LiveType.LiveBroadcast, liveStatus))) {
|
|
1370
|
+
// 未获取成功,直接返回
|
|
1371
|
+
return this.sendPrivateMsg("获取直播间信息失败,推送直播卡片失败!");
|
|
1372
|
+
}
|
|
1373
|
+
// 判断是否需要设置开播时间
|
|
1374
|
+
if (!liveStatus.liveStartTimeInit) {
|
|
1375
|
+
// 设置开播时间
|
|
1376
|
+
liveStatus.liveStartTime = liveStatus.liveRoomInfo.live_time;
|
|
1377
|
+
// 设置开播时间初始化状态
|
|
1378
|
+
liveStatus.liveStartTimeInit = true;
|
|
1379
|
+
}
|
|
1380
|
+
// 获取watched
|
|
1381
|
+
const watched = "暂未获取到";
|
|
1382
|
+
// 设置直播中消息
|
|
1383
|
+
const liveMsg = this.config.customLive
|
|
1384
|
+
? this.config.customLive
|
|
1385
|
+
.replace("-name", liveStatus.masterInfo.username)
|
|
1386
|
+
.replace("-time", await this.ctx.gi.getTimeDifference(liveStatus.liveStartTime))
|
|
1387
|
+
.replace("-watched", watched)
|
|
1388
|
+
.replace("\\n", "\n")
|
|
1389
|
+
.replace("-link", `https://live.bilibili.com/${liveStatus.liveRoomInfo.short_id === 0 ? liveStatus.liveRoomInfo.room_id : liveStatus.liveRoomInfo.short_id}`)
|
|
1390
|
+
: null;
|
|
1391
|
+
// 发送直播通知卡片
|
|
1392
|
+
await this.sendLiveNotifyCard(type_1.LiveType.LiveBroadcast, watched, {
|
|
1393
|
+
liveRoomInfo: liveStatus.liveRoomInfo,
|
|
1394
|
+
masterInfo: liveStatus.masterInfo,
|
|
1395
|
+
cardStyle: sub.card,
|
|
1396
|
+
}, sub.target, liveMsg);
|
|
1397
|
+
// push归零
|
|
1398
|
+
liveStatus.push = 0;
|
|
1399
|
+
}
|
|
1400
|
+
// 结束
|
|
1401
|
+
break;
|
|
1402
|
+
}
|
|
1403
|
+
default:
|
|
1404
|
+
break;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
// 返回一个闭包函数
|
|
1409
|
+
return (0, utils_1.withLock)(handler);
|
|
1410
|
+
}
|
|
1140
1411
|
subShow() {
|
|
1141
1412
|
// 在控制台中显示订阅对象
|
|
1142
1413
|
let table = "";
|
|
@@ -1185,8 +1456,7 @@ class ComRegister {
|
|
|
1185
1456
|
// 获取关注分组信息
|
|
1186
1457
|
const checkGroupIsReady = async () => {
|
|
1187
1458
|
// 判断是否有数据
|
|
1188
|
-
if (this.loginDBData
|
|
1189
|
-
this.loginDBData.dynamic_group_id === null) {
|
|
1459
|
+
if (!this.loginDBData?.dynamic_group_id) {
|
|
1190
1460
|
// 没有数据,没有创建分组,尝试创建分组
|
|
1191
1461
|
const createGroupData = await this.ctx.ba.createGroup("订阅");
|
|
1192
1462
|
// 如果分组已创建,则获取分组id
|
|
@@ -1370,7 +1640,7 @@ class ComRegister {
|
|
|
1370
1640
|
if (userInfoCode !== 0)
|
|
1371
1641
|
return { code: userInfoCode, msg: userInfoMsg };
|
|
1372
1642
|
// 判断是否需要订阅直播
|
|
1373
|
-
if (sub.live) {
|
|
1643
|
+
if (this.config.liveDetectType === "WS" && sub.live) {
|
|
1374
1644
|
// 检查roomid是否存在
|
|
1375
1645
|
if (!userInfoData.live_room) {
|
|
1376
1646
|
// 用户没有开通直播间,无法订阅直播
|
|
@@ -1414,17 +1684,39 @@ class ComRegister {
|
|
|
1414
1684
|
}
|
|
1415
1685
|
checkIfDynamicDetectIsNeeded() {
|
|
1416
1686
|
// 检查是否有订阅对象需要动态监测
|
|
1417
|
-
if (this.
|
|
1687
|
+
if (this.dynamicTimelineManager.size > 0) {
|
|
1688
|
+
// 启动动态监测
|
|
1418
1689
|
this.enableDynamicDetect();
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
checkIfLiveDetectIsNeeded() {
|
|
1693
|
+
// 判断直播监测类型
|
|
1694
|
+
if (this.config.liveDetectType === "API") {
|
|
1695
|
+
// 检查是否有订阅对象需要直播监测
|
|
1696
|
+
if (this.liveStatusManager.size > 0) {
|
|
1697
|
+
// 启动直播监测
|
|
1698
|
+
this.enableLiveDetect();
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1419
1701
|
}
|
|
1420
1702
|
enableDynamicDetect() {
|
|
1421
1703
|
// 定义Job
|
|
1422
1704
|
this.dynamicJob = new cron_1.CronJob("*/2 * * * *", this.config.dynamicDebugMode
|
|
1423
1705
|
? this.debug_dynamicDetect()
|
|
1424
1706
|
: this.dynamicDetect());
|
|
1707
|
+
// logger
|
|
1708
|
+
this.logger.info("动态监测已开启");
|
|
1425
1709
|
// 开始动态监测
|
|
1426
1710
|
this.dynamicJob.start();
|
|
1427
1711
|
}
|
|
1712
|
+
async enableLiveDetect() {
|
|
1713
|
+
// 定义Job
|
|
1714
|
+
this.liveJob = new cron_1.CronJob("*/10 * * * * *", await this.liveDetectWithAPI());
|
|
1715
|
+
// logger
|
|
1716
|
+
this.logger.info("直播监测已开启");
|
|
1717
|
+
// 开始直播监测
|
|
1718
|
+
this.liveJob.start();
|
|
1719
|
+
}
|
|
1428
1720
|
async checkIfIsLogin() {
|
|
1429
1721
|
if ((await this.ctx.database.get("loginBili", 1)).length !== 0) {
|
|
1430
1722
|
// 数据库中有数据
|
|
@@ -1469,6 +1761,7 @@ class ComRegister {
|
|
|
1469
1761
|
masterAccount: koishi_1.Schema.string(),
|
|
1470
1762
|
masterAccountGuildId: koishi_1.Schema.string(),
|
|
1471
1763
|
}),
|
|
1764
|
+
liveDetectType: koishi_1.Schema.string(),
|
|
1472
1765
|
restartPush: koishi_1.Schema.boolean().required(),
|
|
1473
1766
|
pushTime: koishi_1.Schema.number().required(),
|
|
1474
1767
|
pushImgsInDynamic: koishi_1.Schema.boolean().required(),
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -126,6 +126,7 @@ class ServerManager extends koishi_1.Service {
|
|
|
126
126
|
const cr = this.ctx.plugin(comRegister_1.default, {
|
|
127
127
|
sub: globalConfig.sub,
|
|
128
128
|
master: globalConfig.master,
|
|
129
|
+
liveDetectType: globalConfig.liveDetectType,
|
|
129
130
|
restartPush: globalConfig.restartPush,
|
|
130
131
|
pushTime: globalConfig.pushTime,
|
|
131
132
|
pushImgsInDynamic: globalConfig.pushImgsInDynamic,
|
|
@@ -320,6 +321,10 @@ exports.Config = koishi_1.Schema.object({
|
|
|
320
321
|
.default(false)
|
|
321
322
|
.description("是否推送动态中的图片,默认不开启。开启后会单独推送动态中的图片"),
|
|
322
323
|
live: koishi_1.Schema.object({}).description("直播推送设置"),
|
|
324
|
+
liveDetectType: koishi_1.Schema.union(["WS", "API"])
|
|
325
|
+
.role("radio")
|
|
326
|
+
.default("WS")
|
|
327
|
+
.description("直播检测方式,WS为连接到B站弹幕服务器,API为通过轮询发送请求监测,默认使用WS检测"),
|
|
323
328
|
restartPush: koishi_1.Schema.boolean()
|
|
324
329
|
.default(true)
|
|
325
330
|
.description("插件重启后,如果订阅的主播正在直播,是否进行一次推送,默认开启"),
|
package/lib/type/index.d.ts
CHANGED
|
@@ -156,6 +156,47 @@ export type Dynamic = {
|
|
|
156
156
|
type: string;
|
|
157
157
|
visible: boolean;
|
|
158
158
|
};
|
|
159
|
+
export type Live = {
|
|
160
|
+
code: number;
|
|
161
|
+
message: string;
|
|
162
|
+
msg: string;
|
|
163
|
+
data: {
|
|
164
|
+
[key: string]: {
|
|
165
|
+
title: string;
|
|
166
|
+
room_id: number;
|
|
167
|
+
uid: number;
|
|
168
|
+
online: number;
|
|
169
|
+
live_time: number;
|
|
170
|
+
live_status: number;
|
|
171
|
+
short_id: number;
|
|
172
|
+
area: number;
|
|
173
|
+
area_name: string;
|
|
174
|
+
area_v2_id: number;
|
|
175
|
+
area_v2_name: string;
|
|
176
|
+
area_v2_parent_name: string;
|
|
177
|
+
area_v2_parent_id: number;
|
|
178
|
+
uname: string;
|
|
179
|
+
face: string;
|
|
180
|
+
tag_name: string;
|
|
181
|
+
tags: string;
|
|
182
|
+
cover_from_user: string;
|
|
183
|
+
keyframe: string;
|
|
184
|
+
lock_till: string;
|
|
185
|
+
hidden_till: string;
|
|
186
|
+
broadcast_type: number;
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
export type LiveStatus = {
|
|
191
|
+
live: boolean;
|
|
192
|
+
roomId: string;
|
|
193
|
+
liveRoomInfo: any;
|
|
194
|
+
masterInfo: MasterInfo;
|
|
195
|
+
watchedNum: string;
|
|
196
|
+
liveStartTimeInit: boolean;
|
|
197
|
+
liveStartTime: string;
|
|
198
|
+
push: number;
|
|
199
|
+
};
|
|
159
200
|
export type AllDynamicInfo = {
|
|
160
201
|
code: number;
|
|
161
202
|
message: string;
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -247,6 +247,8 @@ uid为必填参数,为要推送的UP主的UID,index为可选参数,为要
|
|
|
247
247
|
- ver 3.1.7-alpha.1 修复:启用自定义卡片样式后取消仍是自定义样式;
|
|
248
248
|
- ver 3.1.7-alpha.2 修复:`liveDetect generateLiveImg() 推送卡片生成失败,原因:Cannot read properties of undefined (reading 'cardColorStart')`;
|
|
249
249
|
- ver 3.1.7-alpha.3 修复:推送视频类动态报错;
|
|
250
|
+
- ver 3.1.7 修复:第一次使用插件报错 `TypeError: Cannot read properties of undefined (reading 'dynamic_group_id')`
|
|
251
|
+
- ver 3.2.0-alpha.0 新增:直播检测 `API` 模式; 优化:提升直播检测 `WS` 模式使用体验;
|
|
250
252
|
|
|
251
253
|
## 交流群
|
|
252
254
|
|