lunibee 0.3.3 → 0.4.0
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/README.md +1 -1
- package/dist/builders/commands.d.ts +1 -1
- package/dist/builders/components.d.ts +9 -11
- package/dist/builders/embed.d.ts +1 -1
- package/dist/builders/index.d.ts +1 -1
- package/dist/builders/index.js +87 -1298
- package/dist/builders/index.js.map +3 -11
- package/dist/chunks/index-0wn81eng.js +2492 -0
- package/dist/chunks/index-0wn81eng.js.map +17 -0
- package/dist/chunks/index-2en489j6.js +40 -0
- package/dist/chunks/index-2en489j6.js.map +10 -0
- package/dist/chunks/index-3hyps48a.js +203 -0
- package/dist/chunks/index-3hyps48a.js.map +11 -0
- package/dist/chunks/index-57c5n3ms.js +2274 -0
- package/dist/chunks/index-57c5n3ms.js.map +19 -0
- package/dist/chunks/index-5yx92e36.js +1170 -0
- package/dist/chunks/index-5yx92e36.js.map +14 -0
- package/dist/chunks/index-690bp093.js +95 -0
- package/dist/chunks/index-690bp093.js.map +10 -0
- package/dist/chunks/index-7fp2hvmg.js +2155 -0
- package/dist/chunks/index-7fp2hvmg.js.map +24 -0
- package/dist/chunks/index-cnmsajvk.js +1119 -0
- package/dist/chunks/index-cnmsajvk.js.map +12 -0
- package/dist/chunks/index-fdvgk2sw.js +1310 -0
- package/dist/chunks/index-fdvgk2sw.js.map +21 -0
- package/dist/chunks/index-gyvps8b9.js +214 -0
- package/dist/chunks/index-gyvps8b9.js.map +12 -0
- package/dist/chunks/index-jzg4bh99.js +1533 -0
- package/dist/chunks/index-jzg4bh99.js.map +21 -0
- package/dist/chunks/index-mgw2yvrm.js +3547 -0
- package/dist/chunks/index-mgw2yvrm.js.map +25 -0
- package/dist/chunks/index-yh76b55h.js +3449 -0
- package/dist/chunks/index-yh76b55h.js.map +29 -0
- package/dist/collection/index.js +9 -1118
- package/dist/collection/index.js.map +3 -6
- package/dist/core/api.d.ts +3 -3
- package/dist/core/channel-create.d.ts +2 -2
- package/dist/core/commands.d.ts +3 -3
- package/dist/core/events.d.ts +4 -4
- package/dist/core/handles.d.ts +4 -4
- package/dist/core/index.d.ts +25 -20
- package/dist/core/index.js +68 -10130
- package/dist/core/index.js.map +3 -65
- package/dist/core/permissions.d.ts +1 -1
- package/dist/core/redis-cache.d.ts +1 -1
- package/dist/formatters/index.js +41 -110
- package/dist/formatters/index.js.map +3 -4
- package/dist/handlers/index.js +5 -37
- package/dist/handlers/index.js.map +3 -4
- package/dist/index.d.ts +21 -21
- package/dist/index.js +641 -16325
- package/dist/index.js.map +3 -92
- package/dist/managers/advanced.d.ts +3 -3
- package/dist/managers/application.d.ts +2 -2
- package/dist/managers/base.d.ts +1 -1
- package/dist/managers/emoji.d.ts +2 -2
- package/dist/managers/guild-resources.d.ts +6 -6
- package/dist/managers/guild.d.ts +3 -3
- package/dist/managers/index.d.ts +4 -8
- package/dist/managers/index.js +51 -4060
- package/dist/managers/index.js.map +3 -29
- package/dist/managers/member.d.ts +2 -2
- package/dist/managers/message.d.ts +14 -6
- package/dist/managers/role.d.ts +2 -2
- package/dist/managers/thread.d.ts +3 -3
- package/dist/managers/user.d.ts +7 -4
- package/dist/rest/index.d.ts +10 -35
- package/dist/rest/index.js +57 -2184
- package/dist/rest/index.js.map +3 -18
- package/dist/rest/limiter.d.ts +9 -1
- package/dist/rest/webhook.d.ts +2 -8
- package/dist/sharding/bus.d.ts +2 -2
- package/dist/sharding/cluster.d.ts +45 -5
- package/dist/sharding/context.d.ts +45 -3
- package/dist/sharding/gateway-bot.d.ts +2 -1
- package/dist/sharding/health.d.ts +1 -1
- package/dist/sharding/identify.d.ts +12 -0
- package/dist/sharding/index.d.ts +44 -11
- package/dist/sharding/index.js +60 -4620
- package/dist/sharding/index.js.map +3 -33
- package/dist/sharding/supervisor.d.ts +4 -2
- package/dist/structures/audit-log.d.ts +1 -1
- package/dist/structures/base.d.ts +6 -6
- package/dist/structures/channels.d.ts +1 -1
- package/dist/structures/embed.d.ts +1 -1
- package/dist/structures/index.d.ts +14 -14
- package/dist/structures/index.js +109 -2382
- package/dist/structures/index.js.map +3 -16
- package/dist/structures/interactions.d.ts +13 -9
- package/dist/structures/options.d.ts +1 -1
- package/dist/structures/permissions.d.ts +2 -2
- package/dist/structures/resources.d.ts +10 -10
- package/dist/structures/sticker.d.ts +1 -1
- package/dist/types/gateway.d.ts +2 -79
- package/dist/types/index.d.ts +0 -6
- package/dist/types/index.js +41 -272
- package/dist/types/index.js.map +3 -6
- package/dist/utils/index.js +23 -209
- package/dist/utils/index.js.map +3 -5
- package/dist/voice/connection.d.ts +200 -0
- package/dist/voice/crypto.d.ts +50 -0
- package/dist/voice/dave.d.ts +85 -0
- package/dist/voice/effects.d.ts +31 -0
- package/dist/voice/emitter.d.ts +14 -0
- package/dist/voice/gateway.d.ts +59 -0
- package/dist/voice/index.d.ts +25 -228
- package/dist/voice/index.js +111 -442
- package/dist/voice/index.js.map +3 -4
- package/dist/voice/libopus.d.ts +88 -0
- package/dist/voice/networking.d.ts +80 -0
- package/dist/voice/ogg.d.ts +24 -0
- package/dist/voice/opus.d.ts +18 -0
- package/dist/voice/player.d.ts +79 -0
- package/dist/voice/protocol.d.ts +76 -0
- package/dist/voice/receiver.d.ts +59 -0
- package/dist/voice/resource.d.ts +102 -0
- package/dist/voice/udp.d.ts +40 -0
- package/dist/ws/close-codes.d.ts +1 -1
- package/dist/ws/index.d.ts +25 -4
- package/dist/ws/index.js +47 -1336
- package/dist/ws/index.js.map +3 -17
- package/dist/ws/protocol.d.ts +1 -1
- package/dist/ws/send-budget.d.ts +0 -2
- package/dist/ws/state.d.ts +0 -10
- package/package.json +19 -16
package/dist/ws/index.js
CHANGED
|
@@ -1,1341 +1,52 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// packages/ws/src/session.ts
|
|
3
|
-
class GatewaySession {
|
|
4
|
-
#state = { status: "none" };
|
|
5
|
-
#sequence = null;
|
|
6
|
-
#generation = 0;
|
|
7
|
-
#lastInvalidation;
|
|
8
|
-
get lastInvalidation() {
|
|
9
|
-
return this.#lastInvalidation;
|
|
10
|
-
}
|
|
11
|
-
get generation() {
|
|
12
|
-
return this.#generation;
|
|
13
|
-
}
|
|
14
|
-
get sessionId() {
|
|
15
|
-
return this.#state.status === "established" ? this.#state.sessionId : undefined;
|
|
16
|
-
}
|
|
17
|
-
get resumeURL() {
|
|
18
|
-
return this.#state.status === "established" ? this.#state.resumeURL : undefined;
|
|
19
|
-
}
|
|
20
|
-
get sequence() {
|
|
21
|
-
return this.#sequence;
|
|
22
|
-
}
|
|
23
|
-
get canResume() {
|
|
24
|
-
return this.#state.status === "established" && this.#sequence !== null;
|
|
25
|
-
}
|
|
26
|
-
beginConnection() {
|
|
27
|
-
return ++this.#generation;
|
|
28
|
-
}
|
|
29
|
-
owns(token) {
|
|
30
|
-
return token === this.#generation;
|
|
31
|
-
}
|
|
32
|
-
recordSequence(sequence, token) {
|
|
33
|
-
if (!this.owns(token))
|
|
34
|
-
return false;
|
|
35
|
-
if (!Number.isInteger(sequence))
|
|
36
|
-
return false;
|
|
37
|
-
if (this.#sequence !== null && sequence < this.#sequence)
|
|
38
|
-
return false;
|
|
39
|
-
this.#sequence = sequence;
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
activate(payload, token) {
|
|
43
|
-
if (!this.owns(token))
|
|
44
|
-
return false;
|
|
45
|
-
const ready = payload;
|
|
46
|
-
if (typeof ready?.session_id !== "string" || typeof ready?.resume_gateway_url !== "string")
|
|
47
|
-
return false;
|
|
48
|
-
this.#state = {
|
|
49
|
-
status: "established",
|
|
50
|
-
sessionId: ready.session_id,
|
|
51
|
-
resumeURL: ready.resume_gateway_url
|
|
52
|
-
};
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
invalidate(token, reason = "explicit") {
|
|
56
|
-
if (!this.owns(token))
|
|
57
|
-
return false;
|
|
58
|
-
this.#lastInvalidation = reason;
|
|
59
|
-
this.#state = { status: "none" };
|
|
60
|
-
this.#sequence = null;
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
resumeInfo() {
|
|
64
|
-
if (this.#state.status !== "established")
|
|
65
|
-
return;
|
|
66
|
-
if (this.#sequence === null)
|
|
67
|
-
return;
|
|
68
|
-
const { sessionId, resumeURL } = this.#state;
|
|
69
|
-
return { sessionId, sequence: this.#sequence, resumeURL };
|
|
70
|
-
}
|
|
71
|
-
handshake() {
|
|
72
|
-
const resume = this.resumeInfo();
|
|
73
|
-
return resume ? { type: "resume", ...resume } : { type: "identify" };
|
|
74
|
-
}
|
|
75
|
-
connectURL(fallback) {
|
|
76
|
-
const resume = this.resumeInfo()?.resumeURL;
|
|
77
|
-
return resume !== undefined && isTrustedGatewayURL(resume, fallback) ? resume : fallback;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function isTrustedGatewayURL(url, fallback) {
|
|
81
|
-
let parsed;
|
|
82
|
-
try {
|
|
83
|
-
parsed = new URL(url);
|
|
84
|
-
} catch {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
if (parsed.protocol !== "wss:" || parsed.username || parsed.password)
|
|
88
|
-
return false;
|
|
89
|
-
const host = parsed.hostname.toLowerCase();
|
|
90
|
-
if (host === "discord.gg" || host.endsWith(".discord.gg"))
|
|
91
|
-
return true;
|
|
92
|
-
try {
|
|
93
|
-
return host === new URL(fallback).hostname.toLowerCase();
|
|
94
|
-
} catch {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// packages/ws/src/heartbeat.ts
|
|
100
|
-
var MAX_MONITOR_INTERVAL = 1000;
|
|
101
|
-
|
|
102
|
-
class GatewayHeartbeat {
|
|
103
|
-
#options;
|
|
104
|
-
#now;
|
|
105
|
-
#interval = 0;
|
|
106
|
-
#acknowledged = true;
|
|
107
|
-
#sentAt = 0;
|
|
108
|
-
#latency = -1;
|
|
109
|
-
#lastMessageAt = 0;
|
|
110
|
-
#zombieReported = false;
|
|
111
|
-
#timer;
|
|
112
|
-
#initialTimer;
|
|
113
|
-
#ackTimer;
|
|
114
|
-
#monitorTimer;
|
|
115
|
-
constructor(options) {
|
|
116
|
-
if (options.zombieTimeout <= options.ackTimeout)
|
|
117
|
-
throw new RangeError("Gateway zombieTimeout must be greater than heartbeatAckTimeout");
|
|
118
|
-
this.#options = options;
|
|
119
|
-
this.#now = options.now ?? (() => Date.now());
|
|
120
|
-
}
|
|
121
|
-
get latency() {
|
|
122
|
-
return this.#latency;
|
|
123
|
-
}
|
|
124
|
-
get interval() {
|
|
125
|
-
return this.#interval;
|
|
126
|
-
}
|
|
127
|
-
get acknowledged() {
|
|
128
|
-
return this.#acknowledged;
|
|
129
|
-
}
|
|
130
|
-
get silentFor() {
|
|
131
|
-
return this.#lastMessageAt === 0 ? 0 : this.#now() - this.#lastMessageAt;
|
|
132
|
-
}
|
|
133
|
-
get stalenessDeadline() {
|
|
134
|
-
return Math.max(this.#options.zombieTimeout, this.#interval + this.#options.ackTimeout);
|
|
135
|
-
}
|
|
136
|
-
isHealthy() {
|
|
137
|
-
if (!this.#acknowledged)
|
|
138
|
-
return false;
|
|
139
|
-
if (this.#lastMessageAt === 0)
|
|
140
|
-
return true;
|
|
141
|
-
return this.silentFor < this.stalenessDeadline;
|
|
142
|
-
}
|
|
143
|
-
watch() {
|
|
144
|
-
this.#lastMessageAt = this.#now();
|
|
145
|
-
this.#zombieReported = false;
|
|
146
|
-
this.#startMonitor();
|
|
147
|
-
}
|
|
148
|
-
receivedMessage() {
|
|
149
|
-
this.#lastMessageAt = this.#now();
|
|
150
|
-
this.#zombieReported = false;
|
|
151
|
-
}
|
|
152
|
-
start(interval) {
|
|
153
|
-
this.#clearBeatTimers();
|
|
154
|
-
this.#interval = interval;
|
|
155
|
-
this.#acknowledged = true;
|
|
156
|
-
this.#initialTimer = setTimeout(() => {
|
|
157
|
-
this.#initialTimer = undefined;
|
|
158
|
-
this.sendHeartbeat();
|
|
159
|
-
this.#timer = setInterval(() => this.sendHeartbeat(), interval);
|
|
160
|
-
}, Math.random() * interval);
|
|
161
|
-
}
|
|
162
|
-
stop() {
|
|
163
|
-
this.#clearBeatTimers();
|
|
164
|
-
if (this.#monitorTimer)
|
|
165
|
-
clearInterval(this.#monitorTimer);
|
|
166
|
-
this.#monitorTimer = undefined;
|
|
167
|
-
}
|
|
168
|
-
sendHeartbeat() {
|
|
169
|
-
this.#acknowledged = false;
|
|
170
|
-
this.#sentAt = this.#now();
|
|
171
|
-
if (!this.#options.send(this.#options.sequence())) {
|
|
172
|
-
this.#options.onError(new Error("Unable to send Gateway heartbeat because the WebSocket is not open."));
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
this.#clearAckTimer();
|
|
176
|
-
this.#ackTimer = setTimeout(() => {
|
|
177
|
-
if (this.#acknowledged)
|
|
178
|
-
return;
|
|
179
|
-
this.#options.onTimeout({
|
|
180
|
-
type: "ack",
|
|
181
|
-
elapsedMs: this.#now() - this.#sentAt
|
|
182
|
-
});
|
|
183
|
-
}, this.#options.ackTimeout);
|
|
184
|
-
}
|
|
185
|
-
acknowledge() {
|
|
186
|
-
if (this.#acknowledged)
|
|
187
|
-
return;
|
|
188
|
-
this.#acknowledged = true;
|
|
189
|
-
this.#latency = this.#now() - this.#sentAt;
|
|
190
|
-
this.#clearAckTimer();
|
|
191
|
-
}
|
|
192
|
-
#startMonitor() {
|
|
193
|
-
if (this.#monitorTimer)
|
|
194
|
-
clearInterval(this.#monitorTimer);
|
|
195
|
-
const interval = Math.max(1, Math.min(MAX_MONITOR_INTERVAL, this.#options.ackTimeout, this.#options.zombieTimeout / 2));
|
|
196
|
-
this.#monitorTimer = setInterval(() => this.#checkStaleness(), interval);
|
|
197
|
-
}
|
|
198
|
-
#checkStaleness() {
|
|
199
|
-
if (!this.#options.isConnected() || this.#lastMessageAt === 0)
|
|
200
|
-
return;
|
|
201
|
-
const silentFor = this.silentFor;
|
|
202
|
-
const deadline = this.stalenessDeadline;
|
|
203
|
-
if (silentFor < deadline || this.#zombieReported)
|
|
204
|
-
return;
|
|
205
|
-
this.#zombieReported = true;
|
|
206
|
-
this.#options.onTimeout({ type: "zombie", silentFor, deadline });
|
|
207
|
-
}
|
|
208
|
-
#clearAckTimer() {
|
|
209
|
-
if (this.#ackTimer)
|
|
210
|
-
clearTimeout(this.#ackTimer);
|
|
211
|
-
this.#ackTimer = undefined;
|
|
212
|
-
}
|
|
213
|
-
#clearBeatTimers() {
|
|
214
|
-
if (this.#timer)
|
|
215
|
-
clearInterval(this.#timer);
|
|
216
|
-
if (this.#initialTimer)
|
|
217
|
-
clearTimeout(this.#initialTimer);
|
|
218
|
-
this.#clearAckTimer();
|
|
219
|
-
this.#timer = undefined;
|
|
220
|
-
this.#initialTimer = undefined;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// packages/ws/src/close-codes.ts
|
|
225
|
-
var GatewayCloseCodes = {
|
|
226
|
-
UnknownError: 4000,
|
|
227
|
-
UnknownOpcode: 4001,
|
|
228
|
-
DecodeError: 4002,
|
|
229
|
-
NotAuthenticated: 4003,
|
|
230
|
-
AuthenticationFailed: 4004,
|
|
231
|
-
AlreadyAuthenticated: 4005,
|
|
232
|
-
InvalidSeq: 4007,
|
|
233
|
-
RateLimited: 4008,
|
|
234
|
-
SessionTimedOut: 4009,
|
|
235
|
-
InvalidShard: 4010,
|
|
236
|
-
ShardingRequired: 4011,
|
|
237
|
-
InvalidAPIVersion: 4012,
|
|
238
|
-
InvalidIntents: 4013,
|
|
239
|
-
DisallowedIntents: 4014
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
// packages/ws/src/reconnect.ts
|
|
243
|
-
var FATAL_CLOSE_CODES = [
|
|
244
|
-
GatewayCloseCodes.AuthenticationFailed,
|
|
245
|
-
GatewayCloseCodes.InvalidShard,
|
|
246
|
-
GatewayCloseCodes.ShardingRequired,
|
|
247
|
-
GatewayCloseCodes.InvalidAPIVersion,
|
|
248
|
-
GatewayCloseCodes.InvalidIntents,
|
|
249
|
-
GatewayCloseCodes.DisallowedIntents
|
|
250
|
-
];
|
|
251
|
-
var IDENTIFY_CLOSE_CODES = [
|
|
252
|
-
GatewayCloseCodes.InvalidSeq,
|
|
253
|
-
GatewayCloseCodes.SessionTimedOut
|
|
254
|
-
];
|
|
255
|
-
function classifyCloseCode(code, canResume) {
|
|
256
|
-
if (FATAL_CLOSE_CODES.includes(code))
|
|
257
|
-
return "stop";
|
|
258
|
-
if (IDENTIFY_CLOSE_CODES.includes(code))
|
|
259
|
-
return "identify";
|
|
260
|
-
return canResume ? "resume" : "identify";
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
class GatewayReconnect {
|
|
264
|
-
#options;
|
|
265
|
-
#random;
|
|
266
|
-
#attempt = 0;
|
|
267
|
-
#recent = [];
|
|
268
|
-
#timer;
|
|
269
|
-
#promise;
|
|
270
|
-
#resolve;
|
|
271
|
-
#reject;
|
|
272
|
-
constructor(options) {
|
|
273
|
-
this.#options = options;
|
|
274
|
-
this.#random = options.random ?? Math.random;
|
|
275
|
-
}
|
|
276
|
-
get enabled() {
|
|
277
|
-
return this.#options.enabled;
|
|
278
|
-
}
|
|
279
|
-
get attempts() {
|
|
280
|
-
return this.#attempt;
|
|
281
|
-
}
|
|
282
|
-
get pending() {
|
|
283
|
-
return this.#timer !== undefined;
|
|
284
|
-
}
|
|
285
|
-
get exhausted() {
|
|
286
|
-
return this.#attempt >= this.#options.maxAttempts;
|
|
287
|
-
}
|
|
288
|
-
get connecting() {
|
|
289
|
-
return this.#promise !== undefined;
|
|
290
|
-
}
|
|
291
|
-
get attemptPromise() {
|
|
292
|
-
return this.#promise;
|
|
293
|
-
}
|
|
294
|
-
classifyClose(code, canResume) {
|
|
295
|
-
return classifyCloseCode(code, canResume);
|
|
296
|
-
}
|
|
297
|
-
canReconnect() {
|
|
298
|
-
return this.#options.enabled && !this.exhausted;
|
|
299
|
-
}
|
|
300
|
-
schedule(run) {
|
|
301
|
-
if (!this.#options.enabled)
|
|
302
|
-
return { scheduled: false, reason: "disabled" };
|
|
303
|
-
if (this.#timer)
|
|
304
|
-
return { scheduled: false, reason: "pending" };
|
|
305
|
-
if (this.exhausted)
|
|
306
|
-
return { scheduled: false, reason: "exhausted" };
|
|
307
|
-
const attempt = this.#attempt;
|
|
308
|
-
const now = (this.#options.now ?? Date.now)();
|
|
309
|
-
const window = this.#options.stormWindow ?? 60000;
|
|
310
|
-
const limit = this.#options.stormLimit ?? 5;
|
|
311
|
-
while (this.#recent.length && now - this.#recent[0] >= window)
|
|
312
|
-
this.#recent.shift();
|
|
313
|
-
const over = this.#recent.length - limit;
|
|
314
|
-
this.#recent.push(now);
|
|
315
|
-
let delay = Math.min(this.#options.maxDelay, this.#options.baseDelay * 2 ** this.#attempt++);
|
|
316
|
-
const unstable = over >= 0;
|
|
317
|
-
if (unstable)
|
|
318
|
-
delay = Math.min(this.#options.maxDelay, Math.max(delay, this.#options.baseDelay * 2 ** (over + 1)));
|
|
319
|
-
const jitter = this.#random() * Math.max(1, delay * 0.25);
|
|
320
|
-
const delayMs = delay + jitter;
|
|
321
|
-
this.#timer = setTimeout(() => {
|
|
322
|
-
this.#timer = undefined;
|
|
323
|
-
run();
|
|
324
|
-
}, delayMs);
|
|
325
|
-
return {
|
|
326
|
-
scheduled: true,
|
|
327
|
-
delayMs,
|
|
328
|
-
attempt,
|
|
329
|
-
...unstable ? { unstable: { reconnects: this.#recent.length } } : {}
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
cancel() {
|
|
333
|
-
if (this.#timer)
|
|
334
|
-
clearTimeout(this.#timer);
|
|
335
|
-
this.#timer = undefined;
|
|
336
|
-
}
|
|
337
|
-
reset() {
|
|
338
|
-
this.#attempt = 0;
|
|
339
|
-
}
|
|
340
|
-
attempt(start) {
|
|
341
|
-
if (this.#promise)
|
|
342
|
-
return this.#promise;
|
|
343
|
-
this.#promise = new Promise((resolve, reject) => {
|
|
344
|
-
this.#resolve = resolve;
|
|
345
|
-
this.#reject = reject;
|
|
346
|
-
start();
|
|
347
|
-
});
|
|
348
|
-
return this.#promise;
|
|
349
|
-
}
|
|
350
|
-
settle(error) {
|
|
351
|
-
const resolve = this.#resolve;
|
|
352
|
-
const reject = this.#reject;
|
|
353
|
-
this.#resolve = undefined;
|
|
354
|
-
this.#reject = undefined;
|
|
355
|
-
this.#promise = undefined;
|
|
356
|
-
if (error)
|
|
357
|
-
reject?.(error);
|
|
358
|
-
else
|
|
359
|
-
resolve?.();
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// packages/ws/src/decoder.ts
|
|
364
2
|
import {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
#chunks = [];
|
|
390
|
-
#size = 0;
|
|
391
|
-
#failure;
|
|
392
|
-
#pendingReject;
|
|
393
|
-
constructor(create = () => createInflate(), maxFrameBytes = 64 * 1024 * 1024) {
|
|
394
|
-
this.#create = create;
|
|
395
|
-
this.#maxFrameBytes = maxFrameBytes;
|
|
396
|
-
}
|
|
397
|
-
push(data) {
|
|
398
|
-
if (typeof data === "string")
|
|
399
|
-
return [data];
|
|
400
|
-
return this.#inflateFrame(data);
|
|
401
|
-
}
|
|
402
|
-
async#inflateFrame(data) {
|
|
403
|
-
const chunk = await toBytes(data);
|
|
404
|
-
const inflate = this.#inflate ??= this.#open();
|
|
405
|
-
if (this.#failure)
|
|
406
|
-
throw this.#failure;
|
|
407
|
-
const complete = chunk.length >= 4 && chunk[chunk.length - 4] === 0 && chunk[chunk.length - 3] === 0 && chunk[chunk.length - 2] === 255 && chunk[chunk.length - 1] === 255;
|
|
408
|
-
await this.#awaiting((settle) => inflate.write(chunk, (error) => error ? settle(error) : settle()));
|
|
409
|
-
if (!complete)
|
|
410
|
-
return [];
|
|
411
|
-
await this.#awaiting((settle) => inflate.flush(zlibConstants.Z_SYNC_FLUSH, () => settle()));
|
|
412
|
-
const parts = this.#chunks;
|
|
413
|
-
this.#chunks = [];
|
|
414
|
-
this.#size = 0;
|
|
415
|
-
if (parts.length === 0)
|
|
416
|
-
return [];
|
|
417
|
-
const total = parts.reduce((size, part) => size + part.length, 0);
|
|
418
|
-
const merged = new Uint8Array(total);
|
|
419
|
-
let offset = 0;
|
|
420
|
-
for (const part of parts) {
|
|
421
|
-
merged.set(part, offset);
|
|
422
|
-
offset += part.length;
|
|
423
|
-
}
|
|
424
|
-
return [new TextDecoder().decode(merged)];
|
|
425
|
-
}
|
|
426
|
-
reset() {
|
|
427
|
-
const inflate = this.#inflate;
|
|
428
|
-
this.#inflate = undefined;
|
|
429
|
-
this.#chunks = [];
|
|
430
|
-
this.#size = 0;
|
|
431
|
-
this.#failure = undefined;
|
|
432
|
-
this.#pendingReject = undefined;
|
|
433
|
-
if (!inflate)
|
|
434
|
-
return;
|
|
435
|
-
inflate.removeAllListeners();
|
|
436
|
-
try {
|
|
437
|
-
inflate.close();
|
|
438
|
-
} catch {}
|
|
439
|
-
}
|
|
440
|
-
#awaiting(run) {
|
|
441
|
-
if (this.#failure)
|
|
442
|
-
return Promise.reject(this.#failure);
|
|
443
|
-
return new Promise((resolve, reject) => {
|
|
444
|
-
this.#pendingReject = reject;
|
|
445
|
-
run((error) => {
|
|
446
|
-
this.#pendingReject = undefined;
|
|
447
|
-
if (error)
|
|
448
|
-
reject(error);
|
|
449
|
-
else if (this.#failure)
|
|
450
|
-
reject(this.#failure);
|
|
451
|
-
else
|
|
452
|
-
resolve();
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
#open() {
|
|
457
|
-
const inflate = this.#create();
|
|
458
|
-
inflate.on("data", (chunk) => {
|
|
459
|
-
if (this.#failure)
|
|
460
|
-
return;
|
|
461
|
-
this.#size += chunk.length;
|
|
462
|
-
if (this.#size > this.#maxFrameBytes) {
|
|
463
|
-
this.#chunks = [];
|
|
464
|
-
inflate.emit("error", new Error(`Gateway frame inflated past ${this.#maxFrameBytes} bytes.`));
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
this.#chunks.push(chunk);
|
|
468
|
-
});
|
|
469
|
-
inflate.on("error", (error) => {
|
|
470
|
-
this.#failure = error;
|
|
471
|
-
const reject = this.#pendingReject;
|
|
472
|
-
this.#pendingReject = undefined;
|
|
473
|
-
reject?.(error);
|
|
474
|
-
});
|
|
475
|
-
return inflate;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
function createDecoder(compress) {
|
|
479
|
-
return compress ? new ZlibStreamDecoder : new PlainTextDecoder;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// packages/ws/src/transport.ts
|
|
483
|
-
var OPEN = 1;
|
|
484
|
-
|
|
485
|
-
class WebSocketTransport {
|
|
486
|
-
#handlers;
|
|
487
|
-
#decoder;
|
|
488
|
-
#createSocket;
|
|
489
|
-
#compress;
|
|
490
|
-
#socket;
|
|
491
|
-
#generation = 0;
|
|
492
|
-
#queue = Promise.resolve();
|
|
493
|
-
constructor(options) {
|
|
494
|
-
this.#handlers = options.handlers;
|
|
495
|
-
this.#compress = options.compress ?? false;
|
|
496
|
-
this.#decoder = options.decoder ?? createDecoder(options.compress);
|
|
497
|
-
this.#createSocket = options.createSocket ?? ((url) => new WebSocket(url));
|
|
498
|
-
}
|
|
499
|
-
get connected() {
|
|
500
|
-
return this.#socket?.readyState === OPEN;
|
|
501
|
-
}
|
|
502
|
-
get live() {
|
|
503
|
-
return this.#socket !== undefined && this.#socket.readyState <= OPEN;
|
|
504
|
-
}
|
|
505
|
-
get generation() {
|
|
506
|
-
return this.#generation;
|
|
507
|
-
}
|
|
508
|
-
connect(url) {
|
|
509
|
-
this.#discard(1000, "Superseded by a new connection");
|
|
510
|
-
const generation = ++this.#generation;
|
|
511
|
-
this.#decoder.reset();
|
|
512
|
-
this.#queue = Promise.resolve();
|
|
513
|
-
let socket;
|
|
514
|
-
try {
|
|
515
|
-
socket = this.#createSocket(url);
|
|
516
|
-
} catch (error) {
|
|
517
|
-
return { ok: false, error: this.#asError(error) };
|
|
518
|
-
}
|
|
519
|
-
if (this.#compress) {
|
|
520
|
-
try {
|
|
521
|
-
socket.binaryType = "arraybuffer";
|
|
522
|
-
} catch {}
|
|
523
|
-
}
|
|
524
|
-
this.#socket = socket;
|
|
525
|
-
socket.addEventListener("open", () => {
|
|
526
|
-
if (!this.#owns(generation))
|
|
527
|
-
return;
|
|
528
|
-
this.#handlers.onOpen();
|
|
529
|
-
});
|
|
530
|
-
socket.addEventListener("message", (event) => {
|
|
531
|
-
if (!this.#owns(generation))
|
|
532
|
-
return;
|
|
533
|
-
let decoded;
|
|
534
|
-
try {
|
|
535
|
-
decoded = this.#decoder.push(event.data);
|
|
536
|
-
} catch (error) {
|
|
537
|
-
this.#handlers.onError(this.#asError(error));
|
|
538
|
-
this.#failDecoding(generation);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
if (!(decoded instanceof Promise)) {
|
|
542
|
-
for (const frame of decoded)
|
|
543
|
-
this.#handlers.onFrame(frame);
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
this.#queue = this.#queue.then(async () => {
|
|
547
|
-
const frames = await decoded;
|
|
548
|
-
if (!this.#owns(generation))
|
|
549
|
-
return;
|
|
550
|
-
for (const frame of frames)
|
|
551
|
-
this.#handlers.onFrame(frame);
|
|
552
|
-
}).catch((error) => {
|
|
553
|
-
if (!this.#owns(generation))
|
|
554
|
-
return;
|
|
555
|
-
this.#handlers.onError(this.#asError(error));
|
|
556
|
-
this.#failDecoding(generation);
|
|
557
|
-
});
|
|
558
|
-
});
|
|
559
|
-
socket.addEventListener("close", (event) => {
|
|
560
|
-
if (!this.#owns(generation))
|
|
561
|
-
return;
|
|
562
|
-
this.#socket = undefined;
|
|
563
|
-
this.#generation++;
|
|
564
|
-
this.#decoder.reset();
|
|
565
|
-
this.#handlers.onClose(event.code, event.reason ?? "");
|
|
566
|
-
});
|
|
567
|
-
socket.addEventListener("error", () => {
|
|
568
|
-
if (!this.#owns(generation))
|
|
569
|
-
return;
|
|
570
|
-
this.#handlers.onError(new Error("Gateway WebSocket error"));
|
|
571
|
-
});
|
|
572
|
-
return { ok: true };
|
|
573
|
-
}
|
|
574
|
-
send(data) {
|
|
575
|
-
if (!this.connected)
|
|
576
|
-
return false;
|
|
577
|
-
try {
|
|
578
|
-
this.#socket.send(data);
|
|
579
|
-
return true;
|
|
580
|
-
} catch (error) {
|
|
581
|
-
this.#handlers.onError(this.#asError(error));
|
|
582
|
-
return false;
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
#failDecoding(generation) {
|
|
586
|
-
if (this.#owns(generation))
|
|
587
|
-
this.close(4000, "decoder failure");
|
|
588
|
-
}
|
|
589
|
-
close(code = 1000, reason = "") {
|
|
590
|
-
const socket = this.#socket;
|
|
591
|
-
if (!socket)
|
|
592
|
-
return;
|
|
593
|
-
try {
|
|
594
|
-
socket.close(code, reason);
|
|
595
|
-
} catch (error) {
|
|
596
|
-
this.#handlers.onError(this.#asError(error));
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
destroy(code = 1000, reason = "") {
|
|
600
|
-
this.#discard(code, reason);
|
|
601
|
-
this.#decoder.reset();
|
|
602
|
-
}
|
|
603
|
-
#owns(generation) {
|
|
604
|
-
return generation === this.#generation;
|
|
605
|
-
}
|
|
606
|
-
#discard(code, reason) {
|
|
607
|
-
const socket = this.#socket;
|
|
608
|
-
if (!socket)
|
|
609
|
-
return;
|
|
610
|
-
this.#generation++;
|
|
611
|
-
this.#socket = undefined;
|
|
612
|
-
try {
|
|
613
|
-
socket.close(code, reason);
|
|
614
|
-
} catch (error) {
|
|
615
|
-
this.#handlers.onError(this.#asError(error));
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
#asError(error) {
|
|
619
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
// packages/ws/src/opcodes.ts
|
|
624
|
-
var GatewayOpcodes = {
|
|
625
|
-
Dispatch: 0,
|
|
626
|
-
Heartbeat: 1,
|
|
627
|
-
Identify: 2,
|
|
628
|
-
PresenceUpdate: 3,
|
|
629
|
-
VoiceStateUpdate: 4,
|
|
630
|
-
Resume: 6,
|
|
631
|
-
Reconnect: 7,
|
|
632
|
-
RequestGuildMembers: 8,
|
|
633
|
-
InvalidSession: 9,
|
|
634
|
-
Hello: 10,
|
|
635
|
-
HeartbeatAck: 11
|
|
636
|
-
};
|
|
637
|
-
|
|
638
|
-
// packages/ws/src/protocol.ts
|
|
639
|
-
function classifyFrame(raw) {
|
|
640
|
-
let payload;
|
|
641
|
-
try {
|
|
642
|
-
payload = JSON.parse(raw);
|
|
643
|
-
} catch (error) {
|
|
644
|
-
return {
|
|
645
|
-
sequence: null,
|
|
646
|
-
action: {
|
|
647
|
-
type: "invalid",
|
|
648
|
-
violation: "invalid-json",
|
|
649
|
-
message: "Gateway returned invalid JSON",
|
|
650
|
-
cause: error
|
|
651
|
-
}
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
return classifyPayload(payload);
|
|
655
|
-
}
|
|
656
|
-
function classifyPayload(payload) {
|
|
657
|
-
if (payload === null || typeof payload !== "object" || typeof payload.op !== "number")
|
|
658
|
-
return {
|
|
659
|
-
sequence: null,
|
|
660
|
-
action: {
|
|
661
|
-
type: "invalid",
|
|
662
|
-
violation: "invalid-payload",
|
|
663
|
-
message: "Gateway returned an invalid payload"
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
|
-
const frame = payload;
|
|
667
|
-
const sequence = typeof frame.s === "number" ? frame.s : null;
|
|
668
|
-
switch (frame.op) {
|
|
669
|
-
case GatewayOpcodes.Dispatch:
|
|
670
|
-
return {
|
|
671
|
-
sequence,
|
|
672
|
-
action: {
|
|
673
|
-
type: "dispatch",
|
|
674
|
-
event: typeof frame.t === "string" ? frame.t : null,
|
|
675
|
-
data: frame.d
|
|
676
|
-
}
|
|
677
|
-
};
|
|
678
|
-
case GatewayOpcodes.Hello: {
|
|
679
|
-
const interval = frame.d?.heartbeat_interval;
|
|
680
|
-
if (typeof interval !== "number" || !Number.isFinite(interval) || interval <= 0)
|
|
681
|
-
return {
|
|
682
|
-
sequence,
|
|
683
|
-
action: {
|
|
684
|
-
type: "invalid",
|
|
685
|
-
violation: "invalid-hello",
|
|
686
|
-
message: "Gateway HELLO payload contains an invalid heartbeat interval"
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
return {
|
|
690
|
-
sequence,
|
|
691
|
-
action: { type: "hello", heartbeatInterval: interval }
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
case GatewayOpcodes.Heartbeat:
|
|
695
|
-
return { sequence, action: { type: "heartbeat" } };
|
|
696
|
-
case GatewayOpcodes.HeartbeatAck:
|
|
697
|
-
return {
|
|
698
|
-
sequence,
|
|
699
|
-
action: { type: "heartbeat-ack", data: frame.d }
|
|
700
|
-
};
|
|
701
|
-
case GatewayOpcodes.Reconnect:
|
|
702
|
-
return { sequence, action: { type: "reconnect" } };
|
|
703
|
-
case GatewayOpcodes.InvalidSession:
|
|
704
|
-
return {
|
|
705
|
-
sequence,
|
|
706
|
-
action: {
|
|
707
|
-
type: "invalid-session",
|
|
708
|
-
resumable: frame.d === true
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
default:
|
|
712
|
-
return { sequence, action: { type: "unknown", opcode: frame.op } };
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
function identifyPayload(options) {
|
|
716
|
-
const props = options.properties ?? {};
|
|
717
|
-
const os = props.os ?? process.platform;
|
|
718
|
-
const browser = props.browser ?? "Lunibee";
|
|
719
|
-
const device = props.device ?? "Lunibee";
|
|
720
|
-
return {
|
|
721
|
-
op: GatewayOpcodes.Identify,
|
|
722
|
-
d: {
|
|
723
|
-
token: options.token,
|
|
724
|
-
intents: options.intents,
|
|
725
|
-
properties: {
|
|
726
|
-
os,
|
|
727
|
-
browser,
|
|
728
|
-
device,
|
|
729
|
-
$os: os,
|
|
730
|
-
$browser: browser,
|
|
731
|
-
$device: device,
|
|
732
|
-
...props
|
|
733
|
-
},
|
|
734
|
-
presence: {
|
|
735
|
-
since: options.presence?.since ?? null,
|
|
736
|
-
activities: options.presence?.activities ?? [],
|
|
737
|
-
status: options.presence?.status ?? "online",
|
|
738
|
-
afk: Boolean(options.presence?.afk)
|
|
739
|
-
},
|
|
740
|
-
shard: [options.shardId, options.shardCount]
|
|
741
|
-
},
|
|
742
|
-
s: null,
|
|
743
|
-
t: null
|
|
744
|
-
};
|
|
745
|
-
}
|
|
746
|
-
function resumePayload(token, resume) {
|
|
747
|
-
return {
|
|
748
|
-
op: GatewayOpcodes.Resume,
|
|
749
|
-
d: {
|
|
750
|
-
token,
|
|
751
|
-
session_id: resume.sessionId,
|
|
752
|
-
seq: resume.sequence
|
|
753
|
-
},
|
|
754
|
-
s: null,
|
|
755
|
-
t: null
|
|
756
|
-
};
|
|
757
|
-
}
|
|
758
|
-
function heartbeatPayload(sequence) {
|
|
759
|
-
return { op: GatewayOpcodes.Heartbeat, d: sequence, s: null, t: null };
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
// packages/types/src/channel-kind.ts
|
|
763
|
-
var ChannelKinds = {
|
|
764
|
-
text: [0],
|
|
765
|
-
dm: [1],
|
|
766
|
-
voice: [2],
|
|
767
|
-
"group-dm": [3],
|
|
768
|
-
category: [4],
|
|
769
|
-
announcement: [5],
|
|
770
|
-
thread: [10, 11, 12],
|
|
771
|
-
stage: [13],
|
|
772
|
-
directory: [14],
|
|
773
|
-
forum: [15],
|
|
774
|
-
media: [16]
|
|
775
|
-
};
|
|
776
|
-
var KIND_OF_TYPE = new Map(Object.keys(ChannelKinds).flatMap((kind) => ChannelKinds[kind].map((type) => [type, kind])));
|
|
777
|
-
// packages/types/src/gateway.ts
|
|
778
|
-
var GatewayIntentBits = {
|
|
779
|
-
Guilds: 1 << 0,
|
|
780
|
-
GuildMembers: 1 << 1,
|
|
781
|
-
GuildModeration: 1 << 2,
|
|
782
|
-
GuildExpressions: 1 << 3,
|
|
783
|
-
GuildIntegrations: 1 << 4,
|
|
784
|
-
GuildWebhooks: 1 << 5,
|
|
785
|
-
GuildInvites: 1 << 6,
|
|
786
|
-
GuildVoiceStates: 1 << 7,
|
|
787
|
-
GuildPresences: 1 << 8,
|
|
788
|
-
GuildMessages: 1 << 9,
|
|
789
|
-
GuildMessageReactions: 1 << 10,
|
|
790
|
-
GuildMessageTyping: 1 << 11,
|
|
791
|
-
DirectMessages: 1 << 12,
|
|
792
|
-
DirectMessageReactions: 1 << 13,
|
|
793
|
-
DirectMessageTyping: 1 << 14,
|
|
794
|
-
MessageContent: 1 << 15,
|
|
795
|
-
GuildScheduledEvents: 1 << 16,
|
|
796
|
-
AutoModerationConfiguration: 1 << 20,
|
|
797
|
-
AutoModerationExecution: 1 << 21,
|
|
798
|
-
GuildMessagePolls: 1 << 24,
|
|
799
|
-
DirectMessagePolls: 1 << 25
|
|
800
|
-
};
|
|
801
|
-
var IntentBits = {
|
|
802
|
-
guild: 1 << 0,
|
|
803
|
-
guilds: 1 << 0,
|
|
804
|
-
guildMembers: 1 << 1,
|
|
805
|
-
guildModeration: 1 << 2,
|
|
806
|
-
guildBans: 1 << 2,
|
|
807
|
-
guildExpressions: 1 << 3,
|
|
808
|
-
guildEmojis: 1 << 3,
|
|
809
|
-
guildEmojisAndStickers: 1 << 3,
|
|
810
|
-
guildIntegrations: 1 << 4,
|
|
811
|
-
guildWebhooks: 1 << 5,
|
|
812
|
-
guildInvites: 1 << 6,
|
|
813
|
-
guildVoiceStates: 1 << 7,
|
|
814
|
-
guildPresences: 1 << 8,
|
|
815
|
-
guildMessages: 1 << 9,
|
|
816
|
-
guildMessage: 1 << 9,
|
|
817
|
-
guildMessageReactions: 1 << 10,
|
|
818
|
-
guildMessageTyping: 1 << 11,
|
|
819
|
-
directMessages: 1 << 12,
|
|
820
|
-
directMessageReactions: 1 << 13,
|
|
821
|
-
directMessageTyping: 1 << 14,
|
|
822
|
-
messageContent: 1 << 15,
|
|
823
|
-
guildScheduledEvents: 1 << 16,
|
|
824
|
-
autoModerationConfiguration: 1 << 20,
|
|
825
|
-
autoModerationExecution: 1 << 21,
|
|
826
|
-
guildMessagePolls: 1 << 24,
|
|
827
|
-
directMessagePolls: 1 << 25
|
|
828
|
-
};
|
|
829
|
-
function resolveGatewayIntents(intents) {
|
|
830
|
-
if (!Array.isArray(intents))
|
|
831
|
-
throw new TypeError("Gateway intents must be an array, e.g. [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages].");
|
|
832
|
-
return intents.reduce((acc, intent) => acc | resolveIntent(intent), 0);
|
|
833
|
-
}
|
|
834
|
-
function resolveIntent(intent) {
|
|
835
|
-
if (typeof intent === "number")
|
|
836
|
-
return intent;
|
|
837
|
-
const bits = {
|
|
838
|
-
...IntentBits,
|
|
839
|
-
...GatewayIntentBits
|
|
840
|
-
};
|
|
841
|
-
const lower = intent.charAt(0).toLowerCase() + intent.slice(1);
|
|
842
|
-
if (Object.hasOwn(bits, intent))
|
|
843
|
-
return bits[intent];
|
|
844
|
-
if (Object.hasOwn(bits, lower))
|
|
845
|
-
return bits[lower];
|
|
846
|
-
const num = Number(intent);
|
|
847
|
-
return Number.isNaN(num) ? 0 : num;
|
|
848
|
-
}
|
|
849
|
-
// packages/ws/src/dispatcher.ts
|
|
850
|
-
class GatewayDispatcher {
|
|
851
|
-
#listeners = new Map;
|
|
852
|
-
#onFailure;
|
|
853
|
-
constructor(onFailure) {
|
|
854
|
-
this.#onFailure = onFailure;
|
|
855
|
-
}
|
|
856
|
-
on(event, listener) {
|
|
857
|
-
let listeners = this.#listeners.get(event);
|
|
858
|
-
if (!listeners)
|
|
859
|
-
this.#listeners.set(event, listeners = new Set);
|
|
860
|
-
listeners.add(listener);
|
|
861
|
-
}
|
|
862
|
-
off(event, listener) {
|
|
863
|
-
this.#listeners.get(event)?.delete(listener);
|
|
864
|
-
}
|
|
865
|
-
emit(event, data) {
|
|
866
|
-
for (const listener of this.#listeners.get(event) ?? []) {
|
|
867
|
-
try {
|
|
868
|
-
const result = listener(data);
|
|
869
|
-
if (result && typeof result.then === "function")
|
|
870
|
-
Promise.resolve(result).catch((error) => {
|
|
871
|
-
if (event !== "error")
|
|
872
|
-
this.#onFailure(error);
|
|
873
|
-
});
|
|
874
|
-
} catch (error) {
|
|
875
|
-
if (event !== "error")
|
|
876
|
-
this.#onFailure(error);
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
// packages/ws/src/send-budget.ts
|
|
882
|
-
class GatewaySendLimiter {
|
|
883
|
-
#timestamps = [];
|
|
884
|
-
#limit;
|
|
885
|
-
#windowMs;
|
|
886
|
-
constructor(limit = 115, windowMs = 60000) {
|
|
887
|
-
this.#limit = limit;
|
|
888
|
-
this.#windowMs = windowMs;
|
|
889
|
-
}
|
|
890
|
-
get used() {
|
|
891
|
-
return this.#timestamps.length;
|
|
892
|
-
}
|
|
893
|
-
allows(privileged, now = Date.now()) {
|
|
894
|
-
while (this.#timestamps.length && now - this.#timestamps[0] >= this.#windowMs)
|
|
895
|
-
this.#timestamps.shift();
|
|
896
|
-
return privileged || this.#timestamps.length < this.#limit;
|
|
897
|
-
}
|
|
898
|
-
record(now = Date.now()) {
|
|
899
|
-
this.#timestamps.push(now);
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
var SendBudget = GatewaySendLimiter;
|
|
903
|
-
// packages/ws/src/state.ts
|
|
904
|
-
var GatewayState;
|
|
905
|
-
((GatewayState) => {
|
|
906
|
-
GatewayState["Connect"] = "CONNECT";
|
|
907
|
-
GatewayState["Hello"] = "HELLO";
|
|
908
|
-
GatewayState["Identify"] = "IDENTIFY";
|
|
909
|
-
GatewayState["Resume"] = "RESUME";
|
|
910
|
-
GatewayState["Ready"] = "READY";
|
|
911
|
-
GatewayState["Dispatch"] = "DISPATCH";
|
|
912
|
-
GatewayState["Heartbeat"] = "HEARTBEAT";
|
|
913
|
-
GatewayState["Reconnect"] = "RECONNECT";
|
|
914
|
-
GatewayState["Closed"] = "CLOSED";
|
|
915
|
-
})(GatewayState ||= {});
|
|
916
|
-
class GatewayError extends Error {
|
|
917
|
-
code;
|
|
918
|
-
constructor(message, code, options) {
|
|
919
|
-
super(message, options);
|
|
920
|
-
this.name = "GatewayError";
|
|
921
|
-
this.code = code;
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
// packages/ws/src/index.ts
|
|
925
|
-
var RESUMABLE_CLOSE_CODE = 4900;
|
|
926
|
-
var DEFAULT_GATEWAY_URL = "wss://gateway.discord.gg/?v=10&encoding=json";
|
|
927
|
-
|
|
928
|
-
class Gateway {
|
|
929
|
-
state = "CONNECT" /* Connect */;
|
|
930
|
-
#options;
|
|
931
|
-
#transport;
|
|
932
|
-
#session = new GatewaySession;
|
|
933
|
-
#token = 0;
|
|
934
|
-
#heartbeat;
|
|
935
|
-
#closed = false;
|
|
936
|
-
#reconnect;
|
|
937
|
-
#events = new GatewayDispatcher((error) => this.#emitError(error));
|
|
938
|
-
#sendBudget = new GatewaySendLimiter;
|
|
939
|
-
#reconnects = 0;
|
|
940
|
-
ping = -1;
|
|
941
|
-
constructor(options) {
|
|
942
|
-
if (!options.token?.trim())
|
|
943
|
-
throw new TypeError("A Gateway token is required.");
|
|
944
|
-
for (const key of [
|
|
945
|
-
"reconnectBaseDelay",
|
|
946
|
-
"reconnectMaxDelay",
|
|
947
|
-
"connectTimeout"
|
|
948
|
-
])
|
|
949
|
-
if (options[key] !== undefined && !(options[key] > 0))
|
|
950
|
-
throw new RangeError(`Gateway ${key} must be greater than 0.`);
|
|
951
|
-
const resolvedIntents = resolveGatewayIntents(options.intents);
|
|
952
|
-
if (!Number.isInteger(resolvedIntents) || resolvedIntents < 0)
|
|
953
|
-
throw new TypeError("Gateway intents must be a non-negative integer.");
|
|
954
|
-
this.#options = {
|
|
955
|
-
shardId: 0,
|
|
956
|
-
shardCount: 1,
|
|
957
|
-
reconnect: true,
|
|
958
|
-
maxReconnectAttempts: Infinity,
|
|
959
|
-
connectTimeout: 30000,
|
|
960
|
-
reconnectBaseDelay: 1000,
|
|
961
|
-
reconnectMaxDelay: 30000,
|
|
962
|
-
heartbeatAckTimeout: 1e4,
|
|
963
|
-
zombieTimeout: 30000,
|
|
964
|
-
properties: {
|
|
965
|
-
os: process.platform,
|
|
966
|
-
browser: "Lunibee",
|
|
967
|
-
device: "Lunibee"
|
|
968
|
-
},
|
|
969
|
-
presence: {
|
|
970
|
-
status: "online",
|
|
971
|
-
activities: [],
|
|
972
|
-
afk: false,
|
|
973
|
-
since: null
|
|
974
|
-
},
|
|
975
|
-
...options,
|
|
976
|
-
intents: resolvedIntents
|
|
977
|
-
};
|
|
978
|
-
if (this.#options.shardId < 0 || this.#options.shardId >= this.#options.shardCount)
|
|
979
|
-
throw new RangeError("Gateway shardId must be within the configured shard count.");
|
|
980
|
-
if (this.#options.zombieTimeout <= this.#options.heartbeatAckTimeout)
|
|
981
|
-
throw new RangeError("Gateway zombieTimeout must be greater than heartbeatAckTimeout");
|
|
982
|
-
this.#transport = new WebSocketTransport({
|
|
983
|
-
compress: this.#options.compress,
|
|
984
|
-
createSocket: options.createSocket,
|
|
985
|
-
handlers: {
|
|
986
|
-
onOpen: () => this.#onOpen(),
|
|
987
|
-
onFrame: (raw) => this.#message(raw, this.#token),
|
|
988
|
-
onClose: (code) => this.#close(code, this.#token),
|
|
989
|
-
onError: (error) => this.#emitError(error instanceof GatewayError ? error : new GatewayError(error.message, undefined, {
|
|
990
|
-
cause: error
|
|
991
|
-
}))
|
|
992
|
-
}
|
|
993
|
-
});
|
|
994
|
-
this.#reconnect = new GatewayReconnect({
|
|
995
|
-
enabled: this.#options.reconnect,
|
|
996
|
-
maxAttempts: this.#options.maxReconnectAttempts,
|
|
997
|
-
baseDelay: this.#options.reconnectBaseDelay,
|
|
998
|
-
maxDelay: this.#options.reconnectMaxDelay,
|
|
999
|
-
stormLimit: options.reconnectStormLimit,
|
|
1000
|
-
stormWindow: options.reconnectStormWindow
|
|
1001
|
-
});
|
|
1002
|
-
this.#heartbeat = new GatewayHeartbeat({
|
|
1003
|
-
ackTimeout: this.#options.heartbeatAckTimeout,
|
|
1004
|
-
zombieTimeout: this.#options.zombieTimeout,
|
|
1005
|
-
send: (sequence) => this.#dispatch(heartbeatPayload(sequence), true),
|
|
1006
|
-
sequence: () => this.#session.sequence,
|
|
1007
|
-
isConnected: () => !this.#closed && this.#transport.connected,
|
|
1008
|
-
onTimeout: (timeout) => this.#onHeartbeatTimeout(timeout),
|
|
1009
|
-
onError: (error) => this.#emitError(error)
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
#onHeartbeatTimeout(timeout) {
|
|
1013
|
-
if (timeout.type === "zombie") {
|
|
1014
|
-
this.#emit("zombie", {
|
|
1015
|
-
silentFor: timeout.silentFor,
|
|
1016
|
-
timeout: timeout.deadline
|
|
1017
|
-
});
|
|
1018
|
-
this.#emitError(new GatewayError(`Gateway connection appears stale after ${timeout.silentFor}ms without traffic.`));
|
|
1019
|
-
} else {
|
|
1020
|
-
this.#emitError(new GatewayError(`Gateway heartbeat acknowledgement timed out after ${timeout.elapsedMs}ms.`));
|
|
1021
|
-
}
|
|
1022
|
-
this.#transport.close(RESUMABLE_CLOSE_CODE, timeout.type === "zombie" ? "Zombie Gateway connection" : "Heartbeat timeout");
|
|
1023
|
-
}
|
|
1024
|
-
connect(url = DEFAULT_GATEWAY_URL) {
|
|
1025
|
-
if (this.state === "CLOSED" /* Closed */)
|
|
1026
|
-
return Promise.reject(new GatewayError("Gateway has been permanently closed."));
|
|
1027
|
-
const inFlight = this.#reconnect.attemptPromise;
|
|
1028
|
-
if (inFlight)
|
|
1029
|
-
return inFlight;
|
|
1030
|
-
if (this.#transport.live)
|
|
1031
|
-
return Promise.resolve();
|
|
1032
|
-
this.#reconnect.cancel();
|
|
1033
|
-
this.#closed = false;
|
|
1034
|
-
this.#setState("CONNECT" /* Connect */);
|
|
1035
|
-
const connectURL = this.#options.compress ? url.includes("compress=") ? url : `${url}${url.includes("?") ? "&" : "?"}compress=zlib-stream` : url;
|
|
1036
|
-
return this.#reconnect.attempt(() => this.#open(connectURL));
|
|
1037
|
-
}
|
|
1038
|
-
close() {
|
|
1039
|
-
this.#closed = true;
|
|
1040
|
-
this.#clearTimers();
|
|
1041
|
-
this.#settleConnect(new GatewayError("Gateway connection closed before socket open."));
|
|
1042
|
-
this.#transport.destroy(1000, "Client closed connection");
|
|
1043
|
-
this.#setState("CLOSED" /* Closed */);
|
|
1044
|
-
}
|
|
1045
|
-
emit(event, data) {
|
|
1046
|
-
this.#emit(event, data);
|
|
1047
|
-
}
|
|
1048
|
-
on(event, listener) {
|
|
1049
|
-
if (!event || typeof listener !== "function")
|
|
1050
|
-
throw new TypeError("Gateway event and listener are required.");
|
|
1051
|
-
this.#events.on(event, listener);
|
|
1052
|
-
return this;
|
|
1053
|
-
}
|
|
1054
|
-
off(event, listener) {
|
|
1055
|
-
this.#events.off(event, listener);
|
|
1056
|
-
return this;
|
|
1057
|
-
}
|
|
1058
|
-
health() {
|
|
1059
|
-
return {
|
|
1060
|
-
state: this.state,
|
|
1061
|
-
latency: this.#heartbeat.latency,
|
|
1062
|
-
silentFor: this.#heartbeat.silentFor,
|
|
1063
|
-
reconnects: this.#reconnects
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
send(payload) {
|
|
1067
|
-
if (!payload || !Number.isInteger(payload.op))
|
|
1068
|
-
throw new TypeError("Gateway payload must contain an integer opcode.");
|
|
1069
|
-
return this.#dispatch(payload, false);
|
|
1070
|
-
}
|
|
1071
|
-
#dispatch(payload, privileged) {
|
|
1072
|
-
if (!this.#transport.connected)
|
|
1073
|
-
return false;
|
|
1074
|
-
const now = Date.now();
|
|
1075
|
-
if (!this.#sendBudget.allows(privileged, now)) {
|
|
1076
|
-
this.#emitError(new GatewayError("Gateway send rate budget exhausted."));
|
|
1077
|
-
return false;
|
|
1078
|
-
}
|
|
1079
|
-
if (!this.#transport.send(JSON.stringify(payload)))
|
|
1080
|
-
return false;
|
|
1081
|
-
this.#sendBudget.record(now);
|
|
1082
|
-
return true;
|
|
1083
|
-
}
|
|
1084
|
-
setPresence(data) {
|
|
1085
|
-
this.#options.presence = { ...this.#options.presence, ...data };
|
|
1086
|
-
const payload = {
|
|
1087
|
-
since: this.#options.presence.since ?? null,
|
|
1088
|
-
activities: this.#options.presence.activities ?? [],
|
|
1089
|
-
status: this.#options.presence.status ?? "online",
|
|
1090
|
-
afk: Boolean(this.#options.presence.afk)
|
|
1091
|
-
};
|
|
1092
|
-
return this.send({
|
|
1093
|
-
op: GatewayOpcodes.PresenceUpdate,
|
|
1094
|
-
d: payload,
|
|
1095
|
-
s: null,
|
|
1096
|
-
t: null
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
setVoiceState(data) {
|
|
1100
|
-
return this.send({
|
|
1101
|
-
op: GatewayOpcodes.VoiceStateUpdate,
|
|
1102
|
-
d: data,
|
|
1103
|
-
s: null,
|
|
1104
|
-
t: null
|
|
1105
|
-
});
|
|
1106
|
-
}
|
|
1107
|
-
sendVoiceState(guildId, channelId, options = {}) {
|
|
1108
|
-
if (!this.ownsGuild(guildId))
|
|
1109
|
-
return false;
|
|
1110
|
-
return this.setVoiceState({
|
|
1111
|
-
guild_id: guildId,
|
|
1112
|
-
channel_id: channelId,
|
|
1113
|
-
self_mute: options.selfMute ?? false,
|
|
1114
|
-
self_deaf: options.selfDeaf ?? false
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
ownsGuild(guildId) {
|
|
1118
|
-
const count = this.#options.shardCount;
|
|
1119
|
-
if (count <= 1)
|
|
1120
|
-
return true;
|
|
1121
|
-
if (!/^\d{1,20}$/.test(guildId))
|
|
1122
|
-
return false;
|
|
1123
|
-
return Number((BigInt(guildId) >> 22n) % BigInt(count)) === this.#options.shardId;
|
|
1124
|
-
}
|
|
1125
|
-
requestGuildMembers(data) {
|
|
1126
|
-
return this.send({
|
|
1127
|
-
op: GatewayOpcodes.RequestGuildMembers,
|
|
1128
|
-
d: data,
|
|
1129
|
-
s: null,
|
|
1130
|
-
t: null
|
|
1131
|
-
});
|
|
1132
|
-
}
|
|
1133
|
-
#open(url) {
|
|
1134
|
-
if (this.#closed)
|
|
1135
|
-
return;
|
|
1136
|
-
this.#token = this.#session.beginConnection();
|
|
1137
|
-
const result = this.#transport.connect(url);
|
|
1138
|
-
if (result.ok) {
|
|
1139
|
-
const token = this.#token;
|
|
1140
|
-
clearTimeout(this.#connectTimer);
|
|
1141
|
-
this.#connectTimer = setTimeout(() => {
|
|
1142
|
-
if (token === this.#token && !this.#closed)
|
|
1143
|
-
this.#transport.close(4000, "connect timeout");
|
|
1144
|
-
}, this.#options.connectTimeout);
|
|
1145
|
-
this.#connectTimer.unref?.();
|
|
1146
|
-
return;
|
|
1147
|
-
}
|
|
1148
|
-
const failure = this.#normalizeError(result.error);
|
|
1149
|
-
this.#emitError(failure);
|
|
1150
|
-
if (this.#options.reconnect) {
|
|
1151
|
-
this.#setState("RECONNECT" /* Reconnect */);
|
|
1152
|
-
this.#scheduleReconnect();
|
|
1153
|
-
} else {
|
|
1154
|
-
this.#settleConnect(failure);
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
#connectTimer;
|
|
1158
|
-
#onOpen() {
|
|
1159
|
-
clearTimeout(this.#connectTimer);
|
|
1160
|
-
this.#heartbeat.watch();
|
|
1161
|
-
this.#emit("open", undefined);
|
|
1162
|
-
this.#settleConnect();
|
|
1163
|
-
}
|
|
1164
|
-
#message(raw, token) {
|
|
1165
|
-
if (!this.#session.owns(token))
|
|
1166
|
-
return;
|
|
1167
|
-
this.#heartbeat.receivedMessage();
|
|
1168
|
-
const { sequence, action } = classifyFrame(raw);
|
|
1169
|
-
if (sequence !== null)
|
|
1170
|
-
this.#session.recordSequence(sequence, token);
|
|
1171
|
-
this.#apply(action, token);
|
|
1172
|
-
}
|
|
1173
|
-
#apply(action, token) {
|
|
1174
|
-
switch (action.type) {
|
|
1175
|
-
case "dispatch":
|
|
1176
|
-
this.#setState("DISPATCH" /* Dispatch */);
|
|
1177
|
-
this.#handleDispatch(action.event, action.data, token);
|
|
1178
|
-
return;
|
|
1179
|
-
case "hello":
|
|
1180
|
-
this.#handleHello(action.heartbeatInterval);
|
|
1181
|
-
return;
|
|
1182
|
-
case "heartbeat":
|
|
1183
|
-
this.#setState("HEARTBEAT" /* Heartbeat */);
|
|
1184
|
-
this.#heartbeat.sendHeartbeat();
|
|
1185
|
-
return;
|
|
1186
|
-
case "heartbeat-ack":
|
|
1187
|
-
this.#heartbeat.acknowledge();
|
|
1188
|
-
this.ping = this.#heartbeat.latency;
|
|
1189
|
-
this.#emit("heartbeatAck", action.data);
|
|
1190
|
-
return;
|
|
1191
|
-
case "reconnect":
|
|
1192
|
-
this.#transport.close(RESUMABLE_CLOSE_CODE, "Server requested reconnect");
|
|
1193
|
-
return;
|
|
1194
|
-
case "invalid-session": {
|
|
1195
|
-
if (!action.resumable)
|
|
1196
|
-
this.#session.invalidate(token, "invalid-session");
|
|
1197
|
-
this.#emit("invalidSession", action.resumable);
|
|
1198
|
-
this.#transport.close(action.resumable ? GatewayCloseCodes.UnknownError : 1000, action.resumable ? "Invalid session (resumable)" : "Invalid session");
|
|
1199
|
-
return;
|
|
1200
|
-
}
|
|
1201
|
-
case "invalid":
|
|
1202
|
-
this.#emitError(new GatewayError(action.message, undefined, action.cause === undefined ? undefined : { cause: action.cause }));
|
|
1203
|
-
this.#transport.close(1002, action.violation === "invalid-json" ? "Invalid JSON" : action.violation === "invalid-hello" ? "Invalid heartbeat interval" : "Invalid payload");
|
|
1204
|
-
return;
|
|
1205
|
-
case "unknown":
|
|
1206
|
-
return;
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
#handleDispatch(event, data, token) {
|
|
1210
|
-
if (event === "READY") {
|
|
1211
|
-
if (!this.#session.activate(data, token)) {
|
|
1212
|
-
if (this.#session.owns(token))
|
|
1213
|
-
this.#emitError(new GatewayError("Gateway READY payload is missing session information"));
|
|
1214
|
-
return;
|
|
1215
|
-
}
|
|
1216
|
-
this.#reconnect.reset();
|
|
1217
|
-
this.#setState("READY" /* Ready */);
|
|
1218
|
-
this.#emit("ready", data);
|
|
1219
|
-
} else if (event === "RESUMED") {
|
|
1220
|
-
this.#reconnect.reset();
|
|
1221
|
-
this.#setState("READY" /* Ready */);
|
|
1222
|
-
this.#emit("resumed", data);
|
|
1223
|
-
}
|
|
1224
|
-
this.#emit("RAW", { event: event ?? "UNKNOWN", data });
|
|
1225
|
-
if (this.#closed)
|
|
1226
|
-
return;
|
|
1227
|
-
if (event == null || /^[A-Z][A-Z0-9_]*$/.test(event))
|
|
1228
|
-
this.#emit(event ?? "dispatch", data);
|
|
1229
|
-
}
|
|
1230
|
-
#handleHello(interval) {
|
|
1231
|
-
this.#setState(this.#session.canResume ? "RESUME" /* Resume */ : "HELLO" /* Hello */);
|
|
1232
|
-
this.#heartbeat.start(interval);
|
|
1233
|
-
this.#identifyOrResume();
|
|
1234
|
-
}
|
|
1235
|
-
#identifyOrResume() {
|
|
1236
|
-
const intent = this.#session.handshake();
|
|
1237
|
-
if (intent.type === "resume") {
|
|
1238
|
-
this.#setState("RESUME" /* Resume */);
|
|
1239
|
-
this.#dispatch(resumePayload(this.#options.token, intent), true);
|
|
1240
|
-
return;
|
|
1241
|
-
}
|
|
1242
|
-
this.#setState("IDENTIFY" /* Identify */);
|
|
1243
|
-
this.#dispatch(identifyPayload({
|
|
1244
|
-
token: this.#options.token,
|
|
1245
|
-
intents: this.#options.intents,
|
|
1246
|
-
shardId: this.#options.shardId,
|
|
1247
|
-
shardCount: this.#options.shardCount,
|
|
1248
|
-
properties: this.#options.properties,
|
|
1249
|
-
presence: this.#options.presence
|
|
1250
|
-
}), true);
|
|
1251
|
-
}
|
|
1252
|
-
#close(code, token) {
|
|
1253
|
-
this.#clearTimers();
|
|
1254
|
-
const action = this.#reconnect.classifyClose(code, this.#session.canResume);
|
|
1255
|
-
this.#emit("close", { code, action });
|
|
1256
|
-
if (this.#closed || !this.#reconnect.enabled || action === "stop") {
|
|
1257
|
-
if (action === "stop")
|
|
1258
|
-
this.#closed = true;
|
|
1259
|
-
this.#setState(this.#closed ? "CLOSED" /* Closed */ : "CONNECT" /* Connect */);
|
|
1260
|
-
if (this.#reconnect.connecting)
|
|
1261
|
-
this.#reconnect.settle(new GatewayError(`Gateway closed before READY (code ${code}).`, code));
|
|
1262
|
-
return;
|
|
1263
|
-
}
|
|
1264
|
-
if (action === "identify")
|
|
1265
|
-
this.#session.invalidate(token, "session-timeout");
|
|
1266
|
-
this.#setState("RECONNECT" /* Reconnect */);
|
|
1267
|
-
this.#scheduleReconnect();
|
|
1268
|
-
}
|
|
1269
|
-
#scheduleReconnect() {
|
|
1270
|
-
if (this.#closed)
|
|
1271
|
-
return;
|
|
1272
|
-
const result = this.#reconnect.schedule(() => this.#open(this.#session.connectURL(DEFAULT_GATEWAY_URL)));
|
|
1273
|
-
if (result.scheduled) {
|
|
1274
|
-
this.#reconnects++;
|
|
1275
|
-
if (result.unstable)
|
|
1276
|
-
this.#emit("unstable", {
|
|
1277
|
-
reconnects: result.unstable.reconnects,
|
|
1278
|
-
delay: result.delayMs
|
|
1279
|
-
});
|
|
1280
|
-
return;
|
|
1281
|
-
}
|
|
1282
|
-
if (result.reason !== "exhausted")
|
|
1283
|
-
return;
|
|
1284
|
-
this.#reconnect.settle(new GatewayError("Gateway reconnect attempts exhausted."));
|
|
1285
|
-
this.#setState("CONNECT" /* Connect */);
|
|
1286
|
-
}
|
|
1287
|
-
#settleConnect(error) {
|
|
1288
|
-
this.#reconnect.settle(error);
|
|
1289
|
-
}
|
|
1290
|
-
#clearTimers() {
|
|
1291
|
-
clearTimeout(this.#connectTimer);
|
|
1292
|
-
this.#reconnect.cancel();
|
|
1293
|
-
this.#heartbeat.stop();
|
|
1294
|
-
}
|
|
1295
|
-
#normalizeError(error) {
|
|
1296
|
-
return error instanceof GatewayError ? error : new GatewayError("Gateway connection failed.", undefined, {
|
|
1297
|
-
cause: error
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
#emitError(error) {
|
|
1301
|
-
this.#emit("error", error instanceof Error ? error : new GatewayError(String(error)));
|
|
1302
|
-
}
|
|
1303
|
-
#emit(event, data) {
|
|
1304
|
-
this.#events.emit(event, data);
|
|
1305
|
-
}
|
|
1306
|
-
#setState(next) {
|
|
1307
|
-
if (this.state === next)
|
|
1308
|
-
return;
|
|
1309
|
-
const previous = this.state;
|
|
1310
|
-
this.state = next;
|
|
1311
|
-
this.#emit("stateChange", { previous, next });
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
3
|
+
GatewaySession2,
|
|
4
|
+
GatewayHeartbeat2,
|
|
5
|
+
GatewayCloseCodes2,
|
|
6
|
+
FATAL_CLOSE_CODES2,
|
|
7
|
+
IDENTIFY_CLOSE_CODES2,
|
|
8
|
+
classifyCloseCode2,
|
|
9
|
+
GatewayReconnect2,
|
|
10
|
+
PlainTextDecoder2,
|
|
11
|
+
ZlibStreamDecoder2,
|
|
12
|
+
createDecoder2,
|
|
13
|
+
WebSocketTransport2,
|
|
14
|
+
GatewayOpcodes2,
|
|
15
|
+
classifyFrame2,
|
|
16
|
+
classifyPayload2,
|
|
17
|
+
identifyPayload2,
|
|
18
|
+
resumePayload2,
|
|
19
|
+
heartbeatPayload2,
|
|
20
|
+
GatewayDispatcher2,
|
|
21
|
+
GatewaySendLimiter2,
|
|
22
|
+
GatewayState2,
|
|
23
|
+
GatewayError2,
|
|
24
|
+
Gateway2
|
|
25
|
+
} from "../chunks/index-fdvgk2sw.js";
|
|
26
|
+
import"../chunks/index-gyvps8b9.js";
|
|
1314
27
|
export {
|
|
1315
|
-
FATAL_CLOSE_CODES,
|
|
1316
|
-
Gateway,
|
|
1317
|
-
GatewayCloseCodes,
|
|
1318
|
-
GatewayDispatcher,
|
|
1319
|
-
GatewayError,
|
|
1320
|
-
GatewayHeartbeat,
|
|
1321
|
-
GatewayOpcodes,
|
|
1322
|
-
GatewayReconnect,
|
|
1323
|
-
GatewaySendLimiter,
|
|
1324
|
-
GatewaySession,
|
|
1325
|
-
GatewayState,
|
|
1326
|
-
IDENTIFY_CLOSE_CODES,
|
|
1327
|
-
PlainTextDecoder,
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
identifyPayload,
|
|
1338
|
-
resumePayload
|
|
28
|
+
FATAL_CLOSE_CODES2 as FATAL_CLOSE_CODES,
|
|
29
|
+
Gateway2 as Gateway,
|
|
30
|
+
GatewayCloseCodes2 as GatewayCloseCodes,
|
|
31
|
+
GatewayDispatcher2 as GatewayDispatcher,
|
|
32
|
+
GatewayError2 as GatewayError,
|
|
33
|
+
GatewayHeartbeat2 as GatewayHeartbeat,
|
|
34
|
+
GatewayOpcodes2 as GatewayOpcodes,
|
|
35
|
+
GatewayReconnect2 as GatewayReconnect,
|
|
36
|
+
GatewaySendLimiter2 as GatewaySendLimiter,
|
|
37
|
+
GatewaySession2 as GatewaySession,
|
|
38
|
+
GatewayState2 as GatewayState,
|
|
39
|
+
IDENTIFY_CLOSE_CODES2 as IDENTIFY_CLOSE_CODES,
|
|
40
|
+
PlainTextDecoder2 as PlainTextDecoder,
|
|
41
|
+
WebSocketTransport2 as WebSocketTransport,
|
|
42
|
+
ZlibStreamDecoder2 as ZlibStreamDecoder,
|
|
43
|
+
classifyCloseCode2 as classifyCloseCode,
|
|
44
|
+
classifyFrame2 as classifyFrame,
|
|
45
|
+
classifyPayload2 as classifyPayload,
|
|
46
|
+
createDecoder2 as createDecoder,
|
|
47
|
+
heartbeatPayload2 as heartbeatPayload,
|
|
48
|
+
identifyPayload2 as identifyPayload,
|
|
49
|
+
resumePayload2 as resumePayload
|
|
1339
50
|
};
|
|
1340
51
|
|
|
1341
|
-
//# debugId=
|
|
52
|
+
//# debugId=64196C225A3F568164756E2164756E21
|