@laplace.live/ws 6.3.5 → 6.3.7

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/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 = buffer.readInt32BE(i);
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(cutBuffer(buffer).map(async (buf) => {
17
- const body = buf.slice(16);
18
- const protocol = buf.readInt16BE(6);
19
- const operation = buf.readInt32BE(8);
20
- let type = "unknow";
21
- if (operation === 3) {
22
- type = "heartbeat";
23
- } else if (operation === 5) {
24
- type = "message";
25
- } else if (operation === 8) {
26
- type = "welcome";
27
- }
28
- let data;
29
- if (protocol === 0) {
30
- data = JSON.parse(String(body));
31
- }
32
- if (protocol === 1 && body.length === 4) {
33
- data = body.readUIntBE(0, 4);
34
- }
35
- if (protocol === 2) {
36
- data = await decoder(await inflateAsync2(body));
37
- }
38
- if (protocol === 3) {
39
- data = await decoder(await brotliDecompressAsync2(body));
40
- }
41
- return { buf, type, protocol, data };
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, { Buffer: Buffer3 }, body = "") => {
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 = Buffer3.from(blank);
58
- const buffer = Buffer3.from(body);
59
- head.writeInt32BE(buffer.length + head.length, 0);
60
- head.writeInt16BE(16, 4);
61
- head.writeInt16BE(1, 6);
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
- head.writeInt32BE(2, 8);
78
+ headView.setInt32(8, 2);
64
79
  }
65
80
  if (type === "join") {
66
- head.writeInt32BE(7, 8);
81
+ headView.setInt32(8, 7);
67
82
  }
68
- head.writeInt32BE(1, 12);
69
- return Buffer3.concat([head, buffer]);
83
+ headView.setInt32(12, 1);
84
+ return concatUint8Arrays([head, buffer]);
70
85
  };
71
86
 
72
87
  // src/common.ts
73
- var relayEvent = /* @__PURE__ */ Symbol("relay");
74
- var NiceEventEmitter = class extends EventEmitter {
75
- emit(eventName, ...params) {
76
- super.emit(eventName, ...params);
77
- super.emit(relayEvent, eventName, ...params);
78
- return true;
88
+ var DataEvent = class extends Event {
89
+ data;
90
+ constructor(type, data) {
91
+ super(type);
92
+ this.data = data;
93
+ }
94
+ };
95
+ var EventEvent = class extends Event {
96
+ event;
97
+ constructor(event) {
98
+ super("event");
99
+ this.event = event;
79
100
  }
80
101
  };
81
- var Live = class extends NiceEventEmitter {
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
- this.on("message", async (buffer) => {
116
- const packs = await makeDecoder(inflates2)(buffer);
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.emit("live");
121
- this.send(encoder("heartbeat", inflates2));
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.emit("heartbeat", this.online);
148
+ this.dispatchEvent(new DataEvent("heartbeat", this.online));
128
149
  }
129
150
  if (type === "message") {
130
- this.emit("msg", data);
131
- const cmd = data.cmd || data.msg && data.msg.cmd;
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.emit("DANMU_MSG", data);
155
+ this.dispatchEvent(new DataEvent("DANMU_MSG", data));
135
156
  } else {
136
- this.emit(cmd, data);
157
+ this.dispatchEvent(new DataEvent(cmd, data));
137
158
  }
138
159
  }
139
160
  }
140
161
  });
141
162
  });
142
- this.on("open", () => {
163
+ this.addEventListener("open", () => {
143
164
  if (authBody) {
144
165
  if (typeof authBody === "object") {
145
- authBody = encoder("join", inflates2, authBody);
166
+ authBody = encoder("join", authBody);
146
167
  }
147
168
  this.send(authBody);
148
169
  } else {
@@ -153,27 +174,40 @@ var Live = class extends NiceEventEmitter {
153
174
  if (buvid) {
154
175
  hi.buvid = buvid;
155
176
  }
156
- const buf = encoder("join", inflates2, hi);
177
+ const buf = encoder("join", hi);
157
178
  this.send(buf);
158
179
  }
159
180
  });
160
- this.on("close", () => {
181
+ this.addEventListener("close", () => {
161
182
  clearTimeout(this.timeout);
162
183
  });
163
- this.on("_error", (error) => {
184
+ this.addEventListener("_error", () => {
164
185
  this.close();
165
- this.emit("error", error);
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", this.inflates));
195
+ this.send(encoder("heartbeat"));
170
196
  }
171
197
  getOnline() {
172
198
  this.heartbeat();
173
- return new Promise((resolve) => this.once("heartbeat", resolve));
199
+ return new Promise(
200
+ (resolve) => this.addEventListener("heartbeat", (e) => resolve(e.data), { once: true })
201
+ );
202
+ }
203
+ on(type, listener, options) {
204
+ this.addEventListener(type, listener, options);
205
+ }
206
+ off(type, listener, options) {
207
+ this.removeEventListener(type, listener, options);
174
208
  }
175
209
  };
176
- var KeepLive = class extends EventEmitter {
210
+ var KeepLive = class extends EventTarget {
177
211
  params;
178
212
  closed;
179
213
  interval;
@@ -190,6 +224,11 @@ var KeepLive = class extends EventEmitter {
190
224
  this.Base = Base;
191
225
  this.connect(false);
192
226
  }
227
+ dispatchEvent(event) {
228
+ const result = super.dispatchEvent(event);
229
+ super.dispatchEvent(new EventEvent(event));
230
+ return result;
231
+ }
193
232
  connect(reconnect = true) {
194
233
  if (reconnect) {
195
234
  this.connection.close();
@@ -198,27 +237,32 @@ var KeepLive = class extends EventEmitter {
198
237
  const connection = this.connection;
199
238
  let timeout = setTimeout(() => {
200
239
  connection.close();
201
- connection.emit("timeout");
240
+ connection.dispatchEvent(new Event("timeout"));
202
241
  }, this.timeout);
203
- connection.on(relayEvent, (eventName, ...params) => {
204
- if (eventName !== "error") {
205
- this.emit(eventName, ...params);
242
+ connection.addEventListener("event", (e) => {
243
+ const evt = e.event;
244
+ if (evt.type !== "error") {
245
+ if (evt instanceof DataEvent) {
246
+ this.dispatchEvent(new DataEvent(evt.type, evt.data));
247
+ } else {
248
+ this.dispatchEvent(new Event(evt.type));
249
+ }
206
250
  }
207
251
  });
208
- connection.on("error", (e) => this.emit("e", e));
209
- connection.on("close", () => {
252
+ connection.addEventListener("error", () => this.dispatchEvent(new Event("e")));
253
+ connection.addEventListener("close", () => {
210
254
  if (!this.closed) {
211
255
  setTimeout(() => this.connect(), this.interval);
212
256
  }
213
257
  });
214
- connection.on("heartbeat", () => {
258
+ connection.addEventListener("heartbeat", () => {
215
259
  clearTimeout(timeout);
216
260
  timeout = setTimeout(() => {
217
261
  connection.close();
218
- connection.emit("timeout");
262
+ connection.dispatchEvent(new Event("timeout"));
219
263
  }, this.timeout);
220
264
  });
221
- connection.on("close", () => {
265
+ connection.addEventListener("close", () => {
222
266
  clearTimeout(timeout);
223
267
  });
224
268
  }
@@ -241,21 +285,28 @@ var KeepLive = class extends EventEmitter {
241
285
  send(data) {
242
286
  return this.connection.send(data);
243
287
  }
288
+ on(type, listener, options) {
289
+ this.addEventListener(type, listener, options);
290
+ }
291
+ off(type, listener, options) {
292
+ this.removeEventListener(type, listener, options);
293
+ }
244
294
  };
245
295
 
246
296
  // src/inflate/node.ts
247
297
  import { promisify } from "util";
248
298
  import { brotliDecompress, inflate } from "zlib";
249
- import { Buffer as Buffer2 } from "buffer";
250
- var inflateAsync = promisify(inflate);
251
- var brotliDecompressAsync = promisify(brotliDecompress);
252
- var inflates = { inflateAsync, brotliDecompressAsync, Buffer: Buffer2 };
299
+ var _inflate = promisify(inflate);
300
+ var _brotli = promisify(brotliDecompress);
301
+ var inflateAsync = (b) => _inflate(b);
302
+ var brotliDecompressAsync = (b) => _brotli(b);
303
+ var inflates = { inflateAsync, brotliDecompressAsync };
253
304
 
254
305
  // src/tcp.ts
255
306
  import net from "net";
256
307
  var LiveTCPBase = class extends Live {
257
308
  socket;
258
- buffer;
309
+ buf;
259
310
  i;
260
311
  constructor(inflates2, roomid, { host = "broadcastlv.chat.bilibili.com", port = 2243, ...options } = {}) {
261
312
  const socket = net.connect(port, host);
@@ -265,59 +316,37 @@ var LiveTCPBase = class extends Live {
265
316
  const close = () => this.socket.end();
266
317
  super(inflates2, roomid, { send, close, ...options });
267
318
  this.i = 0;
268
- this.buffer = Buffer.alloc(0);
269
- socket.on("ready", () => this.emit("open"));
270
- socket.on("close", () => this.emit("close"));
271
- socket.on("error", (...params) => this.emit("_error", ...params));
319
+ this.buf = Buffer.alloc(0);
320
+ socket.on("ready", () => this.dispatchEvent(new Event("open")));
321
+ socket.on("close", () => this.dispatchEvent(new Event("close")));
322
+ socket.on("error", () => this.dispatchEvent(new Event("_error")));
272
323
  socket.on("data", (buffer) => {
273
- this.buffer = Buffer.concat([this.buffer, buffer]);
324
+ this.buf = Buffer.concat([this.buf, buffer]);
274
325
  this.splitBuffer();
275
326
  });
276
327
  this.socket = socket;
277
328
  }
278
329
  splitBuffer() {
279
- while (this.buffer.length >= 4 && this.buffer.readInt32BE(0) <= this.buffer.length) {
280
- const size = this.buffer.readInt32BE(0);
281
- const pack = this.buffer.slice(0, size);
282
- this.buffer = this.buffer.slice(size);
330
+ while (this.buf.length >= 4 && this.buf.readInt32BE(0) <= this.buf.length) {
331
+ const size = this.buf.readInt32BE(0);
332
+ const pack = this.buf.slice(0, size);
333
+ this.buf = this.buf.slice(size);
283
334
  this.i++;
284
335
  if (this.i > 5) {
285
336
  this.i = 0;
286
- this.buffer = Buffer.from(this.buffer);
337
+ this.buf = Buffer.from(this.buf);
287
338
  }
288
- this.emit("message", pack);
339
+ this.dispatchEvent(new DataEvent("message", pack));
289
340
  }
290
341
  }
291
342
  };
292
343
 
293
344
  // src/ws-node.ts
294
- import { EventEmitter as EventEmitter2 } from "events";
295
345
  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
346
  var LiveWSBase = class extends Live {
318
347
  ws;
319
348
  constructor(inflates2, roomid, { address = "wss://broadcastlv.chat.bilibili.com/sub", agent, ...options } = {}) {
320
- const ws = new WSWrapper(address, { agent });
349
+ const ws = new WS(address, { agent });
321
350
  const send = (data) => {
322
351
  if (ws.readyState === 1) {
323
352
  ws.send(data);
@@ -325,10 +354,10 @@ var LiveWSBase = class extends Live {
325
354
  };
326
355
  const close = () => this.ws.close();
327
356
  super(inflates2, roomid, { send, close, ...options });
328
- ws.on("open", (...params) => this.emit("open", ...params));
329
- ws.on("message", (data) => this.emit("message", data));
330
- ws.on("close", (code, reason) => this.emit("close", code, reason));
331
- ws.on("error", (error) => this.emit("_error", error));
357
+ ws.on("open", () => this.dispatchEvent(new Event("open")));
358
+ ws.on("message", (data) => this.dispatchEvent(new DataEvent("message", data)));
359
+ ws.on("close", () => this.dispatchEvent(new Event("close")));
360
+ ws.on("error", () => this.dispatchEvent(new Event("_error")));
332
361
  this.ws = ws;
333
362
  }
334
363
  };
@@ -367,11 +396,12 @@ var KeepLiveTCP = class extends KeepLive {
367
396
  }
368
397
  };
369
398
  export {
399
+ DataEvent,
400
+ EventEvent,
370
401
  KeepLiveTCP,
371
402
  KeepLiveWS,
372
403
  LiveTCP,
373
404
  LiveWS,
374
405
  getConf,
375
- getRoomid,
376
- relayEvent
406
+ getRoomid
377
407
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laplace.live/ws",
3
- "version": "6.3.5",
3
+ "version": "6.3.7",
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
  },
@@ -1,53 +0,0 @@
1
- import { EventEmitter } from 'events';
2
-
3
- type Inflates = {
4
- inflateAsync: (b: Buffer) => Buffer | Promise<Buffer>;
5
- brotliDecompressAsync: (b: Buffer) => Buffer | Promise<Buffer>;
6
- Buffer: typeof Buffer;
7
- };
8
-
9
- type LiveOptions = {
10
- protover?: 1 | 2 | 3;
11
- key?: string;
12
- authBody?: any;
13
- uid?: number;
14
- buvid?: string;
15
- };
16
- declare const relayEvent: unique symbol;
17
- declare class NiceEventEmitter extends EventEmitter {
18
- emit(eventName: string | symbol, ...params: any[]): boolean;
19
- }
20
- declare class Live extends NiceEventEmitter {
21
- roomid: number;
22
- online: number;
23
- live: boolean;
24
- closed: boolean;
25
- timeout: ReturnType<typeof setTimeout>;
26
- inflates: Inflates;
27
- send: (data: Buffer) => void;
28
- close: () => void;
29
- constructor(inflates: Inflates, roomid: number, { send, close, protover, key, authBody, uid, buvid, }: {
30
- send: (data: Buffer) => void;
31
- close: () => void;
32
- } & LiveOptions);
33
- heartbeat(): void;
34
- getOnline(): Promise<number>;
35
- }
36
- declare class KeepLive<Base extends typeof Live> extends EventEmitter {
37
- params: ConstructorParameters<Base>;
38
- closed: boolean;
39
- interval: number;
40
- timeout: number;
41
- connection: InstanceType<Base>;
42
- Base: Base;
43
- constructor(Base: Base, ...params: ConstructorParameters<Base>);
44
- connect(reconnect?: boolean): void;
45
- get online(): number;
46
- get roomid(): number;
47
- close(): void;
48
- heartbeat(): void;
49
- getOnline(): Promise<number>;
50
- send(data: Buffer): void;
51
- }
52
-
53
- export { type Inflates as I, KeepLive as K, Live as L, type LiveOptions as a, relayEvent as r };