@bililive-tools/bilibili-recorder 1.16.1 → 1.18.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/bilibili_api.d.ts +2 -0
- package/lib/danma.d.ts +4 -0
- package/lib/danma.js +60 -16
- package/lib/index.js +60 -13
- package/lib/stream.d.ts +15 -1
- package/lib/stream.js +93 -33
- package/package.json +3 -3
- package/lib/blive-message-listener/chunk-5NTNTWA4.d.ts +0 -1
- package/lib/blive-message-listener/chunk-5NTNTWA4.js +0 -821
- package/lib/blive-message-listener/index.d.ts +0 -14
- package/lib/blive-message-listener/index.js +0 -30
package/lib/bilibili_api.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare function getRoomInit(roomIdOrShortId: number): Promise<{
|
|
|
7
7
|
live_time: number;
|
|
8
8
|
encrypted: boolean;
|
|
9
9
|
is_sp: 0 | 1;
|
|
10
|
+
special_type: number;
|
|
10
11
|
}>;
|
|
11
12
|
export declare function getRoomInfo(roomIdOrShortId: number): Promise<{
|
|
12
13
|
room_id: number;
|
|
@@ -79,6 +80,7 @@ export declare function getRoomPlayInfo(roomIdOrShortId: number, opts?: {
|
|
|
79
80
|
short_id: number;
|
|
80
81
|
live_status: LiveStatus;
|
|
81
82
|
live_time: number;
|
|
83
|
+
all_special_types?: number[];
|
|
82
84
|
playurl_info: {
|
|
83
85
|
conf_json: string;
|
|
84
86
|
playurl: {
|
package/lib/danma.d.ts
CHANGED
|
@@ -4,7 +4,11 @@ declare class DanmaClient extends EventEmitter {
|
|
|
4
4
|
private roomId;
|
|
5
5
|
private auth;
|
|
6
6
|
private uid;
|
|
7
|
+
private readonly maxRetryCount;
|
|
7
8
|
private retryCount;
|
|
9
|
+
private reconnectTimer;
|
|
10
|
+
private connectionGeneration;
|
|
11
|
+
private stopped;
|
|
8
12
|
private useServerTimestamp;
|
|
9
13
|
constructor(roomId: number, { auth, uid, useServerTimestamp, }: {
|
|
10
14
|
auth: string | undefined;
|
package/lib/danma.js
CHANGED
|
@@ -46,7 +46,11 @@ class DanmaClient extends EventEmitter {
|
|
|
46
46
|
roomId;
|
|
47
47
|
auth;
|
|
48
48
|
uid;
|
|
49
|
-
|
|
49
|
+
maxRetryCount = 10;
|
|
50
|
+
retryCount = this.maxRetryCount;
|
|
51
|
+
reconnectTimer = null;
|
|
52
|
+
connectionGeneration = 0;
|
|
53
|
+
stopped = true;
|
|
50
54
|
useServerTimestamp;
|
|
51
55
|
constructor(roomId, { auth, uid, useServerTimestamp, }) {
|
|
52
56
|
super();
|
|
@@ -56,9 +60,21 @@ class DanmaClient extends EventEmitter {
|
|
|
56
60
|
this.useServerTimestamp = useServerTimestamp ?? true;
|
|
57
61
|
}
|
|
58
62
|
async start() {
|
|
63
|
+
const connectionGeneration = ++this.connectionGeneration;
|
|
64
|
+
this.stopped = false;
|
|
65
|
+
this.retryCount = this.maxRetryCount;
|
|
59
66
|
const info = await getCachedBuvidConf();
|
|
67
|
+
if (this.stopped || connectionGeneration !== this.connectionGeneration)
|
|
68
|
+
return;
|
|
60
69
|
const buvid3 = info.data.b_3;
|
|
61
70
|
const handler = {
|
|
71
|
+
onOpen: () => {
|
|
72
|
+
this.retryCount = this.maxRetryCount;
|
|
73
|
+
this.emit("open");
|
|
74
|
+
},
|
|
75
|
+
onClose: () => {
|
|
76
|
+
this.emit("close");
|
|
77
|
+
},
|
|
62
78
|
onIncomeDanmu: (msg) => {
|
|
63
79
|
let content = msg.body.content;
|
|
64
80
|
content = content.replace(/(^\s*)|(\s*$)/g, "").replace(/[\r\n]/g, "");
|
|
@@ -159,26 +175,54 @@ class DanmaClient extends EventEmitter {
|
|
|
159
175
|
lastAuth = `buvid3=${buvid3}`;
|
|
160
176
|
}
|
|
161
177
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
178
|
+
const connect = () => {
|
|
179
|
+
if (this.stopped || connectionGeneration !== this.connectionGeneration)
|
|
180
|
+
return;
|
|
181
|
+
const client = startListen(this.roomId, handler, {
|
|
182
|
+
ws: {
|
|
183
|
+
headers: {
|
|
184
|
+
Cookie: lastAuth,
|
|
185
|
+
},
|
|
186
|
+
uid: this.uid ?? 0,
|
|
187
|
+
// 在本层控制重连次数,避免底层无限重连。
|
|
188
|
+
keepalive: false,
|
|
166
189
|
},
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
190
|
+
});
|
|
191
|
+
this.client = client;
|
|
192
|
+
client.live.on("close", () => {
|
|
193
|
+
if (this.stopped ||
|
|
194
|
+
connectionGeneration !== this.connectionGeneration ||
|
|
195
|
+
this.client !== client ||
|
|
196
|
+
this.reconnectTimer) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (this.retryCount <= 0) {
|
|
200
|
+
console.error(`DanmaClient reconnect failed after ${this.maxRetryCount} attempts`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const attempt = this.maxRetryCount - this.retryCount + 1;
|
|
204
|
+
this.retryCount -= 1;
|
|
205
|
+
this.emit("reconnect", { retryCount: attempt, maxRetry: this.maxRetryCount });
|
|
206
|
+
this.reconnectTimer = setTimeout(() => {
|
|
207
|
+
this.reconnectTimer = null;
|
|
208
|
+
connect();
|
|
175
209
|
}, 2000);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
|
|
210
|
+
});
|
|
211
|
+
client.live.on("error", (err) => {
|
|
212
|
+
console.error("DanmaClient error", err);
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
connect();
|
|
179
216
|
}
|
|
180
217
|
stop() {
|
|
218
|
+
this.stopped = true;
|
|
219
|
+
this.connectionGeneration += 1;
|
|
220
|
+
if (this.reconnectTimer) {
|
|
221
|
+
clearTimeout(this.reconnectTimer);
|
|
222
|
+
this.reconnectTimer = null;
|
|
223
|
+
}
|
|
181
224
|
this.client?.close();
|
|
225
|
+
this.client = null;
|
|
182
226
|
}
|
|
183
227
|
}
|
|
184
228
|
export default DanmaClient;
|
package/lib/index.js
CHANGED
|
@@ -13,6 +13,7 @@ function createRecorder(opts) {
|
|
|
13
13
|
...mitt(),
|
|
14
14
|
...opts,
|
|
15
15
|
cache: null,
|
|
16
|
+
appendTimeline: null,
|
|
16
17
|
availableStreams: [],
|
|
17
18
|
availableSources: [],
|
|
18
19
|
state: "idle",
|
|
@@ -87,10 +88,13 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
87
88
|
liveStartTime: new Date(),
|
|
88
89
|
recordStartTime: new Date(),
|
|
89
90
|
};
|
|
90
|
-
this.state
|
|
91
|
+
this.emit("stateChange", { state: "idle" });
|
|
91
92
|
}
|
|
92
93
|
catch (error) {
|
|
93
|
-
this.
|
|
94
|
+
this.emit("stateChange", {
|
|
95
|
+
state: "check-error",
|
|
96
|
+
msg: `检查失败,` + (error instanceof Error ? error.message : String(error)),
|
|
97
|
+
});
|
|
94
98
|
throw error;
|
|
95
99
|
}
|
|
96
100
|
if (this.liveInfo.liveId === banLiveId) {
|
|
@@ -106,9 +110,29 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
106
110
|
// 检查标题是否包含关键词,如果包含则不自动录制
|
|
107
111
|
if (utils.checkTitleKeywordsBeforeRecord(this.liveInfo.title, this, isManualStart))
|
|
108
112
|
return null;
|
|
109
|
-
const liveInfo = await getInfo(this.channelId);
|
|
113
|
+
const liveInfo = await getInfo(this.channelId, { cookie: this.auth });
|
|
110
114
|
const { owner, title, roomId, liveStartTime, recordStartTime } = liveInfo;
|
|
111
115
|
this.liveInfo = liveInfo;
|
|
116
|
+
// 特殊直播间无法录制(付费/DRM 加密、大航海权限专属、密码房等):识别后跳过并告知用户。
|
|
117
|
+
// - 付费直播流为 DRM(SAMPLE-AES + Widevine/FairPlay/com.bilidrm)加密,ffmpeg 无法解密;
|
|
118
|
+
// - 大航海/权限专属、密码房无观看权限时拿不到可用流。
|
|
119
|
+
// 如需强行尝试(例如后续接入其它录制方式),可设置 recorder.recordCharge = true。
|
|
120
|
+
if (!liveInfo.canRecord && this.recordCharge !== true) {
|
|
121
|
+
this.emit("DebugLog", {
|
|
122
|
+
type: "error",
|
|
123
|
+
text: `检测到${liveInfo.liveTypeDesc}(room ${roomId}),无法录制,已跳过:${title}`,
|
|
124
|
+
});
|
|
125
|
+
// 通知上层:检测到无法录制的特殊直播(供推送通知使用,由 manager 按场次去重)
|
|
126
|
+
this.emit("ChargeLive", { channelId: this.channelId });
|
|
127
|
+
// 持续状态标识:特殊直播已跳过。仅在状态变化时 emit,避免每个检查周期重复写时间线
|
|
128
|
+
if (this.state !== "charge-skipped") {
|
|
129
|
+
this.emit("stateChange", {
|
|
130
|
+
state: "charge-skipped",
|
|
131
|
+
msg: `${liveInfo.liveTypeDesc},已跳过录制`,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
112
136
|
const qualityRetryLeft = (await this.cache.get("qualityRetryLeft")) ?? this.qualityRetry;
|
|
113
137
|
const strictQuality = utils.shouldUseStrictQuality(qualityRetryLeft, this.qualityRetry, isManualStart);
|
|
114
138
|
let res;
|
|
@@ -127,10 +151,13 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
127
151
|
catch (err) {
|
|
128
152
|
if (qualityRetryLeft > 0)
|
|
129
153
|
await this.cache.set("qualityRetryLeft", qualityRetryLeft - 1);
|
|
130
|
-
this.
|
|
154
|
+
this.emit("stateChange", {
|
|
155
|
+
state: "check-error",
|
|
156
|
+
msg: `检查失败,` + (err instanceof Error ? err.message : String(err)),
|
|
157
|
+
});
|
|
131
158
|
throw err;
|
|
132
159
|
}
|
|
133
|
-
this.state
|
|
160
|
+
this.emit("stateChange", { state: "recording" });
|
|
134
161
|
const { streamOptions, currentStream: stream, sources: availableSources, streams: availableStreams, } = res;
|
|
135
162
|
this.availableStreams = availableStreams.map((s) => s.desc);
|
|
136
163
|
this.availableSources = availableSources.map((s) => s.name);
|
|
@@ -193,6 +220,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
193
220
|
headers: {
|
|
194
221
|
Referer: "https://live.bilibili.com/",
|
|
195
222
|
},
|
|
223
|
+
proxy: this.proxy,
|
|
196
224
|
}, onEnd, async () => {
|
|
197
225
|
const info = await getInfo(this.channelId);
|
|
198
226
|
return info;
|
|
@@ -254,7 +282,10 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
254
282
|
const title = msg?.body?.title ?? "";
|
|
255
283
|
const hasTitleKeyword = utils.hasBlockedTitleKeywords(title, this.titleKeywords);
|
|
256
284
|
if (hasTitleKeyword) {
|
|
257
|
-
this.
|
|
285
|
+
this.emit("stateChange", {
|
|
286
|
+
state: "title-blocked",
|
|
287
|
+
msg: `停止录制,直播间标题 "${title}" 包含关键词 "${this.titleKeywords}"`,
|
|
288
|
+
});
|
|
258
289
|
this.emit("DebugLog", {
|
|
259
290
|
type: "common",
|
|
260
291
|
text: `检测到标题包含关键词,停止录制:直播间标题 "${title}" 包含关键词 "${this.titleKeywords}"`,
|
|
@@ -264,16 +295,32 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
264
295
|
}
|
|
265
296
|
}
|
|
266
297
|
});
|
|
298
|
+
danmaClient.on("open", () => {
|
|
299
|
+
this.appendTimeline({
|
|
300
|
+
text: "弹幕连接已建立",
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
danmaClient.on("close", () => {
|
|
304
|
+
this.appendTimeline({
|
|
305
|
+
text: "弹幕连接已关闭",
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
danmaClient.on("reconnect", ({ retryCount, maxRetry }) => {
|
|
309
|
+
this.appendTimeline({
|
|
310
|
+
text: `弹幕连接已断开,正在尝试重连... (重试次数: ${retryCount}/${maxRetry})`,
|
|
311
|
+
});
|
|
312
|
+
this.emit("DebugLog", {
|
|
313
|
+
type: "common",
|
|
314
|
+
text: `弹幕连接已断开,正在尝试重连... (重试次数: ${retryCount}/${maxRetry})`,
|
|
315
|
+
});
|
|
316
|
+
});
|
|
267
317
|
if (enableDanmaListen) {
|
|
268
|
-
|
|
269
|
-
danmaClient.start();
|
|
270
|
-
}
|
|
271
|
-
catch (err) {
|
|
318
|
+
void danmaClient.start().catch((err) => {
|
|
272
319
|
this.emit("DebugLog", {
|
|
273
320
|
type: "error",
|
|
274
321
|
text: `弹幕连接失败,错误信息: ${String(err)}`,
|
|
275
322
|
});
|
|
276
|
-
}
|
|
323
|
+
});
|
|
277
324
|
}
|
|
278
325
|
const downloaderArgs = downloader.getArguments();
|
|
279
326
|
downloader.run();
|
|
@@ -285,7 +332,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
285
332
|
const stop = utils.singleton(async (reason) => {
|
|
286
333
|
if (!this.recordHandle)
|
|
287
334
|
return;
|
|
288
|
-
this.state
|
|
335
|
+
this.emit("stateChange", { state: "stopping-record" });
|
|
289
336
|
intervalId && clearInterval(intervalId);
|
|
290
337
|
try {
|
|
291
338
|
danmaClient.stop();
|
|
@@ -302,7 +349,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
|
|
|
302
349
|
this.emit("RecordStop", { recordHandle: this.recordHandle, reason });
|
|
303
350
|
this.recordHandle = undefined;
|
|
304
351
|
this.liveInfo = undefined;
|
|
305
|
-
this.state
|
|
352
|
+
this.emit("stateChange", { state: "idle" });
|
|
306
353
|
this.cache.set("qualityRetryLeft", this.qualityRetry);
|
|
307
354
|
});
|
|
308
355
|
this.recordHandle = {
|
package/lib/stream.d.ts
CHANGED
|
@@ -14,7 +14,17 @@ export declare function getLiveStatus(channelId: string): Promise<{
|
|
|
14
14
|
owner: string;
|
|
15
15
|
title: string;
|
|
16
16
|
}>;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* 直播类型(B站专属):
|
|
19
|
+
* - normal: 普通直播,可正常录制
|
|
20
|
+
* - paid: 付费/充电直播,流为 DRM(SAMPLE-AES + Widevine/FairPlay/com.bilidrm)加密,无法录制
|
|
21
|
+
* - guard: 大航海/权限专属直播(舰长/提督/总督等),无观看权限时拿不到流
|
|
22
|
+
* - password: 密码加密直播间,未验证密码拿不到流
|
|
23
|
+
*/
|
|
24
|
+
export type BiliLiveType = "normal" | "paid" | "guard" | "password";
|
|
25
|
+
export declare function getInfo(channelId: string, opts?: {
|
|
26
|
+
cookie?: string;
|
|
27
|
+
}): Promise<{
|
|
18
28
|
living: boolean;
|
|
19
29
|
owner: string;
|
|
20
30
|
title: string;
|
|
@@ -26,6 +36,10 @@ export declare function getInfo(channelId: string): Promise<{
|
|
|
26
36
|
liveStartTime: Date;
|
|
27
37
|
recordStartTime: Date;
|
|
28
38
|
area: string;
|
|
39
|
+
liveType: BiliLiveType;
|
|
40
|
+
liveTypeDesc: string;
|
|
41
|
+
canRecord: boolean;
|
|
42
|
+
isCharge: boolean;
|
|
29
43
|
}>;
|
|
30
44
|
export declare function getStream(opts: Pick<Recorder, "channelId" | "quality"> & {
|
|
31
45
|
cookie?: string;
|
package/lib/stream.js
CHANGED
|
@@ -19,7 +19,9 @@ export async function getLiveStatus(channelId) {
|
|
|
19
19
|
if (data) {
|
|
20
20
|
const startTime = new Date(data.live_time);
|
|
21
21
|
return {
|
|
22
|
-
living
|
|
22
|
+
// living 仅反映主播是否在播(live_status===1);加密/付费/权限等"房间特殊状态"
|
|
23
|
+
// 不并入 living,由 getInfo 的 liveType/canRecord 单独判定。
|
|
24
|
+
living: data.live_status === 1,
|
|
23
25
|
liveId: utils.md5(`${channelId}-${startTime?.getTime()}`),
|
|
24
26
|
owner: data.uname,
|
|
25
27
|
title: data.title,
|
|
@@ -28,53 +30,115 @@ export async function getLiveStatus(channelId) {
|
|
|
28
30
|
const roomInit = await getRoomInit(Number(channelId));
|
|
29
31
|
const startTime = new Date(roomInit.live_time * 1000);
|
|
30
32
|
return {
|
|
31
|
-
living: roomInit.live_status === 1
|
|
33
|
+
living: roomInit.live_status === 1,
|
|
32
34
|
liveId: utils.md5(`${roomInit.room_id}-${startTime?.getTime()}`),
|
|
33
35
|
...roomInit,
|
|
34
36
|
owner: "",
|
|
35
37
|
title: "",
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
const LIVE_TYPE_DESC = {
|
|
41
|
+
normal: "普通直播",
|
|
42
|
+
paid: "付费直播(DRM 加密)",
|
|
43
|
+
guard: "大航海/权限专属直播",
|
|
44
|
+
password: "密码加密直播",
|
|
45
|
+
};
|
|
46
|
+
export async function getInfo(channelId, opts = {}) {
|
|
39
47
|
const roomInit = await getRoomInit(Number(channelId));
|
|
40
|
-
|
|
48
|
+
// 判断 1:是否在直播。仅看 live_status,不混入加密/付费等房间特殊状态。
|
|
49
|
+
const living = roomInit.live_status === 1;
|
|
41
50
|
const recordStartTime = new Date();
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
// 基础信息(主播名/标题/封面等)始终获取,供频道预览(离线也要展示)。
|
|
52
|
+
let owner = "";
|
|
53
|
+
let title = "";
|
|
54
|
+
let avatar = "";
|
|
55
|
+
let cover = "";
|
|
56
|
+
let area = "";
|
|
57
|
+
let liveStartTime = new Date(0);
|
|
58
|
+
const { [roomInit.uid]: status } = await getStatusInfoByUIDs([roomInit.uid]);
|
|
59
|
+
if (status) {
|
|
60
|
+
owner = status.uname;
|
|
61
|
+
title = status.title;
|
|
62
|
+
avatar = status.face;
|
|
63
|
+
cover = status.cover_from_user;
|
|
64
|
+
area = status.area_v2_parent_name;
|
|
65
|
+
liveStartTime = new Date(status.live_time * 1000);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// 未获取到直播间信息(可能是加密房等),换一个接口取基础信息
|
|
44
69
|
const data = await getRoomBaseInfo(Number(channelId));
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
liveStartTime: liveStartTime,
|
|
53
|
-
avatar: "",
|
|
54
|
-
cover: status.cover,
|
|
55
|
-
roomId: roomInit.room_id,
|
|
56
|
-
liveId: utils.md5(`${roomInit.room_id}-${liveStartTime?.getTime()}`),
|
|
57
|
-
recordStartTime,
|
|
58
|
-
area: status.parent_area_name,
|
|
59
|
-
};
|
|
70
|
+
const base = data[Number(channelId)];
|
|
71
|
+
if (base) {
|
|
72
|
+
owner = base.uname;
|
|
73
|
+
title = base.title;
|
|
74
|
+
cover = base.cover;
|
|
75
|
+
liveStartTime = new Date(base.live_time);
|
|
76
|
+
}
|
|
60
77
|
}
|
|
61
|
-
|
|
78
|
+
// 判断 2 + 3:直播类型与能否录制。仅在播时才探测流(不在播无需多余请求)。
|
|
79
|
+
// 判定优先级(自上而下,命中即止):
|
|
80
|
+
// 1. 密码房 → 未验证密码拿不到流,优先判定,不再请求取流接口
|
|
81
|
+
// 2. 付费标记 → room_init 的 is_sp/special_type 在付费直播进行时翻 1,无需取流即可确认
|
|
82
|
+
// 3. 取流探测 → 上面都未命中时才请求 getRoomPlayInfo,区分 DRM付费 / 权限受限 / 普通可录
|
|
83
|
+
let liveType = "normal";
|
|
84
|
+
let canRecord = false;
|
|
85
|
+
if (living) {
|
|
86
|
+
const paidByRoomInit = roomInit.is_sp === 1 || roomInit.special_type === 1;
|
|
87
|
+
if (roomInit.encrypted) {
|
|
88
|
+
liveType = "password";
|
|
89
|
+
}
|
|
90
|
+
else if (paidByRoomInit) {
|
|
91
|
+
liveType = "paid";
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
try {
|
|
95
|
+
const playInfo = await getRoomPlayInfo(Number(channelId), { cookie: opts.cookie });
|
|
96
|
+
// all_special_types 含 203 = B站播放器自身判定的 DRM 加密直播
|
|
97
|
+
const allSpecialTypes = playInfo.all_special_types ?? [];
|
|
98
|
+
const isDRM = Array.isArray(allSpecialTypes) && allSpecialTypes.includes(203);
|
|
99
|
+
const hasStream = (playInfo.playurl_info?.playurl?.stream?.length ?? 0) > 0;
|
|
100
|
+
if (isDRM) {
|
|
101
|
+
liveType = "paid";
|
|
102
|
+
}
|
|
103
|
+
else if (!hasStream) {
|
|
104
|
+
// 取流接口正常返回、却拿不到任何流 → 权限受限(舰长/大航海等专属直播)
|
|
105
|
+
liveType = "guard";
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
liveType = "normal";
|
|
109
|
+
canRecord = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// 取流接口异常(网络/瞬时错误):不臆断为权限受限,按普通直播放行,
|
|
114
|
+
// 交由后续 getStream 重试并产生 check-error,避免误跳过导致漏录。
|
|
115
|
+
liveType = "normal";
|
|
116
|
+
canRecord = true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const liveTypeDesc = LIVE_TYPE_DESC[liveType];
|
|
62
121
|
return {
|
|
63
122
|
uid: roomInit.uid,
|
|
64
|
-
living
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
123
|
+
living,
|
|
124
|
+
liveType,
|
|
125
|
+
liveTypeDesc,
|
|
126
|
+
canRecord,
|
|
127
|
+
isCharge: liveType === "paid",
|
|
128
|
+
owner,
|
|
129
|
+
title,
|
|
130
|
+
avatar,
|
|
131
|
+
cover,
|
|
69
132
|
roomId: roomInit.room_id,
|
|
70
|
-
liveStartTime
|
|
133
|
+
liveStartTime,
|
|
71
134
|
liveId: utils.md5(`${roomInit.room_id}-${liveStartTime.getTime()}`),
|
|
72
135
|
recordStartTime,
|
|
73
|
-
area
|
|
136
|
+
area,
|
|
74
137
|
};
|
|
75
138
|
}
|
|
76
139
|
async function getLiveInfo(roomIdOrShortId, opts) {
|
|
77
140
|
const res = await getRoomPlayInfo(roomIdOrShortId, opts);
|
|
141
|
+
assert(res.playurl_info, "没有找到流");
|
|
78
142
|
// https://github.com/FFmpeg/FFmpeg/commit/b76053d8bf322b197a9d07bd27bbdad14fd5bc15
|
|
79
143
|
let conditons = [
|
|
80
144
|
{
|
|
@@ -208,10 +272,6 @@ async function getLiveInfo(roomIdOrShortId, opts) {
|
|
|
208
272
|
}
|
|
209
273
|
export async function getStream(opts) {
|
|
210
274
|
const roomId = Number(opts.channelId);
|
|
211
|
-
const roomInit = await getRoomInit(roomId);
|
|
212
|
-
if (roomInit.live_status !== 1) {
|
|
213
|
-
throw new Error("It must be called getStream when living");
|
|
214
|
-
}
|
|
215
275
|
const qn = BiliQualities.includes(opts.quality) ? opts.quality : 10000;
|
|
216
276
|
let liveInfo = await getLiveInfo(roomId, {
|
|
217
277
|
qn: qn,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bililive-tools/bilibili-recorder",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"description": "bililive-tools bilibili recorder implemention",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"author": "renmu123",
|
|
35
35
|
"license": "LGPL",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"blive-message-listener": "^0.5.
|
|
37
|
+
"blive-message-listener": "^0.5.5",
|
|
38
38
|
"mitt": "^3.0.1",
|
|
39
39
|
"tiny-bilibili-ws": "^1.0.2",
|
|
40
40
|
"lodash-es": "^4.17.21",
|
|
41
41
|
"axios": "^1.15.0",
|
|
42
|
-
"@bililive-tools/manager": "^1.
|
|
42
|
+
"@bililive-tools/manager": "^1.17.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsc",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function listenAll(instance: any, roomId: any, handler: any): void;
|
|
@@ -1,821 +0,0 @@
|
|
|
1
|
-
// src/parser/HEARTBEAT.ts
|
|
2
|
-
var parser = (data) => {
|
|
3
|
-
return {
|
|
4
|
-
attention: data,
|
|
5
|
-
};
|
|
6
|
-
};
|
|
7
|
-
var HEARTBEAT = {
|
|
8
|
-
parser,
|
|
9
|
-
eventName: "heartbeat",
|
|
10
|
-
handlerName: "onAttentionChange",
|
|
11
|
-
};
|
|
12
|
-
// src/parser/LIVE.ts
|
|
13
|
-
var parser2 = (data) => {
|
|
14
|
-
return {
|
|
15
|
-
live_platform: data.live_platform,
|
|
16
|
-
room_id: data.roomid,
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
var LIVE = {
|
|
20
|
-
parser: parser2,
|
|
21
|
-
eventName: "LIVE",
|
|
22
|
-
handlerName: "onLiveStart",
|
|
23
|
-
};
|
|
24
|
-
// src/parser/PREPARING.ts
|
|
25
|
-
var parser3 = (data) => {
|
|
26
|
-
return {
|
|
27
|
-
room_id: parseInt(data.roomid),
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
var PREPARING = {
|
|
31
|
-
parser: parser3,
|
|
32
|
-
eventName: "PREPARING",
|
|
33
|
-
handlerName: "onLiveEnd",
|
|
34
|
-
};
|
|
35
|
-
// src/parser/ANCHOR_LOT_AWARD.ts
|
|
36
|
-
var parser4 = (data, roomId) => {
|
|
37
|
-
const rawData = data.data;
|
|
38
|
-
return {
|
|
39
|
-
id: rawData.id,
|
|
40
|
-
award: {
|
|
41
|
-
image: rawData.award_image,
|
|
42
|
-
name: rawData.award_name,
|
|
43
|
-
virtual: rawData.award_type === 1,
|
|
44
|
-
},
|
|
45
|
-
winner: rawData.award_users.map((user) => ({
|
|
46
|
-
uid: user.uid,
|
|
47
|
-
uname: user.uname,
|
|
48
|
-
face: user.face,
|
|
49
|
-
level: user.level,
|
|
50
|
-
num: user.num,
|
|
51
|
-
})),
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
var ANCHOR_LOT_AWARD = {
|
|
55
|
-
parser: parser4,
|
|
56
|
-
eventName: "ANCHOR_LOT_AWARD",
|
|
57
|
-
handlerName: "onAnchorLotteryEnd",
|
|
58
|
-
};
|
|
59
|
-
// src/parser/ANCHOR_LOT_START.ts
|
|
60
|
-
var parser5 = (data, roomId) => {
|
|
61
|
-
const rawData = data.data;
|
|
62
|
-
return {
|
|
63
|
-
id: rawData.id,
|
|
64
|
-
start_time: rawData.current_time,
|
|
65
|
-
duration: rawData.max_time,
|
|
66
|
-
award: {
|
|
67
|
-
image: rawData.award_image,
|
|
68
|
-
name: rawData.award_name,
|
|
69
|
-
num: rawData.award_num,
|
|
70
|
-
virtual: rawData.award_type === 1,
|
|
71
|
-
price_text: rawData.award_price_text || "",
|
|
72
|
-
},
|
|
73
|
-
require: {
|
|
74
|
-
danmu: rawData.danmu || "",
|
|
75
|
-
gift: rawData.gift_id
|
|
76
|
-
? {
|
|
77
|
-
id: `${rawData.gift_id}`,
|
|
78
|
-
name: rawData.gift_name,
|
|
79
|
-
num: rawData.gift_num,
|
|
80
|
-
price: rawData.gift_price,
|
|
81
|
-
}
|
|
82
|
-
: null,
|
|
83
|
-
user: rawData.require_type
|
|
84
|
-
? {
|
|
85
|
-
type: ["follow", "medal", "guard"][rawData.require_type - 1],
|
|
86
|
-
value: rawData.require_value,
|
|
87
|
-
text: rawData.require_text,
|
|
88
|
-
}
|
|
89
|
-
: null,
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
};
|
|
93
|
-
var ANCHOR_LOT_START = {
|
|
94
|
-
parser: parser5,
|
|
95
|
-
eventName: "ANCHOR_LOT_START",
|
|
96
|
-
handlerName: "onAnchorLotteryStart",
|
|
97
|
-
};
|
|
98
|
-
// src/utils/color.ts
|
|
99
|
-
var intToColorHex = (int) => {
|
|
100
|
-
const hex = int.toString(16);
|
|
101
|
-
return `#${hex.padStart(6, "0")}`;
|
|
102
|
-
};
|
|
103
|
-
// src/parser/DANMU_MSG.ts
|
|
104
|
-
var parser6 = (data, roomId) => {
|
|
105
|
-
const rawData = data.info;
|
|
106
|
-
const content = rawData?.[1];
|
|
107
|
-
if (!content)
|
|
108
|
-
return;
|
|
109
|
-
const shouldParseInMessageEmoticon = /\[.*?\]/.test(content);
|
|
110
|
-
let inMessageEmoticon;
|
|
111
|
-
if (shouldParseInMessageEmoticon) {
|
|
112
|
-
const messageExtraInfo = JSON.parse(rawData[0][15].extra);
|
|
113
|
-
const emoctionDict = {};
|
|
114
|
-
if (messageExtraInfo.emots) {
|
|
115
|
-
inMessageEmoticon = Object.keys(messageExtraInfo.emots).reduce((acc, key) => {
|
|
116
|
-
const emoticon = messageExtraInfo.emots[key];
|
|
117
|
-
acc[key] = {
|
|
118
|
-
id: emoticon.emoticon_unique,
|
|
119
|
-
emoticon_id: emoticon.emoticon_id,
|
|
120
|
-
height: emoticon.height,
|
|
121
|
-
width: emoticon.width,
|
|
122
|
-
url: emoticon.url,
|
|
123
|
-
description: emoticon.descript,
|
|
124
|
-
};
|
|
125
|
-
return acc;
|
|
126
|
-
}, emoctionDict);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return {
|
|
130
|
-
user: {
|
|
131
|
-
uid: rawData[2][0],
|
|
132
|
-
uname: rawData[2][1],
|
|
133
|
-
badge: rawData[3].length
|
|
134
|
-
? {
|
|
135
|
-
active: rawData[3][7] !== 12632256,
|
|
136
|
-
name: rawData[3][1],
|
|
137
|
-
level: rawData[3][0],
|
|
138
|
-
color: intToColorHex(rawData[3][4]),
|
|
139
|
-
gradient: [
|
|
140
|
-
intToColorHex(rawData[3][7]),
|
|
141
|
-
intToColorHex(rawData[3][8]),
|
|
142
|
-
intToColorHex(rawData[3][9]),
|
|
143
|
-
],
|
|
144
|
-
anchor: {
|
|
145
|
-
uid: rawData[3][12],
|
|
146
|
-
uname: rawData[3][2],
|
|
147
|
-
room_id: rawData[3][3],
|
|
148
|
-
is_same_room: rawData[3][3] === roomId,
|
|
149
|
-
},
|
|
150
|
-
}
|
|
151
|
-
: void 0,
|
|
152
|
-
identity: {
|
|
153
|
-
rank: rawData[4][4],
|
|
154
|
-
guard_level: rawData[7],
|
|
155
|
-
room_admin: rawData[2][2] === 1,
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
content,
|
|
159
|
-
type: rawData[0][1],
|
|
160
|
-
content_color: intToColorHex(rawData[0][3]),
|
|
161
|
-
timestamp: rawData[0][4],
|
|
162
|
-
lottery: rawData[0][9] !== 0,
|
|
163
|
-
emoticon: rawData[0][13]?.emoticon_unique
|
|
164
|
-
? {
|
|
165
|
-
id: rawData[0][13].emoticon_unique,
|
|
166
|
-
height: rawData[0][13].height,
|
|
167
|
-
width: rawData[0][13].width,
|
|
168
|
-
url: rawData[0][13].url,
|
|
169
|
-
}
|
|
170
|
-
: void 0,
|
|
171
|
-
in_message_emoticon: inMessageEmoticon,
|
|
172
|
-
};
|
|
173
|
-
};
|
|
174
|
-
var DANMU_MSG = {
|
|
175
|
-
parser: parser6,
|
|
176
|
-
eventName: "DANMU_MSG",
|
|
177
|
-
handlerName: "onIncomeDanmu",
|
|
178
|
-
};
|
|
179
|
-
// src/parser/GUARD_BUY.ts
|
|
180
|
-
var parser7 = (data) => {
|
|
181
|
-
const rawData = data.data;
|
|
182
|
-
return {
|
|
183
|
-
user: {
|
|
184
|
-
uid: rawData.uid,
|
|
185
|
-
uname: rawData.username,
|
|
186
|
-
},
|
|
187
|
-
gift_id: rawData.gift_id,
|
|
188
|
-
gift_name: rawData.gift_name,
|
|
189
|
-
guard_level: rawData.guard_level,
|
|
190
|
-
price: rawData.price,
|
|
191
|
-
start_time: rawData.start_time,
|
|
192
|
-
end_time: rawData.end_time,
|
|
193
|
-
};
|
|
194
|
-
};
|
|
195
|
-
var GUARD_BUY = {
|
|
196
|
-
parser: parser7,
|
|
197
|
-
eventName: "GUARD_BUY",
|
|
198
|
-
handlerName: "onGuardBuy",
|
|
199
|
-
};
|
|
200
|
-
// src/parser/INTERACT_WORD_ENTRY_EFFECT.ts
|
|
201
|
-
var parserNormal = (data, roomId) => {
|
|
202
|
-
const rawData = data.data;
|
|
203
|
-
let actionType = "unknown";
|
|
204
|
-
if (rawData.msg_type === 1) {
|
|
205
|
-
actionType = "enter";
|
|
206
|
-
}
|
|
207
|
-
else if (rawData.msg_type === 2) {
|
|
208
|
-
actionType = "follow";
|
|
209
|
-
}
|
|
210
|
-
else if (rawData.msg_type === 3) {
|
|
211
|
-
actionType = "share";
|
|
212
|
-
}
|
|
213
|
-
return {
|
|
214
|
-
user: {
|
|
215
|
-
uid: rawData.uid,
|
|
216
|
-
uname: rawData.uname,
|
|
217
|
-
face: rawData?.face,
|
|
218
|
-
badge: rawData.fans_medal?.target_id
|
|
219
|
-
? {
|
|
220
|
-
active: !!rawData.fans_medal?.is_lighted,
|
|
221
|
-
name: rawData.fans_medal?.medal_name,
|
|
222
|
-
level: rawData.fans_medal?.medal_level,
|
|
223
|
-
color: intToColorHex(rawData.fans_medal?.medal_color),
|
|
224
|
-
gradient: [
|
|
225
|
-
intToColorHex(rawData.fans_medal?.medal_color_start),
|
|
226
|
-
intToColorHex(rawData.fans_medal?.medal_color_start),
|
|
227
|
-
intToColorHex(rawData.fans_medal?.medal_color_end),
|
|
228
|
-
],
|
|
229
|
-
anchor: {
|
|
230
|
-
uid: rawData.fans_medal?.target_id,
|
|
231
|
-
uname: "",
|
|
232
|
-
room_id: rawData.fans_medal?.anchor_roomid,
|
|
233
|
-
is_same_room: rawData.fans_medal?.anchor_roomid === roomId,
|
|
234
|
-
},
|
|
235
|
-
}
|
|
236
|
-
: void 0,
|
|
237
|
-
identity: {
|
|
238
|
-
rank: 0,
|
|
239
|
-
guard_level: rawData.privilege_type,
|
|
240
|
-
room_admin: false,
|
|
241
|
-
},
|
|
242
|
-
},
|
|
243
|
-
action: actionType,
|
|
244
|
-
timestamp: Math.ceil(rawData.trigger_time / 1e6),
|
|
245
|
-
};
|
|
246
|
-
};
|
|
247
|
-
var parserGuard = (data, roomId) => {
|
|
248
|
-
const rawData = data.data;
|
|
249
|
-
const uname = /<%(.*)%>/.exec(rawData.copy_writing)?.[1] || "";
|
|
250
|
-
return {
|
|
251
|
-
user: {
|
|
252
|
-
uid: rawData.uid,
|
|
253
|
-
uname,
|
|
254
|
-
// 超长会有省略号
|
|
255
|
-
identity: {
|
|
256
|
-
rank: 0,
|
|
257
|
-
guard_level: rawData.privilege_type,
|
|
258
|
-
room_admin: false,
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
action: "enter",
|
|
262
|
-
timestamp: Math.ceil(rawData.trigger_time / 1e6),
|
|
263
|
-
};
|
|
264
|
-
};
|
|
265
|
-
var parserLike = (data, roomId) => {
|
|
266
|
-
const rawData = data.data;
|
|
267
|
-
return {
|
|
268
|
-
user: {
|
|
269
|
-
uid: rawData.uid,
|
|
270
|
-
uname: rawData.uname,
|
|
271
|
-
badge: rawData.fans_medal?.target_id
|
|
272
|
-
? {
|
|
273
|
-
active: rawData.fans_medal?.is_lighted,
|
|
274
|
-
name: rawData.fans_medal?.medal_name,
|
|
275
|
-
level: rawData.fans_medal?.medal_level,
|
|
276
|
-
color: intToColorHex(rawData.fans_medal?.medal_color),
|
|
277
|
-
gradient: [
|
|
278
|
-
intToColorHex(rawData.fans_medal?.medal_color_start),
|
|
279
|
-
intToColorHex(rawData.fans_medal?.medal_color_start),
|
|
280
|
-
intToColorHex(rawData.fans_medal?.medal_color_end),
|
|
281
|
-
],
|
|
282
|
-
anchor: {
|
|
283
|
-
uid: rawData.fans_medal?.target_id,
|
|
284
|
-
uname: "",
|
|
285
|
-
room_id: rawData.fans_medal?.anchor_roomid,
|
|
286
|
-
// 返回为 0
|
|
287
|
-
is_same_room: rawData.fans_medal?.anchor_roomid === roomId,
|
|
288
|
-
},
|
|
289
|
-
}
|
|
290
|
-
: void 0,
|
|
291
|
-
},
|
|
292
|
-
action: "like",
|
|
293
|
-
timestamp: Date.now(),
|
|
294
|
-
};
|
|
295
|
-
};
|
|
296
|
-
var parser8 = (data, roomId) => {
|
|
297
|
-
const msgType = data.cmd;
|
|
298
|
-
if (msgType === "ENTRY_EFFECT") {
|
|
299
|
-
return parserGuard(data, roomId);
|
|
300
|
-
}
|
|
301
|
-
if (msgType === "LIKE_INFO_V3_CLICK") {
|
|
302
|
-
return parserLike(data, roomId);
|
|
303
|
-
}
|
|
304
|
-
return parserNormal(data, roomId);
|
|
305
|
-
};
|
|
306
|
-
var INTERACT_WORD = {
|
|
307
|
-
parser: parser8,
|
|
308
|
-
eventName: "INTERACT_WORD",
|
|
309
|
-
handlerName: "onUserAction",
|
|
310
|
-
};
|
|
311
|
-
var ENTRY_EFFECT = {
|
|
312
|
-
parser: parser8,
|
|
313
|
-
eventName: "ENTRY_EFFECT",
|
|
314
|
-
handlerName: "onUserAction",
|
|
315
|
-
};
|
|
316
|
-
var LIKE_INFO_V3_CLICK = {
|
|
317
|
-
parser: parser8,
|
|
318
|
-
eventName: "LIKE_INFO_V3_CLICK",
|
|
319
|
-
handlerName: "onUserAction",
|
|
320
|
-
};
|
|
321
|
-
// src/parser/LIKE_INFO_V3_UPDATE.ts
|
|
322
|
-
var parser9 = (data) => {
|
|
323
|
-
const rawData = data.data;
|
|
324
|
-
return {
|
|
325
|
-
count: rawData.click_count,
|
|
326
|
-
};
|
|
327
|
-
};
|
|
328
|
-
var LIKE_INFO_V3_UPDATE = {
|
|
329
|
-
parser: parser9,
|
|
330
|
-
eventName: "LIKE_INFO_V3_UPDATE",
|
|
331
|
-
handlerName: "onLikedChange",
|
|
332
|
-
};
|
|
333
|
-
// src/parser/ONLINE_RANK_COUNT.ts
|
|
334
|
-
var parser10 = (data) => {
|
|
335
|
-
const rawData = data.data;
|
|
336
|
-
return {
|
|
337
|
-
count: rawData.count,
|
|
338
|
-
};
|
|
339
|
-
};
|
|
340
|
-
var ONLINE_RANK_COUNT = {
|
|
341
|
-
parser: parser10,
|
|
342
|
-
eventName: "ONLINE_RANK_COUNT",
|
|
343
|
-
handlerName: "onRankCountChange",
|
|
344
|
-
};
|
|
345
|
-
// src/parser/POPULARITY_RED_POCKET_START.ts
|
|
346
|
-
var parser11 = (data, roomId) => {
|
|
347
|
-
const rawData = data.data;
|
|
348
|
-
return {
|
|
349
|
-
id: rawData.lot_id,
|
|
350
|
-
user: {
|
|
351
|
-
uid: rawData.sender_uid,
|
|
352
|
-
uname: rawData.sender_name,
|
|
353
|
-
face: rawData.sender_face,
|
|
354
|
-
},
|
|
355
|
-
start_time: rawData.start_time,
|
|
356
|
-
end_time: rawData.end_time,
|
|
357
|
-
duration: rawData.last_time,
|
|
358
|
-
danmu: rawData.danmu,
|
|
359
|
-
awards: rawData.awards,
|
|
360
|
-
total_price: rawData.total_price,
|
|
361
|
-
wait_num: rawData.wait_num,
|
|
362
|
-
};
|
|
363
|
-
};
|
|
364
|
-
var POPULARITY_RED_POCKET_START = {
|
|
365
|
-
parser: parser11,
|
|
366
|
-
eventName: "POPULARITY_RED_POCKET_START",
|
|
367
|
-
handlerName: "onRedPocketStart",
|
|
368
|
-
};
|
|
369
|
-
// src/parser/POPULARITY_RED_POCKET_WINNER_LIST.ts
|
|
370
|
-
var parser12 = (data, roomId) => {
|
|
371
|
-
const rawData = data.data;
|
|
372
|
-
return {
|
|
373
|
-
id: rawData.lot_id,
|
|
374
|
-
total_num: rawData.total_num,
|
|
375
|
-
winner: rawData.winner_info.map((item) => ({
|
|
376
|
-
uid: item[0],
|
|
377
|
-
uname: item[1],
|
|
378
|
-
award_id: item[3],
|
|
379
|
-
...rawData.awards[item[3]],
|
|
380
|
-
})),
|
|
381
|
-
awards: rawData.awards,
|
|
382
|
-
};
|
|
383
|
-
};
|
|
384
|
-
var POPULARITY_RED_POCKET_WINNER_LIST = {
|
|
385
|
-
parser: parser12,
|
|
386
|
-
eventName: "POPULARITY_RED_POCKET_WINNER_LIST",
|
|
387
|
-
handlerName: "onRedPocketEnd",
|
|
388
|
-
};
|
|
389
|
-
// src/parser/ROOM_ADMIN.ts
|
|
390
|
-
var parser13 = (data, roomId) => {
|
|
391
|
-
const msgType = data.cmd;
|
|
392
|
-
const rawData = data;
|
|
393
|
-
return {
|
|
394
|
-
type: msgType === "room_admin_entrance" ? "set" : "revoke",
|
|
395
|
-
uid: rawData.uid,
|
|
396
|
-
};
|
|
397
|
-
};
|
|
398
|
-
var room_admin_entrance = {
|
|
399
|
-
parser: parser13,
|
|
400
|
-
eventName: "room_admin_entrance",
|
|
401
|
-
handlerName: "onRoomAdminSet",
|
|
402
|
-
};
|
|
403
|
-
var ROOM_ADMIN_REVOKE = {
|
|
404
|
-
parser: parser13,
|
|
405
|
-
eventName: "ROOM_ADMIN_REVOKE",
|
|
406
|
-
handlerName: "onRoomAdminSet",
|
|
407
|
-
};
|
|
408
|
-
// src/parser/ROOM_CHANGE.ts
|
|
409
|
-
var parser14 = (data) => {
|
|
410
|
-
const rawData = data.data;
|
|
411
|
-
return {
|
|
412
|
-
title: rawData.title,
|
|
413
|
-
parent_area_id: rawData.parent_area_id,
|
|
414
|
-
parent_area_name: rawData.parent_area_name,
|
|
415
|
-
area_id: rawData.area_id,
|
|
416
|
-
area_name: rawData.area_name,
|
|
417
|
-
};
|
|
418
|
-
};
|
|
419
|
-
var ROOM_CHANGE = {
|
|
420
|
-
parser: parser14,
|
|
421
|
-
eventName: "ROOM_CHANGE",
|
|
422
|
-
handlerName: "onRoomInfoChange",
|
|
423
|
-
};
|
|
424
|
-
// src/parser/ROOM_SILENT.ts
|
|
425
|
-
var parser15 = (data, roomId) => {
|
|
426
|
-
const msgType = data.cmd;
|
|
427
|
-
const rawData = data.data;
|
|
428
|
-
return {
|
|
429
|
-
type: msgType === "ROOM_SILENT_OFF" ? "off" : rawData.type,
|
|
430
|
-
level: rawData.level,
|
|
431
|
-
second: rawData.second,
|
|
432
|
-
};
|
|
433
|
-
};
|
|
434
|
-
var ROOM_SILENT_ON = {
|
|
435
|
-
parser: parser15,
|
|
436
|
-
eventName: "ROOM_SILENT_ON",
|
|
437
|
-
handlerName: "onRoomSilent",
|
|
438
|
-
};
|
|
439
|
-
var ROOM_SILENT_OFF = {
|
|
440
|
-
parser: parser15,
|
|
441
|
-
eventName: "ROOM_SILENT_OFF",
|
|
442
|
-
handlerName: "onRoomSilent",
|
|
443
|
-
};
|
|
444
|
-
// src/parser/SEND_GIFT.ts
|
|
445
|
-
var parser16 = (data) => {
|
|
446
|
-
const rawData = data.data;
|
|
447
|
-
return {
|
|
448
|
-
user: {
|
|
449
|
-
uid: rawData.uid,
|
|
450
|
-
uname: rawData.uname,
|
|
451
|
-
face: rawData.face,
|
|
452
|
-
badge: rawData.medal_info?.medal_level
|
|
453
|
-
? {
|
|
454
|
-
active: rawData.medal_info.is_lighted === 1,
|
|
455
|
-
name: rawData.medal_info.medal_name,
|
|
456
|
-
level: rawData.medal_info.medal_level,
|
|
457
|
-
color: intToColorHex(rawData.medal_info.medal_color),
|
|
458
|
-
gradient: [
|
|
459
|
-
intToColorHex(rawData.medal_info.medal_color_start),
|
|
460
|
-
intToColorHex(rawData.medal_info.medal_color_start),
|
|
461
|
-
intToColorHex(rawData.medal_info.medal_color_end),
|
|
462
|
-
],
|
|
463
|
-
anchor: {
|
|
464
|
-
uid: rawData.medal_info.target_id,
|
|
465
|
-
uname: rawData.medal_info.anchor_uname,
|
|
466
|
-
// maybe ''
|
|
467
|
-
room_id: rawData.medal_info.anchor_roomid,
|
|
468
|
-
// maybe 0
|
|
469
|
-
},
|
|
470
|
-
}
|
|
471
|
-
: void 0,
|
|
472
|
-
identity: {
|
|
473
|
-
rank: 0,
|
|
474
|
-
guard_level: rawData.guard_level,
|
|
475
|
-
room_admin: false,
|
|
476
|
-
},
|
|
477
|
-
},
|
|
478
|
-
gift_id: rawData.giftId,
|
|
479
|
-
gift_name: rawData.giftName,
|
|
480
|
-
coin_type: rawData.coin_type,
|
|
481
|
-
price: rawData.price,
|
|
482
|
-
amount: rawData.num,
|
|
483
|
-
send_master: rawData.send_master?.uid
|
|
484
|
-
? {
|
|
485
|
-
uid: rawData.send_master.uid,
|
|
486
|
-
uname: rawData.send_master.uname,
|
|
487
|
-
room_id: rawData.send_master.room_id,
|
|
488
|
-
}
|
|
489
|
-
: void 0,
|
|
490
|
-
// 礼物连击:
|
|
491
|
-
// data.combo_send 仅首次连击不为空;data.batch_combo_send 速度过快时可能为空;data.batch_combo_id 常驻存在
|
|
492
|
-
combo: rawData.batch_combo_id
|
|
493
|
-
? {
|
|
494
|
-
batch_id: rawData.batch_combo_id,
|
|
495
|
-
combo_num: rawData.super_batch_gift_num,
|
|
496
|
-
total_price: rawData.combo_total_coin,
|
|
497
|
-
}
|
|
498
|
-
: void 0,
|
|
499
|
-
};
|
|
500
|
-
};
|
|
501
|
-
var SEND_GIFT = {
|
|
502
|
-
parser: parser16,
|
|
503
|
-
eventName: "SEND_GIFT",
|
|
504
|
-
handlerName: "onGift",
|
|
505
|
-
};
|
|
506
|
-
// src/parser/SUPER_CHAT_MESSAGE.ts
|
|
507
|
-
var parser17 = (data, roomId) => {
|
|
508
|
-
const rawData = data.data;
|
|
509
|
-
const { medal_info, user_info } = data.data;
|
|
510
|
-
return {
|
|
511
|
-
id: rawData.id,
|
|
512
|
-
user: {
|
|
513
|
-
uid: rawData.uid,
|
|
514
|
-
uname: rawData.user_info.uname,
|
|
515
|
-
badge: medal_info
|
|
516
|
-
? {
|
|
517
|
-
active: medal_info.is_lighted === 1,
|
|
518
|
-
name: medal_info.medal_name,
|
|
519
|
-
level: medal_info.medal_level,
|
|
520
|
-
color: medal_info.medal_color,
|
|
521
|
-
anchor: {
|
|
522
|
-
uid: medal_info.target_id,
|
|
523
|
-
uname: medal_info.anchor_uname,
|
|
524
|
-
room_id: medal_info.anchor_roomid,
|
|
525
|
-
is_same_room: medal_info.anchor_roomid === roomId,
|
|
526
|
-
},
|
|
527
|
-
}
|
|
528
|
-
: void 0,
|
|
529
|
-
identity: {
|
|
530
|
-
rank: 0,
|
|
531
|
-
guard_level: user_info.guard_level || 0,
|
|
532
|
-
room_admin: user_info.manager === 1,
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
content: rawData.message,
|
|
536
|
-
content_color: rawData.background_price_color,
|
|
537
|
-
price: rawData.price,
|
|
538
|
-
time: rawData.time,
|
|
539
|
-
};
|
|
540
|
-
};
|
|
541
|
-
var SUPER_CHAT_MESSAGE = {
|
|
542
|
-
parser: parser17,
|
|
543
|
-
eventName: "SUPER_CHAT_MESSAGE",
|
|
544
|
-
handlerName: "onIncomeSuperChat",
|
|
545
|
-
};
|
|
546
|
-
// src/parser/WARNING_CUT_OFF.ts
|
|
547
|
-
var parser18 = (data, roomId) => {
|
|
548
|
-
const msgType = data.cmd;
|
|
549
|
-
const rawData = data;
|
|
550
|
-
return {
|
|
551
|
-
type: msgType === "WARNING" ? "warning" : "cut",
|
|
552
|
-
msg: rawData.msg,
|
|
553
|
-
};
|
|
554
|
-
};
|
|
555
|
-
var WARNING = {
|
|
556
|
-
parser: parser18,
|
|
557
|
-
eventName: "WARNING",
|
|
558
|
-
handlerName: "onRoomWarn",
|
|
559
|
-
};
|
|
560
|
-
var CUT_OFF = {
|
|
561
|
-
parser: parser18,
|
|
562
|
-
eventName: "CUT_OFF",
|
|
563
|
-
handlerName: "onRoomWarn",
|
|
564
|
-
};
|
|
565
|
-
// src/parser/WATCHED_CHANGE.ts
|
|
566
|
-
var parser19 = (data) => {
|
|
567
|
-
const rawData = data.data;
|
|
568
|
-
return {
|
|
569
|
-
num: rawData.num,
|
|
570
|
-
text_small: rawData.text_small,
|
|
571
|
-
};
|
|
572
|
-
};
|
|
573
|
-
var WATCHED_CHANGE = {
|
|
574
|
-
parser: parser19,
|
|
575
|
-
eventName: "WATCHED_CHANGE",
|
|
576
|
-
handlerName: "onWatchedChange",
|
|
577
|
-
};
|
|
578
|
-
// src/utils/message.ts
|
|
579
|
-
var normalizeDanmu = (msgType, body, rawBody) => {
|
|
580
|
-
const timestamp = Date.now();
|
|
581
|
-
const randomText = Math.floor(Math.random() * 1e4).toString();
|
|
582
|
-
const id = `${timestamp}:${msgType}:${body.user?.uid}:${randomText}`;
|
|
583
|
-
return {
|
|
584
|
-
id,
|
|
585
|
-
timestamp,
|
|
586
|
-
type: msgType,
|
|
587
|
-
body,
|
|
588
|
-
raw: rawBody,
|
|
589
|
-
};
|
|
590
|
-
};
|
|
591
|
-
// src/listener/index.ts
|
|
592
|
-
var listenAll = (instance, roomId, handler) => {
|
|
593
|
-
if (!handler)
|
|
594
|
-
return;
|
|
595
|
-
const rawHandler = handler.raw || {};
|
|
596
|
-
const rawHandlerNames = new Set(Object.keys(rawHandler));
|
|
597
|
-
const isHandleRaw = rawHandlerNames.size > 0;
|
|
598
|
-
if (handler.onOpen) {
|
|
599
|
-
instance.on("open", () => {
|
|
600
|
-
handler.onOpen?.();
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
if (handler.onClose) {
|
|
604
|
-
instance.on("close", () => {
|
|
605
|
-
handler.onClose?.();
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
if (handler.onStartListen) {
|
|
609
|
-
instance.on("live", () => {
|
|
610
|
-
handler.onStartListen?.();
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
if (handler[HEARTBEAT.handlerName] || rawHandlerNames.has(HEARTBEAT.eventName)) {
|
|
614
|
-
rawHandlerNames.delete(HEARTBEAT.eventName);
|
|
615
|
-
instance.on(HEARTBEAT.eventName, (data) => {
|
|
616
|
-
isHandleRaw && rawHandler[HEARTBEAT.eventName]?.(data);
|
|
617
|
-
const parsedData = HEARTBEAT.parser(data);
|
|
618
|
-
handler[HEARTBEAT.handlerName]?.(normalizeDanmu(HEARTBEAT.eventName, parsedData, data));
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
if (handler[LIVE.handlerName] || rawHandlerNames.has(LIVE.eventName)) {
|
|
622
|
-
rawHandlerNames.delete(LIVE.eventName);
|
|
623
|
-
instance.on(LIVE.eventName, (data) => {
|
|
624
|
-
isHandleRaw && rawHandler[LIVE.eventName]?.(data.data);
|
|
625
|
-
const parsedData = LIVE.parser(data.data);
|
|
626
|
-
handler[LIVE.handlerName]?.(normalizeDanmu(LIVE.eventName, parsedData, data.data));
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
if (handler[PREPARING.handlerName] || rawHandlerNames.has(PREPARING.eventName)) {
|
|
630
|
-
rawHandlerNames.delete(LIVE.eventName);
|
|
631
|
-
instance.on(PREPARING.eventName, (data) => {
|
|
632
|
-
isHandleRaw && rawHandler[PREPARING.eventName]?.(data.data);
|
|
633
|
-
const parsedData = PREPARING.parser(data.data);
|
|
634
|
-
handler[PREPARING.handlerName]?.(normalizeDanmu(PREPARING.eventName, parsedData, data.data));
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
if (handler[ANCHOR_LOT_AWARD.handlerName] || rawHandlerNames.has(ANCHOR_LOT_AWARD.eventName)) {
|
|
638
|
-
rawHandlerNames.delete(ANCHOR_LOT_AWARD.eventName);
|
|
639
|
-
instance.on(ANCHOR_LOT_AWARD.eventName, (data) => {
|
|
640
|
-
isHandleRaw && rawHandler[ANCHOR_LOT_AWARD.eventName]?.(data.data);
|
|
641
|
-
const parsedData = ANCHOR_LOT_AWARD.parser(data.data, roomId);
|
|
642
|
-
handler[ANCHOR_LOT_AWARD.handlerName]?.(normalizeDanmu(ANCHOR_LOT_AWARD.eventName, parsedData, data.data));
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
if (handler[ANCHOR_LOT_START.handlerName] || rawHandlerNames.has(ANCHOR_LOT_START.eventName)) {
|
|
646
|
-
rawHandlerNames.delete(ANCHOR_LOT_START.eventName);
|
|
647
|
-
instance.on(ANCHOR_LOT_START.eventName, (data) => {
|
|
648
|
-
isHandleRaw && rawHandler[ANCHOR_LOT_START.eventName]?.(data.data);
|
|
649
|
-
const parsedData = ANCHOR_LOT_START.parser(data.data, roomId);
|
|
650
|
-
handler[ANCHOR_LOT_START.handlerName]?.(normalizeDanmu(ANCHOR_LOT_START.eventName, parsedData, data.data));
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
if (handler[DANMU_MSG.handlerName] || rawHandlerNames.has(DANMU_MSG.eventName)) {
|
|
654
|
-
rawHandlerNames.delete(DANMU_MSG.eventName);
|
|
655
|
-
instance.on(DANMU_MSG.eventName, (data) => {
|
|
656
|
-
isHandleRaw && rawHandler[DANMU_MSG.eventName]?.(data.data);
|
|
657
|
-
const parsedData = DANMU_MSG.parser(data.data, roomId);
|
|
658
|
-
if (parsedData) {
|
|
659
|
-
handler[DANMU_MSG.handlerName]?.(normalizeDanmu(DANMU_MSG.eventName, parsedData, data.data));
|
|
660
|
-
}
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
if (handler[GUARD_BUY.handlerName] || rawHandlerNames.has(GUARD_BUY.eventName)) {
|
|
664
|
-
rawHandlerNames.delete(GUARD_BUY.eventName);
|
|
665
|
-
instance.on(GUARD_BUY.eventName, (data) => {
|
|
666
|
-
isHandleRaw && rawHandler[GUARD_BUY.eventName]?.(data.data);
|
|
667
|
-
const parsedData = GUARD_BUY.parser(data.data);
|
|
668
|
-
handler[GUARD_BUY.handlerName]?.(normalizeDanmu(GUARD_BUY.eventName, parsedData, data.data));
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
if (handler[INTERACT_WORD.handlerName] ||
|
|
672
|
-
handler[ENTRY_EFFECT.handlerName] ||
|
|
673
|
-
handler[LIKE_INFO_V3_CLICK.handlerName] ||
|
|
674
|
-
rawHandlerNames.has(INTERACT_WORD.eventName) ||
|
|
675
|
-
rawHandlerNames.has(ENTRY_EFFECT.eventName) ||
|
|
676
|
-
rawHandlerNames.has(LIKE_INFO_V3_CLICK.eventName)) {
|
|
677
|
-
rawHandlerNames.delete(INTERACT_WORD.eventName);
|
|
678
|
-
rawHandlerNames.delete(ENTRY_EFFECT.eventName);
|
|
679
|
-
rawHandlerNames.delete(LIKE_INFO_V3_CLICK.eventName);
|
|
680
|
-
instance.on(INTERACT_WORD.eventName, (data) => {
|
|
681
|
-
isHandleRaw && rawHandler[INTERACT_WORD.eventName]?.(data.data);
|
|
682
|
-
const parsedData = INTERACT_WORD.parser(data.data, roomId);
|
|
683
|
-
handler[INTERACT_WORD.handlerName]?.(normalizeDanmu(INTERACT_WORD.eventName, parsedData, data.data));
|
|
684
|
-
});
|
|
685
|
-
instance.on(ENTRY_EFFECT.eventName, (data) => {
|
|
686
|
-
isHandleRaw && rawHandler[ENTRY_EFFECT.eventName]?.(data.data);
|
|
687
|
-
const parsedData = ENTRY_EFFECT.parser(data.data, roomId);
|
|
688
|
-
handler[ENTRY_EFFECT.handlerName]?.(normalizeDanmu(ENTRY_EFFECT.eventName, parsedData, data.data));
|
|
689
|
-
});
|
|
690
|
-
instance.on(LIKE_INFO_V3_CLICK.eventName, (data) => {
|
|
691
|
-
isHandleRaw && rawHandler[LIKE_INFO_V3_CLICK.eventName]?.(data.data);
|
|
692
|
-
const parsedData = LIKE_INFO_V3_CLICK.parser(data.data, roomId);
|
|
693
|
-
handler[LIKE_INFO_V3_CLICK.handlerName]?.(normalizeDanmu(LIKE_INFO_V3_CLICK.eventName, parsedData, data.data));
|
|
694
|
-
});
|
|
695
|
-
}
|
|
696
|
-
if (handler[LIKE_INFO_V3_UPDATE.handlerName] ||
|
|
697
|
-
rawHandlerNames.has(LIKE_INFO_V3_UPDATE.eventName)) {
|
|
698
|
-
rawHandlerNames.delete(LIKE_INFO_V3_UPDATE.eventName);
|
|
699
|
-
instance.on(LIKE_INFO_V3_UPDATE.eventName, (data) => {
|
|
700
|
-
isHandleRaw && rawHandler[LIKE_INFO_V3_UPDATE.eventName]?.(data.data);
|
|
701
|
-
const parsedData = LIKE_INFO_V3_UPDATE.parser(data.data);
|
|
702
|
-
handler[LIKE_INFO_V3_UPDATE.handlerName]?.(normalizeDanmu(LIKE_INFO_V3_UPDATE.eventName, parsedData, data.data));
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
if (handler[ONLINE_RANK_COUNT.handlerName] || rawHandlerNames.has(ONLINE_RANK_COUNT.eventName)) {
|
|
706
|
-
rawHandlerNames.delete(ONLINE_RANK_COUNT.eventName);
|
|
707
|
-
instance.on(ONLINE_RANK_COUNT.eventName, (data) => {
|
|
708
|
-
isHandleRaw && rawHandler[ONLINE_RANK_COUNT.eventName]?.(data.data);
|
|
709
|
-
const parsedData = ONLINE_RANK_COUNT.parser(data.data);
|
|
710
|
-
handler[ONLINE_RANK_COUNT.handlerName]?.(normalizeDanmu(ONLINE_RANK_COUNT.eventName, parsedData, data.data));
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
if (handler[POPULARITY_RED_POCKET_START.handlerName] ||
|
|
714
|
-
rawHandlerNames.has(POPULARITY_RED_POCKET_START.eventName)) {
|
|
715
|
-
rawHandlerNames.delete(POPULARITY_RED_POCKET_START.eventName);
|
|
716
|
-
instance.on(POPULARITY_RED_POCKET_START.eventName, (data) => {
|
|
717
|
-
isHandleRaw && rawHandler[POPULARITY_RED_POCKET_START.eventName]?.(data.data);
|
|
718
|
-
const parsedData = POPULARITY_RED_POCKET_START.parser(data.data, roomId);
|
|
719
|
-
handler[POPULARITY_RED_POCKET_START.handlerName]?.(normalizeDanmu(POPULARITY_RED_POCKET_START.eventName, parsedData, data.data));
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
|
-
if (handler[POPULARITY_RED_POCKET_WINNER_LIST.handlerName] ||
|
|
723
|
-
rawHandlerNames.has(POPULARITY_RED_POCKET_WINNER_LIST.eventName)) {
|
|
724
|
-
rawHandlerNames.delete(POPULARITY_RED_POCKET_WINNER_LIST.eventName);
|
|
725
|
-
instance.on(POPULARITY_RED_POCKET_WINNER_LIST.eventName, (data) => {
|
|
726
|
-
isHandleRaw && rawHandler[POPULARITY_RED_POCKET_WINNER_LIST.eventName]?.(data.data);
|
|
727
|
-
const parsedData = POPULARITY_RED_POCKET_WINNER_LIST.parser(data.data, roomId);
|
|
728
|
-
handler[POPULARITY_RED_POCKET_WINNER_LIST.handlerName]?.(normalizeDanmu(POPULARITY_RED_POCKET_WINNER_LIST.eventName, parsedData, data.data));
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
if (handler[room_admin_entrance.handlerName] ||
|
|
732
|
-
handler[ROOM_ADMIN_REVOKE.handlerName] ||
|
|
733
|
-
rawHandlerNames.has(room_admin_entrance.eventName) ||
|
|
734
|
-
rawHandlerNames.has(ROOM_SILENT_OFF.eventName)) {
|
|
735
|
-
rawHandlerNames.delete(room_admin_entrance.eventName);
|
|
736
|
-
rawHandlerNames.delete(ROOM_ADMIN_REVOKE.eventName);
|
|
737
|
-
instance.on(room_admin_entrance.eventName, (data) => {
|
|
738
|
-
isHandleRaw && rawHandler[room_admin_entrance.eventName]?.(data.data);
|
|
739
|
-
const parsedData = room_admin_entrance.parser(data.data, roomId);
|
|
740
|
-
handler[room_admin_entrance.handlerName]?.(normalizeDanmu(room_admin_entrance.eventName, parsedData, data.data));
|
|
741
|
-
});
|
|
742
|
-
instance.on(ROOM_ADMIN_REVOKE.eventName, (data) => {
|
|
743
|
-
isHandleRaw && rawHandler[ROOM_ADMIN_REVOKE.eventName]?.(data.data);
|
|
744
|
-
const parsedData = ROOM_ADMIN_REVOKE.parser(data.data, roomId);
|
|
745
|
-
handler[ROOM_ADMIN_REVOKE.handlerName]?.(normalizeDanmu(ROOM_ADMIN_REVOKE.eventName, parsedData, data.data));
|
|
746
|
-
});
|
|
747
|
-
}
|
|
748
|
-
if (handler[ROOM_CHANGE.handlerName] || rawHandlerNames.has(ROOM_CHANGE.eventName)) {
|
|
749
|
-
rawHandlerNames.delete(ROOM_CHANGE.eventName);
|
|
750
|
-
instance.on(ROOM_CHANGE.eventName, (data) => {
|
|
751
|
-
isHandleRaw && rawHandler[ROOM_CHANGE.eventName]?.(data.data);
|
|
752
|
-
const parsedData = ROOM_CHANGE.parser(data.data);
|
|
753
|
-
handler[ROOM_CHANGE.handlerName]?.(normalizeDanmu(ROOM_CHANGE.eventName, parsedData, data.data));
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
if (handler[ROOM_SILENT_ON.handlerName] ||
|
|
757
|
-
handler[ROOM_SILENT_OFF.handlerName] ||
|
|
758
|
-
rawHandlerNames.has(ROOM_SILENT_ON.eventName) ||
|
|
759
|
-
rawHandlerNames.has(ROOM_SILENT_OFF.eventName)) {
|
|
760
|
-
rawHandlerNames.delete(ROOM_SILENT_ON.eventName);
|
|
761
|
-
rawHandlerNames.delete(ROOM_SILENT_OFF.eventName);
|
|
762
|
-
instance.on(ROOM_SILENT_ON.eventName, (data) => {
|
|
763
|
-
isHandleRaw && rawHandler[ROOM_SILENT_ON.eventName]?.(data.data);
|
|
764
|
-
const parsedData = ROOM_SILENT_ON.parser(data.data, roomId);
|
|
765
|
-
handler[ROOM_SILENT_ON.handlerName]?.(normalizeDanmu(ROOM_SILENT_ON.eventName, parsedData, data.data));
|
|
766
|
-
});
|
|
767
|
-
instance.on(ROOM_SILENT_OFF.eventName, (data) => {
|
|
768
|
-
isHandleRaw && rawHandler[ROOM_SILENT_OFF.eventName]?.(data.data);
|
|
769
|
-
const parsedData = ROOM_SILENT_OFF.parser(data.data, roomId);
|
|
770
|
-
handler[ROOM_SILENT_OFF.handlerName]?.(normalizeDanmu(ROOM_SILENT_OFF.eventName, parsedData, data.data));
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
if (handler[SEND_GIFT.handlerName] || rawHandlerNames.has(SEND_GIFT.eventName)) {
|
|
774
|
-
rawHandlerNames.delete(SEND_GIFT.eventName);
|
|
775
|
-
instance.on(SEND_GIFT.eventName, (data) => {
|
|
776
|
-
isHandleRaw && rawHandler[SEND_GIFT.eventName]?.(data.data);
|
|
777
|
-
const parsedData = SEND_GIFT.parser(data.data);
|
|
778
|
-
handler[SEND_GIFT.handlerName]?.(normalizeDanmu(SEND_GIFT.eventName, parsedData, data.data));
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
if (handler[SUPER_CHAT_MESSAGE.handlerName] ||
|
|
782
|
-
rawHandlerNames.has(SUPER_CHAT_MESSAGE.eventName)) {
|
|
783
|
-
rawHandlerNames.delete(SUPER_CHAT_MESSAGE.eventName);
|
|
784
|
-
instance.on(SUPER_CHAT_MESSAGE.eventName, (data) => {
|
|
785
|
-
isHandleRaw && rawHandler[SUPER_CHAT_MESSAGE.eventName]?.(data.data);
|
|
786
|
-
const parsedData = SUPER_CHAT_MESSAGE.parser(data.data, roomId);
|
|
787
|
-
handler[SUPER_CHAT_MESSAGE.handlerName]?.(normalizeDanmu(SUPER_CHAT_MESSAGE.eventName, parsedData, data.data));
|
|
788
|
-
});
|
|
789
|
-
}
|
|
790
|
-
if (handler[WARNING.handlerName] ||
|
|
791
|
-
handler[CUT_OFF.handlerName] ||
|
|
792
|
-
rawHandlerNames.has(WARNING.eventName) ||
|
|
793
|
-
rawHandlerNames.has(CUT_OFF.eventName)) {
|
|
794
|
-
rawHandlerNames.delete(WARNING.eventName);
|
|
795
|
-
rawHandlerNames.delete(CUT_OFF.eventName);
|
|
796
|
-
instance.on(WARNING.eventName, (data) => {
|
|
797
|
-
isHandleRaw && rawHandler[WARNING.eventName]?.(data.data);
|
|
798
|
-
const parsedData = WARNING.parser(data.data, roomId);
|
|
799
|
-
handler[WARNING.handlerName]?.(normalizeDanmu(WARNING.eventName, parsedData, data.data));
|
|
800
|
-
});
|
|
801
|
-
instance.on(CUT_OFF.eventName, (data) => {
|
|
802
|
-
isHandleRaw && rawHandler[CUT_OFF.eventName]?.(data.data);
|
|
803
|
-
const parsedData = CUT_OFF.parser(data.data, roomId);
|
|
804
|
-
handler[CUT_OFF.handlerName]?.(normalizeDanmu(CUT_OFF.eventName, parsedData, data.data));
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
|
-
if (handler[WATCHED_CHANGE.handlerName] || rawHandlerNames.has(WATCHED_CHANGE.eventName)) {
|
|
808
|
-
rawHandlerNames.delete(WATCHED_CHANGE.eventName);
|
|
809
|
-
instance.on(WATCHED_CHANGE.eventName, (data) => {
|
|
810
|
-
isHandleRaw && rawHandler[WATCHED_CHANGE.eventName]?.(data.data);
|
|
811
|
-
const parsedData = WATCHED_CHANGE.parser(data.data);
|
|
812
|
-
handler[WATCHED_CHANGE.handlerName]?.(normalizeDanmu(WATCHED_CHANGE.eventName, parsedData, data.data));
|
|
813
|
-
});
|
|
814
|
-
}
|
|
815
|
-
for (const eventName of rawHandlerNames) {
|
|
816
|
-
instance.on(eventName, (data) => {
|
|
817
|
-
rawHandler[eventName]?.(data.data);
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
export { listenAll };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export var GuardLevel: any;
|
|
2
|
-
export function startListen(roomId: any, handler: any, options: any): {
|
|
3
|
-
live: KeepLiveTCP<object>;
|
|
4
|
-
roomId: number;
|
|
5
|
-
online: number;
|
|
6
|
-
closed: boolean;
|
|
7
|
-
close: () => boolean;
|
|
8
|
-
getAttention: () => Promise<number>;
|
|
9
|
-
getOnline: () => Promise<number>;
|
|
10
|
-
reconnect: () => void;
|
|
11
|
-
heartbeat: () => void;
|
|
12
|
-
send: (op: any, data: any) => void;
|
|
13
|
-
};
|
|
14
|
-
import { KeepLiveTCP } from "tiny-bilibili-ws";
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { listenAll } from "./chunk-5NTNTWA4.js";
|
|
2
|
-
// src/index.ts
|
|
3
|
-
import { KeepLiveTCP } from "tiny-bilibili-ws";
|
|
4
|
-
// src/types/const.ts
|
|
5
|
-
var GuardLevel = /* @__PURE__ */ ((GuardLevel2) => {
|
|
6
|
-
GuardLevel2[GuardLevel2["None"] = 0] = "None";
|
|
7
|
-
GuardLevel2[GuardLevel2["Zongdu"] = 1] = "Zongdu";
|
|
8
|
-
GuardLevel2[GuardLevel2["Tidu"] = 2] = "Tidu";
|
|
9
|
-
GuardLevel2[GuardLevel2["Jianzhang"] = 3] = "Jianzhang";
|
|
10
|
-
return GuardLevel2;
|
|
11
|
-
})(GuardLevel || {});
|
|
12
|
-
// src/index.ts
|
|
13
|
-
var startListen = (roomId, handler, options) => {
|
|
14
|
-
const live = new KeepLiveTCP(roomId, options?.ws);
|
|
15
|
-
listenAll(live, roomId, handler);
|
|
16
|
-
const listenerInstance = {
|
|
17
|
-
live,
|
|
18
|
-
roomId: live.roomId,
|
|
19
|
-
online: live.online,
|
|
20
|
-
closed: live.closed,
|
|
21
|
-
close: () => live.close(),
|
|
22
|
-
getAttention: () => live.getOnline(),
|
|
23
|
-
getOnline: () => live.getOnline(),
|
|
24
|
-
reconnect: () => live.reconnect(),
|
|
25
|
-
heartbeat: () => live.heartbeat(),
|
|
26
|
-
send: (op, data) => live.send(op, data)
|
|
27
|
-
};
|
|
28
|
-
return listenerInstance;
|
|
29
|
-
};
|
|
30
|
-
export { GuardLevel, startListen };
|