@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/dist/browser.d.ts +27 -0
- package/dist/browser.js +2094 -0
- package/dist/common-BGRg5uk7.d.ts +53 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +377 -0
- package/package.json +32 -14
- package/src/browser.ts +0 -20
- package/src/buffer.ts +0 -82
- package/src/common.ts +0 -216
- package/src/extra.ts +0 -33
- package/src/index.test.ts +0 -191
- package/src/index.ts +0 -35
- package/src/inflate/brotli.ts +0 -2285
- package/src/inflate/browser.ts +0 -9
- package/src/inflate/node.ts +0 -11
- package/src/tcp.ts +0 -53
- package/src/ws-client.ts +0 -63
- package/src/ws-node.ts +0 -64
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
|
-
}
|