@laplace.live/ws 6.3.5 → 6.3.6
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/dist/browser.d.ts +3 -11
- package/dist/browser.js +131 -112
- package/dist/{common-BGRg5uk7.d.ts → common-D1XOmtU3.d.ts} +17 -15
- package/dist/index.d.ts +4 -12
- package/dist/index.js +141 -123
- package/package.json +1 -3
package/dist/browser.d.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import { L as Live, I as Inflates, a as LiveOptions, K as KeepLive } from './common-
|
|
2
|
-
export {
|
|
3
|
-
import { EventEmitter } from 'events';
|
|
1
|
+
import { L as Live, I as Inflates, a as LiveOptions, K as KeepLive } from './common-D1XOmtU3.js';
|
|
2
|
+
export { D as DataEvent, E as EventEvent } from './common-D1XOmtU3.js';
|
|
4
3
|
|
|
5
4
|
type WSOptions = LiveOptions & {
|
|
6
5
|
address?: string;
|
|
7
6
|
};
|
|
8
|
-
declare class WSWrapper extends EventEmitter {
|
|
9
|
-
ws: WebSocket;
|
|
10
|
-
constructor(address: string, inflates: Inflates);
|
|
11
|
-
get readyState(): number;
|
|
12
|
-
send(data: Buffer): void;
|
|
13
|
-
close(code?: number, reason?: string): void;
|
|
14
|
-
}
|
|
15
7
|
declare class LiveWSBase extends Live {
|
|
16
|
-
ws:
|
|
8
|
+
ws: WebSocket;
|
|
17
9
|
constructor(inflates: Inflates, roomid: number, { address, ...options }?: WSOptions);
|
|
18
10
|
}
|
|
19
11
|
|
package/dist/browser.js
CHANGED
|
@@ -1,45 +1,60 @@
|
|
|
1
|
-
// src/common.ts
|
|
2
|
-
import { EventEmitter } from "events";
|
|
3
|
-
|
|
4
1
|
// src/buffer.ts
|
|
2
|
+
var textEncoder = new TextEncoder();
|
|
3
|
+
var textDecoder = new TextDecoder();
|
|
4
|
+
function concatUint8Arrays(arrs) {
|
|
5
|
+
let totalLength = 0;
|
|
6
|
+
for (const arr of arrs) totalLength += arr.length;
|
|
7
|
+
const result = new Uint8Array(totalLength);
|
|
8
|
+
let offset = 0;
|
|
9
|
+
for (const arr of arrs) {
|
|
10
|
+
result.set(arr, offset);
|
|
11
|
+
offset += arr.length;
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
5
15
|
var cutBuffer = (buffer) => {
|
|
6
16
|
const bufferPacks = [];
|
|
17
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
7
18
|
let size;
|
|
8
19
|
for (let i = 0; i < buffer.length; i += size) {
|
|
9
|
-
size =
|
|
20
|
+
size = view.getInt32(i);
|
|
10
21
|
bufferPacks.push(buffer.slice(i, i + size));
|
|
11
22
|
}
|
|
12
23
|
return bufferPacks;
|
|
13
24
|
};
|
|
14
25
|
var makeDecoder = ({ inflateAsync: inflateAsync2, brotliDecompressAsync: brotliDecompressAsync2 }) => {
|
|
15
26
|
const decoder = async (buffer) => {
|
|
16
|
-
const packs = await Promise.all(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type = "
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
data
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
27
|
+
const packs = await Promise.all(
|
|
28
|
+
cutBuffer(buffer).map(async (buf) => {
|
|
29
|
+
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
30
|
+
const body = buf.slice(16);
|
|
31
|
+
const protocol = view.getInt16(6);
|
|
32
|
+
const operation = view.getInt32(8);
|
|
33
|
+
let type = "unknow";
|
|
34
|
+
if (operation === 3) {
|
|
35
|
+
type = "heartbeat";
|
|
36
|
+
} else if (operation === 5) {
|
|
37
|
+
type = "message";
|
|
38
|
+
} else if (operation === 8) {
|
|
39
|
+
type = "welcome";
|
|
40
|
+
}
|
|
41
|
+
let data;
|
|
42
|
+
if (protocol === 0) {
|
|
43
|
+
data = JSON.parse(textDecoder.decode(body));
|
|
44
|
+
}
|
|
45
|
+
if (protocol === 1 && body.length === 4) {
|
|
46
|
+
const bodyView = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
47
|
+
data = bodyView.getUint32(0);
|
|
48
|
+
}
|
|
49
|
+
if (protocol === 2) {
|
|
50
|
+
data = await decoder(await inflateAsync2(body));
|
|
51
|
+
}
|
|
52
|
+
if (protocol === 3) {
|
|
53
|
+
data = await decoder(await brotliDecompressAsync2(body));
|
|
54
|
+
}
|
|
55
|
+
return { buf, type, protocol, data };
|
|
56
|
+
})
|
|
57
|
+
);
|
|
43
58
|
return packs.flatMap((pack) => {
|
|
44
59
|
if (pack.protocol === 2 || pack.protocol === 3) {
|
|
45
60
|
return pack.data;
|
|
@@ -49,42 +64,47 @@ var makeDecoder = ({ inflateAsync: inflateAsync2, brotliDecompressAsync: brotliD
|
|
|
49
64
|
};
|
|
50
65
|
return decoder;
|
|
51
66
|
};
|
|
52
|
-
var encoder = (type,
|
|
53
|
-
const blank = Buffer2.alloc(16);
|
|
67
|
+
var encoder = (type, body = "") => {
|
|
54
68
|
if (typeof body !== "string") {
|
|
55
69
|
body = JSON.stringify(body);
|
|
56
70
|
}
|
|
57
|
-
const head =
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
const head = new Uint8Array(16);
|
|
72
|
+
const headView = new DataView(head.buffer, head.byteOffset, head.byteLength);
|
|
73
|
+
const buffer = textEncoder.encode(body);
|
|
74
|
+
headView.setInt32(0, buffer.length + head.length);
|
|
75
|
+
headView.setInt16(4, 16);
|
|
76
|
+
headView.setInt16(6, 1);
|
|
62
77
|
if (type === "heartbeat") {
|
|
63
|
-
|
|
78
|
+
headView.setInt32(8, 2);
|
|
64
79
|
}
|
|
65
80
|
if (type === "join") {
|
|
66
|
-
|
|
81
|
+
headView.setInt32(8, 7);
|
|
67
82
|
}
|
|
68
|
-
|
|
69
|
-
return
|
|
83
|
+
headView.setInt32(12, 1);
|
|
84
|
+
return concatUint8Arrays([head, buffer]);
|
|
70
85
|
};
|
|
71
86
|
|
|
72
87
|
// src/common.ts
|
|
73
|
-
var
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
super
|
|
77
|
-
|
|
78
|
-
return true;
|
|
88
|
+
var DataEvent = class extends Event {
|
|
89
|
+
data;
|
|
90
|
+
constructor(type, data) {
|
|
91
|
+
super(type);
|
|
92
|
+
this.data = data;
|
|
79
93
|
}
|
|
80
94
|
};
|
|
81
|
-
var
|
|
95
|
+
var EventEvent = class extends Event {
|
|
96
|
+
event;
|
|
97
|
+
constructor(event) {
|
|
98
|
+
super("event");
|
|
99
|
+
this.event = event;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var Live = class extends EventTarget {
|
|
82
103
|
roomid;
|
|
83
104
|
online;
|
|
84
105
|
live;
|
|
85
106
|
closed;
|
|
86
107
|
timeout;
|
|
87
|
-
inflates;
|
|
88
108
|
send;
|
|
89
109
|
close;
|
|
90
110
|
constructor(inflates2, roomid, {
|
|
@@ -100,7 +120,6 @@ var Live = class extends NiceEventEmitter {
|
|
|
100
120
|
throw new Error(`roomid ${roomid} must be Number not NaN`);
|
|
101
121
|
}
|
|
102
122
|
super();
|
|
103
|
-
this.inflates = inflates2;
|
|
104
123
|
this.roomid = roomid;
|
|
105
124
|
this.online = 0;
|
|
106
125
|
this.live = false;
|
|
@@ -112,37 +131,39 @@ var Live = class extends NiceEventEmitter {
|
|
|
112
131
|
this.closed = true;
|
|
113
132
|
close();
|
|
114
133
|
};
|
|
115
|
-
|
|
116
|
-
|
|
134
|
+
const decode = makeDecoder(inflates2);
|
|
135
|
+
this.addEventListener("message", async (e) => {
|
|
136
|
+
const buffer = e.data;
|
|
137
|
+
const packs = await decode(buffer);
|
|
117
138
|
packs.forEach(({ type, data }) => {
|
|
118
139
|
if (type === "welcome") {
|
|
119
140
|
this.live = true;
|
|
120
|
-
this.
|
|
121
|
-
this.send(encoder("heartbeat"
|
|
141
|
+
this.dispatchEvent(new Event("live"));
|
|
142
|
+
this.send(encoder("heartbeat"));
|
|
122
143
|
}
|
|
123
144
|
if (type === "heartbeat") {
|
|
124
145
|
this.online = data;
|
|
125
146
|
clearTimeout(this.timeout);
|
|
126
147
|
this.timeout = setTimeout(() => this.heartbeat(), 1e3 * 30);
|
|
127
|
-
this.
|
|
148
|
+
this.dispatchEvent(new DataEvent("heartbeat", this.online));
|
|
128
149
|
}
|
|
129
150
|
if (type === "message") {
|
|
130
|
-
this.
|
|
131
|
-
const cmd = data.cmd || data.msg
|
|
151
|
+
this.dispatchEvent(new DataEvent("msg", data));
|
|
152
|
+
const cmd = data.cmd || data.msg?.cmd;
|
|
132
153
|
if (cmd) {
|
|
133
154
|
if (cmd.includes("DANMU_MSG")) {
|
|
134
|
-
this.
|
|
155
|
+
this.dispatchEvent(new DataEvent("DANMU_MSG", data));
|
|
135
156
|
} else {
|
|
136
|
-
this.
|
|
157
|
+
this.dispatchEvent(new DataEvent(cmd, data));
|
|
137
158
|
}
|
|
138
159
|
}
|
|
139
160
|
}
|
|
140
161
|
});
|
|
141
162
|
});
|
|
142
|
-
this.
|
|
163
|
+
this.addEventListener("open", () => {
|
|
143
164
|
if (authBody) {
|
|
144
165
|
if (typeof authBody === "object") {
|
|
145
|
-
authBody = encoder("join",
|
|
166
|
+
authBody = encoder("join", authBody);
|
|
146
167
|
}
|
|
147
168
|
this.send(authBody);
|
|
148
169
|
} else {
|
|
@@ -153,27 +174,34 @@ var Live = class extends NiceEventEmitter {
|
|
|
153
174
|
if (buvid) {
|
|
154
175
|
hi.buvid = buvid;
|
|
155
176
|
}
|
|
156
|
-
const buf = encoder("join",
|
|
177
|
+
const buf = encoder("join", hi);
|
|
157
178
|
this.send(buf);
|
|
158
179
|
}
|
|
159
180
|
});
|
|
160
|
-
this.
|
|
181
|
+
this.addEventListener("close", () => {
|
|
161
182
|
clearTimeout(this.timeout);
|
|
162
183
|
});
|
|
163
|
-
this.
|
|
184
|
+
this.addEventListener("_error", () => {
|
|
164
185
|
this.close();
|
|
165
|
-
this.
|
|
186
|
+
this.dispatchEvent(new Event("error"));
|
|
166
187
|
});
|
|
167
188
|
}
|
|
189
|
+
dispatchEvent(event) {
|
|
190
|
+
const result = super.dispatchEvent(event);
|
|
191
|
+
super.dispatchEvent(new EventEvent(event));
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
168
194
|
heartbeat() {
|
|
169
|
-
this.send(encoder("heartbeat"
|
|
195
|
+
this.send(encoder("heartbeat"));
|
|
170
196
|
}
|
|
171
197
|
getOnline() {
|
|
172
198
|
this.heartbeat();
|
|
173
|
-
return new Promise(
|
|
199
|
+
return new Promise(
|
|
200
|
+
(resolve) => this.addEventListener("heartbeat", (e) => resolve(e.data), { once: true })
|
|
201
|
+
);
|
|
174
202
|
}
|
|
175
203
|
};
|
|
176
|
-
var KeepLive = class extends
|
|
204
|
+
var KeepLive = class extends EventTarget {
|
|
177
205
|
params;
|
|
178
206
|
closed;
|
|
179
207
|
interval;
|
|
@@ -190,6 +218,11 @@ var KeepLive = class extends EventEmitter {
|
|
|
190
218
|
this.Base = Base;
|
|
191
219
|
this.connect(false);
|
|
192
220
|
}
|
|
221
|
+
dispatchEvent(event) {
|
|
222
|
+
const result = super.dispatchEvent(event);
|
|
223
|
+
super.dispatchEvent(new EventEvent(event));
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
193
226
|
connect(reconnect = true) {
|
|
194
227
|
if (reconnect) {
|
|
195
228
|
this.connection.close();
|
|
@@ -198,27 +231,32 @@ var KeepLive = class extends EventEmitter {
|
|
|
198
231
|
const connection = this.connection;
|
|
199
232
|
let timeout = setTimeout(() => {
|
|
200
233
|
connection.close();
|
|
201
|
-
connection.
|
|
234
|
+
connection.dispatchEvent(new Event("timeout"));
|
|
202
235
|
}, this.timeout);
|
|
203
|
-
connection.
|
|
204
|
-
|
|
205
|
-
|
|
236
|
+
connection.addEventListener("event", (e) => {
|
|
237
|
+
const evt = e.event;
|
|
238
|
+
if (evt.type !== "error") {
|
|
239
|
+
if (evt instanceof DataEvent) {
|
|
240
|
+
this.dispatchEvent(new DataEvent(evt.type, evt.data));
|
|
241
|
+
} else {
|
|
242
|
+
this.dispatchEvent(new Event(evt.type));
|
|
243
|
+
}
|
|
206
244
|
}
|
|
207
245
|
});
|
|
208
|
-
connection.
|
|
209
|
-
connection.
|
|
246
|
+
connection.addEventListener("error", () => this.dispatchEvent(new Event("e")));
|
|
247
|
+
connection.addEventListener("close", () => {
|
|
210
248
|
if (!this.closed) {
|
|
211
249
|
setTimeout(() => this.connect(), this.interval);
|
|
212
250
|
}
|
|
213
251
|
});
|
|
214
|
-
connection.
|
|
252
|
+
connection.addEventListener("heartbeat", () => {
|
|
215
253
|
clearTimeout(timeout);
|
|
216
254
|
timeout = setTimeout(() => {
|
|
217
255
|
connection.close();
|
|
218
|
-
connection.
|
|
256
|
+
connection.dispatchEvent(new Event("timeout"));
|
|
219
257
|
}, this.timeout);
|
|
220
258
|
});
|
|
221
|
-
connection.
|
|
259
|
+
connection.addEventListener("close", () => {
|
|
222
260
|
clearTimeout(timeout);
|
|
223
261
|
});
|
|
224
262
|
}
|
|
@@ -244,7 +282,6 @@ var KeepLive = class extends EventEmitter {
|
|
|
244
282
|
};
|
|
245
283
|
|
|
246
284
|
// src/inflate/browser.ts
|
|
247
|
-
import { Buffer } from "buffer";
|
|
248
285
|
import { inflate } from "pako";
|
|
249
286
|
|
|
250
287
|
// src/inflate/brotli.ts
|
|
@@ -2029,38 +2066,15 @@ var makeBrotliDecode = () => {
|
|
|
2029
2066
|
var BrotliDecode = makeBrotliDecode();
|
|
2030
2067
|
|
|
2031
2068
|
// src/inflate/browser.ts
|
|
2032
|
-
var inflateAsync = (d) =>
|
|
2033
|
-
var brotliDecompressAsync = (d) =>
|
|
2034
|
-
var inflates = { inflateAsync, brotliDecompressAsync
|
|
2069
|
+
var inflateAsync = (d) => inflate(d);
|
|
2070
|
+
var brotliDecompressAsync = (d) => Uint8Array.from(BrotliDecode(Int8Array.from(d)));
|
|
2071
|
+
var inflates = { inflateAsync, brotliDecompressAsync };
|
|
2035
2072
|
|
|
2036
2073
|
// src/ws-client.ts
|
|
2037
|
-
import { EventEmitter as EventEmitter2 } from "events";
|
|
2038
|
-
var WSWrapper = class extends EventEmitter2 {
|
|
2039
|
-
ws;
|
|
2040
|
-
constructor(address, inflates2) {
|
|
2041
|
-
super();
|
|
2042
|
-
const ws = new WebSocket(address);
|
|
2043
|
-
this.ws = ws;
|
|
2044
|
-
ws.binaryType = "arraybuffer";
|
|
2045
|
-
ws.onopen = () => this.emit("open");
|
|
2046
|
-
ws.onmessage = ({ data }) => this.emit("message", inflates2.Buffer.from(data));
|
|
2047
|
-
ws.onerror = () => this.emit("error");
|
|
2048
|
-
ws.onclose = () => this.emit("close");
|
|
2049
|
-
}
|
|
2050
|
-
get readyState() {
|
|
2051
|
-
return this.ws.readyState;
|
|
2052
|
-
}
|
|
2053
|
-
send(data) {
|
|
2054
|
-
this.ws.send(data);
|
|
2055
|
-
}
|
|
2056
|
-
close(code, reason) {
|
|
2057
|
-
this.ws.close(code, reason);
|
|
2058
|
-
}
|
|
2059
|
-
};
|
|
2060
2074
|
var LiveWSBase = class extends Live {
|
|
2061
2075
|
ws;
|
|
2062
2076
|
constructor(inflates2, roomid, { address = "wss://broadcastlv.chat.bilibili.com/sub", ...options } = {}) {
|
|
2063
|
-
const ws = new
|
|
2077
|
+
const ws = new WebSocket(address);
|
|
2064
2078
|
const send = (data) => {
|
|
2065
2079
|
if (ws.readyState === 1) {
|
|
2066
2080
|
ws.send(data);
|
|
@@ -2068,10 +2082,14 @@ var LiveWSBase = class extends Live {
|
|
|
2068
2082
|
};
|
|
2069
2083
|
const close = () => this.ws.close();
|
|
2070
2084
|
super(inflates2, roomid, { send, close, ...options });
|
|
2071
|
-
ws.
|
|
2072
|
-
ws.
|
|
2073
|
-
ws.
|
|
2074
|
-
|
|
2085
|
+
ws.binaryType = "arraybuffer";
|
|
2086
|
+
ws.addEventListener("open", (e) => this.dispatchEvent(new Event(e.type)));
|
|
2087
|
+
ws.addEventListener(
|
|
2088
|
+
"message",
|
|
2089
|
+
(e) => this.dispatchEvent(new DataEvent("message", new Uint8Array(e.data)))
|
|
2090
|
+
);
|
|
2091
|
+
ws.addEventListener("close", (e) => this.dispatchEvent(new Event(e.type)));
|
|
2092
|
+
ws.addEventListener("error", () => this.dispatchEvent(new Event("_error")));
|
|
2075
2093
|
this.ws = ws;
|
|
2076
2094
|
}
|
|
2077
2095
|
};
|
|
@@ -2088,7 +2106,8 @@ var KeepLiveWS = class extends KeepLive {
|
|
|
2088
2106
|
}
|
|
2089
2107
|
};
|
|
2090
2108
|
export {
|
|
2109
|
+
DataEvent,
|
|
2110
|
+
EventEvent,
|
|
2091
2111
|
KeepLiveWS,
|
|
2092
|
-
LiveWS
|
|
2093
|
-
relayEvent
|
|
2112
|
+
LiveWS
|
|
2094
2113
|
};
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
|
|
3
1
|
type Inflates = {
|
|
4
|
-
inflateAsync: (b:
|
|
5
|
-
brotliDecompressAsync: (b:
|
|
6
|
-
Buffer: typeof Buffer;
|
|
2
|
+
inflateAsync: (b: Uint8Array) => Uint8Array | Promise<Uint8Array>;
|
|
3
|
+
brotliDecompressAsync: (b: Uint8Array) => Uint8Array | Promise<Uint8Array>;
|
|
7
4
|
};
|
|
8
5
|
|
|
9
6
|
type LiveOptions = {
|
|
@@ -13,27 +10,31 @@ type LiveOptions = {
|
|
|
13
10
|
uid?: number;
|
|
14
11
|
buvid?: string;
|
|
15
12
|
};
|
|
16
|
-
declare
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
declare class DataEvent<T> extends Event {
|
|
14
|
+
data: T;
|
|
15
|
+
constructor(type: string, data: T);
|
|
16
|
+
}
|
|
17
|
+
declare class EventEvent extends Event {
|
|
18
|
+
event: Event;
|
|
19
|
+
constructor(event: Event);
|
|
19
20
|
}
|
|
20
|
-
declare class Live extends
|
|
21
|
+
declare class Live extends EventTarget {
|
|
21
22
|
roomid: number;
|
|
22
23
|
online: number;
|
|
23
24
|
live: boolean;
|
|
24
25
|
closed: boolean;
|
|
25
26
|
timeout: ReturnType<typeof setTimeout>;
|
|
26
|
-
|
|
27
|
-
send: (data: Buffer) => void;
|
|
27
|
+
send: (data: Uint8Array) => void;
|
|
28
28
|
close: () => void;
|
|
29
29
|
constructor(inflates: Inflates, roomid: number, { send, close, protover, key, authBody, uid, buvid, }: {
|
|
30
|
-
send: (data:
|
|
30
|
+
send: (data: Uint8Array) => void;
|
|
31
31
|
close: () => void;
|
|
32
32
|
} & LiveOptions);
|
|
33
|
+
dispatchEvent(event: Event): boolean;
|
|
33
34
|
heartbeat(): void;
|
|
34
35
|
getOnline(): Promise<number>;
|
|
35
36
|
}
|
|
36
|
-
declare class KeepLive<Base extends typeof Live> extends
|
|
37
|
+
declare class KeepLive<Base extends typeof Live> extends EventTarget {
|
|
37
38
|
params: ConstructorParameters<Base>;
|
|
38
39
|
closed: boolean;
|
|
39
40
|
interval: number;
|
|
@@ -41,13 +42,14 @@ declare class KeepLive<Base extends typeof Live> extends EventEmitter {
|
|
|
41
42
|
connection: InstanceType<Base>;
|
|
42
43
|
Base: Base;
|
|
43
44
|
constructor(Base: Base, ...params: ConstructorParameters<Base>);
|
|
45
|
+
dispatchEvent(event: Event): boolean;
|
|
44
46
|
connect(reconnect?: boolean): void;
|
|
45
47
|
get online(): number;
|
|
46
48
|
get roomid(): number;
|
|
47
49
|
close(): void;
|
|
48
50
|
heartbeat(): void;
|
|
49
51
|
getOnline(): Promise<number>;
|
|
50
|
-
send(data:
|
|
52
|
+
send(data: Uint8Array): void;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
export { type Inflates as I, KeepLive as K, Live as L, type LiveOptions as a
|
|
55
|
+
export { DataEvent as D, EventEvent as E, type Inflates as I, KeepLive as K, Live as L, type LiveOptions as a };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { L as Live, I as Inflates, a as LiveOptions, K as KeepLive } from './common-
|
|
2
|
-
export {
|
|
1
|
+
import { L as Live, I as Inflates, a as LiveOptions, K as KeepLive } from './common-D1XOmtU3.js';
|
|
2
|
+
export { D as DataEvent, E as EventEvent } from './common-D1XOmtU3.js';
|
|
3
3
|
import { Socket } from 'node:net';
|
|
4
4
|
import { Agent } from 'node:http';
|
|
5
|
-
import { EventEmitter } from 'events';
|
|
6
5
|
import WS from 'ws';
|
|
7
6
|
|
|
8
7
|
type TCPOptions = LiveOptions & {
|
|
@@ -11,7 +10,7 @@ type TCPOptions = LiveOptions & {
|
|
|
11
10
|
};
|
|
12
11
|
declare class LiveTCPBase extends Live {
|
|
13
12
|
socket: Socket;
|
|
14
|
-
|
|
13
|
+
buf: Buffer;
|
|
15
14
|
i: number;
|
|
16
15
|
constructor(inflates: Inflates, roomid: number, { host, port, ...options }?: TCPOptions);
|
|
17
16
|
splitBuffer(): void;
|
|
@@ -21,15 +20,8 @@ type WSOptions = LiveOptions & {
|
|
|
21
20
|
address?: string;
|
|
22
21
|
agent?: Agent;
|
|
23
22
|
};
|
|
24
|
-
declare class WSWrapper extends EventEmitter {
|
|
25
|
-
ws: WS;
|
|
26
|
-
constructor(address: string, ...args: any[]);
|
|
27
|
-
get readyState(): 0 | 1 | 3 | 2;
|
|
28
|
-
send(data: Buffer): void;
|
|
29
|
-
close(code?: number, data?: string): void;
|
|
30
|
-
}
|
|
31
23
|
declare class LiveWSBase extends Live {
|
|
32
|
-
ws:
|
|
24
|
+
ws: WS;
|
|
33
25
|
constructor(inflates: Inflates, roomid: number, { address, agent, ...options }?: WSOptions);
|
|
34
26
|
}
|
|
35
27
|
|
package/dist/index.js
CHANGED
|
@@ -1,45 +1,60 @@
|
|
|
1
|
-
// src/common.ts
|
|
2
|
-
import { EventEmitter } from "events";
|
|
3
|
-
|
|
4
1
|
// src/buffer.ts
|
|
2
|
+
var textEncoder = new TextEncoder();
|
|
3
|
+
var textDecoder = new TextDecoder();
|
|
4
|
+
function concatUint8Arrays(arrs) {
|
|
5
|
+
let totalLength = 0;
|
|
6
|
+
for (const arr of arrs) totalLength += arr.length;
|
|
7
|
+
const result = new Uint8Array(totalLength);
|
|
8
|
+
let offset = 0;
|
|
9
|
+
for (const arr of arrs) {
|
|
10
|
+
result.set(arr, offset);
|
|
11
|
+
offset += arr.length;
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
5
15
|
var cutBuffer = (buffer) => {
|
|
6
16
|
const bufferPacks = [];
|
|
17
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
7
18
|
let size;
|
|
8
19
|
for (let i = 0; i < buffer.length; i += size) {
|
|
9
|
-
size =
|
|
20
|
+
size = view.getInt32(i);
|
|
10
21
|
bufferPacks.push(buffer.slice(i, i + size));
|
|
11
22
|
}
|
|
12
23
|
return bufferPacks;
|
|
13
24
|
};
|
|
14
25
|
var makeDecoder = ({ inflateAsync: inflateAsync2, brotliDecompressAsync: brotliDecompressAsync2 }) => {
|
|
15
26
|
const decoder = async (buffer) => {
|
|
16
|
-
const packs = await Promise.all(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type = "
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
data
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
27
|
+
const packs = await Promise.all(
|
|
28
|
+
cutBuffer(buffer).map(async (buf) => {
|
|
29
|
+
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
30
|
+
const body = buf.slice(16);
|
|
31
|
+
const protocol = view.getInt16(6);
|
|
32
|
+
const operation = view.getInt32(8);
|
|
33
|
+
let type = "unknow";
|
|
34
|
+
if (operation === 3) {
|
|
35
|
+
type = "heartbeat";
|
|
36
|
+
} else if (operation === 5) {
|
|
37
|
+
type = "message";
|
|
38
|
+
} else if (operation === 8) {
|
|
39
|
+
type = "welcome";
|
|
40
|
+
}
|
|
41
|
+
let data;
|
|
42
|
+
if (protocol === 0) {
|
|
43
|
+
data = JSON.parse(textDecoder.decode(body));
|
|
44
|
+
}
|
|
45
|
+
if (protocol === 1 && body.length === 4) {
|
|
46
|
+
const bodyView = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
47
|
+
data = bodyView.getUint32(0);
|
|
48
|
+
}
|
|
49
|
+
if (protocol === 2) {
|
|
50
|
+
data = await decoder(await inflateAsync2(body));
|
|
51
|
+
}
|
|
52
|
+
if (protocol === 3) {
|
|
53
|
+
data = await decoder(await brotliDecompressAsync2(body));
|
|
54
|
+
}
|
|
55
|
+
return { buf, type, protocol, data };
|
|
56
|
+
})
|
|
57
|
+
);
|
|
43
58
|
return packs.flatMap((pack) => {
|
|
44
59
|
if (pack.protocol === 2 || pack.protocol === 3) {
|
|
45
60
|
return pack.data;
|
|
@@ -49,42 +64,47 @@ var makeDecoder = ({ inflateAsync: inflateAsync2, brotliDecompressAsync: brotliD
|
|
|
49
64
|
};
|
|
50
65
|
return decoder;
|
|
51
66
|
};
|
|
52
|
-
var encoder = (type,
|
|
53
|
-
const blank = Buffer3.alloc(16);
|
|
67
|
+
var encoder = (type, body = "") => {
|
|
54
68
|
if (typeof body !== "string") {
|
|
55
69
|
body = JSON.stringify(body);
|
|
56
70
|
}
|
|
57
|
-
const head =
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
const head = new Uint8Array(16);
|
|
72
|
+
const headView = new DataView(head.buffer, head.byteOffset, head.byteLength);
|
|
73
|
+
const buffer = textEncoder.encode(body);
|
|
74
|
+
headView.setInt32(0, buffer.length + head.length);
|
|
75
|
+
headView.setInt16(4, 16);
|
|
76
|
+
headView.setInt16(6, 1);
|
|
62
77
|
if (type === "heartbeat") {
|
|
63
|
-
|
|
78
|
+
headView.setInt32(8, 2);
|
|
64
79
|
}
|
|
65
80
|
if (type === "join") {
|
|
66
|
-
|
|
81
|
+
headView.setInt32(8, 7);
|
|
67
82
|
}
|
|
68
|
-
|
|
69
|
-
return
|
|
83
|
+
headView.setInt32(12, 1);
|
|
84
|
+
return concatUint8Arrays([head, buffer]);
|
|
70
85
|
};
|
|
71
86
|
|
|
72
87
|
// src/common.ts
|
|
73
|
-
var
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
super
|
|
77
|
-
|
|
78
|
-
return true;
|
|
88
|
+
var DataEvent = class extends Event {
|
|
89
|
+
data;
|
|
90
|
+
constructor(type, data) {
|
|
91
|
+
super(type);
|
|
92
|
+
this.data = data;
|
|
79
93
|
}
|
|
80
94
|
};
|
|
81
|
-
var
|
|
95
|
+
var EventEvent = class extends Event {
|
|
96
|
+
event;
|
|
97
|
+
constructor(event) {
|
|
98
|
+
super("event");
|
|
99
|
+
this.event = event;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var Live = class extends EventTarget {
|
|
82
103
|
roomid;
|
|
83
104
|
online;
|
|
84
105
|
live;
|
|
85
106
|
closed;
|
|
86
107
|
timeout;
|
|
87
|
-
inflates;
|
|
88
108
|
send;
|
|
89
109
|
close;
|
|
90
110
|
constructor(inflates2, roomid, {
|
|
@@ -100,7 +120,6 @@ var Live = class extends NiceEventEmitter {
|
|
|
100
120
|
throw new Error(`roomid ${roomid} must be Number not NaN`);
|
|
101
121
|
}
|
|
102
122
|
super();
|
|
103
|
-
this.inflates = inflates2;
|
|
104
123
|
this.roomid = roomid;
|
|
105
124
|
this.online = 0;
|
|
106
125
|
this.live = false;
|
|
@@ -112,37 +131,39 @@ var Live = class extends NiceEventEmitter {
|
|
|
112
131
|
this.closed = true;
|
|
113
132
|
close();
|
|
114
133
|
};
|
|
115
|
-
|
|
116
|
-
|
|
134
|
+
const decode = makeDecoder(inflates2);
|
|
135
|
+
this.addEventListener("message", async (e) => {
|
|
136
|
+
const buffer = e.data;
|
|
137
|
+
const packs = await decode(buffer);
|
|
117
138
|
packs.forEach(({ type, data }) => {
|
|
118
139
|
if (type === "welcome") {
|
|
119
140
|
this.live = true;
|
|
120
|
-
this.
|
|
121
|
-
this.send(encoder("heartbeat"
|
|
141
|
+
this.dispatchEvent(new Event("live"));
|
|
142
|
+
this.send(encoder("heartbeat"));
|
|
122
143
|
}
|
|
123
144
|
if (type === "heartbeat") {
|
|
124
145
|
this.online = data;
|
|
125
146
|
clearTimeout(this.timeout);
|
|
126
147
|
this.timeout = setTimeout(() => this.heartbeat(), 1e3 * 30);
|
|
127
|
-
this.
|
|
148
|
+
this.dispatchEvent(new DataEvent("heartbeat", this.online));
|
|
128
149
|
}
|
|
129
150
|
if (type === "message") {
|
|
130
|
-
this.
|
|
131
|
-
const cmd = data.cmd || data.msg
|
|
151
|
+
this.dispatchEvent(new DataEvent("msg", data));
|
|
152
|
+
const cmd = data.cmd || data.msg?.cmd;
|
|
132
153
|
if (cmd) {
|
|
133
154
|
if (cmd.includes("DANMU_MSG")) {
|
|
134
|
-
this.
|
|
155
|
+
this.dispatchEvent(new DataEvent("DANMU_MSG", data));
|
|
135
156
|
} else {
|
|
136
|
-
this.
|
|
157
|
+
this.dispatchEvent(new DataEvent(cmd, data));
|
|
137
158
|
}
|
|
138
159
|
}
|
|
139
160
|
}
|
|
140
161
|
});
|
|
141
162
|
});
|
|
142
|
-
this.
|
|
163
|
+
this.addEventListener("open", () => {
|
|
143
164
|
if (authBody) {
|
|
144
165
|
if (typeof authBody === "object") {
|
|
145
|
-
authBody = encoder("join",
|
|
166
|
+
authBody = encoder("join", authBody);
|
|
146
167
|
}
|
|
147
168
|
this.send(authBody);
|
|
148
169
|
} else {
|
|
@@ -153,27 +174,34 @@ var Live = class extends NiceEventEmitter {
|
|
|
153
174
|
if (buvid) {
|
|
154
175
|
hi.buvid = buvid;
|
|
155
176
|
}
|
|
156
|
-
const buf = encoder("join",
|
|
177
|
+
const buf = encoder("join", hi);
|
|
157
178
|
this.send(buf);
|
|
158
179
|
}
|
|
159
180
|
});
|
|
160
|
-
this.
|
|
181
|
+
this.addEventListener("close", () => {
|
|
161
182
|
clearTimeout(this.timeout);
|
|
162
183
|
});
|
|
163
|
-
this.
|
|
184
|
+
this.addEventListener("_error", () => {
|
|
164
185
|
this.close();
|
|
165
|
-
this.
|
|
186
|
+
this.dispatchEvent(new Event("error"));
|
|
166
187
|
});
|
|
167
188
|
}
|
|
189
|
+
dispatchEvent(event) {
|
|
190
|
+
const result = super.dispatchEvent(event);
|
|
191
|
+
super.dispatchEvent(new EventEvent(event));
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
168
194
|
heartbeat() {
|
|
169
|
-
this.send(encoder("heartbeat"
|
|
195
|
+
this.send(encoder("heartbeat"));
|
|
170
196
|
}
|
|
171
197
|
getOnline() {
|
|
172
198
|
this.heartbeat();
|
|
173
|
-
return new Promise(
|
|
199
|
+
return new Promise(
|
|
200
|
+
(resolve) => this.addEventListener("heartbeat", (e) => resolve(e.data), { once: true })
|
|
201
|
+
);
|
|
174
202
|
}
|
|
175
203
|
};
|
|
176
|
-
var KeepLive = class extends
|
|
204
|
+
var KeepLive = class extends EventTarget {
|
|
177
205
|
params;
|
|
178
206
|
closed;
|
|
179
207
|
interval;
|
|
@@ -190,6 +218,11 @@ var KeepLive = class extends EventEmitter {
|
|
|
190
218
|
this.Base = Base;
|
|
191
219
|
this.connect(false);
|
|
192
220
|
}
|
|
221
|
+
dispatchEvent(event) {
|
|
222
|
+
const result = super.dispatchEvent(event);
|
|
223
|
+
super.dispatchEvent(new EventEvent(event));
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
193
226
|
connect(reconnect = true) {
|
|
194
227
|
if (reconnect) {
|
|
195
228
|
this.connection.close();
|
|
@@ -198,27 +231,32 @@ var KeepLive = class extends EventEmitter {
|
|
|
198
231
|
const connection = this.connection;
|
|
199
232
|
let timeout = setTimeout(() => {
|
|
200
233
|
connection.close();
|
|
201
|
-
connection.
|
|
234
|
+
connection.dispatchEvent(new Event("timeout"));
|
|
202
235
|
}, this.timeout);
|
|
203
|
-
connection.
|
|
204
|
-
|
|
205
|
-
|
|
236
|
+
connection.addEventListener("event", (e) => {
|
|
237
|
+
const evt = e.event;
|
|
238
|
+
if (evt.type !== "error") {
|
|
239
|
+
if (evt instanceof DataEvent) {
|
|
240
|
+
this.dispatchEvent(new DataEvent(evt.type, evt.data));
|
|
241
|
+
} else {
|
|
242
|
+
this.dispatchEvent(new Event(evt.type));
|
|
243
|
+
}
|
|
206
244
|
}
|
|
207
245
|
});
|
|
208
|
-
connection.
|
|
209
|
-
connection.
|
|
246
|
+
connection.addEventListener("error", () => this.dispatchEvent(new Event("e")));
|
|
247
|
+
connection.addEventListener("close", () => {
|
|
210
248
|
if (!this.closed) {
|
|
211
249
|
setTimeout(() => this.connect(), this.interval);
|
|
212
250
|
}
|
|
213
251
|
});
|
|
214
|
-
connection.
|
|
252
|
+
connection.addEventListener("heartbeat", () => {
|
|
215
253
|
clearTimeout(timeout);
|
|
216
254
|
timeout = setTimeout(() => {
|
|
217
255
|
connection.close();
|
|
218
|
-
connection.
|
|
256
|
+
connection.dispatchEvent(new Event("timeout"));
|
|
219
257
|
}, this.timeout);
|
|
220
258
|
});
|
|
221
|
-
connection.
|
|
259
|
+
connection.addEventListener("close", () => {
|
|
222
260
|
clearTimeout(timeout);
|
|
223
261
|
});
|
|
224
262
|
}
|
|
@@ -246,16 +284,17 @@ var KeepLive = class extends EventEmitter {
|
|
|
246
284
|
// src/inflate/node.ts
|
|
247
285
|
import { promisify } from "util";
|
|
248
286
|
import { brotliDecompress, inflate } from "zlib";
|
|
249
|
-
|
|
250
|
-
var
|
|
251
|
-
var
|
|
252
|
-
var
|
|
287
|
+
var _inflate = promisify(inflate);
|
|
288
|
+
var _brotli = promisify(brotliDecompress);
|
|
289
|
+
var inflateAsync = (b) => _inflate(b);
|
|
290
|
+
var brotliDecompressAsync = (b) => _brotli(b);
|
|
291
|
+
var inflates = { inflateAsync, brotliDecompressAsync };
|
|
253
292
|
|
|
254
293
|
// src/tcp.ts
|
|
255
294
|
import net from "net";
|
|
256
295
|
var LiveTCPBase = class extends Live {
|
|
257
296
|
socket;
|
|
258
|
-
|
|
297
|
+
buf;
|
|
259
298
|
i;
|
|
260
299
|
constructor(inflates2, roomid, { host = "broadcastlv.chat.bilibili.com", port = 2243, ...options } = {}) {
|
|
261
300
|
const socket = net.connect(port, host);
|
|
@@ -265,59 +304,37 @@ var LiveTCPBase = class extends Live {
|
|
|
265
304
|
const close = () => this.socket.end();
|
|
266
305
|
super(inflates2, roomid, { send, close, ...options });
|
|
267
306
|
this.i = 0;
|
|
268
|
-
this.
|
|
269
|
-
socket.on("ready", () => this.
|
|
270
|
-
socket.on("close", () => this.
|
|
271
|
-
socket.on("error", (
|
|
307
|
+
this.buf = Buffer.alloc(0);
|
|
308
|
+
socket.on("ready", () => this.dispatchEvent(new Event("open")));
|
|
309
|
+
socket.on("close", () => this.dispatchEvent(new Event("close")));
|
|
310
|
+
socket.on("error", () => this.dispatchEvent(new Event("_error")));
|
|
272
311
|
socket.on("data", (buffer) => {
|
|
273
|
-
this.
|
|
312
|
+
this.buf = Buffer.concat([this.buf, buffer]);
|
|
274
313
|
this.splitBuffer();
|
|
275
314
|
});
|
|
276
315
|
this.socket = socket;
|
|
277
316
|
}
|
|
278
317
|
splitBuffer() {
|
|
279
|
-
while (this.
|
|
280
|
-
const size = this.
|
|
281
|
-
const pack = this.
|
|
282
|
-
this.
|
|
318
|
+
while (this.buf.length >= 4 && this.buf.readInt32BE(0) <= this.buf.length) {
|
|
319
|
+
const size = this.buf.readInt32BE(0);
|
|
320
|
+
const pack = this.buf.slice(0, size);
|
|
321
|
+
this.buf = this.buf.slice(size);
|
|
283
322
|
this.i++;
|
|
284
323
|
if (this.i > 5) {
|
|
285
324
|
this.i = 0;
|
|
286
|
-
this.
|
|
325
|
+
this.buf = Buffer.from(this.buf);
|
|
287
326
|
}
|
|
288
|
-
this.
|
|
327
|
+
this.dispatchEvent(new DataEvent("message", pack));
|
|
289
328
|
}
|
|
290
329
|
}
|
|
291
330
|
};
|
|
292
331
|
|
|
293
332
|
// src/ws-node.ts
|
|
294
|
-
import { EventEmitter as EventEmitter2 } from "events";
|
|
295
333
|
import WS from "ws";
|
|
296
|
-
var WSWrapper = class extends EventEmitter2 {
|
|
297
|
-
ws;
|
|
298
|
-
constructor(address, ...args) {
|
|
299
|
-
super();
|
|
300
|
-
const ws = new WS(address, ...args);
|
|
301
|
-
this.ws = ws;
|
|
302
|
-
ws.onopen = () => this.emit("open");
|
|
303
|
-
ws.onmessage = ({ data }) => this.emit("message", data);
|
|
304
|
-
ws.onerror = () => this.emit("error");
|
|
305
|
-
ws.onclose = () => this.emit("close");
|
|
306
|
-
}
|
|
307
|
-
get readyState() {
|
|
308
|
-
return this.ws.readyState;
|
|
309
|
-
}
|
|
310
|
-
send(data) {
|
|
311
|
-
this.ws.send(data);
|
|
312
|
-
}
|
|
313
|
-
close(code, data) {
|
|
314
|
-
this.ws.close(code, data);
|
|
315
|
-
}
|
|
316
|
-
};
|
|
317
334
|
var LiveWSBase = class extends Live {
|
|
318
335
|
ws;
|
|
319
336
|
constructor(inflates2, roomid, { address = "wss://broadcastlv.chat.bilibili.com/sub", agent, ...options } = {}) {
|
|
320
|
-
const ws = new
|
|
337
|
+
const ws = new WS(address, { agent });
|
|
321
338
|
const send = (data) => {
|
|
322
339
|
if (ws.readyState === 1) {
|
|
323
340
|
ws.send(data);
|
|
@@ -325,10 +342,10 @@ var LiveWSBase = class extends Live {
|
|
|
325
342
|
};
|
|
326
343
|
const close = () => this.ws.close();
|
|
327
344
|
super(inflates2, roomid, { send, close, ...options });
|
|
328
|
-
ws.on("open", (
|
|
329
|
-
ws.on("message", (data) => this.
|
|
330
|
-
ws.on("close", (
|
|
331
|
-
ws.on("error", (
|
|
345
|
+
ws.on("open", () => this.dispatchEvent(new Event("open")));
|
|
346
|
+
ws.on("message", (data) => this.dispatchEvent(new DataEvent("message", data)));
|
|
347
|
+
ws.on("close", () => this.dispatchEvent(new Event("close")));
|
|
348
|
+
ws.on("error", () => this.dispatchEvent(new Event("_error")));
|
|
332
349
|
this.ws = ws;
|
|
333
350
|
}
|
|
334
351
|
};
|
|
@@ -367,11 +384,12 @@ var KeepLiveTCP = class extends KeepLive {
|
|
|
367
384
|
}
|
|
368
385
|
};
|
|
369
386
|
export {
|
|
387
|
+
DataEvent,
|
|
388
|
+
EventEvent,
|
|
370
389
|
KeepLiveTCP,
|
|
371
390
|
KeepLiveWS,
|
|
372
391
|
LiveTCP,
|
|
373
392
|
LiveWS,
|
|
374
393
|
getConf,
|
|
375
|
-
getRoomid
|
|
376
|
-
relayEvent
|
|
394
|
+
getRoomid
|
|
377
395
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@laplace.live/ws",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.6",
|
|
4
4
|
"description": "Bilibili Live WebSocket/TCP API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,8 +60,6 @@
|
|
|
60
60
|
"provenance": true
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"buffer": "^6.0.3",
|
|
64
|
-
"events": "^3.3.0",
|
|
65
63
|
"pako": "^2.1.0",
|
|
66
64
|
"ws": "^8.19.0"
|
|
67
65
|
},
|