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