-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
123 lines (110 loc) · 3.27 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import type { ClientRequestArgs } from 'http'
import { WebSocket, type RawData, type ClientOptions } from 'ws'
import type { Credentials } from '../../types/tokens.js'
import { createHeaders } from '../auth/headers.js'
import type {
LcuEvent,
LcuEventLookup
} from '../../types/dto/lcu-event-lookup.js'
import type { LobbyEvent } from '../../types/dto/lobby.js'
type RecordToCallbacks<T> = {
[K in keyof T]: ({
data,
eventType,
uri
}: {
data: T[K]
eventType: 'Update' | 'Create' | 'Delete'
uri: string
}) => void
}
type LcuWebSocketEventCallbacks = Omit<
RecordToCallbacks<LcuEventLookup>,
'OnJsonApiEvent_lol-lobby_v2_lobby'
> & {
'OnJsonApiEvent_lol-lobby_v2_lobby': (event: LobbyEvent) => void
}
export interface ILcuClient {
eventListeners: Partial<
Record<LcuEvent, Array<LcuWebSocketEventCallbacks[LcuEvent]>>
>
subscribe<T extends LcuEvent>(
event: T,
callback: LcuWebSocketEventCallbacks[T]
): void
unsubscribe<T extends LcuEvent>(
event: T,
callback: LcuWebSocketEventCallbacks[T]
): void
unsubscribeAll(event?: LcuEvent): void
}
export class LcuClient extends WebSocket implements ILcuClient {
eventListeners: Partial<
Record<LcuEvent, Array<LcuWebSocketEventCallbacks[LcuEvent]>>
> = {}
constructor(credentials: Credentials) {
const url = `wss://127.0.0.1:${credentials.appPort}/`
const options = {
headers: createHeaders(credentials),
rejectUnauthorized: credentials.certificate ? true : false,
ca: credentials.certificate
} satisfies ClientOptions | ClientRequestArgs | undefined
super(url, options)
this.eventListeners = {}
this.addListener('message', this.publish.bind(this))
}
private publish(data: RawData) {
const [eventCode, eventType, eventData] = (() => {
try {
const json = JSON.parse(data.toString())
if (json[0] === 8) {
return json as any as [8, LcuEvent, any]
}
} catch (error) {
// console.error(error)
}
return [0, undefined, undefined] as [0, undefined, undefined]
})()
if (eventCode) {
const listeners = this.eventListeners[eventType]
if (listeners) {
listeners.forEach((listener) => listener(eventData))
}
}
}
subscribe<T extends keyof LcuEventLookup>(
event: T,
listener: LcuWebSocketEventCallbacks[T]
) {
const isOpen = this.readyState === WebSocket.OPEN
if (!isOpen) {
this.once('open', () => this.subscribe(event, listener))
return
}
this.send(JSON.stringify([5, event]))
if (!this.eventListeners[event]) {
this.eventListeners[event] = []
}
this.eventListeners[event]?.push(listener)
}
unsubscribe(event: LcuEvent) {
this.eventListeners[event] = undefined
if (this.readyState !== WebSocket.OPEN) return
this.send(JSON.stringify([6, event]))
}
unsubscribeAll(event?: LcuEvent) {
if (this.readyState === WebSocket.OPEN) {
if (!event) {
Object.keys(this.eventListeners).forEach((event) => {
this.send(JSON.stringify([6, event as LcuEvent]))
})
} else {
this.send(JSON.stringify([6, event]))
}
}
this.eventListeners = {}
}
}
export function createLcuClient(credentials: Credentials) {
return new LcuClient(credentials)
}