@laplace.live/ws 6.3.3 → 6.3.5

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/src/common.ts DELETED
@@ -1,216 +0,0 @@
1
- import { EventEmitter } from 'events'
2
-
3
- import { encoder, type Inflates, makeDecoder } from './buffer.ts'
4
-
5
- export type LiveOptions = { protover?: 1 | 2 | 3; key?: string; authBody?: any; uid?: number; buvid?: string }
6
-
7
- export const relayEvent = Symbol('relay')
8
-
9
- class NiceEventEmitter extends EventEmitter {
10
- emit(eventName: string | symbol, ...params: any[]) {
11
- super.emit(eventName, ...params)
12
- super.emit(relayEvent, eventName, ...params)
13
- return true
14
- }
15
- }
16
-
17
- export class Live extends NiceEventEmitter {
18
- roomid: number
19
- online: number
20
- live: boolean
21
- closed: boolean
22
- timeout: ReturnType<typeof setTimeout>
23
-
24
- inflates: Inflates
25
-
26
- send: (data: Buffer) => void
27
- close: () => void
28
-
29
- constructor(
30
- inflates: Inflates,
31
- roomid: number,
32
- {
33
- send,
34
- close,
35
- protover = 3,
36
- key,
37
- authBody,
38
- uid = 0,
39
- buvid,
40
- }: { send: (data: Buffer) => void; close: () => void } & LiveOptions
41
- ) {
42
- if (typeof roomid !== 'number' || Number.isNaN(roomid)) {
43
- throw new Error(`roomid ${roomid} must be Number not NaN`)
44
- }
45
-
46
- super()
47
- this.inflates = inflates
48
- this.roomid = roomid
49
- this.online = 0
50
- this.live = false
51
- this.closed = false
52
- this.timeout = setTimeout(() => {}, 0)
53
-
54
- this.send = send
55
- this.close = () => {
56
- this.closed = true
57
- close()
58
- }
59
-
60
- this.on('message', async buffer => {
61
- const packs = await makeDecoder(inflates)(buffer)
62
- packs.forEach(({ type, data }) => {
63
- if (type === 'welcome') {
64
- this.live = true
65
- this.emit('live')
66
- this.send(encoder('heartbeat', inflates))
67
- }
68
- if (type === 'heartbeat') {
69
- this.online = data
70
- clearTimeout(this.timeout)
71
- this.timeout = setTimeout(() => this.heartbeat(), 1000 * 30)
72
- this.emit('heartbeat', this.online)
73
- }
74
- if (type === 'message') {
75
- this.emit('msg', data)
76
- const cmd = data.cmd || (data.msg && data.msg.cmd)
77
- if (cmd) {
78
- if (cmd.includes('DANMU_MSG')) {
79
- this.emit('DANMU_MSG', data)
80
- } else {
81
- this.emit(cmd, data)
82
- }
83
- }
84
- }
85
- })
86
- })
87
-
88
- this.on('open', () => {
89
- if (authBody) {
90
- if (typeof authBody === 'object') {
91
- authBody = encoder('join', inflates, authBody)
92
- }
93
- this.send(authBody)
94
- } else {
95
- const hi: {
96
- uid: number
97
- roomid: number
98
- protover: number
99
- platform: string
100
- type: number
101
- key?: string
102
- buvid?: string
103
- } = { uid: uid, roomid, protover, platform: 'web', type: 2 }
104
- if (key) {
105
- hi.key = key
106
- }
107
- if (buvid) {
108
- hi.buvid = buvid
109
- }
110
- const buf = encoder('join', inflates, hi)
111
- this.send(buf)
112
- }
113
- })
114
-
115
- this.on('close', () => {
116
- clearTimeout(this.timeout)
117
- })
118
-
119
- this.on('_error', error => {
120
- this.close()
121
- this.emit('error', error)
122
- })
123
- }
124
-
125
- heartbeat() {
126
- this.send(encoder('heartbeat', this.inflates))
127
- }
128
-
129
- getOnline() {
130
- this.heartbeat()
131
- return new Promise<number>(resolve => this.once('heartbeat', resolve))
132
- }
133
- }
134
-
135
- export class KeepLive<Base extends typeof Live> extends EventEmitter {
136
- params: ConstructorParameters<Base>
137
- closed: boolean
138
- interval: number
139
- timeout: number
140
- connection: InstanceType<Base>
141
- Base: Base
142
-
143
- constructor(Base: Base, ...params: ConstructorParameters<Base>) {
144
- super()
145
- this.params = params
146
- this.closed = false
147
- this.interval = 100
148
- this.timeout = 45 * 1000
149
- this.connection = new (Base as any)(...this.params)
150
- this.Base = Base
151
- this.connect(false)
152
- }
153
-
154
- connect(reconnect = true) {
155
- if (reconnect) {
156
- this.connection.close()
157
- this.connection = new (this.Base as any)(...this.params)
158
- }
159
- const connection = this.connection
160
-
161
- let timeout = setTimeout(() => {
162
- connection.close()
163
- connection.emit('timeout')
164
- }, this.timeout)
165
-
166
- connection.on(relayEvent, (eventName: string, ...params: any[]) => {
167
- if (eventName !== 'error') {
168
- this.emit(eventName, ...params)
169
- }
170
- })
171
-
172
- connection.on('error', e => this.emit('e', e))
173
- connection.on('close', () => {
174
- if (!this.closed) {
175
- setTimeout(() => this.connect(), this.interval)
176
- }
177
- })
178
-
179
- connection.on('heartbeat', () => {
180
- clearTimeout(timeout)
181
- timeout = setTimeout(() => {
182
- connection.close()
183
- connection.emit('timeout')
184
- }, this.timeout)
185
- })
186
-
187
- connection.on('close', () => {
188
- clearTimeout(timeout)
189
- })
190
- }
191
-
192
- get online() {
193
- return this.connection.online
194
- }
195
-
196
- get roomid() {
197
- return this.connection.roomid
198
- }
199
-
200
- close() {
201
- this.closed = true
202
- this.connection.close()
203
- }
204
-
205
- heartbeat() {
206
- return this.connection.heartbeat()
207
- }
208
-
209
- getOnline() {
210
- return this.connection.getOnline()
211
- }
212
-
213
- send(data: Buffer) {
214
- return this.connection.send(data)
215
- }
216
- }
package/src/extra.ts DELETED
@@ -1,33 +0,0 @@
1
- type GET_DANMU_INFO = {
2
- code: number
3
- message: string
4
- ttl: number
5
- data: {
6
- business_id: number
7
- group: string
8
- host_list: {
9
- host: string
10
- port: number
11
- wss_port: number
12
- ws_port: number
13
- }[]
14
- max_delay: number
15
- refresh_rate: number
16
- refresh_row_factor: number
17
- token: string
18
- }
19
- }
20
-
21
- export const getConf = async (roomid: number) => {
22
- // eslint-disable-next-line @typescript-eslint/no-var-requires
23
- const raw = await fetch(`https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=${roomid}`).then(w => w.json()) as GET_DANMU_INFO
24
- const { data: { token: key, host_list: [{ host }] } } = raw
25
- const address = `wss://${host}/sub`
26
- return { key, host, address, raw }
27
- }
28
-
29
- export const getRoomid = async (short: number) => {
30
- // eslint-disable-next-line @typescript-eslint/no-var-requires
31
- const { data: { room_id } } = await fetch(`https://api.live.bilibili.com/room/v1/Room/mobileRoomInit?id=${short}`).then(w => w.json())
32
- return room_id
33
- }
package/src/index.test.ts DELETED
@@ -1,191 +0,0 @@
1
- import { describe, expect, it } from 'bun:test'
2
- import { once } from 'events'
3
-
4
- import { KeepLiveWS as KeepLiveWSBrowser, LiveWS as LiveWSBrowser } from './browser.ts'
5
- import { getConf, getRoomid, KeepLiveTCP, KeepLiveWS, LiveTCP, LiveWS } from './index.ts'
6
-
7
- const TIMEOUT = 1000 * 25
8
- const watch = (
9
- live:
10
- | LiveWS
11
- | LiveTCP
12
- | KeepLiveWS
13
- | KeepLiveTCP
14
- | InstanceType<typeof LiveWSBrowser>
15
- | InstanceType<typeof KeepLiveWSBrowser>
16
- ) =>
17
- setTimeout(() => {
18
- if (!live.closed) {
19
- live.close()
20
- }
21
- }, TIMEOUT)
22
-
23
- describe('extra', () => {
24
- it('getRoomid', async () => {
25
- const roomid = await getRoomid(255)
26
- expect(roomid).toBe(48743)
27
- })
28
- })
29
-
30
- Object.entries({
31
- LiveWS,
32
- LiveTCP,
33
- KeepLiveWS,
34
- KeepLiveTCP,
35
- LiveWSBrowser,
36
- KeepLiveWSBrowser,
37
- }).forEach(([name, Live]) => {
38
- describe(name, () => {
39
- describe('Connect', () => {
40
- it('online', async () => {
41
- const live = new Live(12235923)
42
- watch(live)
43
- const [online] = await once(live, 'heartbeat')
44
- live.close()
45
- expect(online).toBeGreaterThan(0)
46
- })
47
- it('roomid must be number', () => {
48
- expect(() => new (Live as any)('12235923')).toThrow()
49
- })
50
- it('roomid can not be NaN', () => {
51
- expect(() => new (Live as any)(NaN)).toThrow()
52
- })
53
- })
54
- describe('properties', () => {
55
- describe('roomid', () => {
56
- Object.entries({
57
- Mea: 12235923,
58
- nana: 21304638,
59
- fubuki: 11588230,
60
- }).forEach(([roomName, roomid]) => {
61
- it(`roomid ${roomName}`, async () => {
62
- const live = new Live(roomid)
63
- watch(live)
64
- await once(live, 'live')
65
- live.close()
66
- expect(live.roomid).toBe(roomid)
67
- })
68
- })
69
- })
70
- it('online', async () => {
71
- const live = new Live(12235923)
72
- watch(live)
73
- const [online] = await once(live, 'heartbeat')
74
- live.close()
75
- expect(online).toBe(live.online)
76
- })
77
- it('closed', async () => {
78
- const live = new Live(12235923)
79
- watch(live)
80
- expect(live.closed).toBe(false)
81
- await once(live, 'live')
82
- live.close()
83
- expect(live.closed).toBe(true)
84
- })
85
- })
86
- describe('functions', () => {
87
- it('close', async () => {
88
- const live = new Live(12235923)
89
- watch(live)
90
- await once(live, 'heartbeat')
91
- const close = await new Promise(resolve => {
92
- live.on('close', () => resolve('closed'))
93
- live.close()
94
- })
95
- expect(close).toBe('closed')
96
- })
97
- it('getOnline', async () => {
98
- const live = new Live(12235923)
99
- watch(live)
100
- await once(live, 'live')
101
- const online = await live.getOnline()
102
- live.close()
103
- expect(online).toBeGreaterThan(0)
104
- })
105
- if (name.includes('Keep')) {
106
- it('no error relay', async () => {
107
- const live = new Live(12235923) as KeepLiveWS | KeepLiveTCP
108
- watch(live)
109
- await once(live, 'live')
110
- await new Promise<void>((resolve, reject) => {
111
- live.once('error', reject)
112
- live.connection.emit('error', new Error('This shold not be caught'))
113
- setTimeout(resolve, 1000)
114
- })
115
- live.close()
116
- })
117
- }
118
- if (name.includes('Keep')) {
119
- it('close and reopen', async () => {
120
- const live = new Live(12235923) as KeepLiveWS | KeepLiveTCP
121
- watch(live)
122
- await once(live, 'live')
123
- live.connection.close()
124
- await once(live, 'live')
125
- live.close()
126
- })
127
- } else {
128
- it('close on error', async () => {
129
- const live = new Live(12235923)
130
- watch(live)
131
- await once(live, 'heartbeat')
132
- const close = await new Promise(resolve => {
133
- live.on('close', () => resolve('closed'))
134
- live.on('error', () => {})
135
- live.emit('_error', Error())
136
- })
137
- expect(close).toBe('closed')
138
- })
139
- }
140
- })
141
- describe('options', () => {
142
- it('protover: 1', async () => {
143
- const live = new Live(12235923, { protover: 1 })
144
- watch(live)
145
- const [online] = await once(live, 'heartbeat')
146
- live.close()
147
- expect(online).toBeGreaterThan(0)
148
- })
149
- it('protover: 3', async () => {
150
- const live = new Live(12235923, { protover: 3 })
151
- watch(live)
152
- const [online] = await once(live, 'heartbeat')
153
- live.close()
154
- expect(online).toBeGreaterThan(0)
155
- })
156
- if (name.includes('WS')) {
157
- it('address', async () => {
158
- const L = Live as typeof LiveWS | typeof KeepLiveWS
159
- const live = new L(12235923, {
160
- address: 'wss://broadcastlv.chat.bilibili.com/sub',
161
- })
162
- watch(live)
163
- const [online] = await once(live, 'heartbeat')
164
- live.close()
165
- expect(online).toBeGreaterThan(0)
166
- })
167
- } else if (name.includes('TCP')) {
168
- it('host, port', async () => {
169
- const live = new Live(12235923, {
170
- host: 'broadcastlv.chat.bilibili.com',
171
- port: 2243,
172
- })
173
- watch(live)
174
- const [online] = await once(live, 'heartbeat')
175
- live.close()
176
- expect(online).toBeGreaterThan(0)
177
- })
178
- } else {
179
- throw new Error('no options test')
180
- }
181
- it('key: token', async () => {
182
- const { key, host, address } = await getConf(12235923)
183
- const live = new Live(12235923, { key, host, address })
184
- watch(live)
185
- const [online] = await once(live, 'heartbeat')
186
- live.close()
187
- expect(online).toBeGreaterThan(0)
188
- })
189
- })
190
- })
191
- })
package/src/index.ts DELETED
@@ -1,35 +0,0 @@
1
- import { KeepLive } from './common.ts'
2
- import { inflates } from './inflate/node.ts'
3
- import { LiveTCPBase, type TCPOptions } from './tcp.ts'
4
- import { LiveWSBase, type WSOptions } from './ws-node.ts'
5
-
6
- export type { LiveOptions } from './common.ts'
7
- export type { TCPOptions } from './tcp.ts'
8
- export type { WSOptions } from './ws-node.ts'
9
-
10
- export { relayEvent } from './common.ts'
11
- export { getConf, getRoomid } from './extra.ts'
12
-
13
- export class LiveWS extends LiveWSBase {
14
- constructor(roomid: number, opts?: WSOptions) {
15
- super(inflates, roomid, opts)
16
- }
17
- }
18
-
19
- export class LiveTCP extends LiveTCPBase {
20
- constructor(roomid: number, opts?: TCPOptions) {
21
- super(inflates, roomid, opts)
22
- }
23
- }
24
-
25
- export class KeepLiveWS extends KeepLive<typeof LiveWSBase> {
26
- constructor(roomid: number, opts?: WSOptions) {
27
- super(LiveWSBase, inflates, roomid, opts)
28
- }
29
- }
30
-
31
- export class KeepLiveTCP extends KeepLive<typeof LiveTCPBase> {
32
- constructor(roomid: number, opts?: TCPOptions) {
33
- super(LiveTCPBase, inflates, roomid, opts)
34
- }
35
- }