summaryrefslogtreecommitdiff
path: root/node_modules/@discordjs/ws/dist
diff options
context:
space:
mode:
authorsowgro <tpoke.ferrari@gmail.com>2023-09-02 19:12:47 -0400
committersowgro <tpoke.ferrari@gmail.com>2023-09-02 19:12:47 -0400
commite4450c8417624b71d779cb4f41692538f9165e10 (patch)
treeb70826542223ecdf8a7a259f61b0a1abb8a217d8 /node_modules/@discordjs/ws/dist
downloadsowbot3-e4450c8417624b71d779cb4f41692538f9165e10.tar.gz
sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.tar.bz2
sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.zip
first commit
Diffstat (limited to 'node_modules/@discordjs/ws/dist')
-rw-r--r--node_modules/@discordjs/ws/dist/defaultWorker.d.mts2
-rw-r--r--node_modules/@discordjs/ws/dist/defaultWorker.d.ts2
-rw-r--r--node_modules/@discordjs/ws/dist/defaultWorker.js1051
-rw-r--r--node_modules/@discordjs/ws/dist/defaultWorker.js.map1
-rw-r--r--node_modules/@discordjs/ws/dist/defaultWorker.mjs1033
-rw-r--r--node_modules/@discordjs/ws/dist/defaultWorker.mjs.map1
-rw-r--r--node_modules/@discordjs/ws/dist/index.d.mts669
-rw-r--r--node_modules/@discordjs/ws/dist/index.d.ts669
-rw-r--r--node_modules/@discordjs/ws/dist/index.js1482
-rw-r--r--node_modules/@discordjs/ws/dist/index.js.map1
-rw-r--r--node_modules/@discordjs/ws/dist/index.mjs1446
-rw-r--r--node_modules/@discordjs/ws/dist/index.mjs.map1
12 files changed, 6358 insertions, 0 deletions
diff --git a/node_modules/@discordjs/ws/dist/defaultWorker.d.mts b/node_modules/@discordjs/ws/dist/defaultWorker.d.mts
new file mode 100644
index 0000000..c9247d4
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/defaultWorker.d.mts
@@ -0,0 +1,2 @@
+
+export { }
diff --git a/node_modules/@discordjs/ws/dist/defaultWorker.d.ts b/node_modules/@discordjs/ws/dist/defaultWorker.d.ts
new file mode 100644
index 0000000..c9247d4
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/defaultWorker.d.ts
@@ -0,0 +1,2 @@
+
+export { }
diff --git a/node_modules/@discordjs/ws/dist/defaultWorker.js b/node_modules/@discordjs/ws/dist/defaultWorker.js
new file mode 100644
index 0000000..4e19dff
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/defaultWorker.js
@@ -0,0 +1,1051 @@
+"use strict";
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
+var __copyProps = (to, from, except, desc) => {
+ if (from && typeof from === "object" || typeof from === "function") {
+ for (let key of __getOwnPropNames(from))
+ if (!__hasOwnProp.call(to, key) && key !== except)
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
+ }
+ return to;
+};
+var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
+ // If the importer is in node compatibility mode or this is not an ESM
+ // file that has been converted to a CommonJS file using a Babel-
+ // compatible transform (i.e. "__esModule" has not been set), then set
+ // "default" to the CommonJS "module.exports" for node compatibility.
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
+ mod
+));
+
+// src/utils/WorkerBootstrapper.ts
+var import_node_worker_threads3 = require("worker_threads");
+var import_collection7 = require("@discordjs/collection");
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+var import_node_worker_threads2 = require("worker_threads");
+var import_collection2 = require("@discordjs/collection");
+
+// src/strategies/sharding/WorkerShardingStrategy.ts
+var import_node_events = require("events");
+var import_node_path = require("path");
+var import_node_worker_threads = require("worker_threads");
+var import_collection = require("@discordjs/collection");
+
+// src/strategies/context/IContextFetchingStrategy.ts
+async function managerToFetchingStrategyOptions(manager) {
+ const {
+ buildIdentifyThrottler,
+ buildStrategy,
+ retrieveSessionInfo,
+ updateSessionInfo,
+ shardCount,
+ shardIds,
+ rest,
+ ...managerOptions
+ } = manager.options;
+ return {
+ ...managerOptions,
+ gatewayInformation: await manager.fetchGatewayInformation(),
+ shardCount: await manager.getShardCount()
+ };
+}
+__name(managerToFetchingStrategyOptions, "managerToFetchingStrategyOptions");
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+var WorkerContextFetchingStrategy = class {
+ constructor(options) {
+ this.options = options;
+ if (import_node_worker_threads2.isMainThread) {
+ throw new Error("Cannot instantiate WorkerContextFetchingStrategy on the main thread");
+ }
+ import_node_worker_threads2.parentPort.on("message", (payload) => {
+ if (payload.op === 3 /* SessionInfoResponse */) {
+ this.sessionPromises.get(payload.nonce)?.(payload.session);
+ this.sessionPromises.delete(payload.nonce);
+ }
+ if (payload.op === 4 /* ShardIdentifyResponse */) {
+ const promise = this.waitForIdentifyPromises.get(payload.nonce);
+ if (payload.ok) {
+ promise?.resolve();
+ } else {
+ promise?.reject(promise.signal.reason);
+ }
+ this.waitForIdentifyPromises.delete(payload.nonce);
+ }
+ });
+ }
+ static {
+ __name(this, "WorkerContextFetchingStrategy");
+ }
+ sessionPromises = new import_collection2.Collection();
+ waitForIdentifyPromises = new import_collection2.Collection();
+ async retrieveSessionInfo(shardId) {
+ const nonce = Math.random();
+ const payload = {
+ op: 3 /* RetrieveSessionInfo */,
+ shardId,
+ nonce
+ };
+ const promise = new Promise((resolve2) => this.sessionPromises.set(nonce, resolve2));
+ import_node_worker_threads2.parentPort.postMessage(payload);
+ return promise;
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ const payload = {
+ op: 4 /* UpdateSessionInfo */,
+ shardId,
+ session: sessionInfo
+ };
+ import_node_worker_threads2.parentPort.postMessage(payload);
+ }
+ async waitForIdentify(shardId, signal) {
+ const nonce = Math.random();
+ const payload = {
+ op: 5 /* WaitForIdentify */,
+ nonce,
+ shardId
+ };
+ const promise = new Promise(
+ (resolve2, reject) => (
+ // eslint-disable-next-line no-promise-executor-return
+ this.waitForIdentifyPromises.set(nonce, { signal, resolve: resolve2, reject })
+ )
+ );
+ import_node_worker_threads2.parentPort.postMessage(payload);
+ const listener = /* @__PURE__ */ __name(() => {
+ const payload2 = {
+ op: 8 /* CancelIdentify */,
+ nonce
+ };
+ import_node_worker_threads2.parentPort.postMessage(payload2);
+ }, "listener");
+ signal.addEventListener("abort", listener);
+ try {
+ await promise;
+ } finally {
+ signal.removeEventListener("abort", listener);
+ }
+ }
+};
+
+// src/ws/WebSocketShard.ts
+var import_node_buffer = require("buffer");
+var import_node_events2 = require("events");
+var import_node_timers = require("timers");
+var import_promises2 = require("timers/promises");
+var import_node_url = require("url");
+var import_node_util = require("util");
+var import_node_zlib = require("zlib");
+var import_collection6 = require("@discordjs/collection");
+var import_util2 = require("@discordjs/util");
+var import_async_queue2 = require("@sapphire/async-queue");
+var import_async_event_emitter = require("@vladfrangu/async_event_emitter");
+var import_v102 = require("discord-api-types/v10");
+var import_ws = require("ws");
+
+// src/utils/constants.ts
+var import_node_process = __toESM(require("process"));
+var import_collection5 = require("@discordjs/collection");
+var import_util = require("@discordjs/util");
+var import_v10 = require("discord-api-types/v10");
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+var import_collection3 = require("@discordjs/collection");
+
+// src/strategies/context/SimpleContextFetchingStrategy.ts
+var SimpleContextFetchingStrategy = class _SimpleContextFetchingStrategy {
+ constructor(manager, options) {
+ this.manager = manager;
+ this.options = options;
+ }
+ static {
+ __name(this, "SimpleContextFetchingStrategy");
+ }
+ // This strategy assumes every shard is running under the same process - therefore we need a single
+ // IdentifyThrottler per manager.
+ static throttlerCache = /* @__PURE__ */ new WeakMap();
+ static async ensureThrottler(manager) {
+ const throttler = _SimpleContextFetchingStrategy.throttlerCache.get(manager);
+ if (throttler) {
+ return throttler;
+ }
+ const newThrottler = await manager.options.buildIdentifyThrottler(manager);
+ _SimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);
+ return newThrottler;
+ }
+ async retrieveSessionInfo(shardId) {
+ return this.manager.options.retrieveSessionInfo(shardId);
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ return this.manager.options.updateSessionInfo(shardId, sessionInfo);
+ }
+ async waitForIdentify(shardId, signal) {
+ const throttler = await _SimpleContextFetchingStrategy.ensureThrottler(this.manager);
+ await throttler.waitForIdentify(shardId, signal);
+ }
+};
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+var SimpleShardingStrategy = class {
+ static {
+ __name(this, "SimpleShardingStrategy");
+ }
+ manager;
+ shards = new import_collection3.Collection();
+ constructor(manager) {
+ this.manager = manager;
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ async spawn(shardIds) {
+ const strategyOptions = await managerToFetchingStrategyOptions(this.manager);
+ for (const shardId of shardIds) {
+ const strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);
+ const shard = new WebSocketShard(strategy, shardId);
+ for (const event of Object.values(WebSocketShardEvents)) {
+ shard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));
+ }
+ this.shards.set(shardId, shard);
+ }
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ async connect() {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.connect());
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ async destroy(options) {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.destroy(options));
+ }
+ await Promise.all(promises);
+ this.shards.clear();
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ async send(shardId, payload) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} not found`);
+ }
+ return shard.send(payload);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ async fetchStatus() {
+ return this.shards.mapValues((shard) => shard.status);
+ }
+};
+
+// src/throttling/SimpleIdentifyThrottler.ts
+var import_promises = require("timers/promises");
+var import_collection4 = require("@discordjs/collection");
+var import_async_queue = require("@sapphire/async-queue");
+var SimpleIdentifyThrottler = class {
+ constructor(maxConcurrency) {
+ this.maxConcurrency = maxConcurrency;
+ }
+ static {
+ __name(this, "SimpleIdentifyThrottler");
+ }
+ states = new import_collection4.Collection();
+ /**
+ * {@inheritDoc IIdentifyThrottler.waitForIdentify}
+ */
+ async waitForIdentify(shardId, signal) {
+ const key = shardId % this.maxConcurrency;
+ const state = this.states.ensure(key, () => {
+ return {
+ queue: new import_async_queue.AsyncQueue(),
+ resetsAt: Number.POSITIVE_INFINITY
+ };
+ });
+ await state.queue.wait({ signal });
+ try {
+ const diff = state.resetsAt - Date.now();
+ if (diff <= 5e3) {
+ const time = diff + Math.random() * 1500;
+ await (0, import_promises.setTimeout)(time);
+ }
+ state.resetsAt = Date.now() + 5e3;
+ } finally {
+ state.queue.shift();
+ }
+ }
+};
+
+// src/utils/constants.ts
+var DefaultDeviceProperty = `@discordjs/ws 1.0.1`;
+var getDefaultSessionStore = (0, import_util.lazy)(() => new import_collection5.Collection());
+var DefaultWebSocketManagerOptions = {
+ async buildIdentifyThrottler(manager) {
+ const info = await manager.fetchGatewayInformation();
+ return new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);
+ },
+ buildStrategy: (manager) => new SimpleShardingStrategy(manager),
+ shardCount: null,
+ shardIds: null,
+ largeThreshold: null,
+ initialPresence: null,
+ identifyProperties: {
+ browser: DefaultDeviceProperty,
+ device: DefaultDeviceProperty,
+ os: import_node_process.default.platform
+ },
+ version: import_v10.APIVersion,
+ encoding: "json" /* JSON */,
+ compression: null,
+ retrieveSessionInfo(shardId) {
+ const store = getDefaultSessionStore();
+ return store.get(shardId) ?? null;
+ },
+ updateSessionInfo(shardId, info) {
+ const store = getDefaultSessionStore();
+ if (info) {
+ store.set(shardId, info);
+ } else {
+ store.delete(shardId);
+ }
+ },
+ handshakeTimeout: 3e4,
+ helloTimeout: 6e4,
+ readyTimeout: 15e3
+};
+var ImportantGatewayOpcodes = /* @__PURE__ */ new Set([
+ import_v10.GatewayOpcodes.Heartbeat,
+ import_v10.GatewayOpcodes.Identify,
+ import_v10.GatewayOpcodes.Resume
+]);
+function getInitialSendRateLimitState() {
+ return {
+ remaining: 120,
+ resetAt: Date.now() + 6e4
+ };
+}
+__name(getInitialSendRateLimitState, "getInitialSendRateLimitState");
+
+// src/ws/WebSocketShard.ts
+var getZlibSync = (0, import_util2.lazy)(async () => import("zlib-sync").then((mod) => mod.default).catch(() => null));
+var WebSocketShardEvents = /* @__PURE__ */ ((WebSocketShardEvents2) => {
+ WebSocketShardEvents2["Closed"] = "closed";
+ WebSocketShardEvents2["Debug"] = "debug";
+ WebSocketShardEvents2["Dispatch"] = "dispatch";
+ WebSocketShardEvents2["Error"] = "error";
+ WebSocketShardEvents2["HeartbeatComplete"] = "heartbeat";
+ WebSocketShardEvents2["Hello"] = "hello";
+ WebSocketShardEvents2["Ready"] = "ready";
+ WebSocketShardEvents2["Resumed"] = "resumed";
+ return WebSocketShardEvents2;
+})(WebSocketShardEvents || {});
+var WebSocketShardDestroyRecovery = /* @__PURE__ */ ((WebSocketShardDestroyRecovery2) => {
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Reconnect"] = 0] = "Reconnect";
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Resume"] = 1] = "Resume";
+ return WebSocketShardDestroyRecovery2;
+})(WebSocketShardDestroyRecovery || {});
+var WebSocketConstructor = import_ws.WebSocket;
+var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter {
+ static {
+ __name(this, "WebSocketShard");
+ }
+ connection = null;
+ useIdentifyCompress = false;
+ inflate = null;
+ textDecoder = new import_node_util.TextDecoder();
+ replayedEvents = 0;
+ isAck = true;
+ sendRateLimitState = getInitialSendRateLimitState();
+ initialHeartbeatTimeoutController = null;
+ heartbeatInterval = null;
+ lastHeartbeatAt = -1;
+ // Indicates whether the shard has already resolved its original connect() call
+ initialConnectResolved = false;
+ // Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)
+ failedToConnectDueToNetworkError = false;
+ sendQueue = new import_async_queue2.AsyncQueue();
+ timeoutAbortControllers = new import_collection6.Collection();
+ strategy;
+ id;
+ #status = 0 /* Idle */;
+ get status() {
+ return this.#status;
+ }
+ constructor(strategy, id) {
+ super();
+ this.strategy = strategy;
+ this.id = id;
+ }
+ async connect() {
+ const controller = new AbortController();
+ let promise;
+ if (!this.initialConnectResolved) {
+ promise = Promise.race([
+ (0, import_node_events2.once)(this, "ready" /* Ready */, { signal: controller.signal }),
+ (0, import_node_events2.once)(this, "resumed" /* Resumed */, { signal: controller.signal })
+ ]);
+ }
+ void this.internalConnect();
+ try {
+ await promise;
+ } catch ({ error }) {
+ throw error;
+ } finally {
+ controller.abort();
+ }
+ this.initialConnectResolved = true;
+ }
+ async internalConnect() {
+ if (this.#status !== 0 /* Idle */) {
+ throw new Error("Tried to connect a shard that wasn't idle");
+ }
+ const { version, encoding, compression } = this.strategy.options;
+ const params = new import_node_url.URLSearchParams({ v: version, encoding });
+ if (compression) {
+ const zlib = await getZlibSync();
+ if (zlib) {
+ params.append("compress", compression);
+ this.inflate = new zlib.Inflate({
+ chunkSize: 65535,
+ to: "string"
+ });
+ } else if (!this.useIdentifyCompress) {
+ this.useIdentifyCompress = true;
+ console.warn(
+ "WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress"
+ );
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ const url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;
+ this.debug([`Connecting to ${url}`]);
+ const connection = new WebSocketConstructor(url, {
+ handshakeTimeout: this.strategy.options.handshakeTimeout ?? void 0
+ });
+ connection.binaryType = "arraybuffer";
+ connection.onmessage = (event) => {
+ void this.onMessage(event.data, event.data instanceof ArrayBuffer);
+ };
+ connection.onerror = (event) => {
+ this.onError(event.error);
+ };
+ connection.onclose = (event) => {
+ void this.onClose(event.code);
+ };
+ this.connection = connection;
+ this.#status = 1 /* Connecting */;
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ const { ok } = await this.waitForEvent("hello" /* Hello */, this.strategy.options.helloTimeout);
+ if (!ok) {
+ return;
+ }
+ if (session?.shardCount === this.strategy.options.shardCount) {
+ await this.resume(session);
+ } else {
+ await this.identify();
+ }
+ }
+ async destroy(options = {}) {
+ if (this.#status === 0 /* Idle */) {
+ this.debug(["Tried to destroy a shard that was idle"]);
+ return;
+ }
+ if (!options.code) {
+ options.code = options.recover === 1 /* Resume */ ? 4200 /* Resuming */ : 1e3 /* Normal */;
+ }
+ this.debug([
+ "Destroying shard",
+ `Reason: ${options.reason ?? "none"}`,
+ `Code: ${options.code}`,
+ `Recover: ${options.recover === void 0 ? "none" : WebSocketShardDestroyRecovery[options.recover]}`
+ ]);
+ this.isAck = true;
+ if (this.heartbeatInterval) {
+ (0, import_node_timers.clearInterval)(this.heartbeatInterval);
+ }
+ if (this.initialHeartbeatTimeoutController) {
+ this.initialHeartbeatTimeoutController.abort();
+ this.initialHeartbeatTimeoutController = null;
+ }
+ this.lastHeartbeatAt = -1;
+ for (const controller of this.timeoutAbortControllers.values()) {
+ controller.abort();
+ }
+ this.timeoutAbortControllers.clear();
+ this.failedToConnectDueToNetworkError = false;
+ if (options.recover !== 1 /* Resume */) {
+ await this.strategy.updateSessionInfo(this.id, null);
+ }
+ if (this.connection) {
+ this.connection.onmessage = null;
+ this.connection.onclose = null;
+ const shouldClose = this.connection.readyState === import_ws.WebSocket.OPEN;
+ this.debug([
+ "Connection status during destroy",
+ `Needs closing: ${shouldClose}`,
+ `Ready state: ${this.connection.readyState}`
+ ]);
+ if (shouldClose) {
+ let outerResolve;
+ const promise = new Promise((resolve2) => {
+ outerResolve = resolve2;
+ });
+ this.connection.onclose = outerResolve;
+ this.connection.close(options.code, options.reason);
+ await promise;
+ this.emit("closed" /* Closed */, { code: options.code });
+ }
+ this.connection.onerror = null;
+ } else {
+ this.debug(["Destroying a shard that has no connection; please open an issue on GitHub"]);
+ }
+ this.#status = 0 /* Idle */;
+ if (options.recover !== void 0) {
+ await (0, import_promises2.setTimeout)(500);
+ return this.internalConnect();
+ }
+ }
+ async waitForEvent(event, timeoutDuration) {
+ this.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : "indefinitely"}`]);
+ const timeoutController = new AbortController();
+ const timeout = timeoutDuration ? (0, import_node_timers.setTimeout)(() => timeoutController.abort(), timeoutDuration).unref() : null;
+ this.timeoutAbortControllers.set(event, timeoutController);
+ const closeController = new AbortController();
+ try {
+ const closed = await Promise.race([
+ (0, import_node_events2.once)(this, event, { signal: timeoutController.signal }).then(() => false),
+ (0, import_node_events2.once)(this, "closed" /* Closed */, { signal: closeController.signal }).then(() => true)
+ ]);
+ return { ok: !closed };
+ } catch {
+ void this.destroy({
+ code: 1e3 /* Normal */,
+ reason: "Something timed out or went wrong while waiting for an event",
+ recover: 0 /* Reconnect */
+ });
+ return { ok: false };
+ } finally {
+ if (timeout) {
+ (0, import_node_timers.clearTimeout)(timeout);
+ }
+ this.timeoutAbortControllers.delete(event);
+ if (!closeController.signal.aborted) {
+ closeController.abort();
+ }
+ }
+ }
+ async send(payload) {
+ if (!this.connection) {
+ throw new Error("WebSocketShard wasn't connected");
+ }
+ if (this.#status !== 3 /* Ready */ && !ImportantGatewayOpcodes.has(payload.op)) {
+ this.debug(["Tried to send a non-crucial payload before the shard was ready, waiting"]);
+ try {
+ await (0, import_node_events2.once)(this, "ready" /* Ready */);
+ } catch {
+ return this.send(payload);
+ }
+ }
+ await this.sendQueue.wait();
+ if (--this.sendRateLimitState.remaining <= 0) {
+ const now = Date.now();
+ if (this.sendRateLimitState.resetAt > now) {
+ const sleepFor = this.sendRateLimitState.resetAt - now;
+ this.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);
+ const controller = new AbortController();
+ const interrupted = await Promise.race([
+ (0, import_promises2.setTimeout)(sleepFor).then(() => false),
+ (0, import_node_events2.once)(this, "closed" /* Closed */, { signal: controller.signal }).then(() => true)
+ ]);
+ if (interrupted) {
+ this.debug(["Connection closed while waiting for the send rate limit to reset, re-queueing payload"]);
+ this.sendQueue.shift();
+ return this.send(payload);
+ }
+ controller.abort();
+ }
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ }
+ this.sendQueue.shift();
+ this.connection.send(JSON.stringify(payload));
+ }
+ async identify() {
+ this.debug(["Waiting for identify throttle"]);
+ const controller = new AbortController();
+ const closeHandler = /* @__PURE__ */ __name(() => {
+ controller.abort();
+ }, "closeHandler");
+ this.on("closed" /* Closed */, closeHandler);
+ try {
+ await this.strategy.waitForIdentify(this.id, controller.signal);
+ } catch {
+ if (controller.signal.aborted) {
+ this.debug(["Was waiting for an identify, but the shard closed in the meantime"]);
+ return;
+ }
+ this.debug([
+ "IContextFetchingStrategy#waitForIdentify threw an unknown error.",
+ "If you're using a custom strategy, this is probably nothing to worry about.",
+ "If you're not, please open an issue on GitHub."
+ ]);
+ await this.destroy({
+ reason: "Identify throttling logic failed",
+ recover: 1 /* Resume */
+ });
+ } finally {
+ this.off("closed" /* Closed */, closeHandler);
+ }
+ this.debug([
+ "Identifying",
+ `shard id: ${this.id.toString()}`,
+ `shard count: ${this.strategy.options.shardCount}`,
+ `intents: ${this.strategy.options.intents}`,
+ `compression: ${this.inflate ? "zlib-stream" : this.useIdentifyCompress ? "identify" : "none"}`
+ ]);
+ const d = {
+ token: this.strategy.options.token,
+ properties: this.strategy.options.identifyProperties,
+ intents: this.strategy.options.intents,
+ compress: this.useIdentifyCompress,
+ shard: [this.id, this.strategy.options.shardCount]
+ };
+ if (this.strategy.options.largeThreshold) {
+ d.large_threshold = this.strategy.options.largeThreshold;
+ }
+ if (this.strategy.options.initialPresence) {
+ d.presence = this.strategy.options.initialPresence;
+ }
+ await this.send({
+ op: import_v102.GatewayOpcodes.Identify,
+ d
+ });
+ await this.waitForEvent("ready" /* Ready */, this.strategy.options.readyTimeout);
+ }
+ async resume(session) {
+ this.debug([
+ "Resuming session",
+ `resume url: ${session.resumeURL}`,
+ `sequence: ${session.sequence}`,
+ `shard id: ${this.id.toString()}`
+ ]);
+ this.#status = 2 /* Resuming */;
+ this.replayedEvents = 0;
+ return this.send({
+ op: import_v102.GatewayOpcodes.Resume,
+ d: {
+ token: this.strategy.options.token,
+ seq: session.sequence,
+ session_id: session.sessionId
+ }
+ });
+ }
+ async heartbeat(requested = false) {
+ if (!this.isAck && !requested) {
+ return this.destroy({ reason: "Zombie connection", recover: 1 /* Resume */ });
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ await this.send({
+ op: import_v102.GatewayOpcodes.Heartbeat,
+ d: session?.sequence ?? null
+ });
+ this.lastHeartbeatAt = Date.now();
+ this.isAck = false;
+ }
+ async unpackMessage(data, isBinary) {
+ if (!isBinary) {
+ try {
+ return JSON.parse(data);
+ } catch {
+ return null;
+ }
+ }
+ const decompressable = new Uint8Array(data);
+ if (this.useIdentifyCompress) {
+ return new Promise((resolve2, reject) => {
+ (0, import_node_zlib.inflate)(decompressable, { chunkSize: 65535 }, (err, result) => {
+ if (err) {
+ reject(err);
+ return;
+ }
+ resolve2(JSON.parse(this.textDecoder.decode(result)));
+ });
+ });
+ }
+ if (this.inflate) {
+ const l = decompressable.length;
+ const flush = l >= 4 && decompressable[l - 4] === 0 && decompressable[l - 3] === 0 && decompressable[l - 2] === 255 && decompressable[l - 1] === 255;
+ const zlib = await getZlibSync();
+ this.inflate.push(import_node_buffer.Buffer.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);
+ if (this.inflate.err) {
+ this.emit("error" /* Error */, {
+ error: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ""}`)
+ });
+ }
+ if (!flush) {
+ return null;
+ }
+ const { result } = this.inflate;
+ if (!result) {
+ return null;
+ }
+ return JSON.parse(typeof result === "string" ? result : this.textDecoder.decode(result));
+ }
+ this.debug([
+ "Received a message we were unable to decompress",
+ `isBinary: ${isBinary.toString()}`,
+ `useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,
+ `inflate: ${Boolean(this.inflate).toString()}`
+ ]);
+ return null;
+ }
+ async onMessage(data, isBinary) {
+ const payload = await this.unpackMessage(data, isBinary);
+ if (!payload) {
+ return;
+ }
+ switch (payload.op) {
+ case import_v102.GatewayOpcodes.Dispatch: {
+ if (this.#status === 2 /* Resuming */) {
+ this.replayedEvents++;
+ }
+ switch (payload.t) {
+ case import_v102.GatewayDispatchEvents.Ready: {
+ this.#status = 3 /* Ready */;
+ const session2 = {
+ sequence: payload.s,
+ sessionId: payload.d.session_id,
+ shardId: this.id,
+ shardCount: this.strategy.options.shardCount,
+ resumeURL: payload.d.resume_gateway_url
+ };
+ await this.strategy.updateSessionInfo(this.id, session2);
+ this.emit("ready" /* Ready */, { data: payload.d });
+ break;
+ }
+ case import_v102.GatewayDispatchEvents.Resumed: {
+ this.#status = 3 /* Ready */;
+ this.debug([`Resumed and replayed ${this.replayedEvents} events`]);
+ this.emit("resumed" /* Resumed */);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (session) {
+ if (payload.s > session.sequence) {
+ await this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });
+ }
+ } else {
+ this.debug([
+ `Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`
+ ]);
+ }
+ this.emit("dispatch" /* Dispatch */, { data: payload });
+ break;
+ }
+ case import_v102.GatewayOpcodes.Heartbeat: {
+ await this.heartbeat(true);
+ break;
+ }
+ case import_v102.GatewayOpcodes.Reconnect: {
+ await this.destroy({
+ reason: "Told to reconnect by Discord",
+ recover: 1 /* Resume */
+ });
+ break;
+ }
+ case import_v102.GatewayOpcodes.InvalidSession: {
+ this.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (payload.d && session) {
+ await this.resume(session);
+ } else {
+ await this.destroy({
+ reason: "Invalid session",
+ recover: 0 /* Reconnect */
+ });
+ }
+ break;
+ }
+ case import_v102.GatewayOpcodes.Hello: {
+ this.emit("hello" /* Hello */);
+ const jitter = Math.random();
+ const firstWait = Math.floor(payload.d.heartbeat_interval * jitter);
+ this.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);
+ try {
+ const controller = new AbortController();
+ this.initialHeartbeatTimeoutController = controller;
+ await (0, import_promises2.setTimeout)(firstWait, void 0, { signal: controller.signal });
+ } catch {
+ this.debug(["Cancelled initial heartbeat due to #destroy being called"]);
+ return;
+ } finally {
+ this.initialHeartbeatTimeoutController = null;
+ }
+ await this.heartbeat();
+ this.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);
+ this.heartbeatInterval = (0, import_node_timers.setInterval)(() => void this.heartbeat(), payload.d.heartbeat_interval);
+ break;
+ }
+ case import_v102.GatewayOpcodes.HeartbeatAck: {
+ this.isAck = true;
+ const ackAt = Date.now();
+ this.emit("heartbeat" /* HeartbeatComplete */, {
+ ackAt,
+ heartbeatAt: this.lastHeartbeatAt,
+ latency: ackAt - this.lastHeartbeatAt
+ });
+ break;
+ }
+ }
+ }
+ onError(error) {
+ if ("code" in error && ["ECONNRESET", "ECONNREFUSED"].includes(error.code)) {
+ this.debug(["Failed to connect to the gateway URL specified due to a network error"]);
+ this.failedToConnectDueToNetworkError = true;
+ return;
+ }
+ this.emit("error" /* Error */, { error });
+ }
+ async onClose(code) {
+ this.emit("closed" /* Closed */, { code });
+ switch (code) {
+ case 1e3 /* Normal */: {
+ return this.destroy({
+ code,
+ reason: "Got disconnected by Discord",
+ recover: 0 /* Reconnect */
+ });
+ }
+ case 4200 /* Resuming */: {
+ break;
+ }
+ case import_v102.GatewayCloseCodes.UnknownError: {
+ this.debug([`An unknown error occurred: ${code}`]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.UnknownOpcode: {
+ this.debug(["An invalid opcode was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.DecodeError: {
+ this.debug(["An invalid payload was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.NotAuthenticated: {
+ this.debug(["A request was somehow sent before the identify/resume payload."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.AuthenticationFailed: {
+ this.emit("error" /* Error */, {
+ error: new Error("Authentication failed")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.AlreadyAuthenticated: {
+ this.debug(["More than one auth payload was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.InvalidSeq: {
+ this.debug(["An invalid sequence was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.RateLimited: {
+ this.debug(["The WebSocket rate limit has been hit, this should never happen"]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.SessionTimedOut: {
+ this.debug(["Session timed out."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.InvalidShard: {
+ this.emit("error" /* Error */, {
+ error: new Error("Invalid shard")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.ShardingRequired: {
+ this.emit("error" /* Error */, {
+ error: new Error("Sharding is required")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.InvalidAPIVersion: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used an invalid API version")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.InvalidIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used invalid intents")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.DisallowedIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used disallowed intents")
+ });
+ return this.destroy({ code });
+ }
+ default: {
+ this.debug([
+ `The gateway closed with an unexpected code ${code}, attempting to ${this.failedToConnectDueToNetworkError ? "reconnect" : "resume"}.`
+ ]);
+ return this.destroy({
+ code,
+ recover: this.failedToConnectDueToNetworkError ? 0 /* Reconnect */ : 1 /* Resume */
+ });
+ }
+ }
+ }
+ debug(messages) {
+ const message = `${messages[0]}${messages.length > 1 ? `
+${messages.slice(1).map((m) => ` ${m}`).join("\n")}` : ""}`;
+ this.emit("debug" /* Debug */, { message });
+ }
+};
+
+// src/utils/WorkerBootstrapper.ts
+var WorkerBootstrapper = class {
+ static {
+ __name(this, "WorkerBootstrapper");
+ }
+ /**
+ * The data passed to the worker thread
+ */
+ data = import_node_worker_threads3.workerData;
+ /**
+ * The shards that are managed by this worker
+ */
+ shards = new import_collection7.Collection();
+ constructor() {
+ if (import_node_worker_threads3.isMainThread) {
+ throw new Error("Expected WorkerBootstrap to not be used within the main thread");
+ }
+ }
+ /**
+ * Helper method to initiate a shard's connection process
+ */
+ async connect(shardId) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.connect();
+ }
+ /**
+ * Helper method to destroy a shard
+ */
+ async destroy(shardId, options) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.destroy(options);
+ }
+ /**
+ * Helper method to attach event listeners to the parentPort
+ */
+ setupThreadEvents() {
+ import_node_worker_threads3.parentPort.on("messageerror", (err) => {
+ throw err;
+ }).on("message", async (payload) => {
+ switch (payload.op) {
+ case 0 /* Connect */: {
+ await this.connect(payload.shardId);
+ const response = {
+ op: 0 /* Connected */,
+ shardId: payload.shardId
+ };
+ import_node_worker_threads3.parentPort.postMessage(response);
+ break;
+ }
+ case 1 /* Destroy */: {
+ await this.destroy(payload.shardId, payload.options);
+ const response = {
+ op: 1 /* Destroyed */,
+ shardId: payload.shardId
+ };
+ import_node_worker_threads3.parentPort.postMessage(response);
+ break;
+ }
+ case 2 /* Send */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${payload.shardId} does not exist`);
+ }
+ await shard.send(payload.payload);
+ break;
+ }
+ case 3 /* SessionInfoResponse */: {
+ break;
+ }
+ case 4 /* ShardIdentifyResponse */: {
+ break;
+ }
+ case 5 /* FetchStatus */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new Error(`Shard ${payload.shardId} does not exist`);
+ }
+ const response = {
+ op: 6 /* FetchStatusResponse */,
+ status: shard.status,
+ nonce: payload.nonce
+ };
+ import_node_worker_threads3.parentPort.postMessage(response);
+ break;
+ }
+ }
+ });
+ }
+ /**
+ * Bootstraps the worker thread with the provided options
+ */
+ async bootstrap(options = {}) {
+ for (const shardId of this.data.shardIds) {
+ const shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);
+ for (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {
+ shard.on(event, (data) => {
+ const payload = {
+ op: 2 /* Event */,
+ event,
+ data,
+ shardId
+ };
+ import_node_worker_threads3.parentPort.postMessage(payload);
+ });
+ }
+ await options.shardCallback?.(shard);
+ this.shards.set(shardId, shard);
+ }
+ this.setupThreadEvents();
+ const message = {
+ op: 7 /* WorkerReady */
+ };
+ import_node_worker_threads3.parentPort.postMessage(message);
+ }
+};
+
+// src/strategies/sharding/defaultWorker.ts
+var bootstrapper = new WorkerBootstrapper();
+void bootstrapper.bootstrap();
+//# sourceMappingURL=defaultWorker.js.map \ No newline at end of file
diff --git a/node_modules/@discordjs/ws/dist/defaultWorker.js.map b/node_modules/@discordjs/ws/dist/defaultWorker.js.map
new file mode 100644
index 0000000..1daa8d6
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/defaultWorker.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/utils/WorkerBootstrapper.ts","../src/strategies/context/WorkerContextFetchingStrategy.ts","../src/strategies/sharding/WorkerShardingStrategy.ts","../src/strategies/context/IContextFetchingStrategy.ts","../src/ws/WebSocketShard.ts","../src/utils/constants.ts","../src/strategies/sharding/SimpleShardingStrategy.ts","../src/strategies/context/SimpleContextFetchingStrategy.ts","../src/throttling/SimpleIdentifyThrottler.ts","../src/strategies/sharding/defaultWorker.ts"],"sourcesContent":["import { isMainThread, parentPort, workerData } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { Awaitable } from '@discordjs/util';\nimport { WorkerContextFetchingStrategy } from '../strategies/context/WorkerContextFetchingStrategy.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerData,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../strategies/sharding/WorkerShardingStrategy.js';\nimport type { WebSocketShardDestroyOptions } from '../ws/WebSocketShard.js';\nimport { WebSocketShardEvents, WebSocketShard } from '../ws/WebSocketShard.js';\n\n/**\n * Options for bootstrapping the worker\n */\nexport interface BootstrapOptions {\n\t/**\n\t * Shard events to just arbitrarily forward to the parent thread for the manager to emit\n\t * Note: By default, this will include ALL events\n\t * you most likely want to handle dispatch within the worker itself\n\t */\n\tforwardEvents?: WebSocketShardEvents[];\n\t/**\n\t * Function to call when a shard is created for additional setup\n\t */\n\tshardCallback?(shard: WebSocketShard): Awaitable<void>;\n}\n\n/**\n * Utility class for bootstrapping a worker thread to be used for sharding\n */\nexport class WorkerBootstrapper {\n\t/**\n\t * The data passed to the worker thread\n\t */\n\tprotected readonly data = workerData as WorkerData;\n\n\t/**\n\t * The shards that are managed by this worker\n\t */\n\tprotected readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor() {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Expected WorkerBootstrap to not be used within the main thread');\n\t\t}\n\t}\n\n\t/**\n\t * Helper method to initiate a shard's connection process\n\t */\n\tprotected async connect(shardId: number): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.connect();\n\t}\n\n\t/**\n\t * Helper method to destroy a shard\n\t */\n\tprotected async destroy(shardId: number, options?: WebSocketShardDestroyOptions): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.destroy(options);\n\t}\n\n\t/**\n\t * Helper method to attach event listeners to the parentPort\n\t */\n\tprotected setupThreadEvents(): void {\n\t\tparentPort!\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerSendPayload) => {\n\t\t\t\tswitch (payload.op) {\n\t\t\t\t\tcase WorkerSendPayloadOp.Connect: {\n\t\t\t\t\t\tawait this.connect(payload.shardId);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Connected,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Destroy: {\n\t\t\t\t\t\tawait this.destroy(payload.shardId, payload.options);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Destroyed,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Send: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new RangeError(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait shard.send(payload.payload);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.SessionInfoResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.ShardIdentifyResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.FetchStatus: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new Error(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.FetchStatusResponse,\n\t\t\t\t\t\t\tstatus: shard.status,\n\t\t\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Bootstraps the worker thread with the provided options\n\t */\n\tpublic async bootstrap(options: Readonly<BootstrapOptions> = {}): Promise<void> {\n\t\t// Start by initializing the shards\n\t\tfor (const shardId of this.data.shardIds) {\n\t\t\tconst shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);\n\t\t\tfor (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Event types incompatible\n\t\t\t\tshard.on(event, (data) => {\n\t\t\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\t\t\top: WorkerReceivePayloadOp.Event,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tshardId,\n\t\t\t\t\t};\n\t\t\t\t\tparentPort!.postMessage(payload);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Any additional setup the user might want to do\n\t\t\tawait options.shardCallback?.(shard);\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\n\t\t// Lastly, start listening to messages from the parent thread\n\t\tthis.setupThreadEvents();\n\n\t\tconst message: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WorkerReady,\n\t\t};\n\t\tparentPort!.postMessage(message);\n\t}\n}\n","import { isMainThread, parentPort } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { SessionInfo } from '../../ws/WebSocketManager.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../sharding/WorkerShardingStrategy.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class WorkerContextFetchingStrategy implements IContextFetchingStrategy {\n\tprivate readonly sessionPromises = new Collection<number, (session: SessionInfo | null) => void>();\n\n\tprivate readonly waitForIdentifyPromises = new Collection<\n\t\tnumber,\n\t\t{ reject(error: unknown): void; resolve(): void; signal: AbortSignal }\n\t>();\n\n\tpublic constructor(public readonly options: FetchingStrategyOptions) {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Cannot instantiate WorkerContextFetchingStrategy on the main thread');\n\t\t}\n\n\t\tparentPort!.on('message', (payload: WorkerSendPayload) => {\n\t\t\tif (payload.op === WorkerSendPayloadOp.SessionInfoResponse) {\n\t\t\t\tthis.sessionPromises.get(payload.nonce)?.(payload.session);\n\t\t\t\tthis.sessionPromises.delete(payload.nonce);\n\t\t\t}\n\n\t\t\tif (payload.op === WorkerSendPayloadOp.ShardIdentifyResponse) {\n\t\t\t\tconst promise = this.waitForIdentifyPromises.get(payload.nonce);\n\t\t\t\tif (payload.ok) {\n\t\t\t\t\tpromise?.resolve();\n\t\t\t\t} else {\n\t\t\t\t\t// We need to make sure we reject with an abort error\n\t\t\t\t\tpromise?.reject(promise.signal.reason);\n\t\t\t\t}\n\n\t\t\t\tthis.waitForIdentifyPromises.delete(payload.nonce);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\tconst nonce = Math.random();\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.RetrieveSessionInfo,\n\t\t\tshardId,\n\t\t\tnonce,\n\t\t};\n\t\t// eslint-disable-next-line no-promise-executor-return\n\t\tconst promise = new Promise<SessionInfo | null>((resolve) => this.sessionPromises.set(nonce, resolve));\n\t\tparentPort!.postMessage(payload);\n\t\treturn promise;\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.UpdateSessionInfo,\n\t\t\tshardId,\n\t\t\tsession: sessionInfo,\n\t\t};\n\t\tparentPort!.postMessage(payload);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst nonce = Math.random();\n\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WaitForIdentify,\n\t\t\tnonce,\n\t\t\tshardId,\n\t\t};\n\t\tconst promise = new Promise<void>((resolve, reject) =>\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tthis.waitForIdentifyPromises.set(nonce, { signal, resolve, reject }),\n\t\t);\n\n\t\tparentPort!.postMessage(payload);\n\n\t\tconst listener = () => {\n\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\top: WorkerReceivePayloadOp.CancelIdentify,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\tparentPort!.postMessage(payload);\n\t\t};\n\n\t\tsignal.addEventListener('abort', listener);\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} finally {\n\t\t\tsignal.removeEventListener('abort', listener);\n\t\t}\n\t}\n}\n","import { once } from 'node:events';\nimport { join, isAbsolute, resolve } from 'node:path';\nimport { Worker } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type {\n\tWebSocketShardDestroyOptions,\n\tWebSocketShardEvents,\n\tWebSocketShardStatus,\n} from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions, type FetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\nexport interface WorkerData extends FetchingStrategyOptions {\n\tshardIds: number[];\n}\n\nexport enum WorkerSendPayloadOp {\n\tConnect,\n\tDestroy,\n\tSend,\n\tSessionInfoResponse,\n\tShardIdentifyResponse,\n\tFetchStatus,\n}\n\nexport type WorkerSendPayload =\n\t| { nonce: number; ok: boolean; op: WorkerSendPayloadOp.ShardIdentifyResponse }\n\t| { nonce: number; op: WorkerSendPayloadOp.FetchStatus; shardId: number }\n\t| { nonce: number; op: WorkerSendPayloadOp.SessionInfoResponse; session: SessionInfo | null }\n\t| { op: WorkerSendPayloadOp.Connect; shardId: number }\n\t| { op: WorkerSendPayloadOp.Destroy; options?: WebSocketShardDestroyOptions; shardId: number }\n\t| { op: WorkerSendPayloadOp.Send; payload: GatewaySendPayload; shardId: number };\n\nexport enum WorkerReceivePayloadOp {\n\tConnected,\n\tDestroyed,\n\tEvent,\n\tRetrieveSessionInfo,\n\tUpdateSessionInfo,\n\tWaitForIdentify,\n\tFetchStatusResponse,\n\tWorkerReady,\n\tCancelIdentify,\n}\n\nexport type WorkerReceivePayload =\n\t// Can't seem to get a type-safe union based off of the event, so I'm sadly leaving data as any for now\n\t| { data: any; event: WebSocketShardEvents; op: WorkerReceivePayloadOp.Event; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.CancelIdentify }\n\t| { nonce: number; op: WorkerReceivePayloadOp.FetchStatusResponse; status: WebSocketShardStatus }\n\t| { nonce: number; op: WorkerReceivePayloadOp.RetrieveSessionInfo; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.WaitForIdentify; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Connected; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Destroyed; shardId: number }\n\t| { op: WorkerReceivePayloadOp.UpdateSessionInfo; session: SessionInfo | null; shardId: number }\n\t| { op: WorkerReceivePayloadOp.WorkerReady };\n\n/**\n * Options for a {@link WorkerShardingStrategy}\n */\nexport interface WorkerShardingStrategyOptions {\n\t/**\n\t * Dictates how many shards should be spawned per worker thread.\n\t */\n\tshardsPerWorker: number | 'all';\n\t/**\n\t * Path to the worker file to use. The worker requires quite a bit of setup, it is recommended you leverage the {@link WorkerBootstrapper} class.\n\t */\n\tworkerPath?: string;\n}\n\n/**\n * Strategy used to spawn threads in worker_threads\n */\nexport class WorkerShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly options: WorkerShardingStrategyOptions;\n\n\t#workers: Worker[] = [];\n\n\treadonly #workerByShardId = new Collection<number, Worker>();\n\n\tprivate readonly connectPromises = new Collection<number, () => void>();\n\n\tprivate readonly destroyPromises = new Collection<number, () => void>();\n\n\tprivate readonly fetchStatusPromises = new Collection<number, (status: WebSocketShardStatus) => void>();\n\n\tprivate readonly waitForIdentifyControllers = new Collection<number, AbortController>();\n\n\tprivate throttler?: IIdentifyThrottler;\n\n\tpublic constructor(manager: WebSocketManager, options: WorkerShardingStrategyOptions) {\n\t\tthis.manager = manager;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst shardsPerWorker = this.options.shardsPerWorker === 'all' ? shardIds.length : this.options.shardsPerWorker;\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tconst loops = Math.ceil(shardIds.length / shardsPerWorker);\n\t\tconst promises: Promise<void>[] = [];\n\n\t\tfor (let idx = 0; idx < loops; idx++) {\n\t\t\tconst slice = shardIds.slice(idx * shardsPerWorker, (idx + 1) * shardsPerWorker);\n\t\t\tconst workerData: WorkerData = {\n\t\t\t\t...strategyOptions,\n\t\t\t\tshardIds: slice,\n\t\t\t};\n\n\t\t\tpromises.push(this.setupWorker(workerData));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Connect,\n\t\t\t\tshardId,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<void>((resolve) => this.connectPromises.set(shardId, resolve));\n\t\t\tworker.postMessage(payload);\n\t\t\tpromises.push(promise);\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options: Omit<WebSocketShardDestroyOptions, 'recover'> = {}) {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Destroy,\n\t\t\t\tshardId,\n\t\t\t\toptions,\n\t\t\t};\n\n\t\t\tpromises.push(\n\t\t\t\t// eslint-disable-next-line no-promise-executor-return, promise/prefer-await-to-then\n\t\t\t\tnew Promise<void>((resolve) => this.destroyPromises.set(shardId, resolve)).then(async () => worker.terminate()),\n\t\t\t);\n\t\t\tworker.postMessage(payload);\n\t\t}\n\n\t\tthis.#workers = [];\n\t\tthis.#workerByShardId.clear();\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic send(shardId: number, data: GatewaySendPayload) {\n\t\tconst worker = this.#workerByShardId.get(shardId);\n\t\tif (!worker) {\n\t\t\tthrow new Error(`No worker found for shard ${shardId}`);\n\t\t}\n\n\t\tconst payload: WorkerSendPayload = {\n\t\t\top: WorkerSendPayloadOp.Send,\n\t\t\tshardId,\n\t\t\tpayload: data,\n\t\t};\n\t\tworker.postMessage(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\tconst statuses = new Collection<number, WebSocketShardStatus>();\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst nonce = Math.random();\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.FetchStatus,\n\t\t\t\tshardId,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<WebSocketShardStatus>((resolve) => this.fetchStatusPromises.set(nonce, resolve));\n\t\t\tworker.postMessage(payload);\n\n\t\t\tconst status = await promise;\n\t\t\tstatuses.set(shardId, status);\n\t\t}\n\n\t\treturn statuses;\n\t}\n\n\tprivate async setupWorker(workerData: WorkerData) {\n\t\tconst worker = new Worker(this.resolveWorkerPath(), { workerData });\n\n\t\tawait once(worker, 'online');\n\t\t// We do this in case the user has any potentially long running code in their worker\n\t\tawait this.waitForWorkerReady(worker);\n\n\t\tworker\n\t\t\t.on('error', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerReceivePayload) => this.onMessage(worker, payload));\n\n\t\tthis.#workers.push(worker);\n\t\tfor (const shardId of workerData.shardIds) {\n\t\t\tthis.#workerByShardId.set(shardId, worker);\n\t\t}\n\t}\n\n\tprivate resolveWorkerPath(): string {\n\t\tconst path = this.options.workerPath;\n\n\t\tif (!path) {\n\t\t\treturn join(__dirname, 'defaultWorker.js');\n\t\t}\n\n\t\tif (isAbsolute(path)) {\n\t\t\treturn path;\n\t\t}\n\n\t\tif (/^\\.\\.?[/\\\\]/.test(path)) {\n\t\t\treturn resolve(path);\n\t\t}\n\n\t\ttry {\n\t\t\treturn require.resolve(path);\n\t\t} catch {\n\t\t\treturn resolve(path);\n\t\t}\n\t}\n\n\tprivate async waitForWorkerReady(worker: Worker): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst handler = (payload: WorkerReceivePayload) => {\n\t\t\t\tif (payload.op === WorkerReceivePayloadOp.WorkerReady) {\n\t\t\t\t\tresolve();\n\t\t\t\t\tworker.off('message', handler);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tworker.on('message', handler);\n\t\t});\n\t}\n\n\tprivate async onMessage(worker: Worker, payload: WorkerReceivePayload) {\n\t\tswitch (payload.op) {\n\t\t\tcase WorkerReceivePayloadOp.Connected: {\n\t\t\t\tthis.connectPromises.get(payload.shardId)?.();\n\t\t\t\tthis.connectPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Destroyed: {\n\t\t\t\tthis.destroyPromises.get(payload.shardId)?.();\n\t\t\t\tthis.destroyPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Event: {\n\t\t\t\tthis.manager.emit(payload.event, { ...payload.data, shardId: payload.shardId });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.RetrieveSessionInfo: {\n\t\t\t\tconst session = await this.manager.options.retrieveSessionInfo(payload.shardId);\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.SessionInfoResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tsession,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.UpdateSessionInfo: {\n\t\t\t\tawait this.manager.options.updateSessionInfo(payload.shardId, payload.session);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WaitForIdentify: {\n\t\t\t\tconst throttler = await this.ensureThrottler();\n\n\t\t\t\t// If this rejects it means we aborted, in which case we reply elsewhere.\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.waitForIdentifyControllers.set(payload.nonce, controller);\n\t\t\t\t\tawait throttler.waitForIdentify(payload.shardId, controller.signal);\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: true,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.FetchStatusResponse: {\n\t\t\t\tthis.fetchStatusPromises.get(payload.nonce)?.(payload.status);\n\t\t\t\tthis.fetchStatusPromises.delete(payload.nonce);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WorkerReady: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.CancelIdentify: {\n\t\t\t\tthis.waitForIdentifyControllers.get(payload.nonce)?.abort();\n\t\t\t\tthis.waitForIdentifyControllers.delete(payload.nonce);\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: false,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async ensureThrottler(): Promise<IIdentifyThrottler> {\n\t\tthis.throttler ??= await this.manager.options.buildIdentifyThrottler(this.manager);\n\t\treturn this.throttler;\n\t}\n}\n","import type { Awaitable } from '@discordjs/util';\nimport type { APIGatewayBotInfo } from 'discord-api-types/v10';\nimport type { SessionInfo, WebSocketManager, WebSocketManagerOptions } from '../../ws/WebSocketManager.js';\n\nexport interface FetchingStrategyOptions\n\textends Omit<\n\t\tWebSocketManagerOptions,\n\t\t| 'buildIdentifyThrottler'\n\t\t| 'buildStrategy'\n\t\t| 'rest'\n\t\t| 'retrieveSessionInfo'\n\t\t| 'shardCount'\n\t\t| 'shardIds'\n\t\t| 'updateSessionInfo'\n\t> {\n\treadonly gatewayInformation: APIGatewayBotInfo;\n\treadonly shardCount: number;\n}\n\n/**\n * Strategies responsible solely for making manager information accessible\n */\nexport interface IContextFetchingStrategy {\n\treadonly options: FetchingStrategyOptions;\n\tretrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;\n\tupdateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;\n\t/**\n\t * Resolves once the given shard should be allowed to identify\n\t * This should correctly handle the signal and reject with an abort error if the operation is aborted.\n\t * Other errors will cause the shard to reconnect.\n\t */\n\twaitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;\n}\n\nexport async function managerToFetchingStrategyOptions(manager: WebSocketManager): Promise<FetchingStrategyOptions> {\n\t/* eslint-disable @typescript-eslint/unbound-method */\n\tconst {\n\t\tbuildIdentifyThrottler,\n\t\tbuildStrategy,\n\t\tretrieveSessionInfo,\n\t\tupdateSessionInfo,\n\t\tshardCount,\n\t\tshardIds,\n\t\trest,\n\t\t...managerOptions\n\t} = manager.options;\n\t/* eslint-enable @typescript-eslint/unbound-method */\n\n\treturn {\n\t\t...managerOptions,\n\t\tgatewayInformation: await manager.fetchGatewayInformation(),\n\t\tshardCount: await manager.getShardCount(),\n\t};\n}\n","/* eslint-disable id-length */\nimport { Buffer } from 'node:buffer';\nimport { once } from 'node:events';\nimport { clearInterval, clearTimeout, setInterval, setTimeout } from 'node:timers';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { URLSearchParams } from 'node:url';\nimport { TextDecoder } from 'node:util';\nimport { inflate } from 'node:zlib';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tGatewayCloseCodes,\n\tGatewayDispatchEvents,\n\tGatewayOpcodes,\n\ttype GatewayDispatchPayload,\n\ttype GatewayIdentifyData,\n\ttype GatewayReadyDispatchData,\n\ttype GatewayReceivePayload,\n\ttype GatewaySendPayload,\n} from 'discord-api-types/v10';\nimport { WebSocket, type Data } from 'ws';\nimport type { Inflate } from 'zlib-sync';\nimport type { IContextFetchingStrategy } from '../strategies/context/IContextFetchingStrategy.js';\nimport { ImportantGatewayOpcodes, getInitialSendRateLimitState } from '../utils/constants.js';\nimport type { SessionInfo } from './WebSocketManager.js';\n\n// eslint-disable-next-line promise/prefer-await-to-then\nconst getZlibSync = lazy(async () => import('zlib-sync').then((mod) => mod.default).catch(() => null));\n\nexport enum WebSocketShardEvents {\n\tClosed = 'closed',\n\tDebug = 'debug',\n\tDispatch = 'dispatch',\n\tError = 'error',\n\tHeartbeatComplete = 'heartbeat',\n\tHello = 'hello',\n\tReady = 'ready',\n\tResumed = 'resumed',\n}\n\nexport enum WebSocketShardStatus {\n\tIdle,\n\tConnecting,\n\tResuming,\n\tReady,\n}\n\nexport enum WebSocketShardDestroyRecovery {\n\tReconnect,\n\tResume,\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport type WebSocketShardEventsMap = {\n\t[WebSocketShardEvents.Closed]: [{ code: number }];\n\t[WebSocketShardEvents.Debug]: [payload: { message: string }];\n\t[WebSocketShardEvents.Dispatch]: [payload: { data: GatewayDispatchPayload }];\n\t[WebSocketShardEvents.Error]: [payload: { error: Error }];\n\t[WebSocketShardEvents.Hello]: [];\n\t[WebSocketShardEvents.Ready]: [payload: { data: GatewayReadyDispatchData }];\n\t[WebSocketShardEvents.Resumed]: [];\n\t[WebSocketShardEvents.HeartbeatComplete]: [payload: { ackAt: number; heartbeatAt: number; latency: number }];\n};\n\nexport interface WebSocketShardDestroyOptions {\n\tcode?: number;\n\treason?: string;\n\trecover?: WebSocketShardDestroyRecovery;\n}\n\nexport enum CloseCodes {\n\tNormal = 1_000,\n\tResuming = 4_200,\n}\n\nexport interface SendRateLimitState {\n\tremaining: number;\n\tresetAt: number;\n}\n\n// TODO(vladfrangu): enable this once https://github.com/oven-sh/bun/issues/3392 is solved\n// const WebSocketConstructor: typeof WebSocket = shouldUseGlobalFetchAndWebSocket()\n// \t? (globalThis as any).WebSocket\n// \t: WebSocket;\nconst WebSocketConstructor: typeof WebSocket = WebSocket;\n\nexport class WebSocketShard extends AsyncEventEmitter<WebSocketShardEventsMap> {\n\tprivate connection: WebSocket | null = null;\n\n\tprivate useIdentifyCompress = false;\n\n\tprivate inflate: Inflate | null = null;\n\n\tprivate readonly textDecoder = new TextDecoder();\n\n\tprivate replayedEvents = 0;\n\n\tprivate isAck = true;\n\n\tprivate sendRateLimitState: SendRateLimitState = getInitialSendRateLimitState();\n\n\tprivate initialHeartbeatTimeoutController: AbortController | null = null;\n\n\tprivate heartbeatInterval: NodeJS.Timer | null = null;\n\n\tprivate lastHeartbeatAt = -1;\n\n\t// Indicates whether the shard has already resolved its original connect() call\n\tprivate initialConnectResolved = false;\n\n\t// Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)\n\tprivate failedToConnectDueToNetworkError = false;\n\n\tprivate readonly sendQueue = new AsyncQueue();\n\n\tprivate readonly timeoutAbortControllers = new Collection<WebSocketShardEvents, AbortController>();\n\n\tprivate readonly strategy: IContextFetchingStrategy;\n\n\tpublic readonly id: number;\n\n\t#status: WebSocketShardStatus = WebSocketShardStatus.Idle;\n\n\tpublic get status(): WebSocketShardStatus {\n\t\treturn this.#status;\n\t}\n\n\tpublic constructor(strategy: IContextFetchingStrategy, id: number) {\n\t\tsuper();\n\t\tthis.strategy = strategy;\n\t\tthis.id = id;\n\t}\n\n\tpublic async connect() {\n\t\tconst controller = new AbortController();\n\t\tlet promise;\n\n\t\tif (!this.initialConnectResolved) {\n\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\tpromise = Promise.race([\n\t\t\t\tonce(this, WebSocketShardEvents.Ready, { signal: controller.signal }),\n\t\t\t\tonce(this, WebSocketShardEvents.Resumed, { signal: controller.signal }),\n\t\t\t]);\n\t\t}\n\n\t\tvoid this.internalConnect();\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} catch ({ error }: any) {\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// cleanup hanging listeners\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.initialConnectResolved = true;\n\t}\n\n\tprivate async internalConnect() {\n\t\tif (this.#status !== WebSocketShardStatus.Idle) {\n\t\t\tthrow new Error(\"Tried to connect a shard that wasn't idle\");\n\t\t}\n\n\t\tconst { version, encoding, compression } = this.strategy.options;\n\t\tconst params = new URLSearchParams({ v: version, encoding });\n\t\tif (compression) {\n\t\t\tconst zlib = await getZlibSync();\n\t\t\tif (zlib) {\n\t\t\t\tparams.append('compress', compression);\n\t\t\t\tthis.inflate = new zlib.Inflate({\n\t\t\t\t\tchunkSize: 65_535,\n\t\t\t\t\tto: 'string',\n\t\t\t\t});\n\t\t\t} else if (!this.useIdentifyCompress) {\n\t\t\t\tthis.useIdentifyCompress = true;\n\t\t\t\tconsole.warn(\n\t\t\t\t\t'WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress',\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tconst url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;\n\n\t\tthis.debug([`Connecting to ${url}`]);\n\n\t\tconst connection = new WebSocketConstructor(url, {\n\t\t\thandshakeTimeout: this.strategy.options.handshakeTimeout ?? undefined,\n\t\t});\n\n\t\tconnection.binaryType = 'arraybuffer';\n\n\t\tconnection.onmessage = (event) => {\n\t\t\tvoid this.onMessage(event.data, event.data instanceof ArrayBuffer);\n\t\t};\n\n\t\tconnection.onerror = (event) => {\n\t\t\tthis.onError(event.error);\n\t\t};\n\n\t\tconnection.onclose = (event) => {\n\t\t\tvoid this.onClose(event.code);\n\t\t};\n\n\t\tthis.connection = connection;\n\n\t\tthis.#status = WebSocketShardStatus.Connecting;\n\n\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\n\t\tconst { ok } = await this.waitForEvent(WebSocketShardEvents.Hello, this.strategy.options.helloTimeout);\n\t\tif (!ok) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (session?.shardCount === this.strategy.options.shardCount) {\n\t\t\tawait this.resume(session);\n\t\t} else {\n\t\t\tawait this.identify();\n\t\t}\n\t}\n\n\tpublic async destroy(options: WebSocketShardDestroyOptions = {}) {\n\t\tif (this.#status === WebSocketShardStatus.Idle) {\n\t\t\tthis.debug(['Tried to destroy a shard that was idle']);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!options.code) {\n\t\t\toptions.code = options.recover === WebSocketShardDestroyRecovery.Resume ? CloseCodes.Resuming : CloseCodes.Normal;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Destroying shard',\n\t\t\t`Reason: ${options.reason ?? 'none'}`,\n\t\t\t`Code: ${options.code}`,\n\t\t\t`Recover: ${options.recover === undefined ? 'none' : WebSocketShardDestroyRecovery[options.recover]!}`,\n\t\t]);\n\n\t\t// Reset state\n\t\tthis.isAck = true;\n\t\tif (this.heartbeatInterval) {\n\t\t\tclearInterval(this.heartbeatInterval);\n\t\t}\n\n\t\tif (this.initialHeartbeatTimeoutController) {\n\t\t\tthis.initialHeartbeatTimeoutController.abort();\n\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t}\n\n\t\tthis.lastHeartbeatAt = -1;\n\n\t\tfor (const controller of this.timeoutAbortControllers.values()) {\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.timeoutAbortControllers.clear();\n\n\t\tthis.failedToConnectDueToNetworkError = false;\n\n\t\t// Clear session state if applicable\n\t\tif (options.recover !== WebSocketShardDestroyRecovery.Resume) {\n\t\t\tawait this.strategy.updateSessionInfo(this.id, null);\n\t\t}\n\n\t\tif (this.connection) {\n\t\t\t// No longer need to listen to messages\n\t\t\tthis.connection.onmessage = null;\n\t\t\t// Prevent a reconnection loop by unbinding the main close event\n\t\t\tthis.connection.onclose = null;\n\n\t\t\tconst shouldClose = this.connection.readyState === WebSocket.OPEN;\n\n\t\t\tthis.debug([\n\t\t\t\t'Connection status during destroy',\n\t\t\t\t`Needs closing: ${shouldClose}`,\n\t\t\t\t`Ready state: ${this.connection.readyState}`,\n\t\t\t]);\n\n\t\t\tif (shouldClose) {\n\t\t\t\tlet outerResolve: () => void;\n\t\t\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\t\t\touterResolve = resolve;\n\t\t\t\t});\n\n\t\t\t\tthis.connection.onclose = outerResolve!;\n\n\t\t\t\tthis.connection.close(options.code, options.reason);\n\n\t\t\t\tawait promise;\n\t\t\t\tthis.emit(WebSocketShardEvents.Closed, { code: options.code });\n\t\t\t}\n\n\t\t\t// Lastly, remove the error event.\n\t\t\t// Doing this earlier would cause a hard crash in case an error event fired on our `close` call\n\t\t\tthis.connection.onerror = null;\n\t\t} else {\n\t\t\tthis.debug(['Destroying a shard that has no connection; please open an issue on GitHub']);\n\t\t}\n\n\t\tthis.#status = WebSocketShardStatus.Idle;\n\n\t\tif (options.recover !== undefined) {\n\t\t\t// There's cases (like no internet connection) where we immediately fail to connect,\n\t\t\t// causing a very fast and draining reconnection loop.\n\t\t\tawait sleep(500);\n\t\t\treturn this.internalConnect();\n\t\t}\n\t}\n\n\tprivate async waitForEvent(event: WebSocketShardEvents, timeoutDuration?: number | null): Promise<{ ok: boolean }> {\n\t\tthis.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : 'indefinitely'}`]);\n\t\tconst timeoutController = new AbortController();\n\t\tconst timeout = timeoutDuration ? setTimeout(() => timeoutController.abort(), timeoutDuration).unref() : null;\n\n\t\tthis.timeoutAbortControllers.set(event, timeoutController);\n\n\t\tconst closeController = new AbortController();\n\n\t\ttry {\n\t\t\t// If the first promise resolves, all is well. If the 2nd promise resolves,\n\t\t\t// the shard has meanwhile closed. In that case, a destroy is already ongoing, so we just need to\n\t\t\t// return false. Meanwhile, if something rejects (error event) or the first controller is aborted,\n\t\t\t// we enter the catch block and trigger a destroy there.\n\t\t\tconst closed = await Promise.race<boolean>([\n\t\t\t\tonce(this, event, { signal: timeoutController.signal }).then(() => false),\n\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: closeController.signal }).then(() => true),\n\t\t\t]);\n\n\t\t\treturn { ok: !closed };\n\t\t} catch {\n\t\t\t// If we're here because of other reasons, we need to destroy the shard\n\t\t\tvoid this.destroy({\n\t\t\t\tcode: CloseCodes.Normal,\n\t\t\t\treason: 'Something timed out or went wrong while waiting for an event',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t});\n\n\t\t\treturn { ok: false };\n\t\t} finally {\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\n\t\t\tthis.timeoutAbortControllers.delete(event);\n\n\t\t\t// Clean up the close listener to not leak memory\n\t\t\tif (!closeController.signal.aborted) {\n\t\t\t\tcloseController.abort();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async send(payload: GatewaySendPayload): Promise<void> {\n\t\tif (!this.connection) {\n\t\t\tthrow new Error(\"WebSocketShard wasn't connected\");\n\t\t}\n\n\t\tif (this.#status !== WebSocketShardStatus.Ready && !ImportantGatewayOpcodes.has(payload.op)) {\n\t\t\tthis.debug(['Tried to send a non-crucial payload before the shard was ready, waiting']);\n\t\t\t// This will throw if the shard throws an error event in the meantime, just requeue the payload\n\t\t\ttry {\n\t\t\t\tawait once(this, WebSocketShardEvents.Ready);\n\t\t\t} catch {\n\t\t\t\treturn this.send(payload);\n\t\t\t}\n\t\t}\n\n\t\tawait this.sendQueue.wait();\n\n\t\tif (--this.sendRateLimitState.remaining <= 0) {\n\t\t\tconst now = Date.now();\n\n\t\t\tif (this.sendRateLimitState.resetAt > now) {\n\t\t\t\tconst sleepFor = this.sendRateLimitState.resetAt - now;\n\n\t\t\t\tthis.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);\n\t\t\t\tconst controller = new AbortController();\n\n\t\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\t\tconst interrupted = await Promise.race([\n\t\t\t\t\tsleep(sleepFor).then(() => false),\n\t\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: controller.signal }).then(() => true),\n\t\t\t\t]);\n\n\t\t\t\tif (interrupted) {\n\t\t\t\t\tthis.debug(['Connection closed while waiting for the send rate limit to reset, re-queueing payload']);\n\t\t\t\t\tthis.sendQueue.shift();\n\t\t\t\t\treturn this.send(payload);\n\t\t\t\t}\n\n\t\t\t\t// This is so the listener from the `once` call is removed\n\t\t\t\tcontroller.abort();\n\t\t\t}\n\n\t\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\t\t}\n\n\t\tthis.sendQueue.shift();\n\t\tthis.connection.send(JSON.stringify(payload));\n\t}\n\n\tprivate async identify() {\n\t\tthis.debug(['Waiting for identify throttle']);\n\n\t\tconst controller = new AbortController();\n\t\tconst closeHandler = () => {\n\t\t\tcontroller.abort();\n\t\t};\n\n\t\tthis.on(WebSocketShardEvents.Closed, closeHandler);\n\n\t\ttry {\n\t\t\tawait this.strategy.waitForIdentify(this.id, controller.signal);\n\t\t} catch {\n\t\t\tif (controller.signal.aborted) {\n\t\t\t\tthis.debug(['Was waiting for an identify, but the shard closed in the meantime']);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.debug([\n\t\t\t\t'IContextFetchingStrategy#waitForIdentify threw an unknown error.',\n\t\t\t\t\"If you're using a custom strategy, this is probably nothing to worry about.\",\n\t\t\t\t\"If you're not, please open an issue on GitHub.\",\n\t\t\t]);\n\n\t\t\tawait this.destroy({\n\t\t\t\treason: 'Identify throttling logic failed',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t});\n\t\t} finally {\n\t\t\tthis.off(WebSocketShardEvents.Closed, closeHandler);\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Identifying',\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t\t`shard count: ${this.strategy.options.shardCount}`,\n\t\t\t`intents: ${this.strategy.options.intents}`,\n\t\t\t`compression: ${this.inflate ? 'zlib-stream' : this.useIdentifyCompress ? 'identify' : 'none'}`,\n\t\t]);\n\n\t\tconst d: GatewayIdentifyData = {\n\t\t\ttoken: this.strategy.options.token,\n\t\t\tproperties: this.strategy.options.identifyProperties,\n\t\t\tintents: this.strategy.options.intents,\n\t\t\tcompress: this.useIdentifyCompress,\n\t\t\tshard: [this.id, this.strategy.options.shardCount],\n\t\t};\n\n\t\tif (this.strategy.options.largeThreshold) {\n\t\t\td.large_threshold = this.strategy.options.largeThreshold;\n\t\t}\n\n\t\tif (this.strategy.options.initialPresence) {\n\t\t\td.presence = this.strategy.options.initialPresence;\n\t\t}\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Identify,\n\t\t\td,\n\t\t});\n\n\t\tawait this.waitForEvent(WebSocketShardEvents.Ready, this.strategy.options.readyTimeout);\n\t}\n\n\tprivate async resume(session: SessionInfo) {\n\t\tthis.debug([\n\t\t\t'Resuming session',\n\t\t\t`resume url: ${session.resumeURL}`,\n\t\t\t`sequence: ${session.sequence}`,\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t]);\n\n\t\tthis.#status = WebSocketShardStatus.Resuming;\n\t\tthis.replayedEvents = 0;\n\t\treturn this.send({\n\t\t\top: GatewayOpcodes.Resume,\n\t\t\td: {\n\t\t\t\ttoken: this.strategy.options.token,\n\t\t\t\tseq: session.sequence,\n\t\t\t\tsession_id: session.sessionId,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async heartbeat(requested = false) {\n\t\tif (!this.isAck && !requested) {\n\t\t\treturn this.destroy({ reason: 'Zombie connection', recover: WebSocketShardDestroyRecovery.Resume });\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Heartbeat,\n\t\t\td: session?.sequence ?? null,\n\t\t});\n\n\t\tthis.lastHeartbeatAt = Date.now();\n\t\tthis.isAck = false;\n\t}\n\n\tprivate async unpackMessage(data: Data, isBinary: boolean): Promise<GatewayReceivePayload | null> {\n\t\t// Deal with no compression\n\t\tif (!isBinary) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(data as string) as GatewayReceivePayload;\n\t\t\t} catch {\n\t\t\t\t// This is a non-JSON payload / (at the time of writing this comment) emitted by bun wrongly interpreting custom close codes https://github.com/oven-sh/bun/issues/3392\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tconst decompressable = new Uint8Array(data as ArrayBuffer);\n\n\t\t// Deal with identify compress\n\t\tif (this.useIdentifyCompress) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-callbacks\n\t\t\t\tinflate(decompressable, { chunkSize: 65_535 }, (err, result) => {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve(JSON.parse(this.textDecoder.decode(result)) as GatewayReceivePayload);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\t// Deal with gw wide zlib-stream compression\n\t\tif (this.inflate) {\n\t\t\tconst l = decompressable.length;\n\t\t\tconst flush =\n\t\t\t\tl >= 4 &&\n\t\t\t\tdecompressable[l - 4] === 0x00 &&\n\t\t\t\tdecompressable[l - 3] === 0x00 &&\n\t\t\t\tdecompressable[l - 2] === 0xff &&\n\t\t\t\tdecompressable[l - 1] === 0xff;\n\n\t\t\tconst zlib = (await getZlibSync())!;\n\t\t\tthis.inflate.push(Buffer.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);\n\n\t\t\tif (this.inflate.err) {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ''}`),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!flush) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { result } = this.inflate;\n\t\t\tif (!result) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn JSON.parse(typeof result === 'string' ? result : this.textDecoder.decode(result)) as GatewayReceivePayload;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Received a message we were unable to decompress',\n\t\t\t`isBinary: ${isBinary.toString()}`,\n\t\t\t`useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,\n\t\t\t`inflate: ${Boolean(this.inflate).toString()}`,\n\t\t]);\n\n\t\treturn null;\n\t}\n\n\tprivate async onMessage(data: Data, isBinary: boolean) {\n\t\tconst payload = await this.unpackMessage(data, isBinary);\n\t\tif (!payload) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (payload.op) {\n\t\t\tcase GatewayOpcodes.Dispatch: {\n\t\t\t\tif (this.#status === WebSocketShardStatus.Resuming) {\n\t\t\t\t\tthis.replayedEvents++;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line sonarjs/no-nested-switch\n\t\t\t\tswitch (payload.t) {\n\t\t\t\t\tcase GatewayDispatchEvents.Ready: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\n\t\t\t\t\t\tconst session = {\n\t\t\t\t\t\t\tsequence: payload.s,\n\t\t\t\t\t\t\tsessionId: payload.d.session_id,\n\t\t\t\t\t\t\tshardId: this.id,\n\t\t\t\t\t\t\tshardCount: this.strategy.options.shardCount,\n\t\t\t\t\t\t\tresumeURL: payload.d.resume_gateway_url,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, session);\n\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Ready, { data: payload.d });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase GatewayDispatchEvents.Resumed: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\t\t\t\t\t\tthis.debug([`Resumed and replayed ${this.replayedEvents} events`]);\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Resumed);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (session) {\n\t\t\t\t\tif (payload.s > session.sequence) {\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.debug([\n\t\t\t\t\t\t`Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`,\n\t\t\t\t\t]);\n\t\t\t\t}\n\n\t\t\t\tthis.emit(WebSocketShardEvents.Dispatch, { data: payload });\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Heartbeat: {\n\t\t\t\tawait this.heartbeat(true);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Reconnect: {\n\t\t\t\tawait this.destroy({\n\t\t\t\t\treason: 'Told to reconnect by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.InvalidSession: {\n\t\t\t\tthis.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (payload.d && session) {\n\t\t\t\t\tawait this.resume(session);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.destroy({\n\t\t\t\t\t\treason: 'Invalid session',\n\t\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Hello: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Hello);\n\t\t\t\tconst jitter = Math.random();\n\t\t\t\tconst firstWait = Math.floor(payload.d.heartbeat_interval * jitter);\n\t\t\t\tthis.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = controller;\n\t\t\t\t\tawait sleep(firstWait, undefined, { signal: controller.signal });\n\t\t\t\t} catch {\n\t\t\t\t\tthis.debug(['Cancelled initial heartbeat due to #destroy being called']);\n\t\t\t\t\treturn;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t\t\t}\n\n\t\t\t\tawait this.heartbeat();\n\n\t\t\t\tthis.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);\n\t\t\t\tthis.heartbeatInterval = setInterval(() => void this.heartbeat(), payload.d.heartbeat_interval);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.HeartbeatAck: {\n\t\t\t\tthis.isAck = true;\n\n\t\t\t\tconst ackAt = Date.now();\n\t\t\t\tthis.emit(WebSocketShardEvents.HeartbeatComplete, {\n\t\t\t\t\tackAt,\n\t\t\t\t\theartbeatAt: this.lastHeartbeatAt,\n\t\t\t\t\tlatency: ackAt - this.lastHeartbeatAt,\n\t\t\t\t});\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onError(error: Error) {\n\t\tif ('code' in error && ['ECONNRESET', 'ECONNREFUSED'].includes(error.code as string)) {\n\t\t\tthis.debug(['Failed to connect to the gateway URL specified due to a network error']);\n\t\t\tthis.failedToConnectDueToNetworkError = true;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit(WebSocketShardEvents.Error, { error });\n\t}\n\n\tprivate async onClose(code: number) {\n\t\tthis.emit(WebSocketShardEvents.Closed, { code });\n\n\t\tswitch (code) {\n\t\t\tcase CloseCodes.Normal: {\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\treason: 'Got disconnected by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tcase CloseCodes.Resuming: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownError: {\n\t\t\t\tthis.debug([`An unknown error occurred: ${code}`]);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownOpcode: {\n\t\t\t\tthis.debug(['An invalid opcode was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DecodeError: {\n\t\t\t\tthis.debug(['An invalid payload was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.NotAuthenticated: {\n\t\t\t\tthis.debug(['A request was somehow sent before the identify/resume payload.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AuthenticationFailed: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Authentication failed'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AlreadyAuthenticated: {\n\t\t\t\tthis.debug(['More than one auth payload was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidSeq: {\n\t\t\t\tthis.debug(['An invalid sequence was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.RateLimited: {\n\t\t\t\tthis.debug(['The WebSocket rate limit has been hit, this should never happen']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.SessionTimedOut: {\n\t\t\t\tthis.debug(['Session timed out.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidShard: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Invalid shard'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.ShardingRequired: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Sharding is required'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidAPIVersion: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used an invalid API version'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used invalid intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DisallowedIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used disallowed intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tthis.debug([\n\t\t\t\t\t`The gateway closed with an unexpected code ${code}, attempting to ${\n\t\t\t\t\t\tthis.failedToConnectDueToNetworkError ? 'reconnect' : 'resume'\n\t\t\t\t\t}.`,\n\t\t\t\t]);\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\trecover: this.failedToConnectDueToNetworkError\n\t\t\t\t\t\t? WebSocketShardDestroyRecovery.Reconnect\n\t\t\t\t\t\t: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate debug(messages: [string, ...string[]]) {\n\t\tconst message = `${messages[0]}${\n\t\t\tmessages.length > 1\n\t\t\t\t? `\\n${messages\n\t\t\t\t\t\t.slice(1)\n\t\t\t\t\t\t.map((m) => `\t${m}`)\n\t\t\t\t\t\t.join('\\n')}`\n\t\t\t\t: ''\n\t\t}`;\n\n\t\tthis.emit(WebSocketShardEvents.Debug, { message });\n\t}\n}\n","import process from 'node:process';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { APIVersion, GatewayOpcodes } from 'discord-api-types/v10';\nimport { SimpleShardingStrategy } from '../strategies/sharding/SimpleShardingStrategy.js';\nimport { SimpleIdentifyThrottler } from '../throttling/SimpleIdentifyThrottler.js';\nimport type { SessionInfo, OptionalWebSocketManagerOptions, WebSocketManager } from '../ws/WebSocketManager.js';\nimport type { SendRateLimitState } from '../ws/WebSocketShard.js';\n\n/**\n * Valid encoding types\n */\nexport enum Encoding {\n\tJSON = 'json',\n}\n\n/**\n * Valid compression methods\n */\nexport enum CompressionMethod {\n\tZlibStream = 'zlib-stream',\n}\n\nexport const DefaultDeviceProperty = `@discordjs/ws 1.0.1` as `@discordjs/ws ${string}`;\n\nconst getDefaultSessionStore = lazy(() => new Collection<number, SessionInfo | null>());\n\n/**\n * Default options used by the manager\n */\nexport const DefaultWebSocketManagerOptions = {\n\tasync buildIdentifyThrottler(manager: WebSocketManager) {\n\t\tconst info = await manager.fetchGatewayInformation();\n\t\treturn new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);\n\t},\n\tbuildStrategy: (manager) => new SimpleShardingStrategy(manager),\n\tshardCount: null,\n\tshardIds: null,\n\tlargeThreshold: null,\n\tinitialPresence: null,\n\tidentifyProperties: {\n\t\tbrowser: DefaultDeviceProperty,\n\t\tdevice: DefaultDeviceProperty,\n\t\tos: process.platform,\n\t},\n\tversion: APIVersion,\n\tencoding: Encoding.JSON,\n\tcompression: null,\n\tretrieveSessionInfo(shardId) {\n\t\tconst store = getDefaultSessionStore();\n\t\treturn store.get(shardId) ?? null;\n\t},\n\tupdateSessionInfo(shardId: number, info: SessionInfo | null) {\n\t\tconst store = getDefaultSessionStore();\n\t\tif (info) {\n\t\t\tstore.set(shardId, info);\n\t\t} else {\n\t\t\tstore.delete(shardId);\n\t\t}\n\t},\n\thandshakeTimeout: 30_000,\n\thelloTimeout: 60_000,\n\treadyTimeout: 15_000,\n} as const satisfies OptionalWebSocketManagerOptions;\n\nexport const ImportantGatewayOpcodes = new Set([\n\tGatewayOpcodes.Heartbeat,\n\tGatewayOpcodes.Identify,\n\tGatewayOpcodes.Resume,\n]);\n\nexport function getInitialSendRateLimitState(): SendRateLimitState {\n\treturn {\n\t\tremaining: 120,\n\t\tresetAt: Date.now() + 60_000,\n\t};\n}\n","import { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { WebSocketManager } from '../../ws/WebSocketManager.js';\nimport { WebSocketShard, WebSocketShardEvents, type WebSocketShardDestroyOptions } from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport { SimpleContextFetchingStrategy } from '../context/SimpleContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\n/**\n * Simple strategy that just spawns shards in the current process\n */\nexport class SimpleShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor(manager: WebSocketManager) {\n\t\tthis.manager = manager;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tfor (const shardId of shardIds) {\n\t\t\tconst strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);\n\t\t\tconst shard = new WebSocketShard(strategy, shardId);\n\t\t\tfor (const event of Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Intentional\n\t\t\t\tshard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));\n\t\t\t}\n\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.connect());\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.destroy(options));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t\tthis.shards.clear();\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic async send(shardId: number, payload: GatewaySendPayload) {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} not found`);\n\t\t}\n\n\t\treturn shard.send(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\treturn this.shards.mapValues((shard) => shard.status);\n\t}\n}\n","import type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class SimpleContextFetchingStrategy implements IContextFetchingStrategy {\n\t// This strategy assumes every shard is running under the same process - therefore we need a single\n\t// IdentifyThrottler per manager.\n\tprivate static throttlerCache = new WeakMap<WebSocketManager, IIdentifyThrottler>();\n\n\tprivate static async ensureThrottler(manager: WebSocketManager): Promise<IIdentifyThrottler> {\n\t\tconst throttler = SimpleContextFetchingStrategy.throttlerCache.get(manager);\n\t\tif (throttler) {\n\t\t\treturn throttler;\n\t\t}\n\n\t\tconst newThrottler = await manager.options.buildIdentifyThrottler(manager);\n\t\tSimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);\n\n\t\treturn newThrottler;\n\t}\n\n\tpublic constructor(private readonly manager: WebSocketManager, public readonly options: FetchingStrategyOptions) {}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\treturn this.manager.options.retrieveSessionInfo(shardId);\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\treturn this.manager.options.updateSessionInfo(shardId, sessionInfo);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst throttler = await SimpleContextFetchingStrategy.ensureThrottler(this.manager);\n\t\tawait throttler.waitForIdentify(shardId, signal);\n\t}\n}\n","import { setTimeout as sleep } from 'node:timers/promises';\nimport { Collection } from '@discordjs/collection';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport type { IIdentifyThrottler } from './IIdentifyThrottler.js';\n\n/**\n * The state of a rate limit key's identify queue.\n */\nexport interface IdentifyState {\n\tqueue: AsyncQueue;\n\tresetsAt: number;\n}\n\n/**\n * Local, in-memory identify throttler.\n */\nexport class SimpleIdentifyThrottler implements IIdentifyThrottler {\n\tprivate readonly states = new Collection<number, IdentifyState>();\n\n\tpublic constructor(private readonly maxConcurrency: number) {}\n\n\t/**\n\t * {@inheritDoc IIdentifyThrottler.waitForIdentify}\n\t */\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst key = shardId % this.maxConcurrency;\n\n\t\tconst state = this.states.ensure(key, () => {\n\t\t\treturn {\n\t\t\t\tqueue: new AsyncQueue(),\n\t\t\t\tresetsAt: Number.POSITIVE_INFINITY,\n\t\t\t};\n\t\t});\n\n\t\tawait state.queue.wait({ signal });\n\n\t\ttry {\n\t\t\tconst diff = state.resetsAt - Date.now();\n\t\t\tif (diff <= 5_000) {\n\t\t\t\t// To account for the latency the IDENTIFY payload goes through, we add a bit more wait time\n\t\t\t\tconst time = diff + Math.random() * 1_500;\n\t\t\t\tawait sleep(time);\n\t\t\t}\n\n\t\t\tstate.resetsAt = Date.now() + 5_000;\n\t\t} finally {\n\t\t\tstate.queue.shift();\n\t\t}\n\t}\n}\n","import { WorkerBootstrapper } from '../../utils/WorkerBootstrapper.js';\n\nconst bootstrapper = new WorkerBootstrapper();\nvoid bootstrapper.bootstrap();\n"],"mappings":"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","names":["import_node_worker_threads","import_collection","import_node_worker_threads","import_collection","resolve","payload","import_node_events","import_promises","import_collection","import_util","import_async_queue","import_v10","import_collection","import_collection","import_collection","sleep","process","WebSocketShardEvents","WebSocketShardDestroyRecovery","resolve","sleep","session"]} \ No newline at end of file
diff --git a/node_modules/@discordjs/ws/dist/defaultWorker.mjs b/node_modules/@discordjs/ws/dist/defaultWorker.mjs
new file mode 100644
index 0000000..9f90978
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/defaultWorker.mjs
@@ -0,0 +1,1033 @@
+var __defProp = Object.defineProperty;
+var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
+
+// src/utils/WorkerBootstrapper.ts
+import { isMainThread as isMainThread2, parentPort as parentPort2, workerData } from "node:worker_threads";
+import { Collection as Collection7 } from "@discordjs/collection";
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+import { isMainThread, parentPort } from "node:worker_threads";
+import { Collection as Collection2 } from "@discordjs/collection";
+
+// src/strategies/sharding/WorkerShardingStrategy.ts
+import { once } from "node:events";
+import { join, isAbsolute, resolve } from "node:path";
+import { Worker } from "node:worker_threads";
+import { Collection } from "@discordjs/collection";
+
+// src/strategies/context/IContextFetchingStrategy.ts
+async function managerToFetchingStrategyOptions(manager) {
+ const {
+ buildIdentifyThrottler,
+ buildStrategy,
+ retrieveSessionInfo,
+ updateSessionInfo,
+ shardCount,
+ shardIds,
+ rest,
+ ...managerOptions
+ } = manager.options;
+ return {
+ ...managerOptions,
+ gatewayInformation: await manager.fetchGatewayInformation(),
+ shardCount: await manager.getShardCount()
+ };
+}
+__name(managerToFetchingStrategyOptions, "managerToFetchingStrategyOptions");
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+var WorkerContextFetchingStrategy = class {
+ constructor(options) {
+ this.options = options;
+ if (isMainThread) {
+ throw new Error("Cannot instantiate WorkerContextFetchingStrategy on the main thread");
+ }
+ parentPort.on("message", (payload) => {
+ if (payload.op === 3 /* SessionInfoResponse */) {
+ this.sessionPromises.get(payload.nonce)?.(payload.session);
+ this.sessionPromises.delete(payload.nonce);
+ }
+ if (payload.op === 4 /* ShardIdentifyResponse */) {
+ const promise = this.waitForIdentifyPromises.get(payload.nonce);
+ if (payload.ok) {
+ promise?.resolve();
+ } else {
+ promise?.reject(promise.signal.reason);
+ }
+ this.waitForIdentifyPromises.delete(payload.nonce);
+ }
+ });
+ }
+ static {
+ __name(this, "WorkerContextFetchingStrategy");
+ }
+ sessionPromises = new Collection2();
+ waitForIdentifyPromises = new Collection2();
+ async retrieveSessionInfo(shardId) {
+ const nonce = Math.random();
+ const payload = {
+ op: 3 /* RetrieveSessionInfo */,
+ shardId,
+ nonce
+ };
+ const promise = new Promise((resolve2) => this.sessionPromises.set(nonce, resolve2));
+ parentPort.postMessage(payload);
+ return promise;
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ const payload = {
+ op: 4 /* UpdateSessionInfo */,
+ shardId,
+ session: sessionInfo
+ };
+ parentPort.postMessage(payload);
+ }
+ async waitForIdentify(shardId, signal) {
+ const nonce = Math.random();
+ const payload = {
+ op: 5 /* WaitForIdentify */,
+ nonce,
+ shardId
+ };
+ const promise = new Promise(
+ (resolve2, reject) => (
+ // eslint-disable-next-line no-promise-executor-return
+ this.waitForIdentifyPromises.set(nonce, { signal, resolve: resolve2, reject })
+ )
+ );
+ parentPort.postMessage(payload);
+ const listener = /* @__PURE__ */ __name(() => {
+ const payload2 = {
+ op: 8 /* CancelIdentify */,
+ nonce
+ };
+ parentPort.postMessage(payload2);
+ }, "listener");
+ signal.addEventListener("abort", listener);
+ try {
+ await promise;
+ } finally {
+ signal.removeEventListener("abort", listener);
+ }
+ }
+};
+
+// src/ws/WebSocketShard.ts
+import { Buffer as Buffer2 } from "node:buffer";
+import { once as once2 } from "node:events";
+import { clearInterval, clearTimeout, setInterval, setTimeout } from "node:timers";
+import { setTimeout as sleep2 } from "node:timers/promises";
+import { URLSearchParams } from "node:url";
+import { TextDecoder } from "node:util";
+import { inflate } from "node:zlib";
+import { Collection as Collection6 } from "@discordjs/collection";
+import { lazy as lazy2 } from "@discordjs/util";
+import { AsyncQueue as AsyncQueue2 } from "@sapphire/async-queue";
+import { AsyncEventEmitter } from "@vladfrangu/async_event_emitter";
+import {
+ GatewayCloseCodes,
+ GatewayDispatchEvents,
+ GatewayOpcodes as GatewayOpcodes2
+} from "discord-api-types/v10";
+import { WebSocket } from "ws";
+
+// src/utils/constants.ts
+import process from "node:process";
+import { Collection as Collection5 } from "@discordjs/collection";
+import { lazy } from "@discordjs/util";
+import { APIVersion, GatewayOpcodes } from "discord-api-types/v10";
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+import { Collection as Collection3 } from "@discordjs/collection";
+
+// src/strategies/context/SimpleContextFetchingStrategy.ts
+var SimpleContextFetchingStrategy = class _SimpleContextFetchingStrategy {
+ constructor(manager, options) {
+ this.manager = manager;
+ this.options = options;
+ }
+ static {
+ __name(this, "SimpleContextFetchingStrategy");
+ }
+ // This strategy assumes every shard is running under the same process - therefore we need a single
+ // IdentifyThrottler per manager.
+ static throttlerCache = /* @__PURE__ */ new WeakMap();
+ static async ensureThrottler(manager) {
+ const throttler = _SimpleContextFetchingStrategy.throttlerCache.get(manager);
+ if (throttler) {
+ return throttler;
+ }
+ const newThrottler = await manager.options.buildIdentifyThrottler(manager);
+ _SimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);
+ return newThrottler;
+ }
+ async retrieveSessionInfo(shardId) {
+ return this.manager.options.retrieveSessionInfo(shardId);
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ return this.manager.options.updateSessionInfo(shardId, sessionInfo);
+ }
+ async waitForIdentify(shardId, signal) {
+ const throttler = await _SimpleContextFetchingStrategy.ensureThrottler(this.manager);
+ await throttler.waitForIdentify(shardId, signal);
+ }
+};
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+var SimpleShardingStrategy = class {
+ static {
+ __name(this, "SimpleShardingStrategy");
+ }
+ manager;
+ shards = new Collection3();
+ constructor(manager) {
+ this.manager = manager;
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ async spawn(shardIds) {
+ const strategyOptions = await managerToFetchingStrategyOptions(this.manager);
+ for (const shardId of shardIds) {
+ const strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);
+ const shard = new WebSocketShard(strategy, shardId);
+ for (const event of Object.values(WebSocketShardEvents)) {
+ shard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));
+ }
+ this.shards.set(shardId, shard);
+ }
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ async connect() {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.connect());
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ async destroy(options) {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.destroy(options));
+ }
+ await Promise.all(promises);
+ this.shards.clear();
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ async send(shardId, payload) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} not found`);
+ }
+ return shard.send(payload);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ async fetchStatus() {
+ return this.shards.mapValues((shard) => shard.status);
+ }
+};
+
+// src/throttling/SimpleIdentifyThrottler.ts
+import { setTimeout as sleep } from "node:timers/promises";
+import { Collection as Collection4 } from "@discordjs/collection";
+import { AsyncQueue } from "@sapphire/async-queue";
+var SimpleIdentifyThrottler = class {
+ constructor(maxConcurrency) {
+ this.maxConcurrency = maxConcurrency;
+ }
+ static {
+ __name(this, "SimpleIdentifyThrottler");
+ }
+ states = new Collection4();
+ /**
+ * {@inheritDoc IIdentifyThrottler.waitForIdentify}
+ */
+ async waitForIdentify(shardId, signal) {
+ const key = shardId % this.maxConcurrency;
+ const state = this.states.ensure(key, () => {
+ return {
+ queue: new AsyncQueue(),
+ resetsAt: Number.POSITIVE_INFINITY
+ };
+ });
+ await state.queue.wait({ signal });
+ try {
+ const diff = state.resetsAt - Date.now();
+ if (diff <= 5e3) {
+ const time = diff + Math.random() * 1500;
+ await sleep(time);
+ }
+ state.resetsAt = Date.now() + 5e3;
+ } finally {
+ state.queue.shift();
+ }
+ }
+};
+
+// src/utils/constants.ts
+var DefaultDeviceProperty = `@discordjs/ws 1.0.1`;
+var getDefaultSessionStore = lazy(() => new Collection5());
+var DefaultWebSocketManagerOptions = {
+ async buildIdentifyThrottler(manager) {
+ const info = await manager.fetchGatewayInformation();
+ return new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);
+ },
+ buildStrategy: (manager) => new SimpleShardingStrategy(manager),
+ shardCount: null,
+ shardIds: null,
+ largeThreshold: null,
+ initialPresence: null,
+ identifyProperties: {
+ browser: DefaultDeviceProperty,
+ device: DefaultDeviceProperty,
+ os: process.platform
+ },
+ version: APIVersion,
+ encoding: "json" /* JSON */,
+ compression: null,
+ retrieveSessionInfo(shardId) {
+ const store = getDefaultSessionStore();
+ return store.get(shardId) ?? null;
+ },
+ updateSessionInfo(shardId, info) {
+ const store = getDefaultSessionStore();
+ if (info) {
+ store.set(shardId, info);
+ } else {
+ store.delete(shardId);
+ }
+ },
+ handshakeTimeout: 3e4,
+ helloTimeout: 6e4,
+ readyTimeout: 15e3
+};
+var ImportantGatewayOpcodes = /* @__PURE__ */ new Set([
+ GatewayOpcodes.Heartbeat,
+ GatewayOpcodes.Identify,
+ GatewayOpcodes.Resume
+]);
+function getInitialSendRateLimitState() {
+ return {
+ remaining: 120,
+ resetAt: Date.now() + 6e4
+ };
+}
+__name(getInitialSendRateLimitState, "getInitialSendRateLimitState");
+
+// src/ws/WebSocketShard.ts
+var getZlibSync = lazy2(async () => import("zlib-sync").then((mod) => mod.default).catch(() => null));
+var WebSocketShardEvents = /* @__PURE__ */ ((WebSocketShardEvents2) => {
+ WebSocketShardEvents2["Closed"] = "closed";
+ WebSocketShardEvents2["Debug"] = "debug";
+ WebSocketShardEvents2["Dispatch"] = "dispatch";
+ WebSocketShardEvents2["Error"] = "error";
+ WebSocketShardEvents2["HeartbeatComplete"] = "heartbeat";
+ WebSocketShardEvents2["Hello"] = "hello";
+ WebSocketShardEvents2["Ready"] = "ready";
+ WebSocketShardEvents2["Resumed"] = "resumed";
+ return WebSocketShardEvents2;
+})(WebSocketShardEvents || {});
+var WebSocketShardDestroyRecovery = /* @__PURE__ */ ((WebSocketShardDestroyRecovery2) => {
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Reconnect"] = 0] = "Reconnect";
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Resume"] = 1] = "Resume";
+ return WebSocketShardDestroyRecovery2;
+})(WebSocketShardDestroyRecovery || {});
+var WebSocketConstructor = WebSocket;
+var WebSocketShard = class extends AsyncEventEmitter {
+ static {
+ __name(this, "WebSocketShard");
+ }
+ connection = null;
+ useIdentifyCompress = false;
+ inflate = null;
+ textDecoder = new TextDecoder();
+ replayedEvents = 0;
+ isAck = true;
+ sendRateLimitState = getInitialSendRateLimitState();
+ initialHeartbeatTimeoutController = null;
+ heartbeatInterval = null;
+ lastHeartbeatAt = -1;
+ // Indicates whether the shard has already resolved its original connect() call
+ initialConnectResolved = false;
+ // Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)
+ failedToConnectDueToNetworkError = false;
+ sendQueue = new AsyncQueue2();
+ timeoutAbortControllers = new Collection6();
+ strategy;
+ id;
+ #status = 0 /* Idle */;
+ get status() {
+ return this.#status;
+ }
+ constructor(strategy, id) {
+ super();
+ this.strategy = strategy;
+ this.id = id;
+ }
+ async connect() {
+ const controller = new AbortController();
+ let promise;
+ if (!this.initialConnectResolved) {
+ promise = Promise.race([
+ once2(this, "ready" /* Ready */, { signal: controller.signal }),
+ once2(this, "resumed" /* Resumed */, { signal: controller.signal })
+ ]);
+ }
+ void this.internalConnect();
+ try {
+ await promise;
+ } catch ({ error }) {
+ throw error;
+ } finally {
+ controller.abort();
+ }
+ this.initialConnectResolved = true;
+ }
+ async internalConnect() {
+ if (this.#status !== 0 /* Idle */) {
+ throw new Error("Tried to connect a shard that wasn't idle");
+ }
+ const { version, encoding, compression } = this.strategy.options;
+ const params = new URLSearchParams({ v: version, encoding });
+ if (compression) {
+ const zlib = await getZlibSync();
+ if (zlib) {
+ params.append("compress", compression);
+ this.inflate = new zlib.Inflate({
+ chunkSize: 65535,
+ to: "string"
+ });
+ } else if (!this.useIdentifyCompress) {
+ this.useIdentifyCompress = true;
+ console.warn(
+ "WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress"
+ );
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ const url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;
+ this.debug([`Connecting to ${url}`]);
+ const connection = new WebSocketConstructor(url, {
+ handshakeTimeout: this.strategy.options.handshakeTimeout ?? void 0
+ });
+ connection.binaryType = "arraybuffer";
+ connection.onmessage = (event) => {
+ void this.onMessage(event.data, event.data instanceof ArrayBuffer);
+ };
+ connection.onerror = (event) => {
+ this.onError(event.error);
+ };
+ connection.onclose = (event) => {
+ void this.onClose(event.code);
+ };
+ this.connection = connection;
+ this.#status = 1 /* Connecting */;
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ const { ok } = await this.waitForEvent("hello" /* Hello */, this.strategy.options.helloTimeout);
+ if (!ok) {
+ return;
+ }
+ if (session?.shardCount === this.strategy.options.shardCount) {
+ await this.resume(session);
+ } else {
+ await this.identify();
+ }
+ }
+ async destroy(options = {}) {
+ if (this.#status === 0 /* Idle */) {
+ this.debug(["Tried to destroy a shard that was idle"]);
+ return;
+ }
+ if (!options.code) {
+ options.code = options.recover === 1 /* Resume */ ? 4200 /* Resuming */ : 1e3 /* Normal */;
+ }
+ this.debug([
+ "Destroying shard",
+ `Reason: ${options.reason ?? "none"}`,
+ `Code: ${options.code}`,
+ `Recover: ${options.recover === void 0 ? "none" : WebSocketShardDestroyRecovery[options.recover]}`
+ ]);
+ this.isAck = true;
+ if (this.heartbeatInterval) {
+ clearInterval(this.heartbeatInterval);
+ }
+ if (this.initialHeartbeatTimeoutController) {
+ this.initialHeartbeatTimeoutController.abort();
+ this.initialHeartbeatTimeoutController = null;
+ }
+ this.lastHeartbeatAt = -1;
+ for (const controller of this.timeoutAbortControllers.values()) {
+ controller.abort();
+ }
+ this.timeoutAbortControllers.clear();
+ this.failedToConnectDueToNetworkError = false;
+ if (options.recover !== 1 /* Resume */) {
+ await this.strategy.updateSessionInfo(this.id, null);
+ }
+ if (this.connection) {
+ this.connection.onmessage = null;
+ this.connection.onclose = null;
+ const shouldClose = this.connection.readyState === WebSocket.OPEN;
+ this.debug([
+ "Connection status during destroy",
+ `Needs closing: ${shouldClose}`,
+ `Ready state: ${this.connection.readyState}`
+ ]);
+ if (shouldClose) {
+ let outerResolve;
+ const promise = new Promise((resolve2) => {
+ outerResolve = resolve2;
+ });
+ this.connection.onclose = outerResolve;
+ this.connection.close(options.code, options.reason);
+ await promise;
+ this.emit("closed" /* Closed */, { code: options.code });
+ }
+ this.connection.onerror = null;
+ } else {
+ this.debug(["Destroying a shard that has no connection; please open an issue on GitHub"]);
+ }
+ this.#status = 0 /* Idle */;
+ if (options.recover !== void 0) {
+ await sleep2(500);
+ return this.internalConnect();
+ }
+ }
+ async waitForEvent(event, timeoutDuration) {
+ this.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : "indefinitely"}`]);
+ const timeoutController = new AbortController();
+ const timeout = timeoutDuration ? setTimeout(() => timeoutController.abort(), timeoutDuration).unref() : null;
+ this.timeoutAbortControllers.set(event, timeoutController);
+ const closeController = new AbortController();
+ try {
+ const closed = await Promise.race([
+ once2(this, event, { signal: timeoutController.signal }).then(() => false),
+ once2(this, "closed" /* Closed */, { signal: closeController.signal }).then(() => true)
+ ]);
+ return { ok: !closed };
+ } catch {
+ void this.destroy({
+ code: 1e3 /* Normal */,
+ reason: "Something timed out or went wrong while waiting for an event",
+ recover: 0 /* Reconnect */
+ });
+ return { ok: false };
+ } finally {
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ this.timeoutAbortControllers.delete(event);
+ if (!closeController.signal.aborted) {
+ closeController.abort();
+ }
+ }
+ }
+ async send(payload) {
+ if (!this.connection) {
+ throw new Error("WebSocketShard wasn't connected");
+ }
+ if (this.#status !== 3 /* Ready */ && !ImportantGatewayOpcodes.has(payload.op)) {
+ this.debug(["Tried to send a non-crucial payload before the shard was ready, waiting"]);
+ try {
+ await once2(this, "ready" /* Ready */);
+ } catch {
+ return this.send(payload);
+ }
+ }
+ await this.sendQueue.wait();
+ if (--this.sendRateLimitState.remaining <= 0) {
+ const now = Date.now();
+ if (this.sendRateLimitState.resetAt > now) {
+ const sleepFor = this.sendRateLimitState.resetAt - now;
+ this.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);
+ const controller = new AbortController();
+ const interrupted = await Promise.race([
+ sleep2(sleepFor).then(() => false),
+ once2(this, "closed" /* Closed */, { signal: controller.signal }).then(() => true)
+ ]);
+ if (interrupted) {
+ this.debug(["Connection closed while waiting for the send rate limit to reset, re-queueing payload"]);
+ this.sendQueue.shift();
+ return this.send(payload);
+ }
+ controller.abort();
+ }
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ }
+ this.sendQueue.shift();
+ this.connection.send(JSON.stringify(payload));
+ }
+ async identify() {
+ this.debug(["Waiting for identify throttle"]);
+ const controller = new AbortController();
+ const closeHandler = /* @__PURE__ */ __name(() => {
+ controller.abort();
+ }, "closeHandler");
+ this.on("closed" /* Closed */, closeHandler);
+ try {
+ await this.strategy.waitForIdentify(this.id, controller.signal);
+ } catch {
+ if (controller.signal.aborted) {
+ this.debug(["Was waiting for an identify, but the shard closed in the meantime"]);
+ return;
+ }
+ this.debug([
+ "IContextFetchingStrategy#waitForIdentify threw an unknown error.",
+ "If you're using a custom strategy, this is probably nothing to worry about.",
+ "If you're not, please open an issue on GitHub."
+ ]);
+ await this.destroy({
+ reason: "Identify throttling logic failed",
+ recover: 1 /* Resume */
+ });
+ } finally {
+ this.off("closed" /* Closed */, closeHandler);
+ }
+ this.debug([
+ "Identifying",
+ `shard id: ${this.id.toString()}`,
+ `shard count: ${this.strategy.options.shardCount}`,
+ `intents: ${this.strategy.options.intents}`,
+ `compression: ${this.inflate ? "zlib-stream" : this.useIdentifyCompress ? "identify" : "none"}`
+ ]);
+ const d = {
+ token: this.strategy.options.token,
+ properties: this.strategy.options.identifyProperties,
+ intents: this.strategy.options.intents,
+ compress: this.useIdentifyCompress,
+ shard: [this.id, this.strategy.options.shardCount]
+ };
+ if (this.strategy.options.largeThreshold) {
+ d.large_threshold = this.strategy.options.largeThreshold;
+ }
+ if (this.strategy.options.initialPresence) {
+ d.presence = this.strategy.options.initialPresence;
+ }
+ await this.send({
+ op: GatewayOpcodes2.Identify,
+ d
+ });
+ await this.waitForEvent("ready" /* Ready */, this.strategy.options.readyTimeout);
+ }
+ async resume(session) {
+ this.debug([
+ "Resuming session",
+ `resume url: ${session.resumeURL}`,
+ `sequence: ${session.sequence}`,
+ `shard id: ${this.id.toString()}`
+ ]);
+ this.#status = 2 /* Resuming */;
+ this.replayedEvents = 0;
+ return this.send({
+ op: GatewayOpcodes2.Resume,
+ d: {
+ token: this.strategy.options.token,
+ seq: session.sequence,
+ session_id: session.sessionId
+ }
+ });
+ }
+ async heartbeat(requested = false) {
+ if (!this.isAck && !requested) {
+ return this.destroy({ reason: "Zombie connection", recover: 1 /* Resume */ });
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ await this.send({
+ op: GatewayOpcodes2.Heartbeat,
+ d: session?.sequence ?? null
+ });
+ this.lastHeartbeatAt = Date.now();
+ this.isAck = false;
+ }
+ async unpackMessage(data, isBinary) {
+ if (!isBinary) {
+ try {
+ return JSON.parse(data);
+ } catch {
+ return null;
+ }
+ }
+ const decompressable = new Uint8Array(data);
+ if (this.useIdentifyCompress) {
+ return new Promise((resolve2, reject) => {
+ inflate(decompressable, { chunkSize: 65535 }, (err, result) => {
+ if (err) {
+ reject(err);
+ return;
+ }
+ resolve2(JSON.parse(this.textDecoder.decode(result)));
+ });
+ });
+ }
+ if (this.inflate) {
+ const l = decompressable.length;
+ const flush = l >= 4 && decompressable[l - 4] === 0 && decompressable[l - 3] === 0 && decompressable[l - 2] === 255 && decompressable[l - 1] === 255;
+ const zlib = await getZlibSync();
+ this.inflate.push(Buffer2.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);
+ if (this.inflate.err) {
+ this.emit("error" /* Error */, {
+ error: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ""}`)
+ });
+ }
+ if (!flush) {
+ return null;
+ }
+ const { result } = this.inflate;
+ if (!result) {
+ return null;
+ }
+ return JSON.parse(typeof result === "string" ? result : this.textDecoder.decode(result));
+ }
+ this.debug([
+ "Received a message we were unable to decompress",
+ `isBinary: ${isBinary.toString()}`,
+ `useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,
+ `inflate: ${Boolean(this.inflate).toString()}`
+ ]);
+ return null;
+ }
+ async onMessage(data, isBinary) {
+ const payload = await this.unpackMessage(data, isBinary);
+ if (!payload) {
+ return;
+ }
+ switch (payload.op) {
+ case GatewayOpcodes2.Dispatch: {
+ if (this.#status === 2 /* Resuming */) {
+ this.replayedEvents++;
+ }
+ switch (payload.t) {
+ case GatewayDispatchEvents.Ready: {
+ this.#status = 3 /* Ready */;
+ const session2 = {
+ sequence: payload.s,
+ sessionId: payload.d.session_id,
+ shardId: this.id,
+ shardCount: this.strategy.options.shardCount,
+ resumeURL: payload.d.resume_gateway_url
+ };
+ await this.strategy.updateSessionInfo(this.id, session2);
+ this.emit("ready" /* Ready */, { data: payload.d });
+ break;
+ }
+ case GatewayDispatchEvents.Resumed: {
+ this.#status = 3 /* Ready */;
+ this.debug([`Resumed and replayed ${this.replayedEvents} events`]);
+ this.emit("resumed" /* Resumed */);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (session) {
+ if (payload.s > session.sequence) {
+ await this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });
+ }
+ } else {
+ this.debug([
+ `Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`
+ ]);
+ }
+ this.emit("dispatch" /* Dispatch */, { data: payload });
+ break;
+ }
+ case GatewayOpcodes2.Heartbeat: {
+ await this.heartbeat(true);
+ break;
+ }
+ case GatewayOpcodes2.Reconnect: {
+ await this.destroy({
+ reason: "Told to reconnect by Discord",
+ recover: 1 /* Resume */
+ });
+ break;
+ }
+ case GatewayOpcodes2.InvalidSession: {
+ this.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (payload.d && session) {
+ await this.resume(session);
+ } else {
+ await this.destroy({
+ reason: "Invalid session",
+ recover: 0 /* Reconnect */
+ });
+ }
+ break;
+ }
+ case GatewayOpcodes2.Hello: {
+ this.emit("hello" /* Hello */);
+ const jitter = Math.random();
+ const firstWait = Math.floor(payload.d.heartbeat_interval * jitter);
+ this.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);
+ try {
+ const controller = new AbortController();
+ this.initialHeartbeatTimeoutController = controller;
+ await sleep2(firstWait, void 0, { signal: controller.signal });
+ } catch {
+ this.debug(["Cancelled initial heartbeat due to #destroy being called"]);
+ return;
+ } finally {
+ this.initialHeartbeatTimeoutController = null;
+ }
+ await this.heartbeat();
+ this.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);
+ this.heartbeatInterval = setInterval(() => void this.heartbeat(), payload.d.heartbeat_interval);
+ break;
+ }
+ case GatewayOpcodes2.HeartbeatAck: {
+ this.isAck = true;
+ const ackAt = Date.now();
+ this.emit("heartbeat" /* HeartbeatComplete */, {
+ ackAt,
+ heartbeatAt: this.lastHeartbeatAt,
+ latency: ackAt - this.lastHeartbeatAt
+ });
+ break;
+ }
+ }
+ }
+ onError(error) {
+ if ("code" in error && ["ECONNRESET", "ECONNREFUSED"].includes(error.code)) {
+ this.debug(["Failed to connect to the gateway URL specified due to a network error"]);
+ this.failedToConnectDueToNetworkError = true;
+ return;
+ }
+ this.emit("error" /* Error */, { error });
+ }
+ async onClose(code) {
+ this.emit("closed" /* Closed */, { code });
+ switch (code) {
+ case 1e3 /* Normal */: {
+ return this.destroy({
+ code,
+ reason: "Got disconnected by Discord",
+ recover: 0 /* Reconnect */
+ });
+ }
+ case 4200 /* Resuming */: {
+ break;
+ }
+ case GatewayCloseCodes.UnknownError: {
+ this.debug([`An unknown error occurred: ${code}`]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.UnknownOpcode: {
+ this.debug(["An invalid opcode was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.DecodeError: {
+ this.debug(["An invalid payload was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.NotAuthenticated: {
+ this.debug(["A request was somehow sent before the identify/resume payload."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.AuthenticationFailed: {
+ this.emit("error" /* Error */, {
+ error: new Error("Authentication failed")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.AlreadyAuthenticated: {
+ this.debug(["More than one auth payload was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.InvalidSeq: {
+ this.debug(["An invalid sequence was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.RateLimited: {
+ this.debug(["The WebSocket rate limit has been hit, this should never happen"]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.SessionTimedOut: {
+ this.debug(["Session timed out."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.InvalidShard: {
+ this.emit("error" /* Error */, {
+ error: new Error("Invalid shard")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.ShardingRequired: {
+ this.emit("error" /* Error */, {
+ error: new Error("Sharding is required")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.InvalidAPIVersion: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used an invalid API version")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.InvalidIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used invalid intents")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.DisallowedIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used disallowed intents")
+ });
+ return this.destroy({ code });
+ }
+ default: {
+ this.debug([
+ `The gateway closed with an unexpected code ${code}, attempting to ${this.failedToConnectDueToNetworkError ? "reconnect" : "resume"}.`
+ ]);
+ return this.destroy({
+ code,
+ recover: this.failedToConnectDueToNetworkError ? 0 /* Reconnect */ : 1 /* Resume */
+ });
+ }
+ }
+ }
+ debug(messages) {
+ const message = `${messages[0]}${messages.length > 1 ? `
+${messages.slice(1).map((m) => ` ${m}`).join("\n")}` : ""}`;
+ this.emit("debug" /* Debug */, { message });
+ }
+};
+
+// src/utils/WorkerBootstrapper.ts
+var WorkerBootstrapper = class {
+ static {
+ __name(this, "WorkerBootstrapper");
+ }
+ /**
+ * The data passed to the worker thread
+ */
+ data = workerData;
+ /**
+ * The shards that are managed by this worker
+ */
+ shards = new Collection7();
+ constructor() {
+ if (isMainThread2) {
+ throw new Error("Expected WorkerBootstrap to not be used within the main thread");
+ }
+ }
+ /**
+ * Helper method to initiate a shard's connection process
+ */
+ async connect(shardId) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.connect();
+ }
+ /**
+ * Helper method to destroy a shard
+ */
+ async destroy(shardId, options) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.destroy(options);
+ }
+ /**
+ * Helper method to attach event listeners to the parentPort
+ */
+ setupThreadEvents() {
+ parentPort2.on("messageerror", (err) => {
+ throw err;
+ }).on("message", async (payload) => {
+ switch (payload.op) {
+ case 0 /* Connect */: {
+ await this.connect(payload.shardId);
+ const response = {
+ op: 0 /* Connected */,
+ shardId: payload.shardId
+ };
+ parentPort2.postMessage(response);
+ break;
+ }
+ case 1 /* Destroy */: {
+ await this.destroy(payload.shardId, payload.options);
+ const response = {
+ op: 1 /* Destroyed */,
+ shardId: payload.shardId
+ };
+ parentPort2.postMessage(response);
+ break;
+ }
+ case 2 /* Send */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${payload.shardId} does not exist`);
+ }
+ await shard.send(payload.payload);
+ break;
+ }
+ case 3 /* SessionInfoResponse */: {
+ break;
+ }
+ case 4 /* ShardIdentifyResponse */: {
+ break;
+ }
+ case 5 /* FetchStatus */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new Error(`Shard ${payload.shardId} does not exist`);
+ }
+ const response = {
+ op: 6 /* FetchStatusResponse */,
+ status: shard.status,
+ nonce: payload.nonce
+ };
+ parentPort2.postMessage(response);
+ break;
+ }
+ }
+ });
+ }
+ /**
+ * Bootstraps the worker thread with the provided options
+ */
+ async bootstrap(options = {}) {
+ for (const shardId of this.data.shardIds) {
+ const shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);
+ for (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {
+ shard.on(event, (data) => {
+ const payload = {
+ op: 2 /* Event */,
+ event,
+ data,
+ shardId
+ };
+ parentPort2.postMessage(payload);
+ });
+ }
+ await options.shardCallback?.(shard);
+ this.shards.set(shardId, shard);
+ }
+ this.setupThreadEvents();
+ const message = {
+ op: 7 /* WorkerReady */
+ };
+ parentPort2.postMessage(message);
+ }
+};
+
+// src/strategies/sharding/defaultWorker.ts
+var bootstrapper = new WorkerBootstrapper();
+void bootstrapper.bootstrap();
+//# sourceMappingURL=defaultWorker.mjs.map \ No newline at end of file
diff --git a/node_modules/@discordjs/ws/dist/defaultWorker.mjs.map b/node_modules/@discordjs/ws/dist/defaultWorker.mjs.map
new file mode 100644
index 0000000..8ef3f02
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/defaultWorker.mjs.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/utils/WorkerBootstrapper.ts","../src/strategies/context/WorkerContextFetchingStrategy.ts","../src/strategies/sharding/WorkerShardingStrategy.ts","../src/strategies/context/IContextFetchingStrategy.ts","../src/ws/WebSocketShard.ts","../src/utils/constants.ts","../src/strategies/sharding/SimpleShardingStrategy.ts","../src/strategies/context/SimpleContextFetchingStrategy.ts","../src/throttling/SimpleIdentifyThrottler.ts","../src/strategies/sharding/defaultWorker.ts"],"sourcesContent":["import { isMainThread, parentPort, workerData } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { Awaitable } from '@discordjs/util';\nimport { WorkerContextFetchingStrategy } from '../strategies/context/WorkerContextFetchingStrategy.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerData,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../strategies/sharding/WorkerShardingStrategy.js';\nimport type { WebSocketShardDestroyOptions } from '../ws/WebSocketShard.js';\nimport { WebSocketShardEvents, WebSocketShard } from '../ws/WebSocketShard.js';\n\n/**\n * Options for bootstrapping the worker\n */\nexport interface BootstrapOptions {\n\t/**\n\t * Shard events to just arbitrarily forward to the parent thread for the manager to emit\n\t * Note: By default, this will include ALL events\n\t * you most likely want to handle dispatch within the worker itself\n\t */\n\tforwardEvents?: WebSocketShardEvents[];\n\t/**\n\t * Function to call when a shard is created for additional setup\n\t */\n\tshardCallback?(shard: WebSocketShard): Awaitable<void>;\n}\n\n/**\n * Utility class for bootstrapping a worker thread to be used for sharding\n */\nexport class WorkerBootstrapper {\n\t/**\n\t * The data passed to the worker thread\n\t */\n\tprotected readonly data = workerData as WorkerData;\n\n\t/**\n\t * The shards that are managed by this worker\n\t */\n\tprotected readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor() {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Expected WorkerBootstrap to not be used within the main thread');\n\t\t}\n\t}\n\n\t/**\n\t * Helper method to initiate a shard's connection process\n\t */\n\tprotected async connect(shardId: number): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.connect();\n\t}\n\n\t/**\n\t * Helper method to destroy a shard\n\t */\n\tprotected async destroy(shardId: number, options?: WebSocketShardDestroyOptions): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.destroy(options);\n\t}\n\n\t/**\n\t * Helper method to attach event listeners to the parentPort\n\t */\n\tprotected setupThreadEvents(): void {\n\t\tparentPort!\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerSendPayload) => {\n\t\t\t\tswitch (payload.op) {\n\t\t\t\t\tcase WorkerSendPayloadOp.Connect: {\n\t\t\t\t\t\tawait this.connect(payload.shardId);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Connected,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Destroy: {\n\t\t\t\t\t\tawait this.destroy(payload.shardId, payload.options);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Destroyed,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Send: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new RangeError(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait shard.send(payload.payload);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.SessionInfoResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.ShardIdentifyResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.FetchStatus: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new Error(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.FetchStatusResponse,\n\t\t\t\t\t\t\tstatus: shard.status,\n\t\t\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Bootstraps the worker thread with the provided options\n\t */\n\tpublic async bootstrap(options: Readonly<BootstrapOptions> = {}): Promise<void> {\n\t\t// Start by initializing the shards\n\t\tfor (const shardId of this.data.shardIds) {\n\t\t\tconst shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);\n\t\t\tfor (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Event types incompatible\n\t\t\t\tshard.on(event, (data) => {\n\t\t\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\t\t\top: WorkerReceivePayloadOp.Event,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tshardId,\n\t\t\t\t\t};\n\t\t\t\t\tparentPort!.postMessage(payload);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Any additional setup the user might want to do\n\t\t\tawait options.shardCallback?.(shard);\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\n\t\t// Lastly, start listening to messages from the parent thread\n\t\tthis.setupThreadEvents();\n\n\t\tconst message: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WorkerReady,\n\t\t};\n\t\tparentPort!.postMessage(message);\n\t}\n}\n","import { isMainThread, parentPort } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { SessionInfo } from '../../ws/WebSocketManager.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../sharding/WorkerShardingStrategy.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class WorkerContextFetchingStrategy implements IContextFetchingStrategy {\n\tprivate readonly sessionPromises = new Collection<number, (session: SessionInfo | null) => void>();\n\n\tprivate readonly waitForIdentifyPromises = new Collection<\n\t\tnumber,\n\t\t{ reject(error: unknown): void; resolve(): void; signal: AbortSignal }\n\t>();\n\n\tpublic constructor(public readonly options: FetchingStrategyOptions) {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Cannot instantiate WorkerContextFetchingStrategy on the main thread');\n\t\t}\n\n\t\tparentPort!.on('message', (payload: WorkerSendPayload) => {\n\t\t\tif (payload.op === WorkerSendPayloadOp.SessionInfoResponse) {\n\t\t\t\tthis.sessionPromises.get(payload.nonce)?.(payload.session);\n\t\t\t\tthis.sessionPromises.delete(payload.nonce);\n\t\t\t}\n\n\t\t\tif (payload.op === WorkerSendPayloadOp.ShardIdentifyResponse) {\n\t\t\t\tconst promise = this.waitForIdentifyPromises.get(payload.nonce);\n\t\t\t\tif (payload.ok) {\n\t\t\t\t\tpromise?.resolve();\n\t\t\t\t} else {\n\t\t\t\t\t// We need to make sure we reject with an abort error\n\t\t\t\t\tpromise?.reject(promise.signal.reason);\n\t\t\t\t}\n\n\t\t\t\tthis.waitForIdentifyPromises.delete(payload.nonce);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\tconst nonce = Math.random();\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.RetrieveSessionInfo,\n\t\t\tshardId,\n\t\t\tnonce,\n\t\t};\n\t\t// eslint-disable-next-line no-promise-executor-return\n\t\tconst promise = new Promise<SessionInfo | null>((resolve) => this.sessionPromises.set(nonce, resolve));\n\t\tparentPort!.postMessage(payload);\n\t\treturn promise;\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.UpdateSessionInfo,\n\t\t\tshardId,\n\t\t\tsession: sessionInfo,\n\t\t};\n\t\tparentPort!.postMessage(payload);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst nonce = Math.random();\n\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WaitForIdentify,\n\t\t\tnonce,\n\t\t\tshardId,\n\t\t};\n\t\tconst promise = new Promise<void>((resolve, reject) =>\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tthis.waitForIdentifyPromises.set(nonce, { signal, resolve, reject }),\n\t\t);\n\n\t\tparentPort!.postMessage(payload);\n\n\t\tconst listener = () => {\n\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\top: WorkerReceivePayloadOp.CancelIdentify,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\tparentPort!.postMessage(payload);\n\t\t};\n\n\t\tsignal.addEventListener('abort', listener);\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} finally {\n\t\t\tsignal.removeEventListener('abort', listener);\n\t\t}\n\t}\n}\n","import { once } from 'node:events';\nimport { join, isAbsolute, resolve } from 'node:path';\nimport { Worker } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type {\n\tWebSocketShardDestroyOptions,\n\tWebSocketShardEvents,\n\tWebSocketShardStatus,\n} from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions, type FetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\nexport interface WorkerData extends FetchingStrategyOptions {\n\tshardIds: number[];\n}\n\nexport enum WorkerSendPayloadOp {\n\tConnect,\n\tDestroy,\n\tSend,\n\tSessionInfoResponse,\n\tShardIdentifyResponse,\n\tFetchStatus,\n}\n\nexport type WorkerSendPayload =\n\t| { nonce: number; ok: boolean; op: WorkerSendPayloadOp.ShardIdentifyResponse }\n\t| { nonce: number; op: WorkerSendPayloadOp.FetchStatus; shardId: number }\n\t| { nonce: number; op: WorkerSendPayloadOp.SessionInfoResponse; session: SessionInfo | null }\n\t| { op: WorkerSendPayloadOp.Connect; shardId: number }\n\t| { op: WorkerSendPayloadOp.Destroy; options?: WebSocketShardDestroyOptions; shardId: number }\n\t| { op: WorkerSendPayloadOp.Send; payload: GatewaySendPayload; shardId: number };\n\nexport enum WorkerReceivePayloadOp {\n\tConnected,\n\tDestroyed,\n\tEvent,\n\tRetrieveSessionInfo,\n\tUpdateSessionInfo,\n\tWaitForIdentify,\n\tFetchStatusResponse,\n\tWorkerReady,\n\tCancelIdentify,\n}\n\nexport type WorkerReceivePayload =\n\t// Can't seem to get a type-safe union based off of the event, so I'm sadly leaving data as any for now\n\t| { data: any; event: WebSocketShardEvents; op: WorkerReceivePayloadOp.Event; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.CancelIdentify }\n\t| { nonce: number; op: WorkerReceivePayloadOp.FetchStatusResponse; status: WebSocketShardStatus }\n\t| { nonce: number; op: WorkerReceivePayloadOp.RetrieveSessionInfo; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.WaitForIdentify; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Connected; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Destroyed; shardId: number }\n\t| { op: WorkerReceivePayloadOp.UpdateSessionInfo; session: SessionInfo | null; shardId: number }\n\t| { op: WorkerReceivePayloadOp.WorkerReady };\n\n/**\n * Options for a {@link WorkerShardingStrategy}\n */\nexport interface WorkerShardingStrategyOptions {\n\t/**\n\t * Dictates how many shards should be spawned per worker thread.\n\t */\n\tshardsPerWorker: number | 'all';\n\t/**\n\t * Path to the worker file to use. The worker requires quite a bit of setup, it is recommended you leverage the {@link WorkerBootstrapper} class.\n\t */\n\tworkerPath?: string;\n}\n\n/**\n * Strategy used to spawn threads in worker_threads\n */\nexport class WorkerShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly options: WorkerShardingStrategyOptions;\n\n\t#workers: Worker[] = [];\n\n\treadonly #workerByShardId = new Collection<number, Worker>();\n\n\tprivate readonly connectPromises = new Collection<number, () => void>();\n\n\tprivate readonly destroyPromises = new Collection<number, () => void>();\n\n\tprivate readonly fetchStatusPromises = new Collection<number, (status: WebSocketShardStatus) => void>();\n\n\tprivate readonly waitForIdentifyControllers = new Collection<number, AbortController>();\n\n\tprivate throttler?: IIdentifyThrottler;\n\n\tpublic constructor(manager: WebSocketManager, options: WorkerShardingStrategyOptions) {\n\t\tthis.manager = manager;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst shardsPerWorker = this.options.shardsPerWorker === 'all' ? shardIds.length : this.options.shardsPerWorker;\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tconst loops = Math.ceil(shardIds.length / shardsPerWorker);\n\t\tconst promises: Promise<void>[] = [];\n\n\t\tfor (let idx = 0; idx < loops; idx++) {\n\t\t\tconst slice = shardIds.slice(idx * shardsPerWorker, (idx + 1) * shardsPerWorker);\n\t\t\tconst workerData: WorkerData = {\n\t\t\t\t...strategyOptions,\n\t\t\t\tshardIds: slice,\n\t\t\t};\n\n\t\t\tpromises.push(this.setupWorker(workerData));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Connect,\n\t\t\t\tshardId,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<void>((resolve) => this.connectPromises.set(shardId, resolve));\n\t\t\tworker.postMessage(payload);\n\t\t\tpromises.push(promise);\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options: Omit<WebSocketShardDestroyOptions, 'recover'> = {}) {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Destroy,\n\t\t\t\tshardId,\n\t\t\t\toptions,\n\t\t\t};\n\n\t\t\tpromises.push(\n\t\t\t\t// eslint-disable-next-line no-promise-executor-return, promise/prefer-await-to-then\n\t\t\t\tnew Promise<void>((resolve) => this.destroyPromises.set(shardId, resolve)).then(async () => worker.terminate()),\n\t\t\t);\n\t\t\tworker.postMessage(payload);\n\t\t}\n\n\t\tthis.#workers = [];\n\t\tthis.#workerByShardId.clear();\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic send(shardId: number, data: GatewaySendPayload) {\n\t\tconst worker = this.#workerByShardId.get(shardId);\n\t\tif (!worker) {\n\t\t\tthrow new Error(`No worker found for shard ${shardId}`);\n\t\t}\n\n\t\tconst payload: WorkerSendPayload = {\n\t\t\top: WorkerSendPayloadOp.Send,\n\t\t\tshardId,\n\t\t\tpayload: data,\n\t\t};\n\t\tworker.postMessage(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\tconst statuses = new Collection<number, WebSocketShardStatus>();\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst nonce = Math.random();\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.FetchStatus,\n\t\t\t\tshardId,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<WebSocketShardStatus>((resolve) => this.fetchStatusPromises.set(nonce, resolve));\n\t\t\tworker.postMessage(payload);\n\n\t\t\tconst status = await promise;\n\t\t\tstatuses.set(shardId, status);\n\t\t}\n\n\t\treturn statuses;\n\t}\n\n\tprivate async setupWorker(workerData: WorkerData) {\n\t\tconst worker = new Worker(this.resolveWorkerPath(), { workerData });\n\n\t\tawait once(worker, 'online');\n\t\t// We do this in case the user has any potentially long running code in their worker\n\t\tawait this.waitForWorkerReady(worker);\n\n\t\tworker\n\t\t\t.on('error', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerReceivePayload) => this.onMessage(worker, payload));\n\n\t\tthis.#workers.push(worker);\n\t\tfor (const shardId of workerData.shardIds) {\n\t\t\tthis.#workerByShardId.set(shardId, worker);\n\t\t}\n\t}\n\n\tprivate resolveWorkerPath(): string {\n\t\tconst path = this.options.workerPath;\n\n\t\tif (!path) {\n\t\t\treturn join(__dirname, 'defaultWorker.js');\n\t\t}\n\n\t\tif (isAbsolute(path)) {\n\t\t\treturn path;\n\t\t}\n\n\t\tif (/^\\.\\.?[/\\\\]/.test(path)) {\n\t\t\treturn resolve(path);\n\t\t}\n\n\t\ttry {\n\t\t\treturn require.resolve(path);\n\t\t} catch {\n\t\t\treturn resolve(path);\n\t\t}\n\t}\n\n\tprivate async waitForWorkerReady(worker: Worker): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst handler = (payload: WorkerReceivePayload) => {\n\t\t\t\tif (payload.op === WorkerReceivePayloadOp.WorkerReady) {\n\t\t\t\t\tresolve();\n\t\t\t\t\tworker.off('message', handler);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tworker.on('message', handler);\n\t\t});\n\t}\n\n\tprivate async onMessage(worker: Worker, payload: WorkerReceivePayload) {\n\t\tswitch (payload.op) {\n\t\t\tcase WorkerReceivePayloadOp.Connected: {\n\t\t\t\tthis.connectPromises.get(payload.shardId)?.();\n\t\t\t\tthis.connectPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Destroyed: {\n\t\t\t\tthis.destroyPromises.get(payload.shardId)?.();\n\t\t\t\tthis.destroyPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Event: {\n\t\t\t\tthis.manager.emit(payload.event, { ...payload.data, shardId: payload.shardId });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.RetrieveSessionInfo: {\n\t\t\t\tconst session = await this.manager.options.retrieveSessionInfo(payload.shardId);\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.SessionInfoResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tsession,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.UpdateSessionInfo: {\n\t\t\t\tawait this.manager.options.updateSessionInfo(payload.shardId, payload.session);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WaitForIdentify: {\n\t\t\t\tconst throttler = await this.ensureThrottler();\n\n\t\t\t\t// If this rejects it means we aborted, in which case we reply elsewhere.\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.waitForIdentifyControllers.set(payload.nonce, controller);\n\t\t\t\t\tawait throttler.waitForIdentify(payload.shardId, controller.signal);\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: true,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.FetchStatusResponse: {\n\t\t\t\tthis.fetchStatusPromises.get(payload.nonce)?.(payload.status);\n\t\t\t\tthis.fetchStatusPromises.delete(payload.nonce);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WorkerReady: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.CancelIdentify: {\n\t\t\t\tthis.waitForIdentifyControllers.get(payload.nonce)?.abort();\n\t\t\t\tthis.waitForIdentifyControllers.delete(payload.nonce);\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: false,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async ensureThrottler(): Promise<IIdentifyThrottler> {\n\t\tthis.throttler ??= await this.manager.options.buildIdentifyThrottler(this.manager);\n\t\treturn this.throttler;\n\t}\n}\n","import type { Awaitable } from '@discordjs/util';\nimport type { APIGatewayBotInfo } from 'discord-api-types/v10';\nimport type { SessionInfo, WebSocketManager, WebSocketManagerOptions } from '../../ws/WebSocketManager.js';\n\nexport interface FetchingStrategyOptions\n\textends Omit<\n\t\tWebSocketManagerOptions,\n\t\t| 'buildIdentifyThrottler'\n\t\t| 'buildStrategy'\n\t\t| 'rest'\n\t\t| 'retrieveSessionInfo'\n\t\t| 'shardCount'\n\t\t| 'shardIds'\n\t\t| 'updateSessionInfo'\n\t> {\n\treadonly gatewayInformation: APIGatewayBotInfo;\n\treadonly shardCount: number;\n}\n\n/**\n * Strategies responsible solely for making manager information accessible\n */\nexport interface IContextFetchingStrategy {\n\treadonly options: FetchingStrategyOptions;\n\tretrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;\n\tupdateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;\n\t/**\n\t * Resolves once the given shard should be allowed to identify\n\t * This should correctly handle the signal and reject with an abort error if the operation is aborted.\n\t * Other errors will cause the shard to reconnect.\n\t */\n\twaitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;\n}\n\nexport async function managerToFetchingStrategyOptions(manager: WebSocketManager): Promise<FetchingStrategyOptions> {\n\t/* eslint-disable @typescript-eslint/unbound-method */\n\tconst {\n\t\tbuildIdentifyThrottler,\n\t\tbuildStrategy,\n\t\tretrieveSessionInfo,\n\t\tupdateSessionInfo,\n\t\tshardCount,\n\t\tshardIds,\n\t\trest,\n\t\t...managerOptions\n\t} = manager.options;\n\t/* eslint-enable @typescript-eslint/unbound-method */\n\n\treturn {\n\t\t...managerOptions,\n\t\tgatewayInformation: await manager.fetchGatewayInformation(),\n\t\tshardCount: await manager.getShardCount(),\n\t};\n}\n","/* eslint-disable id-length */\nimport { Buffer } from 'node:buffer';\nimport { once } from 'node:events';\nimport { clearInterval, clearTimeout, setInterval, setTimeout } from 'node:timers';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { URLSearchParams } from 'node:url';\nimport { TextDecoder } from 'node:util';\nimport { inflate } from 'node:zlib';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tGatewayCloseCodes,\n\tGatewayDispatchEvents,\n\tGatewayOpcodes,\n\ttype GatewayDispatchPayload,\n\ttype GatewayIdentifyData,\n\ttype GatewayReadyDispatchData,\n\ttype GatewayReceivePayload,\n\ttype GatewaySendPayload,\n} from 'discord-api-types/v10';\nimport { WebSocket, type Data } from 'ws';\nimport type { Inflate } from 'zlib-sync';\nimport type { IContextFetchingStrategy } from '../strategies/context/IContextFetchingStrategy.js';\nimport { ImportantGatewayOpcodes, getInitialSendRateLimitState } from '../utils/constants.js';\nimport type { SessionInfo } from './WebSocketManager.js';\n\n// eslint-disable-next-line promise/prefer-await-to-then\nconst getZlibSync = lazy(async () => import('zlib-sync').then((mod) => mod.default).catch(() => null));\n\nexport enum WebSocketShardEvents {\n\tClosed = 'closed',\n\tDebug = 'debug',\n\tDispatch = 'dispatch',\n\tError = 'error',\n\tHeartbeatComplete = 'heartbeat',\n\tHello = 'hello',\n\tReady = 'ready',\n\tResumed = 'resumed',\n}\n\nexport enum WebSocketShardStatus {\n\tIdle,\n\tConnecting,\n\tResuming,\n\tReady,\n}\n\nexport enum WebSocketShardDestroyRecovery {\n\tReconnect,\n\tResume,\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport type WebSocketShardEventsMap = {\n\t[WebSocketShardEvents.Closed]: [{ code: number }];\n\t[WebSocketShardEvents.Debug]: [payload: { message: string }];\n\t[WebSocketShardEvents.Dispatch]: [payload: { data: GatewayDispatchPayload }];\n\t[WebSocketShardEvents.Error]: [payload: { error: Error }];\n\t[WebSocketShardEvents.Hello]: [];\n\t[WebSocketShardEvents.Ready]: [payload: { data: GatewayReadyDispatchData }];\n\t[WebSocketShardEvents.Resumed]: [];\n\t[WebSocketShardEvents.HeartbeatComplete]: [payload: { ackAt: number; heartbeatAt: number; latency: number }];\n};\n\nexport interface WebSocketShardDestroyOptions {\n\tcode?: number;\n\treason?: string;\n\trecover?: WebSocketShardDestroyRecovery;\n}\n\nexport enum CloseCodes {\n\tNormal = 1_000,\n\tResuming = 4_200,\n}\n\nexport interface SendRateLimitState {\n\tremaining: number;\n\tresetAt: number;\n}\n\n// TODO(vladfrangu): enable this once https://github.com/oven-sh/bun/issues/3392 is solved\n// const WebSocketConstructor: typeof WebSocket = shouldUseGlobalFetchAndWebSocket()\n// \t? (globalThis as any).WebSocket\n// \t: WebSocket;\nconst WebSocketConstructor: typeof WebSocket = WebSocket;\n\nexport class WebSocketShard extends AsyncEventEmitter<WebSocketShardEventsMap> {\n\tprivate connection: WebSocket | null = null;\n\n\tprivate useIdentifyCompress = false;\n\n\tprivate inflate: Inflate | null = null;\n\n\tprivate readonly textDecoder = new TextDecoder();\n\n\tprivate replayedEvents = 0;\n\n\tprivate isAck = true;\n\n\tprivate sendRateLimitState: SendRateLimitState = getInitialSendRateLimitState();\n\n\tprivate initialHeartbeatTimeoutController: AbortController | null = null;\n\n\tprivate heartbeatInterval: NodeJS.Timer | null = null;\n\n\tprivate lastHeartbeatAt = -1;\n\n\t// Indicates whether the shard has already resolved its original connect() call\n\tprivate initialConnectResolved = false;\n\n\t// Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)\n\tprivate failedToConnectDueToNetworkError = false;\n\n\tprivate readonly sendQueue = new AsyncQueue();\n\n\tprivate readonly timeoutAbortControllers = new Collection<WebSocketShardEvents, AbortController>();\n\n\tprivate readonly strategy: IContextFetchingStrategy;\n\n\tpublic readonly id: number;\n\n\t#status: WebSocketShardStatus = WebSocketShardStatus.Idle;\n\n\tpublic get status(): WebSocketShardStatus {\n\t\treturn this.#status;\n\t}\n\n\tpublic constructor(strategy: IContextFetchingStrategy, id: number) {\n\t\tsuper();\n\t\tthis.strategy = strategy;\n\t\tthis.id = id;\n\t}\n\n\tpublic async connect() {\n\t\tconst controller = new AbortController();\n\t\tlet promise;\n\n\t\tif (!this.initialConnectResolved) {\n\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\tpromise = Promise.race([\n\t\t\t\tonce(this, WebSocketShardEvents.Ready, { signal: controller.signal }),\n\t\t\t\tonce(this, WebSocketShardEvents.Resumed, { signal: controller.signal }),\n\t\t\t]);\n\t\t}\n\n\t\tvoid this.internalConnect();\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} catch ({ error }: any) {\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// cleanup hanging listeners\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.initialConnectResolved = true;\n\t}\n\n\tprivate async internalConnect() {\n\t\tif (this.#status !== WebSocketShardStatus.Idle) {\n\t\t\tthrow new Error(\"Tried to connect a shard that wasn't idle\");\n\t\t}\n\n\t\tconst { version, encoding, compression } = this.strategy.options;\n\t\tconst params = new URLSearchParams({ v: version, encoding });\n\t\tif (compression) {\n\t\t\tconst zlib = await getZlibSync();\n\t\t\tif (zlib) {\n\t\t\t\tparams.append('compress', compression);\n\t\t\t\tthis.inflate = new zlib.Inflate({\n\t\t\t\t\tchunkSize: 65_535,\n\t\t\t\t\tto: 'string',\n\t\t\t\t});\n\t\t\t} else if (!this.useIdentifyCompress) {\n\t\t\t\tthis.useIdentifyCompress = true;\n\t\t\t\tconsole.warn(\n\t\t\t\t\t'WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress',\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tconst url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;\n\n\t\tthis.debug([`Connecting to ${url}`]);\n\n\t\tconst connection = new WebSocketConstructor(url, {\n\t\t\thandshakeTimeout: this.strategy.options.handshakeTimeout ?? undefined,\n\t\t});\n\n\t\tconnection.binaryType = 'arraybuffer';\n\n\t\tconnection.onmessage = (event) => {\n\t\t\tvoid this.onMessage(event.data, event.data instanceof ArrayBuffer);\n\t\t};\n\n\t\tconnection.onerror = (event) => {\n\t\t\tthis.onError(event.error);\n\t\t};\n\n\t\tconnection.onclose = (event) => {\n\t\t\tvoid this.onClose(event.code);\n\t\t};\n\n\t\tthis.connection = connection;\n\n\t\tthis.#status = WebSocketShardStatus.Connecting;\n\n\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\n\t\tconst { ok } = await this.waitForEvent(WebSocketShardEvents.Hello, this.strategy.options.helloTimeout);\n\t\tif (!ok) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (session?.shardCount === this.strategy.options.shardCount) {\n\t\t\tawait this.resume(session);\n\t\t} else {\n\t\t\tawait this.identify();\n\t\t}\n\t}\n\n\tpublic async destroy(options: WebSocketShardDestroyOptions = {}) {\n\t\tif (this.#status === WebSocketShardStatus.Idle) {\n\t\t\tthis.debug(['Tried to destroy a shard that was idle']);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!options.code) {\n\t\t\toptions.code = options.recover === WebSocketShardDestroyRecovery.Resume ? CloseCodes.Resuming : CloseCodes.Normal;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Destroying shard',\n\t\t\t`Reason: ${options.reason ?? 'none'}`,\n\t\t\t`Code: ${options.code}`,\n\t\t\t`Recover: ${options.recover === undefined ? 'none' : WebSocketShardDestroyRecovery[options.recover]!}`,\n\t\t]);\n\n\t\t// Reset state\n\t\tthis.isAck = true;\n\t\tif (this.heartbeatInterval) {\n\t\t\tclearInterval(this.heartbeatInterval);\n\t\t}\n\n\t\tif (this.initialHeartbeatTimeoutController) {\n\t\t\tthis.initialHeartbeatTimeoutController.abort();\n\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t}\n\n\t\tthis.lastHeartbeatAt = -1;\n\n\t\tfor (const controller of this.timeoutAbortControllers.values()) {\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.timeoutAbortControllers.clear();\n\n\t\tthis.failedToConnectDueToNetworkError = false;\n\n\t\t// Clear session state if applicable\n\t\tif (options.recover !== WebSocketShardDestroyRecovery.Resume) {\n\t\t\tawait this.strategy.updateSessionInfo(this.id, null);\n\t\t}\n\n\t\tif (this.connection) {\n\t\t\t// No longer need to listen to messages\n\t\t\tthis.connection.onmessage = null;\n\t\t\t// Prevent a reconnection loop by unbinding the main close event\n\t\t\tthis.connection.onclose = null;\n\n\t\t\tconst shouldClose = this.connection.readyState === WebSocket.OPEN;\n\n\t\t\tthis.debug([\n\t\t\t\t'Connection status during destroy',\n\t\t\t\t`Needs closing: ${shouldClose}`,\n\t\t\t\t`Ready state: ${this.connection.readyState}`,\n\t\t\t]);\n\n\t\t\tif (shouldClose) {\n\t\t\t\tlet outerResolve: () => void;\n\t\t\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\t\t\touterResolve = resolve;\n\t\t\t\t});\n\n\t\t\t\tthis.connection.onclose = outerResolve!;\n\n\t\t\t\tthis.connection.close(options.code, options.reason);\n\n\t\t\t\tawait promise;\n\t\t\t\tthis.emit(WebSocketShardEvents.Closed, { code: options.code });\n\t\t\t}\n\n\t\t\t// Lastly, remove the error event.\n\t\t\t// Doing this earlier would cause a hard crash in case an error event fired on our `close` call\n\t\t\tthis.connection.onerror = null;\n\t\t} else {\n\t\t\tthis.debug(['Destroying a shard that has no connection; please open an issue on GitHub']);\n\t\t}\n\n\t\tthis.#status = WebSocketShardStatus.Idle;\n\n\t\tif (options.recover !== undefined) {\n\t\t\t// There's cases (like no internet connection) where we immediately fail to connect,\n\t\t\t// causing a very fast and draining reconnection loop.\n\t\t\tawait sleep(500);\n\t\t\treturn this.internalConnect();\n\t\t}\n\t}\n\n\tprivate async waitForEvent(event: WebSocketShardEvents, timeoutDuration?: number | null): Promise<{ ok: boolean }> {\n\t\tthis.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : 'indefinitely'}`]);\n\t\tconst timeoutController = new AbortController();\n\t\tconst timeout = timeoutDuration ? setTimeout(() => timeoutController.abort(), timeoutDuration).unref() : null;\n\n\t\tthis.timeoutAbortControllers.set(event, timeoutController);\n\n\t\tconst closeController = new AbortController();\n\n\t\ttry {\n\t\t\t// If the first promise resolves, all is well. If the 2nd promise resolves,\n\t\t\t// the shard has meanwhile closed. In that case, a destroy is already ongoing, so we just need to\n\t\t\t// return false. Meanwhile, if something rejects (error event) or the first controller is aborted,\n\t\t\t// we enter the catch block and trigger a destroy there.\n\t\t\tconst closed = await Promise.race<boolean>([\n\t\t\t\tonce(this, event, { signal: timeoutController.signal }).then(() => false),\n\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: closeController.signal }).then(() => true),\n\t\t\t]);\n\n\t\t\treturn { ok: !closed };\n\t\t} catch {\n\t\t\t// If we're here because of other reasons, we need to destroy the shard\n\t\t\tvoid this.destroy({\n\t\t\t\tcode: CloseCodes.Normal,\n\t\t\t\treason: 'Something timed out or went wrong while waiting for an event',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t});\n\n\t\t\treturn { ok: false };\n\t\t} finally {\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\n\t\t\tthis.timeoutAbortControllers.delete(event);\n\n\t\t\t// Clean up the close listener to not leak memory\n\t\t\tif (!closeController.signal.aborted) {\n\t\t\t\tcloseController.abort();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async send(payload: GatewaySendPayload): Promise<void> {\n\t\tif (!this.connection) {\n\t\t\tthrow new Error(\"WebSocketShard wasn't connected\");\n\t\t}\n\n\t\tif (this.#status !== WebSocketShardStatus.Ready && !ImportantGatewayOpcodes.has(payload.op)) {\n\t\t\tthis.debug(['Tried to send a non-crucial payload before the shard was ready, waiting']);\n\t\t\t// This will throw if the shard throws an error event in the meantime, just requeue the payload\n\t\t\ttry {\n\t\t\t\tawait once(this, WebSocketShardEvents.Ready);\n\t\t\t} catch {\n\t\t\t\treturn this.send(payload);\n\t\t\t}\n\t\t}\n\n\t\tawait this.sendQueue.wait();\n\n\t\tif (--this.sendRateLimitState.remaining <= 0) {\n\t\t\tconst now = Date.now();\n\n\t\t\tif (this.sendRateLimitState.resetAt > now) {\n\t\t\t\tconst sleepFor = this.sendRateLimitState.resetAt - now;\n\n\t\t\t\tthis.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);\n\t\t\t\tconst controller = new AbortController();\n\n\t\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\t\tconst interrupted = await Promise.race([\n\t\t\t\t\tsleep(sleepFor).then(() => false),\n\t\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: controller.signal }).then(() => true),\n\t\t\t\t]);\n\n\t\t\t\tif (interrupted) {\n\t\t\t\t\tthis.debug(['Connection closed while waiting for the send rate limit to reset, re-queueing payload']);\n\t\t\t\t\tthis.sendQueue.shift();\n\t\t\t\t\treturn this.send(payload);\n\t\t\t\t}\n\n\t\t\t\t// This is so the listener from the `once` call is removed\n\t\t\t\tcontroller.abort();\n\t\t\t}\n\n\t\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\t\t}\n\n\t\tthis.sendQueue.shift();\n\t\tthis.connection.send(JSON.stringify(payload));\n\t}\n\n\tprivate async identify() {\n\t\tthis.debug(['Waiting for identify throttle']);\n\n\t\tconst controller = new AbortController();\n\t\tconst closeHandler = () => {\n\t\t\tcontroller.abort();\n\t\t};\n\n\t\tthis.on(WebSocketShardEvents.Closed, closeHandler);\n\n\t\ttry {\n\t\t\tawait this.strategy.waitForIdentify(this.id, controller.signal);\n\t\t} catch {\n\t\t\tif (controller.signal.aborted) {\n\t\t\t\tthis.debug(['Was waiting for an identify, but the shard closed in the meantime']);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.debug([\n\t\t\t\t'IContextFetchingStrategy#waitForIdentify threw an unknown error.',\n\t\t\t\t\"If you're using a custom strategy, this is probably nothing to worry about.\",\n\t\t\t\t\"If you're not, please open an issue on GitHub.\",\n\t\t\t]);\n\n\t\t\tawait this.destroy({\n\t\t\t\treason: 'Identify throttling logic failed',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t});\n\t\t} finally {\n\t\t\tthis.off(WebSocketShardEvents.Closed, closeHandler);\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Identifying',\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t\t`shard count: ${this.strategy.options.shardCount}`,\n\t\t\t`intents: ${this.strategy.options.intents}`,\n\t\t\t`compression: ${this.inflate ? 'zlib-stream' : this.useIdentifyCompress ? 'identify' : 'none'}`,\n\t\t]);\n\n\t\tconst d: GatewayIdentifyData = {\n\t\t\ttoken: this.strategy.options.token,\n\t\t\tproperties: this.strategy.options.identifyProperties,\n\t\t\tintents: this.strategy.options.intents,\n\t\t\tcompress: this.useIdentifyCompress,\n\t\t\tshard: [this.id, this.strategy.options.shardCount],\n\t\t};\n\n\t\tif (this.strategy.options.largeThreshold) {\n\t\t\td.large_threshold = this.strategy.options.largeThreshold;\n\t\t}\n\n\t\tif (this.strategy.options.initialPresence) {\n\t\t\td.presence = this.strategy.options.initialPresence;\n\t\t}\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Identify,\n\t\t\td,\n\t\t});\n\n\t\tawait this.waitForEvent(WebSocketShardEvents.Ready, this.strategy.options.readyTimeout);\n\t}\n\n\tprivate async resume(session: SessionInfo) {\n\t\tthis.debug([\n\t\t\t'Resuming session',\n\t\t\t`resume url: ${session.resumeURL}`,\n\t\t\t`sequence: ${session.sequence}`,\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t]);\n\n\t\tthis.#status = WebSocketShardStatus.Resuming;\n\t\tthis.replayedEvents = 0;\n\t\treturn this.send({\n\t\t\top: GatewayOpcodes.Resume,\n\t\t\td: {\n\t\t\t\ttoken: this.strategy.options.token,\n\t\t\t\tseq: session.sequence,\n\t\t\t\tsession_id: session.sessionId,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async heartbeat(requested = false) {\n\t\tif (!this.isAck && !requested) {\n\t\t\treturn this.destroy({ reason: 'Zombie connection', recover: WebSocketShardDestroyRecovery.Resume });\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Heartbeat,\n\t\t\td: session?.sequence ?? null,\n\t\t});\n\n\t\tthis.lastHeartbeatAt = Date.now();\n\t\tthis.isAck = false;\n\t}\n\n\tprivate async unpackMessage(data: Data, isBinary: boolean): Promise<GatewayReceivePayload | null> {\n\t\t// Deal with no compression\n\t\tif (!isBinary) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(data as string) as GatewayReceivePayload;\n\t\t\t} catch {\n\t\t\t\t// This is a non-JSON payload / (at the time of writing this comment) emitted by bun wrongly interpreting custom close codes https://github.com/oven-sh/bun/issues/3392\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tconst decompressable = new Uint8Array(data as ArrayBuffer);\n\n\t\t// Deal with identify compress\n\t\tif (this.useIdentifyCompress) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-callbacks\n\t\t\t\tinflate(decompressable, { chunkSize: 65_535 }, (err, result) => {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve(JSON.parse(this.textDecoder.decode(result)) as GatewayReceivePayload);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\t// Deal with gw wide zlib-stream compression\n\t\tif (this.inflate) {\n\t\t\tconst l = decompressable.length;\n\t\t\tconst flush =\n\t\t\t\tl >= 4 &&\n\t\t\t\tdecompressable[l - 4] === 0x00 &&\n\t\t\t\tdecompressable[l - 3] === 0x00 &&\n\t\t\t\tdecompressable[l - 2] === 0xff &&\n\t\t\t\tdecompressable[l - 1] === 0xff;\n\n\t\t\tconst zlib = (await getZlibSync())!;\n\t\t\tthis.inflate.push(Buffer.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);\n\n\t\t\tif (this.inflate.err) {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ''}`),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!flush) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { result } = this.inflate;\n\t\t\tif (!result) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn JSON.parse(typeof result === 'string' ? result : this.textDecoder.decode(result)) as GatewayReceivePayload;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Received a message we were unable to decompress',\n\t\t\t`isBinary: ${isBinary.toString()}`,\n\t\t\t`useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,\n\t\t\t`inflate: ${Boolean(this.inflate).toString()}`,\n\t\t]);\n\n\t\treturn null;\n\t}\n\n\tprivate async onMessage(data: Data, isBinary: boolean) {\n\t\tconst payload = await this.unpackMessage(data, isBinary);\n\t\tif (!payload) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (payload.op) {\n\t\t\tcase GatewayOpcodes.Dispatch: {\n\t\t\t\tif (this.#status === WebSocketShardStatus.Resuming) {\n\t\t\t\t\tthis.replayedEvents++;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line sonarjs/no-nested-switch\n\t\t\t\tswitch (payload.t) {\n\t\t\t\t\tcase GatewayDispatchEvents.Ready: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\n\t\t\t\t\t\tconst session = {\n\t\t\t\t\t\t\tsequence: payload.s,\n\t\t\t\t\t\t\tsessionId: payload.d.session_id,\n\t\t\t\t\t\t\tshardId: this.id,\n\t\t\t\t\t\t\tshardCount: this.strategy.options.shardCount,\n\t\t\t\t\t\t\tresumeURL: payload.d.resume_gateway_url,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, session);\n\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Ready, { data: payload.d });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase GatewayDispatchEvents.Resumed: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\t\t\t\t\t\tthis.debug([`Resumed and replayed ${this.replayedEvents} events`]);\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Resumed);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (session) {\n\t\t\t\t\tif (payload.s > session.sequence) {\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.debug([\n\t\t\t\t\t\t`Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`,\n\t\t\t\t\t]);\n\t\t\t\t}\n\n\t\t\t\tthis.emit(WebSocketShardEvents.Dispatch, { data: payload });\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Heartbeat: {\n\t\t\t\tawait this.heartbeat(true);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Reconnect: {\n\t\t\t\tawait this.destroy({\n\t\t\t\t\treason: 'Told to reconnect by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.InvalidSession: {\n\t\t\t\tthis.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (payload.d && session) {\n\t\t\t\t\tawait this.resume(session);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.destroy({\n\t\t\t\t\t\treason: 'Invalid session',\n\t\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Hello: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Hello);\n\t\t\t\tconst jitter = Math.random();\n\t\t\t\tconst firstWait = Math.floor(payload.d.heartbeat_interval * jitter);\n\t\t\t\tthis.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = controller;\n\t\t\t\t\tawait sleep(firstWait, undefined, { signal: controller.signal });\n\t\t\t\t} catch {\n\t\t\t\t\tthis.debug(['Cancelled initial heartbeat due to #destroy being called']);\n\t\t\t\t\treturn;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t\t\t}\n\n\t\t\t\tawait this.heartbeat();\n\n\t\t\t\tthis.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);\n\t\t\t\tthis.heartbeatInterval = setInterval(() => void this.heartbeat(), payload.d.heartbeat_interval);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.HeartbeatAck: {\n\t\t\t\tthis.isAck = true;\n\n\t\t\t\tconst ackAt = Date.now();\n\t\t\t\tthis.emit(WebSocketShardEvents.HeartbeatComplete, {\n\t\t\t\t\tackAt,\n\t\t\t\t\theartbeatAt: this.lastHeartbeatAt,\n\t\t\t\t\tlatency: ackAt - this.lastHeartbeatAt,\n\t\t\t\t});\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onError(error: Error) {\n\t\tif ('code' in error && ['ECONNRESET', 'ECONNREFUSED'].includes(error.code as string)) {\n\t\t\tthis.debug(['Failed to connect to the gateway URL specified due to a network error']);\n\t\t\tthis.failedToConnectDueToNetworkError = true;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit(WebSocketShardEvents.Error, { error });\n\t}\n\n\tprivate async onClose(code: number) {\n\t\tthis.emit(WebSocketShardEvents.Closed, { code });\n\n\t\tswitch (code) {\n\t\t\tcase CloseCodes.Normal: {\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\treason: 'Got disconnected by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tcase CloseCodes.Resuming: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownError: {\n\t\t\t\tthis.debug([`An unknown error occurred: ${code}`]);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownOpcode: {\n\t\t\t\tthis.debug(['An invalid opcode was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DecodeError: {\n\t\t\t\tthis.debug(['An invalid payload was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.NotAuthenticated: {\n\t\t\t\tthis.debug(['A request was somehow sent before the identify/resume payload.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AuthenticationFailed: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Authentication failed'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AlreadyAuthenticated: {\n\t\t\t\tthis.debug(['More than one auth payload was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidSeq: {\n\t\t\t\tthis.debug(['An invalid sequence was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.RateLimited: {\n\t\t\t\tthis.debug(['The WebSocket rate limit has been hit, this should never happen']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.SessionTimedOut: {\n\t\t\t\tthis.debug(['Session timed out.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidShard: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Invalid shard'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.ShardingRequired: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Sharding is required'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidAPIVersion: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used an invalid API version'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used invalid intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DisallowedIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used disallowed intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tthis.debug([\n\t\t\t\t\t`The gateway closed with an unexpected code ${code}, attempting to ${\n\t\t\t\t\t\tthis.failedToConnectDueToNetworkError ? 'reconnect' : 'resume'\n\t\t\t\t\t}.`,\n\t\t\t\t]);\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\trecover: this.failedToConnectDueToNetworkError\n\t\t\t\t\t\t? WebSocketShardDestroyRecovery.Reconnect\n\t\t\t\t\t\t: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate debug(messages: [string, ...string[]]) {\n\t\tconst message = `${messages[0]}${\n\t\t\tmessages.length > 1\n\t\t\t\t? `\\n${messages\n\t\t\t\t\t\t.slice(1)\n\t\t\t\t\t\t.map((m) => `\t${m}`)\n\t\t\t\t\t\t.join('\\n')}`\n\t\t\t\t: ''\n\t\t}`;\n\n\t\tthis.emit(WebSocketShardEvents.Debug, { message });\n\t}\n}\n","import process from 'node:process';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { APIVersion, GatewayOpcodes } from 'discord-api-types/v10';\nimport { SimpleShardingStrategy } from '../strategies/sharding/SimpleShardingStrategy.js';\nimport { SimpleIdentifyThrottler } from '../throttling/SimpleIdentifyThrottler.js';\nimport type { SessionInfo, OptionalWebSocketManagerOptions, WebSocketManager } from '../ws/WebSocketManager.js';\nimport type { SendRateLimitState } from '../ws/WebSocketShard.js';\n\n/**\n * Valid encoding types\n */\nexport enum Encoding {\n\tJSON = 'json',\n}\n\n/**\n * Valid compression methods\n */\nexport enum CompressionMethod {\n\tZlibStream = 'zlib-stream',\n}\n\nexport const DefaultDeviceProperty = `@discordjs/ws 1.0.1` as `@discordjs/ws ${string}`;\n\nconst getDefaultSessionStore = lazy(() => new Collection<number, SessionInfo | null>());\n\n/**\n * Default options used by the manager\n */\nexport const DefaultWebSocketManagerOptions = {\n\tasync buildIdentifyThrottler(manager: WebSocketManager) {\n\t\tconst info = await manager.fetchGatewayInformation();\n\t\treturn new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);\n\t},\n\tbuildStrategy: (manager) => new SimpleShardingStrategy(manager),\n\tshardCount: null,\n\tshardIds: null,\n\tlargeThreshold: null,\n\tinitialPresence: null,\n\tidentifyProperties: {\n\t\tbrowser: DefaultDeviceProperty,\n\t\tdevice: DefaultDeviceProperty,\n\t\tos: process.platform,\n\t},\n\tversion: APIVersion,\n\tencoding: Encoding.JSON,\n\tcompression: null,\n\tretrieveSessionInfo(shardId) {\n\t\tconst store = getDefaultSessionStore();\n\t\treturn store.get(shardId) ?? null;\n\t},\n\tupdateSessionInfo(shardId: number, info: SessionInfo | null) {\n\t\tconst store = getDefaultSessionStore();\n\t\tif (info) {\n\t\t\tstore.set(shardId, info);\n\t\t} else {\n\t\t\tstore.delete(shardId);\n\t\t}\n\t},\n\thandshakeTimeout: 30_000,\n\thelloTimeout: 60_000,\n\treadyTimeout: 15_000,\n} as const satisfies OptionalWebSocketManagerOptions;\n\nexport const ImportantGatewayOpcodes = new Set([\n\tGatewayOpcodes.Heartbeat,\n\tGatewayOpcodes.Identify,\n\tGatewayOpcodes.Resume,\n]);\n\nexport function getInitialSendRateLimitState(): SendRateLimitState {\n\treturn {\n\t\tremaining: 120,\n\t\tresetAt: Date.now() + 60_000,\n\t};\n}\n","import { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { WebSocketManager } from '../../ws/WebSocketManager.js';\nimport { WebSocketShard, WebSocketShardEvents, type WebSocketShardDestroyOptions } from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport { SimpleContextFetchingStrategy } from '../context/SimpleContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\n/**\n * Simple strategy that just spawns shards in the current process\n */\nexport class SimpleShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor(manager: WebSocketManager) {\n\t\tthis.manager = manager;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tfor (const shardId of shardIds) {\n\t\t\tconst strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);\n\t\t\tconst shard = new WebSocketShard(strategy, shardId);\n\t\t\tfor (const event of Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Intentional\n\t\t\t\tshard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));\n\t\t\t}\n\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.connect());\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.destroy(options));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t\tthis.shards.clear();\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic async send(shardId: number, payload: GatewaySendPayload) {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} not found`);\n\t\t}\n\n\t\treturn shard.send(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\treturn this.shards.mapValues((shard) => shard.status);\n\t}\n}\n","import type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class SimpleContextFetchingStrategy implements IContextFetchingStrategy {\n\t// This strategy assumes every shard is running under the same process - therefore we need a single\n\t// IdentifyThrottler per manager.\n\tprivate static throttlerCache = new WeakMap<WebSocketManager, IIdentifyThrottler>();\n\n\tprivate static async ensureThrottler(manager: WebSocketManager): Promise<IIdentifyThrottler> {\n\t\tconst throttler = SimpleContextFetchingStrategy.throttlerCache.get(manager);\n\t\tif (throttler) {\n\t\t\treturn throttler;\n\t\t}\n\n\t\tconst newThrottler = await manager.options.buildIdentifyThrottler(manager);\n\t\tSimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);\n\n\t\treturn newThrottler;\n\t}\n\n\tpublic constructor(private readonly manager: WebSocketManager, public readonly options: FetchingStrategyOptions) {}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\treturn this.manager.options.retrieveSessionInfo(shardId);\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\treturn this.manager.options.updateSessionInfo(shardId, sessionInfo);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst throttler = await SimpleContextFetchingStrategy.ensureThrottler(this.manager);\n\t\tawait throttler.waitForIdentify(shardId, signal);\n\t}\n}\n","import { setTimeout as sleep } from 'node:timers/promises';\nimport { Collection } from '@discordjs/collection';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport type { IIdentifyThrottler } from './IIdentifyThrottler.js';\n\n/**\n * The state of a rate limit key's identify queue.\n */\nexport interface IdentifyState {\n\tqueue: AsyncQueue;\n\tresetsAt: number;\n}\n\n/**\n * Local, in-memory identify throttler.\n */\nexport class SimpleIdentifyThrottler implements IIdentifyThrottler {\n\tprivate readonly states = new Collection<number, IdentifyState>();\n\n\tpublic constructor(private readonly maxConcurrency: number) {}\n\n\t/**\n\t * {@inheritDoc IIdentifyThrottler.waitForIdentify}\n\t */\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst key = shardId % this.maxConcurrency;\n\n\t\tconst state = this.states.ensure(key, () => {\n\t\t\treturn {\n\t\t\t\tqueue: new AsyncQueue(),\n\t\t\t\tresetsAt: Number.POSITIVE_INFINITY,\n\t\t\t};\n\t\t});\n\n\t\tawait state.queue.wait({ signal });\n\n\t\ttry {\n\t\t\tconst diff = state.resetsAt - Date.now();\n\t\t\tif (diff <= 5_000) {\n\t\t\t\t// To account for the latency the IDENTIFY payload goes through, we add a bit more wait time\n\t\t\t\tconst time = diff + Math.random() * 1_500;\n\t\t\t\tawait sleep(time);\n\t\t\t}\n\n\t\t\tstate.resetsAt = Date.now() + 5_000;\n\t\t} finally {\n\t\t\tstate.queue.shift();\n\t\t}\n\t}\n}\n","import { WorkerBootstrapper } from '../../utils/WorkerBootstrapper.js';\n\nconst bootstrapper = new WorkerBootstrapper();\nvoid bootstrapper.bootstrap();\n"],"mappings":"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","names":["isMainThread","parentPort","Collection","Collection","Collection","resolve","payload","Buffer","once","sleep","Collection","lazy","AsyncQueue","GatewayOpcodes","Collection","Collection","Collection","Collection","Collection","Collection","lazy","WebSocketShardEvents","WebSocketShardDestroyRecovery","AsyncQueue","Collection","once","resolve","sleep","GatewayOpcodes","Buffer","session","Collection","isMainThread","parentPort"]} \ No newline at end of file
diff --git a/node_modules/@discordjs/ws/dist/index.d.mts b/node_modules/@discordjs/ws/dist/index.d.mts
new file mode 100644
index 0000000..cf7bb7c
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/index.d.mts
@@ -0,0 +1,669 @@
+import * as _discordjs_util from '@discordjs/util';
+import { Awaitable } from '@discordjs/util';
+import { GatewayDispatchPayload, GatewayReadyDispatchData, GatewaySendPayload, GatewayOpcodes, GatewayIntentBits, GatewayIdentifyProperties, GatewayPresenceUpdateData, APIGatewayBotInfo } from 'discord-api-types/v10';
+import * as _discordjs_collection from '@discordjs/collection';
+import { Collection } from '@discordjs/collection';
+import { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';
+import { REST } from '@discordjs/rest';
+import { AsyncQueue } from '@sapphire/async-queue';
+
+declare enum WebSocketShardEvents {
+ Closed = "closed",
+ Debug = "debug",
+ Dispatch = "dispatch",
+ Error = "error",
+ HeartbeatComplete = "heartbeat",
+ Hello = "hello",
+ Ready = "ready",
+ Resumed = "resumed"
+}
+declare enum WebSocketShardStatus {
+ Idle = 0,
+ Connecting = 1,
+ Resuming = 2,
+ Ready = 3
+}
+declare enum WebSocketShardDestroyRecovery {
+ Reconnect = 0,
+ Resume = 1
+}
+type WebSocketShardEventsMap = {
+ [WebSocketShardEvents.Closed]: [{
+ code: number;
+ }];
+ [WebSocketShardEvents.Debug]: [payload: {
+ message: string;
+ }];
+ [WebSocketShardEvents.Dispatch]: [payload: {
+ data: GatewayDispatchPayload;
+ }];
+ [WebSocketShardEvents.Error]: [payload: {
+ error: Error;
+ }];
+ [WebSocketShardEvents.Hello]: [];
+ [WebSocketShardEvents.Ready]: [payload: {
+ data: GatewayReadyDispatchData;
+ }];
+ [WebSocketShardEvents.Resumed]: [];
+ [WebSocketShardEvents.HeartbeatComplete]: [payload: {
+ ackAt: number;
+ heartbeatAt: number;
+ latency: number;
+ }];
+};
+interface WebSocketShardDestroyOptions {
+ code?: number;
+ reason?: string;
+ recover?: WebSocketShardDestroyRecovery;
+}
+declare enum CloseCodes {
+ Normal = 1000,
+ Resuming = 4200
+}
+interface SendRateLimitState {
+ remaining: number;
+ resetAt: number;
+}
+declare class WebSocketShard extends AsyncEventEmitter<WebSocketShardEventsMap> {
+ #private;
+ private connection;
+ private useIdentifyCompress;
+ private inflate;
+ private readonly textDecoder;
+ private replayedEvents;
+ private isAck;
+ private sendRateLimitState;
+ private initialHeartbeatTimeoutController;
+ private heartbeatInterval;
+ private lastHeartbeatAt;
+ private initialConnectResolved;
+ private failedToConnectDueToNetworkError;
+ private readonly sendQueue;
+ private readonly timeoutAbortControllers;
+ private readonly strategy;
+ readonly id: number;
+ get status(): WebSocketShardStatus;
+ constructor(strategy: IContextFetchingStrategy, id: number);
+ connect(): Promise<void>;
+ private internalConnect;
+ destroy(options?: WebSocketShardDestroyOptions): Promise<void>;
+ private waitForEvent;
+ send(payload: GatewaySendPayload): Promise<void>;
+ private identify;
+ private resume;
+ private heartbeat;
+ private unpackMessage;
+ private onMessage;
+ private onError;
+ private onClose;
+ private debug;
+}
+
+/**
+ * Strategies responsible for spawning, initializing connections, destroying shards, and relaying events
+ */
+interface IShardingStrategy {
+ /**
+ * Initializes all the shards
+ */
+ connect(): Awaitable<void>;
+ /**
+ * Destroys all the shards
+ */
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Awaitable<void>;
+ /**
+ * Fetches the status of all the shards
+ */
+ fetchStatus(): Awaitable<Collection<number, WebSocketShardStatus>>;
+ /**
+ * Sends a payload to a shard
+ */
+ send(shardId: number, payload: GatewaySendPayload): Awaitable<void>;
+ /**
+ * Spawns all the shards
+ */
+ spawn(shardIds: number[]): Awaitable<void>;
+}
+
+/**
+ * IdentifyThrottlers are responsible for dictating when a shard is allowed to identify.
+ *
+ * @see {@link https://discord.com/developers/docs/topics/gateway#sharding-max-concurrency}
+ */
+interface IIdentifyThrottler {
+ /**
+ * Resolves once the given shard should be allowed to identify, or rejects if the operation was aborted.
+ */
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+/**
+ * Simple strategy that just spawns shards in the current process
+ */
+declare class SimpleShardingStrategy implements IShardingStrategy {
+ private readonly manager;
+ private readonly shards;
+ constructor(manager: WebSocketManager);
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ spawn(shardIds: number[]): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ connect(): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ send(shardId: number, payload: GatewaySendPayload): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ fetchStatus(): Promise<Collection<number, WebSocketShardStatus>>;
+}
+
+/**
+ * The state of a rate limit key's identify queue.
+ */
+interface IdentifyState {
+ queue: AsyncQueue;
+ resetsAt: number;
+}
+/**
+ * Local, in-memory identify throttler.
+ */
+declare class SimpleIdentifyThrottler implements IIdentifyThrottler {
+ private readonly maxConcurrency;
+ private readonly states;
+ constructor(maxConcurrency: number);
+ /**
+ * {@inheritDoc IIdentifyThrottler.waitForIdentify}
+ */
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+/**
+ * Valid encoding types
+ */
+declare enum Encoding {
+ JSON = "json"
+}
+/**
+ * Valid compression methods
+ */
+declare enum CompressionMethod {
+ ZlibStream = "zlib-stream"
+}
+declare const DefaultDeviceProperty: `@discordjs/ws ${string}`;
+/**
+ * Default options used by the manager
+ */
+declare const DefaultWebSocketManagerOptions: {
+ readonly buildIdentifyThrottler: (manager: WebSocketManager) => Promise<SimpleIdentifyThrottler>;
+ readonly buildStrategy: (manager: WebSocketManager) => SimpleShardingStrategy;
+ readonly shardCount: null;
+ readonly shardIds: null;
+ readonly largeThreshold: null;
+ readonly initialPresence: null;
+ readonly identifyProperties: {
+ readonly browser: `@discordjs/ws ${string}`;
+ readonly device: `@discordjs/ws ${string}`;
+ readonly os: NodeJS.Platform;
+ };
+ readonly version: "10";
+ readonly encoding: Encoding;
+ readonly compression: null;
+ readonly retrieveSessionInfo: (shardId: number) => SessionInfo | null;
+ readonly updateSessionInfo: (shardId: number, info: SessionInfo | null) => void;
+ readonly handshakeTimeout: 30000;
+ readonly helloTimeout: 60000;
+ readonly readyTimeout: 15000;
+};
+declare const ImportantGatewayOpcodes: Set<GatewayOpcodes>;
+declare function getInitialSendRateLimitState(): SendRateLimitState;
+
+/**
+ * Represents a range of shard ids
+ */
+interface ShardRange {
+ end: number;
+ start: number;
+}
+/**
+ * Session information for a given shard, used to resume a session
+ */
+interface SessionInfo {
+ /**
+ * URL to use when resuming
+ */
+ resumeURL: string;
+ /**
+ * The sequence number of the last message sent by the shard
+ */
+ sequence: number;
+ /**
+ * Session id for this shard
+ */
+ sessionId: string;
+ /**
+ * The total number of shards at the time of this shard identifying
+ */
+ shardCount: number;
+ /**
+ * The id of the shard
+ */
+ shardId: number;
+}
+/**
+ * Required options for the WebSocketManager
+ */
+interface RequiredWebSocketManagerOptions {
+ /**
+ * The intents to request
+ */
+ intents: GatewayIntentBits | 0;
+ /**
+ * The REST instance to use for fetching gateway information
+ */
+ rest: REST;
+ /**
+ * The token to use for identifying with the gateway
+ */
+ token: string;
+}
+/**
+ * Optional additional configuration for the WebSocketManager
+ */
+interface OptionalWebSocketManagerOptions {
+ /**
+ * Builds an identify throttler to use for this manager's shards
+ */
+ buildIdentifyThrottler(manager: WebSocketManager): Awaitable<IIdentifyThrottler>;
+ /**
+ * Builds the strategy to use for sharding
+ *
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * token: process.env.DISCORD_TOKEN,
+ * intents: 0, // for no intents
+ * rest,
+ * buildStrategy: (manager) => new WorkerShardingStrategy(manager, { shardsPerWorker: 2 }),
+ * });
+ * ```
+ */
+ buildStrategy(manager: WebSocketManager): IShardingStrategy;
+ /**
+ * The compression method to use
+ *
+ * @defaultValue `null` (no compression)
+ */
+ compression: CompressionMethod | null;
+ /**
+ * The encoding to use
+ *
+ * @defaultValue `'json'`
+ */
+ encoding: Encoding;
+ /**
+ * How long to wait for a shard to connect before giving up
+ */
+ handshakeTimeout: number | null;
+ /**
+ * How long to wait for a shard's HELLO packet before giving up
+ */
+ helloTimeout: number | null;
+ /**
+ * Properties to send to the gateway when identifying
+ */
+ identifyProperties: GatewayIdentifyProperties;
+ /**
+ * Initial presence data to send to the gateway when identifying
+ */
+ initialPresence: GatewayPresenceUpdateData | null;
+ /**
+ * Value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list
+ */
+ largeThreshold: number | null;
+ /**
+ * How long to wait for a shard's READY packet before giving up
+ */
+ readyTimeout: number | null;
+ /**
+ * Function used to retrieve session information (and attempt to resume) for a given shard
+ *
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * async retrieveSessionInfo(shardId): Awaitable<SessionInfo | null> {
+ * // Fetch this info from redis or similar
+ * return { sessionId: string, sequence: number };
+ * // Return null if no information is found
+ * },
+ * });
+ * ```
+ */
+ retrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;
+ /**
+ * The total number of shards across all WebsocketManagers you intend to instantiate.
+ * Use `null` to use Discord's recommended shard count
+ */
+ shardCount: number | null;
+ /**
+ * The ids of the shards this WebSocketManager should manage.
+ * Use `null` to simply spawn 0 through `shardCount - 1`
+ *
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * shardIds: [1, 3, 7], // spawns shard 1, 3, and 7, nothing else
+ * });
+ * ```
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * shardIds: {
+ * start: 3,
+ * end: 6,
+ * }, // spawns shards 3, 4, 5, and 6
+ * });
+ * ```
+ */
+ shardIds: number[] | ShardRange | null;
+ /**
+ * Function used to store session information for a given shard
+ */
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;
+ /**
+ * The gateway version to use
+ *
+ * @defaultValue `'10'`
+ */
+ version: string;
+}
+type WebSocketManagerOptions = OptionalWebSocketManagerOptions & RequiredWebSocketManagerOptions;
+type ManagerShardEventsMap = {
+ [K in keyof WebSocketShardEventsMap]: [
+ WebSocketShardEventsMap[K] extends [] ? {
+ shardId: number;
+ } : WebSocketShardEventsMap[K][0] & {
+ shardId: number;
+ }
+ ];
+};
+declare class WebSocketManager extends AsyncEventEmitter<ManagerShardEventsMap> {
+ /**
+ * The options being used by this manager
+ */
+ readonly options: WebSocketManagerOptions;
+ /**
+ * Internal cache for a GET /gateway/bot result
+ */
+ private gatewayInformation;
+ /**
+ * Internal cache for the shard ids
+ */
+ private shardIds;
+ /**
+ * Strategy used to manage shards
+ *
+ * @defaultValue `SimpleShardingStrategy`
+ */
+ private readonly strategy;
+ constructor(options: Partial<OptionalWebSocketManagerOptions> & RequiredWebSocketManagerOptions);
+ /**
+ * Fetches the gateway information from Discord - or returns it from cache if available
+ *
+ * @param force - Whether to ignore the cache and force a fresh fetch
+ */
+ fetchGatewayInformation(force?: boolean): Promise<APIGatewayBotInfo>;
+ /**
+ * Updates your total shard count on-the-fly, spawning shards as needed
+ *
+ * @param shardCount - The new shard count to use
+ */
+ updateShardCount(shardCount: number | null): Promise<this>;
+ /**
+ * Yields the total number of shards across for your bot, accounting for Discord recommendations
+ */
+ getShardCount(): Promise<number>;
+ /**
+ * Yields the ids of the shards this manager should manage
+ */
+ getShardIds(force?: boolean): Promise<number[]>;
+ connect(): Promise<void>;
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Awaitable<void>;
+ send(shardId: number, payload: GatewaySendPayload): Awaitable<void>;
+ fetchStatus(): Awaitable<_discordjs_collection.Collection<number, WebSocketShardStatus>>;
+}
+
+interface FetchingStrategyOptions extends Omit<WebSocketManagerOptions, 'buildIdentifyThrottler' | 'buildStrategy' | 'rest' | 'retrieveSessionInfo' | 'shardCount' | 'shardIds' | 'updateSessionInfo'> {
+ readonly gatewayInformation: APIGatewayBotInfo;
+ readonly shardCount: number;
+}
+/**
+ * Strategies responsible solely for making manager information accessible
+ */
+interface IContextFetchingStrategy {
+ readonly options: FetchingStrategyOptions;
+ retrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;
+ /**
+ * Resolves once the given shard should be allowed to identify
+ * This should correctly handle the signal and reject with an abort error if the operation is aborted.
+ * Other errors will cause the shard to reconnect.
+ */
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+declare function managerToFetchingStrategyOptions(manager: WebSocketManager): Promise<FetchingStrategyOptions>;
+
+declare class SimpleContextFetchingStrategy implements IContextFetchingStrategy {
+ private readonly manager;
+ readonly options: FetchingStrategyOptions;
+ private static throttlerCache;
+ private static ensureThrottler;
+ constructor(manager: WebSocketManager, options: FetchingStrategyOptions);
+ retrieveSessionInfo(shardId: number): Promise<SessionInfo | null>;
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): _discordjs_util.Awaitable<void>;
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+declare class WorkerContextFetchingStrategy implements IContextFetchingStrategy {
+ readonly options: FetchingStrategyOptions;
+ private readonly sessionPromises;
+ private readonly waitForIdentifyPromises;
+ constructor(options: FetchingStrategyOptions);
+ retrieveSessionInfo(shardId: number): Promise<SessionInfo | null>;
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): void;
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+interface WorkerData extends FetchingStrategyOptions {
+ shardIds: number[];
+}
+declare enum WorkerSendPayloadOp {
+ Connect = 0,
+ Destroy = 1,
+ Send = 2,
+ SessionInfoResponse = 3,
+ ShardIdentifyResponse = 4,
+ FetchStatus = 5
+}
+type WorkerSendPayload = {
+ nonce: number;
+ ok: boolean;
+ op: WorkerSendPayloadOp.ShardIdentifyResponse;
+} | {
+ nonce: number;
+ op: WorkerSendPayloadOp.FetchStatus;
+ shardId: number;
+} | {
+ nonce: number;
+ op: WorkerSendPayloadOp.SessionInfoResponse;
+ session: SessionInfo | null;
+} | {
+ op: WorkerSendPayloadOp.Connect;
+ shardId: number;
+} | {
+ op: WorkerSendPayloadOp.Destroy;
+ options?: WebSocketShardDestroyOptions;
+ shardId: number;
+} | {
+ op: WorkerSendPayloadOp.Send;
+ payload: GatewaySendPayload;
+ shardId: number;
+};
+declare enum WorkerReceivePayloadOp {
+ Connected = 0,
+ Destroyed = 1,
+ Event = 2,
+ RetrieveSessionInfo = 3,
+ UpdateSessionInfo = 4,
+ WaitForIdentify = 5,
+ FetchStatusResponse = 6,
+ WorkerReady = 7,
+ CancelIdentify = 8
+}
+type WorkerReceivePayload = {
+ data: any;
+ event: WebSocketShardEvents;
+ op: WorkerReceivePayloadOp.Event;
+ shardId: number;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.CancelIdentify;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.FetchStatusResponse;
+ status: WebSocketShardStatus;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.RetrieveSessionInfo;
+ shardId: number;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.WaitForIdentify;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.Connected;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.Destroyed;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.UpdateSessionInfo;
+ session: SessionInfo | null;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.WorkerReady;
+};
+/**
+ * Options for a {@link WorkerShardingStrategy}
+ */
+interface WorkerShardingStrategyOptions {
+ /**
+ * Dictates how many shards should be spawned per worker thread.
+ */
+ shardsPerWorker: number | 'all';
+ /**
+ * Path to the worker file to use. The worker requires quite a bit of setup, it is recommended you leverage the {@link WorkerBootstrapper} class.
+ */
+ workerPath?: string;
+}
+/**
+ * Strategy used to spawn threads in worker_threads
+ */
+declare class WorkerShardingStrategy implements IShardingStrategy {
+ #private;
+ private readonly manager;
+ private readonly options;
+ private readonly connectPromises;
+ private readonly destroyPromises;
+ private readonly fetchStatusPromises;
+ private readonly waitForIdentifyControllers;
+ private throttler?;
+ constructor(manager: WebSocketManager, options: WorkerShardingStrategyOptions);
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ spawn(shardIds: number[]): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ connect(): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ send(shardId: number, data: GatewaySendPayload): void;
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ fetchStatus(): Promise<Collection<number, WebSocketShardStatus>>;
+ private setupWorker;
+ private resolveWorkerPath;
+ private waitForWorkerReady;
+ private onMessage;
+ private ensureThrottler;
+}
+
+/**
+ * Options for bootstrapping the worker
+ */
+interface BootstrapOptions {
+ /**
+ * Shard events to just arbitrarily forward to the parent thread for the manager to emit
+ * Note: By default, this will include ALL events
+ * you most likely want to handle dispatch within the worker itself
+ */
+ forwardEvents?: WebSocketShardEvents[];
+ /**
+ * Function to call when a shard is created for additional setup
+ */
+ shardCallback?(shard: WebSocketShard): Awaitable<void>;
+}
+/**
+ * Utility class for bootstrapping a worker thread to be used for sharding
+ */
+declare class WorkerBootstrapper {
+ /**
+ * The data passed to the worker thread
+ */
+ protected readonly data: WorkerData;
+ /**
+ * The shards that are managed by this worker
+ */
+ protected readonly shards: Collection<number, WebSocketShard>;
+ constructor();
+ /**
+ * Helper method to initiate a shard's connection process
+ */
+ protected connect(shardId: number): Promise<void>;
+ /**
+ * Helper method to destroy a shard
+ */
+ protected destroy(shardId: number, options?: WebSocketShardDestroyOptions): Promise<void>;
+ /**
+ * Helper method to attach event listeners to the parentPort
+ */
+ protected setupThreadEvents(): void;
+ /**
+ * Bootstraps the worker thread with the provided options
+ */
+ bootstrap(options?: Readonly<BootstrapOptions>): Promise<void>;
+}
+
+/**
+ * The {@link https://github.com/discordjs/discord.js/blob/main/packages/ws/#readme | @discordjs/ws} version
+ * that you are currently using.
+ */
+declare const version: string;
+
+export { BootstrapOptions, CloseCodes, CompressionMethod, DefaultDeviceProperty, DefaultWebSocketManagerOptions, Encoding, FetchingStrategyOptions, IContextFetchingStrategy, IIdentifyThrottler, IShardingStrategy, IdentifyState, ImportantGatewayOpcodes, ManagerShardEventsMap, OptionalWebSocketManagerOptions, RequiredWebSocketManagerOptions, SendRateLimitState, SessionInfo, ShardRange, SimpleContextFetchingStrategy, SimpleIdentifyThrottler, SimpleShardingStrategy, WebSocketManager, WebSocketManagerOptions, WebSocketShard, WebSocketShardDestroyOptions, WebSocketShardDestroyRecovery, WebSocketShardEvents, WebSocketShardEventsMap, WebSocketShardStatus, WorkerBootstrapper, WorkerContextFetchingStrategy, WorkerData, WorkerReceivePayload, WorkerReceivePayloadOp, WorkerSendPayload, WorkerSendPayloadOp, WorkerShardingStrategy, WorkerShardingStrategyOptions, getInitialSendRateLimitState, managerToFetchingStrategyOptions, version };
diff --git a/node_modules/@discordjs/ws/dist/index.d.ts b/node_modules/@discordjs/ws/dist/index.d.ts
new file mode 100644
index 0000000..cf7bb7c
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/index.d.ts
@@ -0,0 +1,669 @@
+import * as _discordjs_util from '@discordjs/util';
+import { Awaitable } from '@discordjs/util';
+import { GatewayDispatchPayload, GatewayReadyDispatchData, GatewaySendPayload, GatewayOpcodes, GatewayIntentBits, GatewayIdentifyProperties, GatewayPresenceUpdateData, APIGatewayBotInfo } from 'discord-api-types/v10';
+import * as _discordjs_collection from '@discordjs/collection';
+import { Collection } from '@discordjs/collection';
+import { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';
+import { REST } from '@discordjs/rest';
+import { AsyncQueue } from '@sapphire/async-queue';
+
+declare enum WebSocketShardEvents {
+ Closed = "closed",
+ Debug = "debug",
+ Dispatch = "dispatch",
+ Error = "error",
+ HeartbeatComplete = "heartbeat",
+ Hello = "hello",
+ Ready = "ready",
+ Resumed = "resumed"
+}
+declare enum WebSocketShardStatus {
+ Idle = 0,
+ Connecting = 1,
+ Resuming = 2,
+ Ready = 3
+}
+declare enum WebSocketShardDestroyRecovery {
+ Reconnect = 0,
+ Resume = 1
+}
+type WebSocketShardEventsMap = {
+ [WebSocketShardEvents.Closed]: [{
+ code: number;
+ }];
+ [WebSocketShardEvents.Debug]: [payload: {
+ message: string;
+ }];
+ [WebSocketShardEvents.Dispatch]: [payload: {
+ data: GatewayDispatchPayload;
+ }];
+ [WebSocketShardEvents.Error]: [payload: {
+ error: Error;
+ }];
+ [WebSocketShardEvents.Hello]: [];
+ [WebSocketShardEvents.Ready]: [payload: {
+ data: GatewayReadyDispatchData;
+ }];
+ [WebSocketShardEvents.Resumed]: [];
+ [WebSocketShardEvents.HeartbeatComplete]: [payload: {
+ ackAt: number;
+ heartbeatAt: number;
+ latency: number;
+ }];
+};
+interface WebSocketShardDestroyOptions {
+ code?: number;
+ reason?: string;
+ recover?: WebSocketShardDestroyRecovery;
+}
+declare enum CloseCodes {
+ Normal = 1000,
+ Resuming = 4200
+}
+interface SendRateLimitState {
+ remaining: number;
+ resetAt: number;
+}
+declare class WebSocketShard extends AsyncEventEmitter<WebSocketShardEventsMap> {
+ #private;
+ private connection;
+ private useIdentifyCompress;
+ private inflate;
+ private readonly textDecoder;
+ private replayedEvents;
+ private isAck;
+ private sendRateLimitState;
+ private initialHeartbeatTimeoutController;
+ private heartbeatInterval;
+ private lastHeartbeatAt;
+ private initialConnectResolved;
+ private failedToConnectDueToNetworkError;
+ private readonly sendQueue;
+ private readonly timeoutAbortControllers;
+ private readonly strategy;
+ readonly id: number;
+ get status(): WebSocketShardStatus;
+ constructor(strategy: IContextFetchingStrategy, id: number);
+ connect(): Promise<void>;
+ private internalConnect;
+ destroy(options?: WebSocketShardDestroyOptions): Promise<void>;
+ private waitForEvent;
+ send(payload: GatewaySendPayload): Promise<void>;
+ private identify;
+ private resume;
+ private heartbeat;
+ private unpackMessage;
+ private onMessage;
+ private onError;
+ private onClose;
+ private debug;
+}
+
+/**
+ * Strategies responsible for spawning, initializing connections, destroying shards, and relaying events
+ */
+interface IShardingStrategy {
+ /**
+ * Initializes all the shards
+ */
+ connect(): Awaitable<void>;
+ /**
+ * Destroys all the shards
+ */
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Awaitable<void>;
+ /**
+ * Fetches the status of all the shards
+ */
+ fetchStatus(): Awaitable<Collection<number, WebSocketShardStatus>>;
+ /**
+ * Sends a payload to a shard
+ */
+ send(shardId: number, payload: GatewaySendPayload): Awaitable<void>;
+ /**
+ * Spawns all the shards
+ */
+ spawn(shardIds: number[]): Awaitable<void>;
+}
+
+/**
+ * IdentifyThrottlers are responsible for dictating when a shard is allowed to identify.
+ *
+ * @see {@link https://discord.com/developers/docs/topics/gateway#sharding-max-concurrency}
+ */
+interface IIdentifyThrottler {
+ /**
+ * Resolves once the given shard should be allowed to identify, or rejects if the operation was aborted.
+ */
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+/**
+ * Simple strategy that just spawns shards in the current process
+ */
+declare class SimpleShardingStrategy implements IShardingStrategy {
+ private readonly manager;
+ private readonly shards;
+ constructor(manager: WebSocketManager);
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ spawn(shardIds: number[]): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ connect(): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ send(shardId: number, payload: GatewaySendPayload): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ fetchStatus(): Promise<Collection<number, WebSocketShardStatus>>;
+}
+
+/**
+ * The state of a rate limit key's identify queue.
+ */
+interface IdentifyState {
+ queue: AsyncQueue;
+ resetsAt: number;
+}
+/**
+ * Local, in-memory identify throttler.
+ */
+declare class SimpleIdentifyThrottler implements IIdentifyThrottler {
+ private readonly maxConcurrency;
+ private readonly states;
+ constructor(maxConcurrency: number);
+ /**
+ * {@inheritDoc IIdentifyThrottler.waitForIdentify}
+ */
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+/**
+ * Valid encoding types
+ */
+declare enum Encoding {
+ JSON = "json"
+}
+/**
+ * Valid compression methods
+ */
+declare enum CompressionMethod {
+ ZlibStream = "zlib-stream"
+}
+declare const DefaultDeviceProperty: `@discordjs/ws ${string}`;
+/**
+ * Default options used by the manager
+ */
+declare const DefaultWebSocketManagerOptions: {
+ readonly buildIdentifyThrottler: (manager: WebSocketManager) => Promise<SimpleIdentifyThrottler>;
+ readonly buildStrategy: (manager: WebSocketManager) => SimpleShardingStrategy;
+ readonly shardCount: null;
+ readonly shardIds: null;
+ readonly largeThreshold: null;
+ readonly initialPresence: null;
+ readonly identifyProperties: {
+ readonly browser: `@discordjs/ws ${string}`;
+ readonly device: `@discordjs/ws ${string}`;
+ readonly os: NodeJS.Platform;
+ };
+ readonly version: "10";
+ readonly encoding: Encoding;
+ readonly compression: null;
+ readonly retrieveSessionInfo: (shardId: number) => SessionInfo | null;
+ readonly updateSessionInfo: (shardId: number, info: SessionInfo | null) => void;
+ readonly handshakeTimeout: 30000;
+ readonly helloTimeout: 60000;
+ readonly readyTimeout: 15000;
+};
+declare const ImportantGatewayOpcodes: Set<GatewayOpcodes>;
+declare function getInitialSendRateLimitState(): SendRateLimitState;
+
+/**
+ * Represents a range of shard ids
+ */
+interface ShardRange {
+ end: number;
+ start: number;
+}
+/**
+ * Session information for a given shard, used to resume a session
+ */
+interface SessionInfo {
+ /**
+ * URL to use when resuming
+ */
+ resumeURL: string;
+ /**
+ * The sequence number of the last message sent by the shard
+ */
+ sequence: number;
+ /**
+ * Session id for this shard
+ */
+ sessionId: string;
+ /**
+ * The total number of shards at the time of this shard identifying
+ */
+ shardCount: number;
+ /**
+ * The id of the shard
+ */
+ shardId: number;
+}
+/**
+ * Required options for the WebSocketManager
+ */
+interface RequiredWebSocketManagerOptions {
+ /**
+ * The intents to request
+ */
+ intents: GatewayIntentBits | 0;
+ /**
+ * The REST instance to use for fetching gateway information
+ */
+ rest: REST;
+ /**
+ * The token to use for identifying with the gateway
+ */
+ token: string;
+}
+/**
+ * Optional additional configuration for the WebSocketManager
+ */
+interface OptionalWebSocketManagerOptions {
+ /**
+ * Builds an identify throttler to use for this manager's shards
+ */
+ buildIdentifyThrottler(manager: WebSocketManager): Awaitable<IIdentifyThrottler>;
+ /**
+ * Builds the strategy to use for sharding
+ *
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * token: process.env.DISCORD_TOKEN,
+ * intents: 0, // for no intents
+ * rest,
+ * buildStrategy: (manager) => new WorkerShardingStrategy(manager, { shardsPerWorker: 2 }),
+ * });
+ * ```
+ */
+ buildStrategy(manager: WebSocketManager): IShardingStrategy;
+ /**
+ * The compression method to use
+ *
+ * @defaultValue `null` (no compression)
+ */
+ compression: CompressionMethod | null;
+ /**
+ * The encoding to use
+ *
+ * @defaultValue `'json'`
+ */
+ encoding: Encoding;
+ /**
+ * How long to wait for a shard to connect before giving up
+ */
+ handshakeTimeout: number | null;
+ /**
+ * How long to wait for a shard's HELLO packet before giving up
+ */
+ helloTimeout: number | null;
+ /**
+ * Properties to send to the gateway when identifying
+ */
+ identifyProperties: GatewayIdentifyProperties;
+ /**
+ * Initial presence data to send to the gateway when identifying
+ */
+ initialPresence: GatewayPresenceUpdateData | null;
+ /**
+ * Value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list
+ */
+ largeThreshold: number | null;
+ /**
+ * How long to wait for a shard's READY packet before giving up
+ */
+ readyTimeout: number | null;
+ /**
+ * Function used to retrieve session information (and attempt to resume) for a given shard
+ *
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * async retrieveSessionInfo(shardId): Awaitable<SessionInfo | null> {
+ * // Fetch this info from redis or similar
+ * return { sessionId: string, sequence: number };
+ * // Return null if no information is found
+ * },
+ * });
+ * ```
+ */
+ retrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;
+ /**
+ * The total number of shards across all WebsocketManagers you intend to instantiate.
+ * Use `null` to use Discord's recommended shard count
+ */
+ shardCount: number | null;
+ /**
+ * The ids of the shards this WebSocketManager should manage.
+ * Use `null` to simply spawn 0 through `shardCount - 1`
+ *
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * shardIds: [1, 3, 7], // spawns shard 1, 3, and 7, nothing else
+ * });
+ * ```
+ * @example
+ * ```ts
+ * const manager = new WebSocketManager({
+ * shardIds: {
+ * start: 3,
+ * end: 6,
+ * }, // spawns shards 3, 4, 5, and 6
+ * });
+ * ```
+ */
+ shardIds: number[] | ShardRange | null;
+ /**
+ * Function used to store session information for a given shard
+ */
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;
+ /**
+ * The gateway version to use
+ *
+ * @defaultValue `'10'`
+ */
+ version: string;
+}
+type WebSocketManagerOptions = OptionalWebSocketManagerOptions & RequiredWebSocketManagerOptions;
+type ManagerShardEventsMap = {
+ [K in keyof WebSocketShardEventsMap]: [
+ WebSocketShardEventsMap[K] extends [] ? {
+ shardId: number;
+ } : WebSocketShardEventsMap[K][0] & {
+ shardId: number;
+ }
+ ];
+};
+declare class WebSocketManager extends AsyncEventEmitter<ManagerShardEventsMap> {
+ /**
+ * The options being used by this manager
+ */
+ readonly options: WebSocketManagerOptions;
+ /**
+ * Internal cache for a GET /gateway/bot result
+ */
+ private gatewayInformation;
+ /**
+ * Internal cache for the shard ids
+ */
+ private shardIds;
+ /**
+ * Strategy used to manage shards
+ *
+ * @defaultValue `SimpleShardingStrategy`
+ */
+ private readonly strategy;
+ constructor(options: Partial<OptionalWebSocketManagerOptions> & RequiredWebSocketManagerOptions);
+ /**
+ * Fetches the gateway information from Discord - or returns it from cache if available
+ *
+ * @param force - Whether to ignore the cache and force a fresh fetch
+ */
+ fetchGatewayInformation(force?: boolean): Promise<APIGatewayBotInfo>;
+ /**
+ * Updates your total shard count on-the-fly, spawning shards as needed
+ *
+ * @param shardCount - The new shard count to use
+ */
+ updateShardCount(shardCount: number | null): Promise<this>;
+ /**
+ * Yields the total number of shards across for your bot, accounting for Discord recommendations
+ */
+ getShardCount(): Promise<number>;
+ /**
+ * Yields the ids of the shards this manager should manage
+ */
+ getShardIds(force?: boolean): Promise<number[]>;
+ connect(): Promise<void>;
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Awaitable<void>;
+ send(shardId: number, payload: GatewaySendPayload): Awaitable<void>;
+ fetchStatus(): Awaitable<_discordjs_collection.Collection<number, WebSocketShardStatus>>;
+}
+
+interface FetchingStrategyOptions extends Omit<WebSocketManagerOptions, 'buildIdentifyThrottler' | 'buildStrategy' | 'rest' | 'retrieveSessionInfo' | 'shardCount' | 'shardIds' | 'updateSessionInfo'> {
+ readonly gatewayInformation: APIGatewayBotInfo;
+ readonly shardCount: number;
+}
+/**
+ * Strategies responsible solely for making manager information accessible
+ */
+interface IContextFetchingStrategy {
+ readonly options: FetchingStrategyOptions;
+ retrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;
+ /**
+ * Resolves once the given shard should be allowed to identify
+ * This should correctly handle the signal and reject with an abort error if the operation is aborted.
+ * Other errors will cause the shard to reconnect.
+ */
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+declare function managerToFetchingStrategyOptions(manager: WebSocketManager): Promise<FetchingStrategyOptions>;
+
+declare class SimpleContextFetchingStrategy implements IContextFetchingStrategy {
+ private readonly manager;
+ readonly options: FetchingStrategyOptions;
+ private static throttlerCache;
+ private static ensureThrottler;
+ constructor(manager: WebSocketManager, options: FetchingStrategyOptions);
+ retrieveSessionInfo(shardId: number): Promise<SessionInfo | null>;
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): _discordjs_util.Awaitable<void>;
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+declare class WorkerContextFetchingStrategy implements IContextFetchingStrategy {
+ readonly options: FetchingStrategyOptions;
+ private readonly sessionPromises;
+ private readonly waitForIdentifyPromises;
+ constructor(options: FetchingStrategyOptions);
+ retrieveSessionInfo(shardId: number): Promise<SessionInfo | null>;
+ updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): void;
+ waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
+}
+
+interface WorkerData extends FetchingStrategyOptions {
+ shardIds: number[];
+}
+declare enum WorkerSendPayloadOp {
+ Connect = 0,
+ Destroy = 1,
+ Send = 2,
+ SessionInfoResponse = 3,
+ ShardIdentifyResponse = 4,
+ FetchStatus = 5
+}
+type WorkerSendPayload = {
+ nonce: number;
+ ok: boolean;
+ op: WorkerSendPayloadOp.ShardIdentifyResponse;
+} | {
+ nonce: number;
+ op: WorkerSendPayloadOp.FetchStatus;
+ shardId: number;
+} | {
+ nonce: number;
+ op: WorkerSendPayloadOp.SessionInfoResponse;
+ session: SessionInfo | null;
+} | {
+ op: WorkerSendPayloadOp.Connect;
+ shardId: number;
+} | {
+ op: WorkerSendPayloadOp.Destroy;
+ options?: WebSocketShardDestroyOptions;
+ shardId: number;
+} | {
+ op: WorkerSendPayloadOp.Send;
+ payload: GatewaySendPayload;
+ shardId: number;
+};
+declare enum WorkerReceivePayloadOp {
+ Connected = 0,
+ Destroyed = 1,
+ Event = 2,
+ RetrieveSessionInfo = 3,
+ UpdateSessionInfo = 4,
+ WaitForIdentify = 5,
+ FetchStatusResponse = 6,
+ WorkerReady = 7,
+ CancelIdentify = 8
+}
+type WorkerReceivePayload = {
+ data: any;
+ event: WebSocketShardEvents;
+ op: WorkerReceivePayloadOp.Event;
+ shardId: number;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.CancelIdentify;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.FetchStatusResponse;
+ status: WebSocketShardStatus;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.RetrieveSessionInfo;
+ shardId: number;
+} | {
+ nonce: number;
+ op: WorkerReceivePayloadOp.WaitForIdentify;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.Connected;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.Destroyed;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.UpdateSessionInfo;
+ session: SessionInfo | null;
+ shardId: number;
+} | {
+ op: WorkerReceivePayloadOp.WorkerReady;
+};
+/**
+ * Options for a {@link WorkerShardingStrategy}
+ */
+interface WorkerShardingStrategyOptions {
+ /**
+ * Dictates how many shards should be spawned per worker thread.
+ */
+ shardsPerWorker: number | 'all';
+ /**
+ * Path to the worker file to use. The worker requires quite a bit of setup, it is recommended you leverage the {@link WorkerBootstrapper} class.
+ */
+ workerPath?: string;
+}
+/**
+ * Strategy used to spawn threads in worker_threads
+ */
+declare class WorkerShardingStrategy implements IShardingStrategy {
+ #private;
+ private readonly manager;
+ private readonly options;
+ private readonly connectPromises;
+ private readonly destroyPromises;
+ private readonly fetchStatusPromises;
+ private readonly waitForIdentifyControllers;
+ private throttler?;
+ constructor(manager: WebSocketManager, options: WorkerShardingStrategyOptions);
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ spawn(shardIds: number[]): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ connect(): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Promise<void>;
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ send(shardId: number, data: GatewaySendPayload): void;
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ fetchStatus(): Promise<Collection<number, WebSocketShardStatus>>;
+ private setupWorker;
+ private resolveWorkerPath;
+ private waitForWorkerReady;
+ private onMessage;
+ private ensureThrottler;
+}
+
+/**
+ * Options for bootstrapping the worker
+ */
+interface BootstrapOptions {
+ /**
+ * Shard events to just arbitrarily forward to the parent thread for the manager to emit
+ * Note: By default, this will include ALL events
+ * you most likely want to handle dispatch within the worker itself
+ */
+ forwardEvents?: WebSocketShardEvents[];
+ /**
+ * Function to call when a shard is created for additional setup
+ */
+ shardCallback?(shard: WebSocketShard): Awaitable<void>;
+}
+/**
+ * Utility class for bootstrapping a worker thread to be used for sharding
+ */
+declare class WorkerBootstrapper {
+ /**
+ * The data passed to the worker thread
+ */
+ protected readonly data: WorkerData;
+ /**
+ * The shards that are managed by this worker
+ */
+ protected readonly shards: Collection<number, WebSocketShard>;
+ constructor();
+ /**
+ * Helper method to initiate a shard's connection process
+ */
+ protected connect(shardId: number): Promise<void>;
+ /**
+ * Helper method to destroy a shard
+ */
+ protected destroy(shardId: number, options?: WebSocketShardDestroyOptions): Promise<void>;
+ /**
+ * Helper method to attach event listeners to the parentPort
+ */
+ protected setupThreadEvents(): void;
+ /**
+ * Bootstraps the worker thread with the provided options
+ */
+ bootstrap(options?: Readonly<BootstrapOptions>): Promise<void>;
+}
+
+/**
+ * The {@link https://github.com/discordjs/discord.js/blob/main/packages/ws/#readme | @discordjs/ws} version
+ * that you are currently using.
+ */
+declare const version: string;
+
+export { BootstrapOptions, CloseCodes, CompressionMethod, DefaultDeviceProperty, DefaultWebSocketManagerOptions, Encoding, FetchingStrategyOptions, IContextFetchingStrategy, IIdentifyThrottler, IShardingStrategy, IdentifyState, ImportantGatewayOpcodes, ManagerShardEventsMap, OptionalWebSocketManagerOptions, RequiredWebSocketManagerOptions, SendRateLimitState, SessionInfo, ShardRange, SimpleContextFetchingStrategy, SimpleIdentifyThrottler, SimpleShardingStrategy, WebSocketManager, WebSocketManagerOptions, WebSocketShard, WebSocketShardDestroyOptions, WebSocketShardDestroyRecovery, WebSocketShardEvents, WebSocketShardEventsMap, WebSocketShardStatus, WorkerBootstrapper, WorkerContextFetchingStrategy, WorkerData, WorkerReceivePayload, WorkerReceivePayloadOp, WorkerSendPayload, WorkerSendPayloadOp, WorkerShardingStrategy, WorkerShardingStrategyOptions, getInitialSendRateLimitState, managerToFetchingStrategyOptions, version };
diff --git a/node_modules/@discordjs/ws/dist/index.js b/node_modules/@discordjs/ws/dist/index.js
new file mode 100644
index 0000000..9931550
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/index.js
@@ -0,0 +1,1482 @@
+"use strict";
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
+var __export = (target, all) => {
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+};
+var __copyProps = (to, from, except, desc) => {
+ if (from && typeof from === "object" || typeof from === "function") {
+ for (let key of __getOwnPropNames(from))
+ if (!__hasOwnProp.call(to, key) && key !== except)
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
+ }
+ return to;
+};
+var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
+ // If the importer is in node compatibility mode or this is not an ESM
+ // file that has been converted to a CommonJS file using a Babel-
+ // compatible transform (i.e. "__esModule" has not been set), then set
+ // "default" to the CommonJS "module.exports" for node compatibility.
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
+ mod
+));
+var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
+
+// src/index.ts
+var src_exports = {};
+__export(src_exports, {
+ CloseCodes: () => CloseCodes,
+ CompressionMethod: () => CompressionMethod,
+ DefaultDeviceProperty: () => DefaultDeviceProperty,
+ DefaultWebSocketManagerOptions: () => DefaultWebSocketManagerOptions,
+ Encoding: () => Encoding,
+ ImportantGatewayOpcodes: () => ImportantGatewayOpcodes,
+ SimpleContextFetchingStrategy: () => SimpleContextFetchingStrategy,
+ SimpleIdentifyThrottler: () => SimpleIdentifyThrottler,
+ SimpleShardingStrategy: () => SimpleShardingStrategy,
+ WebSocketManager: () => WebSocketManager,
+ WebSocketShard: () => WebSocketShard,
+ WebSocketShardDestroyRecovery: () => WebSocketShardDestroyRecovery,
+ WebSocketShardEvents: () => WebSocketShardEvents,
+ WebSocketShardStatus: () => WebSocketShardStatus,
+ WorkerBootstrapper: () => WorkerBootstrapper,
+ WorkerContextFetchingStrategy: () => WorkerContextFetchingStrategy,
+ WorkerReceivePayloadOp: () => WorkerReceivePayloadOp,
+ WorkerSendPayloadOp: () => WorkerSendPayloadOp,
+ WorkerShardingStrategy: () => WorkerShardingStrategy,
+ getInitialSendRateLimitState: () => getInitialSendRateLimitState,
+ managerToFetchingStrategyOptions: () => managerToFetchingStrategyOptions,
+ version: () => version
+});
+module.exports = __toCommonJS(src_exports);
+
+// src/strategies/context/IContextFetchingStrategy.ts
+async function managerToFetchingStrategyOptions(manager) {
+ const {
+ buildIdentifyThrottler,
+ buildStrategy,
+ retrieveSessionInfo,
+ updateSessionInfo,
+ shardCount,
+ shardIds,
+ rest,
+ ...managerOptions
+ } = manager.options;
+ return {
+ ...managerOptions,
+ gatewayInformation: await manager.fetchGatewayInformation(),
+ shardCount: await manager.getShardCount()
+ };
+}
+__name(managerToFetchingStrategyOptions, "managerToFetchingStrategyOptions");
+
+// src/strategies/context/SimpleContextFetchingStrategy.ts
+var SimpleContextFetchingStrategy = class _SimpleContextFetchingStrategy {
+ constructor(manager, options) {
+ this.manager = manager;
+ this.options = options;
+ }
+ static {
+ __name(this, "SimpleContextFetchingStrategy");
+ }
+ // This strategy assumes every shard is running under the same process - therefore we need a single
+ // IdentifyThrottler per manager.
+ static throttlerCache = /* @__PURE__ */ new WeakMap();
+ static async ensureThrottler(manager) {
+ const throttler = _SimpleContextFetchingStrategy.throttlerCache.get(manager);
+ if (throttler) {
+ return throttler;
+ }
+ const newThrottler = await manager.options.buildIdentifyThrottler(manager);
+ _SimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);
+ return newThrottler;
+ }
+ async retrieveSessionInfo(shardId) {
+ return this.manager.options.retrieveSessionInfo(shardId);
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ return this.manager.options.updateSessionInfo(shardId, sessionInfo);
+ }
+ async waitForIdentify(shardId, signal) {
+ const throttler = await _SimpleContextFetchingStrategy.ensureThrottler(this.manager);
+ await throttler.waitForIdentify(shardId, signal);
+ }
+};
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+var import_node_worker_threads2 = require("worker_threads");
+var import_collection2 = require("@discordjs/collection");
+
+// src/strategies/sharding/WorkerShardingStrategy.ts
+var import_node_events = require("events");
+var import_node_path = require("path");
+var import_node_worker_threads = require("worker_threads");
+var import_collection = require("@discordjs/collection");
+var WorkerSendPayloadOp = /* @__PURE__ */ ((WorkerSendPayloadOp2) => {
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["Connect"] = 0] = "Connect";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["Destroy"] = 1] = "Destroy";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["Send"] = 2] = "Send";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["SessionInfoResponse"] = 3] = "SessionInfoResponse";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["ShardIdentifyResponse"] = 4] = "ShardIdentifyResponse";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["FetchStatus"] = 5] = "FetchStatus";
+ return WorkerSendPayloadOp2;
+})(WorkerSendPayloadOp || {});
+var WorkerReceivePayloadOp = /* @__PURE__ */ ((WorkerReceivePayloadOp2) => {
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["Connected"] = 0] = "Connected";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["Destroyed"] = 1] = "Destroyed";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["Event"] = 2] = "Event";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["RetrieveSessionInfo"] = 3] = "RetrieveSessionInfo";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["UpdateSessionInfo"] = 4] = "UpdateSessionInfo";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["WaitForIdentify"] = 5] = "WaitForIdentify";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["FetchStatusResponse"] = 6] = "FetchStatusResponse";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["WorkerReady"] = 7] = "WorkerReady";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["CancelIdentify"] = 8] = "CancelIdentify";
+ return WorkerReceivePayloadOp2;
+})(WorkerReceivePayloadOp || {});
+var WorkerShardingStrategy = class {
+ static {
+ __name(this, "WorkerShardingStrategy");
+ }
+ manager;
+ options;
+ #workers = [];
+ #workerByShardId = new import_collection.Collection();
+ connectPromises = new import_collection.Collection();
+ destroyPromises = new import_collection.Collection();
+ fetchStatusPromises = new import_collection.Collection();
+ waitForIdentifyControllers = new import_collection.Collection();
+ throttler;
+ constructor(manager, options) {
+ this.manager = manager;
+ this.options = options;
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ async spawn(shardIds) {
+ const shardsPerWorker = this.options.shardsPerWorker === "all" ? shardIds.length : this.options.shardsPerWorker;
+ const strategyOptions = await managerToFetchingStrategyOptions(this.manager);
+ const loops = Math.ceil(shardIds.length / shardsPerWorker);
+ const promises = [];
+ for (let idx = 0; idx < loops; idx++) {
+ const slice = shardIds.slice(idx * shardsPerWorker, (idx + 1) * shardsPerWorker);
+ const workerData2 = {
+ ...strategyOptions,
+ shardIds: slice
+ };
+ promises.push(this.setupWorker(workerData2));
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ async connect() {
+ const promises = [];
+ for (const [shardId, worker] of this.#workerByShardId.entries()) {
+ const payload = {
+ op: 0 /* Connect */,
+ shardId
+ };
+ const promise = new Promise((resolve2) => this.connectPromises.set(shardId, resolve2));
+ worker.postMessage(payload);
+ promises.push(promise);
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ async destroy(options = {}) {
+ const promises = [];
+ for (const [shardId, worker] of this.#workerByShardId.entries()) {
+ const payload = {
+ op: 1 /* Destroy */,
+ shardId,
+ options
+ };
+ promises.push(
+ // eslint-disable-next-line no-promise-executor-return, promise/prefer-await-to-then
+ new Promise((resolve2) => this.destroyPromises.set(shardId, resolve2)).then(async () => worker.terminate())
+ );
+ worker.postMessage(payload);
+ }
+ this.#workers = [];
+ this.#workerByShardId.clear();
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ send(shardId, data) {
+ const worker = this.#workerByShardId.get(shardId);
+ if (!worker) {
+ throw new Error(`No worker found for shard ${shardId}`);
+ }
+ const payload = {
+ op: 2 /* Send */,
+ shardId,
+ payload: data
+ };
+ worker.postMessage(payload);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ async fetchStatus() {
+ const statuses = new import_collection.Collection();
+ for (const [shardId, worker] of this.#workerByShardId.entries()) {
+ const nonce = Math.random();
+ const payload = {
+ op: 5 /* FetchStatus */,
+ shardId,
+ nonce
+ };
+ const promise = new Promise((resolve2) => this.fetchStatusPromises.set(nonce, resolve2));
+ worker.postMessage(payload);
+ const status = await promise;
+ statuses.set(shardId, status);
+ }
+ return statuses;
+ }
+ async setupWorker(workerData2) {
+ const worker = new import_node_worker_threads.Worker(this.resolveWorkerPath(), { workerData: workerData2 });
+ await (0, import_node_events.once)(worker, "online");
+ await this.waitForWorkerReady(worker);
+ worker.on("error", (err) => {
+ throw err;
+ }).on("messageerror", (err) => {
+ throw err;
+ }).on("message", async (payload) => this.onMessage(worker, payload));
+ this.#workers.push(worker);
+ for (const shardId of workerData2.shardIds) {
+ this.#workerByShardId.set(shardId, worker);
+ }
+ }
+ resolveWorkerPath() {
+ const path = this.options.workerPath;
+ if (!path) {
+ return (0, import_node_path.join)(__dirname, "defaultWorker.js");
+ }
+ if ((0, import_node_path.isAbsolute)(path)) {
+ return path;
+ }
+ if (/^\.\.?[/\\]/.test(path)) {
+ return (0, import_node_path.resolve)(path);
+ }
+ try {
+ return require.resolve(path);
+ } catch {
+ return (0, import_node_path.resolve)(path);
+ }
+ }
+ async waitForWorkerReady(worker) {
+ return new Promise((resolve2) => {
+ const handler = /* @__PURE__ */ __name((payload) => {
+ if (payload.op === 7 /* WorkerReady */) {
+ resolve2();
+ worker.off("message", handler);
+ }
+ }, "handler");
+ worker.on("message", handler);
+ });
+ }
+ async onMessage(worker, payload) {
+ switch (payload.op) {
+ case 0 /* Connected */: {
+ this.connectPromises.get(payload.shardId)?.();
+ this.connectPromises.delete(payload.shardId);
+ break;
+ }
+ case 1 /* Destroyed */: {
+ this.destroyPromises.get(payload.shardId)?.();
+ this.destroyPromises.delete(payload.shardId);
+ break;
+ }
+ case 2 /* Event */: {
+ this.manager.emit(payload.event, { ...payload.data, shardId: payload.shardId });
+ break;
+ }
+ case 3 /* RetrieveSessionInfo */: {
+ const session = await this.manager.options.retrieveSessionInfo(payload.shardId);
+ const response = {
+ op: 3 /* SessionInfoResponse */,
+ nonce: payload.nonce,
+ session
+ };
+ worker.postMessage(response);
+ break;
+ }
+ case 4 /* UpdateSessionInfo */: {
+ await this.manager.options.updateSessionInfo(payload.shardId, payload.session);
+ break;
+ }
+ case 5 /* WaitForIdentify */: {
+ const throttler = await this.ensureThrottler();
+ try {
+ const controller = new AbortController();
+ this.waitForIdentifyControllers.set(payload.nonce, controller);
+ await throttler.waitForIdentify(payload.shardId, controller.signal);
+ } catch {
+ return;
+ }
+ const response = {
+ op: 4 /* ShardIdentifyResponse */,
+ nonce: payload.nonce,
+ ok: true
+ };
+ worker.postMessage(response);
+ break;
+ }
+ case 6 /* FetchStatusResponse */: {
+ this.fetchStatusPromises.get(payload.nonce)?.(payload.status);
+ this.fetchStatusPromises.delete(payload.nonce);
+ break;
+ }
+ case 7 /* WorkerReady */: {
+ break;
+ }
+ case 8 /* CancelIdentify */: {
+ this.waitForIdentifyControllers.get(payload.nonce)?.abort();
+ this.waitForIdentifyControllers.delete(payload.nonce);
+ const response = {
+ op: 4 /* ShardIdentifyResponse */,
+ nonce: payload.nonce,
+ ok: false
+ };
+ worker.postMessage(response);
+ break;
+ }
+ }
+ }
+ async ensureThrottler() {
+ this.throttler ??= await this.manager.options.buildIdentifyThrottler(this.manager);
+ return this.throttler;
+ }
+};
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+var WorkerContextFetchingStrategy = class {
+ constructor(options) {
+ this.options = options;
+ if (import_node_worker_threads2.isMainThread) {
+ throw new Error("Cannot instantiate WorkerContextFetchingStrategy on the main thread");
+ }
+ import_node_worker_threads2.parentPort.on("message", (payload) => {
+ if (payload.op === 3 /* SessionInfoResponse */) {
+ this.sessionPromises.get(payload.nonce)?.(payload.session);
+ this.sessionPromises.delete(payload.nonce);
+ }
+ if (payload.op === 4 /* ShardIdentifyResponse */) {
+ const promise = this.waitForIdentifyPromises.get(payload.nonce);
+ if (payload.ok) {
+ promise?.resolve();
+ } else {
+ promise?.reject(promise.signal.reason);
+ }
+ this.waitForIdentifyPromises.delete(payload.nonce);
+ }
+ });
+ }
+ static {
+ __name(this, "WorkerContextFetchingStrategy");
+ }
+ sessionPromises = new import_collection2.Collection();
+ waitForIdentifyPromises = new import_collection2.Collection();
+ async retrieveSessionInfo(shardId) {
+ const nonce = Math.random();
+ const payload = {
+ op: 3 /* RetrieveSessionInfo */,
+ shardId,
+ nonce
+ };
+ const promise = new Promise((resolve2) => this.sessionPromises.set(nonce, resolve2));
+ import_node_worker_threads2.parentPort.postMessage(payload);
+ return promise;
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ const payload = {
+ op: 4 /* UpdateSessionInfo */,
+ shardId,
+ session: sessionInfo
+ };
+ import_node_worker_threads2.parentPort.postMessage(payload);
+ }
+ async waitForIdentify(shardId, signal) {
+ const nonce = Math.random();
+ const payload = {
+ op: 5 /* WaitForIdentify */,
+ nonce,
+ shardId
+ };
+ const promise = new Promise(
+ (resolve2, reject) => (
+ // eslint-disable-next-line no-promise-executor-return
+ this.waitForIdentifyPromises.set(nonce, { signal, resolve: resolve2, reject })
+ )
+ );
+ import_node_worker_threads2.parentPort.postMessage(payload);
+ const listener = /* @__PURE__ */ __name(() => {
+ const payload2 = {
+ op: 8 /* CancelIdentify */,
+ nonce
+ };
+ import_node_worker_threads2.parentPort.postMessage(payload2);
+ }, "listener");
+ signal.addEventListener("abort", listener);
+ try {
+ await promise;
+ } finally {
+ signal.removeEventListener("abort", listener);
+ }
+ }
+};
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+var import_collection6 = require("@discordjs/collection");
+
+// src/ws/WebSocketShard.ts
+var import_node_buffer = require("buffer");
+var import_node_events2 = require("events");
+var import_node_timers = require("timers");
+var import_promises2 = require("timers/promises");
+var import_node_url = require("url");
+var import_node_util = require("util");
+var import_node_zlib = require("zlib");
+var import_collection5 = require("@discordjs/collection");
+var import_util2 = require("@discordjs/util");
+var import_async_queue2 = require("@sapphire/async-queue");
+var import_async_event_emitter = require("@vladfrangu/async_event_emitter");
+var import_v102 = require("discord-api-types/v10");
+var import_ws = require("ws");
+
+// src/utils/constants.ts
+var import_node_process = __toESM(require("process"));
+var import_collection4 = require("@discordjs/collection");
+var import_util = require("@discordjs/util");
+var import_v10 = require("discord-api-types/v10");
+
+// src/throttling/SimpleIdentifyThrottler.ts
+var import_promises = require("timers/promises");
+var import_collection3 = require("@discordjs/collection");
+var import_async_queue = require("@sapphire/async-queue");
+var SimpleIdentifyThrottler = class {
+ constructor(maxConcurrency) {
+ this.maxConcurrency = maxConcurrency;
+ }
+ static {
+ __name(this, "SimpleIdentifyThrottler");
+ }
+ states = new import_collection3.Collection();
+ /**
+ * {@inheritDoc IIdentifyThrottler.waitForIdentify}
+ */
+ async waitForIdentify(shardId, signal) {
+ const key = shardId % this.maxConcurrency;
+ const state = this.states.ensure(key, () => {
+ return {
+ queue: new import_async_queue.AsyncQueue(),
+ resetsAt: Number.POSITIVE_INFINITY
+ };
+ });
+ await state.queue.wait({ signal });
+ try {
+ const diff = state.resetsAt - Date.now();
+ if (diff <= 5e3) {
+ const time = diff + Math.random() * 1500;
+ await (0, import_promises.setTimeout)(time);
+ }
+ state.resetsAt = Date.now() + 5e3;
+ } finally {
+ state.queue.shift();
+ }
+ }
+};
+
+// src/utils/constants.ts
+var Encoding = /* @__PURE__ */ ((Encoding2) => {
+ Encoding2["JSON"] = "json";
+ return Encoding2;
+})(Encoding || {});
+var CompressionMethod = /* @__PURE__ */ ((CompressionMethod2) => {
+ CompressionMethod2["ZlibStream"] = "zlib-stream";
+ return CompressionMethod2;
+})(CompressionMethod || {});
+var DefaultDeviceProperty = `@discordjs/ws 1.0.1`;
+var getDefaultSessionStore = (0, import_util.lazy)(() => new import_collection4.Collection());
+var DefaultWebSocketManagerOptions = {
+ async buildIdentifyThrottler(manager) {
+ const info = await manager.fetchGatewayInformation();
+ return new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);
+ },
+ buildStrategy: (manager) => new SimpleShardingStrategy(manager),
+ shardCount: null,
+ shardIds: null,
+ largeThreshold: null,
+ initialPresence: null,
+ identifyProperties: {
+ browser: DefaultDeviceProperty,
+ device: DefaultDeviceProperty,
+ os: import_node_process.default.platform
+ },
+ version: import_v10.APIVersion,
+ encoding: "json" /* JSON */,
+ compression: null,
+ retrieveSessionInfo(shardId) {
+ const store = getDefaultSessionStore();
+ return store.get(shardId) ?? null;
+ },
+ updateSessionInfo(shardId, info) {
+ const store = getDefaultSessionStore();
+ if (info) {
+ store.set(shardId, info);
+ } else {
+ store.delete(shardId);
+ }
+ },
+ handshakeTimeout: 3e4,
+ helloTimeout: 6e4,
+ readyTimeout: 15e3
+};
+var ImportantGatewayOpcodes = /* @__PURE__ */ new Set([
+ import_v10.GatewayOpcodes.Heartbeat,
+ import_v10.GatewayOpcodes.Identify,
+ import_v10.GatewayOpcodes.Resume
+]);
+function getInitialSendRateLimitState() {
+ return {
+ remaining: 120,
+ resetAt: Date.now() + 6e4
+ };
+}
+__name(getInitialSendRateLimitState, "getInitialSendRateLimitState");
+
+// src/ws/WebSocketShard.ts
+var getZlibSync = (0, import_util2.lazy)(async () => import("zlib-sync").then((mod) => mod.default).catch(() => null));
+var WebSocketShardEvents = /* @__PURE__ */ ((WebSocketShardEvents2) => {
+ WebSocketShardEvents2["Closed"] = "closed";
+ WebSocketShardEvents2["Debug"] = "debug";
+ WebSocketShardEvents2["Dispatch"] = "dispatch";
+ WebSocketShardEvents2["Error"] = "error";
+ WebSocketShardEvents2["HeartbeatComplete"] = "heartbeat";
+ WebSocketShardEvents2["Hello"] = "hello";
+ WebSocketShardEvents2["Ready"] = "ready";
+ WebSocketShardEvents2["Resumed"] = "resumed";
+ return WebSocketShardEvents2;
+})(WebSocketShardEvents || {});
+var WebSocketShardStatus = /* @__PURE__ */ ((WebSocketShardStatus2) => {
+ WebSocketShardStatus2[WebSocketShardStatus2["Idle"] = 0] = "Idle";
+ WebSocketShardStatus2[WebSocketShardStatus2["Connecting"] = 1] = "Connecting";
+ WebSocketShardStatus2[WebSocketShardStatus2["Resuming"] = 2] = "Resuming";
+ WebSocketShardStatus2[WebSocketShardStatus2["Ready"] = 3] = "Ready";
+ return WebSocketShardStatus2;
+})(WebSocketShardStatus || {});
+var WebSocketShardDestroyRecovery = /* @__PURE__ */ ((WebSocketShardDestroyRecovery2) => {
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Reconnect"] = 0] = "Reconnect";
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Resume"] = 1] = "Resume";
+ return WebSocketShardDestroyRecovery2;
+})(WebSocketShardDestroyRecovery || {});
+var CloseCodes = /* @__PURE__ */ ((CloseCodes2) => {
+ CloseCodes2[CloseCodes2["Normal"] = 1e3] = "Normal";
+ CloseCodes2[CloseCodes2["Resuming"] = 4200] = "Resuming";
+ return CloseCodes2;
+})(CloseCodes || {});
+var WebSocketConstructor = import_ws.WebSocket;
+var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter {
+ static {
+ __name(this, "WebSocketShard");
+ }
+ connection = null;
+ useIdentifyCompress = false;
+ inflate = null;
+ textDecoder = new import_node_util.TextDecoder();
+ replayedEvents = 0;
+ isAck = true;
+ sendRateLimitState = getInitialSendRateLimitState();
+ initialHeartbeatTimeoutController = null;
+ heartbeatInterval = null;
+ lastHeartbeatAt = -1;
+ // Indicates whether the shard has already resolved its original connect() call
+ initialConnectResolved = false;
+ // Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)
+ failedToConnectDueToNetworkError = false;
+ sendQueue = new import_async_queue2.AsyncQueue();
+ timeoutAbortControllers = new import_collection5.Collection();
+ strategy;
+ id;
+ #status = 0 /* Idle */;
+ get status() {
+ return this.#status;
+ }
+ constructor(strategy, id) {
+ super();
+ this.strategy = strategy;
+ this.id = id;
+ }
+ async connect() {
+ const controller = new AbortController();
+ let promise;
+ if (!this.initialConnectResolved) {
+ promise = Promise.race([
+ (0, import_node_events2.once)(this, "ready" /* Ready */, { signal: controller.signal }),
+ (0, import_node_events2.once)(this, "resumed" /* Resumed */, { signal: controller.signal })
+ ]);
+ }
+ void this.internalConnect();
+ try {
+ await promise;
+ } catch ({ error }) {
+ throw error;
+ } finally {
+ controller.abort();
+ }
+ this.initialConnectResolved = true;
+ }
+ async internalConnect() {
+ if (this.#status !== 0 /* Idle */) {
+ throw new Error("Tried to connect a shard that wasn't idle");
+ }
+ const { version: version2, encoding, compression } = this.strategy.options;
+ const params = new import_node_url.URLSearchParams({ v: version2, encoding });
+ if (compression) {
+ const zlib = await getZlibSync();
+ if (zlib) {
+ params.append("compress", compression);
+ this.inflate = new zlib.Inflate({
+ chunkSize: 65535,
+ to: "string"
+ });
+ } else if (!this.useIdentifyCompress) {
+ this.useIdentifyCompress = true;
+ console.warn(
+ "WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress"
+ );
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ const url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;
+ this.debug([`Connecting to ${url}`]);
+ const connection = new WebSocketConstructor(url, {
+ handshakeTimeout: this.strategy.options.handshakeTimeout ?? void 0
+ });
+ connection.binaryType = "arraybuffer";
+ connection.onmessage = (event) => {
+ void this.onMessage(event.data, event.data instanceof ArrayBuffer);
+ };
+ connection.onerror = (event) => {
+ this.onError(event.error);
+ };
+ connection.onclose = (event) => {
+ void this.onClose(event.code);
+ };
+ this.connection = connection;
+ this.#status = 1 /* Connecting */;
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ const { ok } = await this.waitForEvent("hello" /* Hello */, this.strategy.options.helloTimeout);
+ if (!ok) {
+ return;
+ }
+ if (session?.shardCount === this.strategy.options.shardCount) {
+ await this.resume(session);
+ } else {
+ await this.identify();
+ }
+ }
+ async destroy(options = {}) {
+ if (this.#status === 0 /* Idle */) {
+ this.debug(["Tried to destroy a shard that was idle"]);
+ return;
+ }
+ if (!options.code) {
+ options.code = options.recover === 1 /* Resume */ ? 4200 /* Resuming */ : 1e3 /* Normal */;
+ }
+ this.debug([
+ "Destroying shard",
+ `Reason: ${options.reason ?? "none"}`,
+ `Code: ${options.code}`,
+ `Recover: ${options.recover === void 0 ? "none" : WebSocketShardDestroyRecovery[options.recover]}`
+ ]);
+ this.isAck = true;
+ if (this.heartbeatInterval) {
+ (0, import_node_timers.clearInterval)(this.heartbeatInterval);
+ }
+ if (this.initialHeartbeatTimeoutController) {
+ this.initialHeartbeatTimeoutController.abort();
+ this.initialHeartbeatTimeoutController = null;
+ }
+ this.lastHeartbeatAt = -1;
+ for (const controller of this.timeoutAbortControllers.values()) {
+ controller.abort();
+ }
+ this.timeoutAbortControllers.clear();
+ this.failedToConnectDueToNetworkError = false;
+ if (options.recover !== 1 /* Resume */) {
+ await this.strategy.updateSessionInfo(this.id, null);
+ }
+ if (this.connection) {
+ this.connection.onmessage = null;
+ this.connection.onclose = null;
+ const shouldClose = this.connection.readyState === import_ws.WebSocket.OPEN;
+ this.debug([
+ "Connection status during destroy",
+ `Needs closing: ${shouldClose}`,
+ `Ready state: ${this.connection.readyState}`
+ ]);
+ if (shouldClose) {
+ let outerResolve;
+ const promise = new Promise((resolve2) => {
+ outerResolve = resolve2;
+ });
+ this.connection.onclose = outerResolve;
+ this.connection.close(options.code, options.reason);
+ await promise;
+ this.emit("closed" /* Closed */, { code: options.code });
+ }
+ this.connection.onerror = null;
+ } else {
+ this.debug(["Destroying a shard that has no connection; please open an issue on GitHub"]);
+ }
+ this.#status = 0 /* Idle */;
+ if (options.recover !== void 0) {
+ await (0, import_promises2.setTimeout)(500);
+ return this.internalConnect();
+ }
+ }
+ async waitForEvent(event, timeoutDuration) {
+ this.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : "indefinitely"}`]);
+ const timeoutController = new AbortController();
+ const timeout = timeoutDuration ? (0, import_node_timers.setTimeout)(() => timeoutController.abort(), timeoutDuration).unref() : null;
+ this.timeoutAbortControllers.set(event, timeoutController);
+ const closeController = new AbortController();
+ try {
+ const closed = await Promise.race([
+ (0, import_node_events2.once)(this, event, { signal: timeoutController.signal }).then(() => false),
+ (0, import_node_events2.once)(this, "closed" /* Closed */, { signal: closeController.signal }).then(() => true)
+ ]);
+ return { ok: !closed };
+ } catch {
+ void this.destroy({
+ code: 1e3 /* Normal */,
+ reason: "Something timed out or went wrong while waiting for an event",
+ recover: 0 /* Reconnect */
+ });
+ return { ok: false };
+ } finally {
+ if (timeout) {
+ (0, import_node_timers.clearTimeout)(timeout);
+ }
+ this.timeoutAbortControllers.delete(event);
+ if (!closeController.signal.aborted) {
+ closeController.abort();
+ }
+ }
+ }
+ async send(payload) {
+ if (!this.connection) {
+ throw new Error("WebSocketShard wasn't connected");
+ }
+ if (this.#status !== 3 /* Ready */ && !ImportantGatewayOpcodes.has(payload.op)) {
+ this.debug(["Tried to send a non-crucial payload before the shard was ready, waiting"]);
+ try {
+ await (0, import_node_events2.once)(this, "ready" /* Ready */);
+ } catch {
+ return this.send(payload);
+ }
+ }
+ await this.sendQueue.wait();
+ if (--this.sendRateLimitState.remaining <= 0) {
+ const now = Date.now();
+ if (this.sendRateLimitState.resetAt > now) {
+ const sleepFor = this.sendRateLimitState.resetAt - now;
+ this.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);
+ const controller = new AbortController();
+ const interrupted = await Promise.race([
+ (0, import_promises2.setTimeout)(sleepFor).then(() => false),
+ (0, import_node_events2.once)(this, "closed" /* Closed */, { signal: controller.signal }).then(() => true)
+ ]);
+ if (interrupted) {
+ this.debug(["Connection closed while waiting for the send rate limit to reset, re-queueing payload"]);
+ this.sendQueue.shift();
+ return this.send(payload);
+ }
+ controller.abort();
+ }
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ }
+ this.sendQueue.shift();
+ this.connection.send(JSON.stringify(payload));
+ }
+ async identify() {
+ this.debug(["Waiting for identify throttle"]);
+ const controller = new AbortController();
+ const closeHandler = /* @__PURE__ */ __name(() => {
+ controller.abort();
+ }, "closeHandler");
+ this.on("closed" /* Closed */, closeHandler);
+ try {
+ await this.strategy.waitForIdentify(this.id, controller.signal);
+ } catch {
+ if (controller.signal.aborted) {
+ this.debug(["Was waiting for an identify, but the shard closed in the meantime"]);
+ return;
+ }
+ this.debug([
+ "IContextFetchingStrategy#waitForIdentify threw an unknown error.",
+ "If you're using a custom strategy, this is probably nothing to worry about.",
+ "If you're not, please open an issue on GitHub."
+ ]);
+ await this.destroy({
+ reason: "Identify throttling logic failed",
+ recover: 1 /* Resume */
+ });
+ } finally {
+ this.off("closed" /* Closed */, closeHandler);
+ }
+ this.debug([
+ "Identifying",
+ `shard id: ${this.id.toString()}`,
+ `shard count: ${this.strategy.options.shardCount}`,
+ `intents: ${this.strategy.options.intents}`,
+ `compression: ${this.inflate ? "zlib-stream" : this.useIdentifyCompress ? "identify" : "none"}`
+ ]);
+ const d = {
+ token: this.strategy.options.token,
+ properties: this.strategy.options.identifyProperties,
+ intents: this.strategy.options.intents,
+ compress: this.useIdentifyCompress,
+ shard: [this.id, this.strategy.options.shardCount]
+ };
+ if (this.strategy.options.largeThreshold) {
+ d.large_threshold = this.strategy.options.largeThreshold;
+ }
+ if (this.strategy.options.initialPresence) {
+ d.presence = this.strategy.options.initialPresence;
+ }
+ await this.send({
+ op: import_v102.GatewayOpcodes.Identify,
+ d
+ });
+ await this.waitForEvent("ready" /* Ready */, this.strategy.options.readyTimeout);
+ }
+ async resume(session) {
+ this.debug([
+ "Resuming session",
+ `resume url: ${session.resumeURL}`,
+ `sequence: ${session.sequence}`,
+ `shard id: ${this.id.toString()}`
+ ]);
+ this.#status = 2 /* Resuming */;
+ this.replayedEvents = 0;
+ return this.send({
+ op: import_v102.GatewayOpcodes.Resume,
+ d: {
+ token: this.strategy.options.token,
+ seq: session.sequence,
+ session_id: session.sessionId
+ }
+ });
+ }
+ async heartbeat(requested = false) {
+ if (!this.isAck && !requested) {
+ return this.destroy({ reason: "Zombie connection", recover: 1 /* Resume */ });
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ await this.send({
+ op: import_v102.GatewayOpcodes.Heartbeat,
+ d: session?.sequence ?? null
+ });
+ this.lastHeartbeatAt = Date.now();
+ this.isAck = false;
+ }
+ async unpackMessage(data, isBinary) {
+ if (!isBinary) {
+ try {
+ return JSON.parse(data);
+ } catch {
+ return null;
+ }
+ }
+ const decompressable = new Uint8Array(data);
+ if (this.useIdentifyCompress) {
+ return new Promise((resolve2, reject) => {
+ (0, import_node_zlib.inflate)(decompressable, { chunkSize: 65535 }, (err, result) => {
+ if (err) {
+ reject(err);
+ return;
+ }
+ resolve2(JSON.parse(this.textDecoder.decode(result)));
+ });
+ });
+ }
+ if (this.inflate) {
+ const l = decompressable.length;
+ const flush = l >= 4 && decompressable[l - 4] === 0 && decompressable[l - 3] === 0 && decompressable[l - 2] === 255 && decompressable[l - 1] === 255;
+ const zlib = await getZlibSync();
+ this.inflate.push(import_node_buffer.Buffer.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);
+ if (this.inflate.err) {
+ this.emit("error" /* Error */, {
+ error: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ""}`)
+ });
+ }
+ if (!flush) {
+ return null;
+ }
+ const { result } = this.inflate;
+ if (!result) {
+ return null;
+ }
+ return JSON.parse(typeof result === "string" ? result : this.textDecoder.decode(result));
+ }
+ this.debug([
+ "Received a message we were unable to decompress",
+ `isBinary: ${isBinary.toString()}`,
+ `useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,
+ `inflate: ${Boolean(this.inflate).toString()}`
+ ]);
+ return null;
+ }
+ async onMessage(data, isBinary) {
+ const payload = await this.unpackMessage(data, isBinary);
+ if (!payload) {
+ return;
+ }
+ switch (payload.op) {
+ case import_v102.GatewayOpcodes.Dispatch: {
+ if (this.#status === 2 /* Resuming */) {
+ this.replayedEvents++;
+ }
+ switch (payload.t) {
+ case import_v102.GatewayDispatchEvents.Ready: {
+ this.#status = 3 /* Ready */;
+ const session2 = {
+ sequence: payload.s,
+ sessionId: payload.d.session_id,
+ shardId: this.id,
+ shardCount: this.strategy.options.shardCount,
+ resumeURL: payload.d.resume_gateway_url
+ };
+ await this.strategy.updateSessionInfo(this.id, session2);
+ this.emit("ready" /* Ready */, { data: payload.d });
+ break;
+ }
+ case import_v102.GatewayDispatchEvents.Resumed: {
+ this.#status = 3 /* Ready */;
+ this.debug([`Resumed and replayed ${this.replayedEvents} events`]);
+ this.emit("resumed" /* Resumed */);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (session) {
+ if (payload.s > session.sequence) {
+ await this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });
+ }
+ } else {
+ this.debug([
+ `Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`
+ ]);
+ }
+ this.emit("dispatch" /* Dispatch */, { data: payload });
+ break;
+ }
+ case import_v102.GatewayOpcodes.Heartbeat: {
+ await this.heartbeat(true);
+ break;
+ }
+ case import_v102.GatewayOpcodes.Reconnect: {
+ await this.destroy({
+ reason: "Told to reconnect by Discord",
+ recover: 1 /* Resume */
+ });
+ break;
+ }
+ case import_v102.GatewayOpcodes.InvalidSession: {
+ this.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (payload.d && session) {
+ await this.resume(session);
+ } else {
+ await this.destroy({
+ reason: "Invalid session",
+ recover: 0 /* Reconnect */
+ });
+ }
+ break;
+ }
+ case import_v102.GatewayOpcodes.Hello: {
+ this.emit("hello" /* Hello */);
+ const jitter = Math.random();
+ const firstWait = Math.floor(payload.d.heartbeat_interval * jitter);
+ this.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);
+ try {
+ const controller = new AbortController();
+ this.initialHeartbeatTimeoutController = controller;
+ await (0, import_promises2.setTimeout)(firstWait, void 0, { signal: controller.signal });
+ } catch {
+ this.debug(["Cancelled initial heartbeat due to #destroy being called"]);
+ return;
+ } finally {
+ this.initialHeartbeatTimeoutController = null;
+ }
+ await this.heartbeat();
+ this.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);
+ this.heartbeatInterval = (0, import_node_timers.setInterval)(() => void this.heartbeat(), payload.d.heartbeat_interval);
+ break;
+ }
+ case import_v102.GatewayOpcodes.HeartbeatAck: {
+ this.isAck = true;
+ const ackAt = Date.now();
+ this.emit("heartbeat" /* HeartbeatComplete */, {
+ ackAt,
+ heartbeatAt: this.lastHeartbeatAt,
+ latency: ackAt - this.lastHeartbeatAt
+ });
+ break;
+ }
+ }
+ }
+ onError(error) {
+ if ("code" in error && ["ECONNRESET", "ECONNREFUSED"].includes(error.code)) {
+ this.debug(["Failed to connect to the gateway URL specified due to a network error"]);
+ this.failedToConnectDueToNetworkError = true;
+ return;
+ }
+ this.emit("error" /* Error */, { error });
+ }
+ async onClose(code) {
+ this.emit("closed" /* Closed */, { code });
+ switch (code) {
+ case 1e3 /* Normal */: {
+ return this.destroy({
+ code,
+ reason: "Got disconnected by Discord",
+ recover: 0 /* Reconnect */
+ });
+ }
+ case 4200 /* Resuming */: {
+ break;
+ }
+ case import_v102.GatewayCloseCodes.UnknownError: {
+ this.debug([`An unknown error occurred: ${code}`]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.UnknownOpcode: {
+ this.debug(["An invalid opcode was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.DecodeError: {
+ this.debug(["An invalid payload was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.NotAuthenticated: {
+ this.debug(["A request was somehow sent before the identify/resume payload."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.AuthenticationFailed: {
+ this.emit("error" /* Error */, {
+ error: new Error("Authentication failed")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.AlreadyAuthenticated: {
+ this.debug(["More than one auth payload was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.InvalidSeq: {
+ this.debug(["An invalid sequence was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.RateLimited: {
+ this.debug(["The WebSocket rate limit has been hit, this should never happen"]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case import_v102.GatewayCloseCodes.SessionTimedOut: {
+ this.debug(["Session timed out."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case import_v102.GatewayCloseCodes.InvalidShard: {
+ this.emit("error" /* Error */, {
+ error: new Error("Invalid shard")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.ShardingRequired: {
+ this.emit("error" /* Error */, {
+ error: new Error("Sharding is required")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.InvalidAPIVersion: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used an invalid API version")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.InvalidIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used invalid intents")
+ });
+ return this.destroy({ code });
+ }
+ case import_v102.GatewayCloseCodes.DisallowedIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used disallowed intents")
+ });
+ return this.destroy({ code });
+ }
+ default: {
+ this.debug([
+ `The gateway closed with an unexpected code ${code}, attempting to ${this.failedToConnectDueToNetworkError ? "reconnect" : "resume"}.`
+ ]);
+ return this.destroy({
+ code,
+ recover: this.failedToConnectDueToNetworkError ? 0 /* Reconnect */ : 1 /* Resume */
+ });
+ }
+ }
+ }
+ debug(messages) {
+ const message = `${messages[0]}${messages.length > 1 ? `
+${messages.slice(1).map((m) => ` ${m}`).join("\n")}` : ""}`;
+ this.emit("debug" /* Debug */, { message });
+ }
+};
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+var SimpleShardingStrategy = class {
+ static {
+ __name(this, "SimpleShardingStrategy");
+ }
+ manager;
+ shards = new import_collection6.Collection();
+ constructor(manager) {
+ this.manager = manager;
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ async spawn(shardIds) {
+ const strategyOptions = await managerToFetchingStrategyOptions(this.manager);
+ for (const shardId of shardIds) {
+ const strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);
+ const shard = new WebSocketShard(strategy, shardId);
+ for (const event of Object.values(WebSocketShardEvents)) {
+ shard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));
+ }
+ this.shards.set(shardId, shard);
+ }
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ async connect() {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.connect());
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ async destroy(options) {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.destroy(options));
+ }
+ await Promise.all(promises);
+ this.shards.clear();
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ async send(shardId, payload) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} not found`);
+ }
+ return shard.send(payload);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ async fetchStatus() {
+ return this.shards.mapValues((shard) => shard.status);
+ }
+};
+
+// src/utils/WorkerBootstrapper.ts
+var import_node_worker_threads3 = require("worker_threads");
+var import_collection7 = require("@discordjs/collection");
+var WorkerBootstrapper = class {
+ static {
+ __name(this, "WorkerBootstrapper");
+ }
+ /**
+ * The data passed to the worker thread
+ */
+ data = import_node_worker_threads3.workerData;
+ /**
+ * The shards that are managed by this worker
+ */
+ shards = new import_collection7.Collection();
+ constructor() {
+ if (import_node_worker_threads3.isMainThread) {
+ throw new Error("Expected WorkerBootstrap to not be used within the main thread");
+ }
+ }
+ /**
+ * Helper method to initiate a shard's connection process
+ */
+ async connect(shardId) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.connect();
+ }
+ /**
+ * Helper method to destroy a shard
+ */
+ async destroy(shardId, options) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.destroy(options);
+ }
+ /**
+ * Helper method to attach event listeners to the parentPort
+ */
+ setupThreadEvents() {
+ import_node_worker_threads3.parentPort.on("messageerror", (err) => {
+ throw err;
+ }).on("message", async (payload) => {
+ switch (payload.op) {
+ case 0 /* Connect */: {
+ await this.connect(payload.shardId);
+ const response = {
+ op: 0 /* Connected */,
+ shardId: payload.shardId
+ };
+ import_node_worker_threads3.parentPort.postMessage(response);
+ break;
+ }
+ case 1 /* Destroy */: {
+ await this.destroy(payload.shardId, payload.options);
+ const response = {
+ op: 1 /* Destroyed */,
+ shardId: payload.shardId
+ };
+ import_node_worker_threads3.parentPort.postMessage(response);
+ break;
+ }
+ case 2 /* Send */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${payload.shardId} does not exist`);
+ }
+ await shard.send(payload.payload);
+ break;
+ }
+ case 3 /* SessionInfoResponse */: {
+ break;
+ }
+ case 4 /* ShardIdentifyResponse */: {
+ break;
+ }
+ case 5 /* FetchStatus */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new Error(`Shard ${payload.shardId} does not exist`);
+ }
+ const response = {
+ op: 6 /* FetchStatusResponse */,
+ status: shard.status,
+ nonce: payload.nonce
+ };
+ import_node_worker_threads3.parentPort.postMessage(response);
+ break;
+ }
+ }
+ });
+ }
+ /**
+ * Bootstraps the worker thread with the provided options
+ */
+ async bootstrap(options = {}) {
+ for (const shardId of this.data.shardIds) {
+ const shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);
+ for (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {
+ shard.on(event, (data) => {
+ const payload = {
+ op: 2 /* Event */,
+ event,
+ data,
+ shardId
+ };
+ import_node_worker_threads3.parentPort.postMessage(payload);
+ });
+ }
+ await options.shardCallback?.(shard);
+ this.shards.set(shardId, shard);
+ }
+ this.setupThreadEvents();
+ const message = {
+ op: 7 /* WorkerReady */
+ };
+ import_node_worker_threads3.parentPort.postMessage(message);
+ }
+};
+
+// src/ws/WebSocketManager.ts
+var import_util3 = require("@discordjs/util");
+var import_async_event_emitter2 = require("@vladfrangu/async_event_emitter");
+var import_v103 = require("discord-api-types/v10");
+var WebSocketManager = class extends import_async_event_emitter2.AsyncEventEmitter {
+ static {
+ __name(this, "WebSocketManager");
+ }
+ /**
+ * The options being used by this manager
+ */
+ options;
+ /**
+ * Internal cache for a GET /gateway/bot result
+ */
+ gatewayInformation = null;
+ /**
+ * Internal cache for the shard ids
+ */
+ shardIds = null;
+ /**
+ * Strategy used to manage shards
+ *
+ * @defaultValue `SimpleShardingStrategy`
+ */
+ strategy;
+ constructor(options) {
+ super();
+ this.options = { ...DefaultWebSocketManagerOptions, ...options };
+ this.strategy = this.options.buildStrategy(this);
+ }
+ /**
+ * Fetches the gateway information from Discord - or returns it from cache if available
+ *
+ * @param force - Whether to ignore the cache and force a fresh fetch
+ */
+ async fetchGatewayInformation(force = false) {
+ if (this.gatewayInformation) {
+ if (this.gatewayInformation.expiresAt <= Date.now()) {
+ this.gatewayInformation = null;
+ } else if (!force) {
+ return this.gatewayInformation.data;
+ }
+ }
+ const data = await this.options.rest.get(import_v103.Routes.gatewayBot());
+ this.gatewayInformation = { data, expiresAt: Date.now() + (data.session_start_limit.reset_after || 5e3) };
+ return this.gatewayInformation.data;
+ }
+ /**
+ * Updates your total shard count on-the-fly, spawning shards as needed
+ *
+ * @param shardCount - The new shard count to use
+ */
+ async updateShardCount(shardCount) {
+ await this.strategy.destroy({ reason: "User is adjusting their shards" });
+ this.options.shardCount = shardCount;
+ const shardIds = await this.getShardIds(true);
+ await this.strategy.spawn(shardIds);
+ return this;
+ }
+ /**
+ * Yields the total number of shards across for your bot, accounting for Discord recommendations
+ */
+ async getShardCount() {
+ if (this.options.shardCount) {
+ return this.options.shardCount;
+ }
+ const shardIds = await this.getShardIds();
+ return Math.max(...shardIds) + 1;
+ }
+ /**
+ * Yields the ids of the shards this manager should manage
+ */
+ async getShardIds(force = false) {
+ if (this.shardIds && !force) {
+ return this.shardIds;
+ }
+ let shardIds;
+ if (this.options.shardIds) {
+ if (Array.isArray(this.options.shardIds)) {
+ shardIds = this.options.shardIds;
+ } else {
+ const { start, end } = this.options.shardIds;
+ shardIds = [...(0, import_util3.range)({ start, end: end + 1 })];
+ }
+ } else {
+ const data = await this.fetchGatewayInformation();
+ shardIds = [...(0, import_util3.range)(this.options.shardCount ?? data.shards)];
+ }
+ this.shardIds = shardIds;
+ return shardIds;
+ }
+ async connect() {
+ const shardCount = await this.getShardCount();
+ const data = await this.fetchGatewayInformation();
+ if (data.session_start_limit.remaining < shardCount) {
+ throw new Error(
+ `Not enough sessions remaining to spawn ${shardCount} shards; only ${data.session_start_limit.remaining} remaining; resets at ${new Date(Date.now() + data.session_start_limit.reset_after).toISOString()}`
+ );
+ }
+ await this.updateShardCount(shardCount);
+ await this.strategy.connect();
+ }
+ destroy(options) {
+ return this.strategy.destroy(options);
+ }
+ send(shardId, payload) {
+ return this.strategy.send(shardId, payload);
+ }
+ fetchStatus() {
+ return this.strategy.fetchStatus();
+ }
+};
+
+// src/index.ts
+var version = "1.0.1";
+// Annotate the CommonJS export names for ESM import in node:
+0 && (module.exports = {
+ CloseCodes,
+ CompressionMethod,
+ DefaultDeviceProperty,
+ DefaultWebSocketManagerOptions,
+ Encoding,
+ ImportantGatewayOpcodes,
+ SimpleContextFetchingStrategy,
+ SimpleIdentifyThrottler,
+ SimpleShardingStrategy,
+ WebSocketManager,
+ WebSocketShard,
+ WebSocketShardDestroyRecovery,
+ WebSocketShardEvents,
+ WebSocketShardStatus,
+ WorkerBootstrapper,
+ WorkerContextFetchingStrategy,
+ WorkerReceivePayloadOp,
+ WorkerSendPayloadOp,
+ WorkerShardingStrategy,
+ getInitialSendRateLimitState,
+ managerToFetchingStrategyOptions,
+ version
+});
+//# sourceMappingURL=index.js.map \ No newline at end of file
diff --git a/node_modules/@discordjs/ws/dist/index.js.map b/node_modules/@discordjs/ws/dist/index.js.map
new file mode 100644
index 0000000..b89bb50
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/index.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/index.ts","../src/strategies/context/IContextFetchingStrategy.ts","../src/strategies/context/SimpleContextFetchingStrategy.ts","../src/strategies/context/WorkerContextFetchingStrategy.ts","../src/strategies/sharding/WorkerShardingStrategy.ts","../src/strategies/sharding/SimpleShardingStrategy.ts","../src/ws/WebSocketShard.ts","../src/utils/constants.ts","../src/throttling/SimpleIdentifyThrottler.ts","../src/utils/WorkerBootstrapper.ts","../src/ws/WebSocketManager.ts"],"sourcesContent":["export * from './strategies/context/IContextFetchingStrategy.js';\nexport * from './strategies/context/SimpleContextFetchingStrategy.js';\nexport * from './strategies/context/WorkerContextFetchingStrategy.js';\n\nexport * from './strategies/sharding/IShardingStrategy.js';\nexport * from './strategies/sharding/SimpleShardingStrategy.js';\nexport * from './strategies/sharding/WorkerShardingStrategy.js';\n\nexport * from './throttling/IIdentifyThrottler.js';\nexport * from './throttling/SimpleIdentifyThrottler.js';\n\nexport * from './utils/constants.js';\nexport * from './utils/WorkerBootstrapper.js';\n\nexport * from './ws/WebSocketManager.js';\nexport * from './ws/WebSocketShard.js';\n\n/**\n * The {@link https://github.com/discordjs/discord.js/blob/main/packages/ws/#readme | @discordjs/ws} version\n * that you are currently using.\n */\n// This needs to explicitly be `string` so it is not typed as a \"const string\" that gets injected by esbuild\nexport const version = '1.0.1' as string;\n","import type { Awaitable } from '@discordjs/util';\nimport type { APIGatewayBotInfo } from 'discord-api-types/v10';\nimport type { SessionInfo, WebSocketManager, WebSocketManagerOptions } from '../../ws/WebSocketManager.js';\n\nexport interface FetchingStrategyOptions\n\textends Omit<\n\t\tWebSocketManagerOptions,\n\t\t| 'buildIdentifyThrottler'\n\t\t| 'buildStrategy'\n\t\t| 'rest'\n\t\t| 'retrieveSessionInfo'\n\t\t| 'shardCount'\n\t\t| 'shardIds'\n\t\t| 'updateSessionInfo'\n\t> {\n\treadonly gatewayInformation: APIGatewayBotInfo;\n\treadonly shardCount: number;\n}\n\n/**\n * Strategies responsible solely for making manager information accessible\n */\nexport interface IContextFetchingStrategy {\n\treadonly options: FetchingStrategyOptions;\n\tretrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;\n\tupdateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;\n\t/**\n\t * Resolves once the given shard should be allowed to identify\n\t * This should correctly handle the signal and reject with an abort error if the operation is aborted.\n\t * Other errors will cause the shard to reconnect.\n\t */\n\twaitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;\n}\n\nexport async function managerToFetchingStrategyOptions(manager: WebSocketManager): Promise<FetchingStrategyOptions> {\n\t/* eslint-disable @typescript-eslint/unbound-method */\n\tconst {\n\t\tbuildIdentifyThrottler,\n\t\tbuildStrategy,\n\t\tretrieveSessionInfo,\n\t\tupdateSessionInfo,\n\t\tshardCount,\n\t\tshardIds,\n\t\trest,\n\t\t...managerOptions\n\t} = manager.options;\n\t/* eslint-enable @typescript-eslint/unbound-method */\n\n\treturn {\n\t\t...managerOptions,\n\t\tgatewayInformation: await manager.fetchGatewayInformation(),\n\t\tshardCount: await manager.getShardCount(),\n\t};\n}\n","import type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class SimpleContextFetchingStrategy implements IContextFetchingStrategy {\n\t// This strategy assumes every shard is running under the same process - therefore we need a single\n\t// IdentifyThrottler per manager.\n\tprivate static throttlerCache = new WeakMap<WebSocketManager, IIdentifyThrottler>();\n\n\tprivate static async ensureThrottler(manager: WebSocketManager): Promise<IIdentifyThrottler> {\n\t\tconst throttler = SimpleContextFetchingStrategy.throttlerCache.get(manager);\n\t\tif (throttler) {\n\t\t\treturn throttler;\n\t\t}\n\n\t\tconst newThrottler = await manager.options.buildIdentifyThrottler(manager);\n\t\tSimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);\n\n\t\treturn newThrottler;\n\t}\n\n\tpublic constructor(private readonly manager: WebSocketManager, public readonly options: FetchingStrategyOptions) {}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\treturn this.manager.options.retrieveSessionInfo(shardId);\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\treturn this.manager.options.updateSessionInfo(shardId, sessionInfo);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst throttler = await SimpleContextFetchingStrategy.ensureThrottler(this.manager);\n\t\tawait throttler.waitForIdentify(shardId, signal);\n\t}\n}\n","import { isMainThread, parentPort } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { SessionInfo } from '../../ws/WebSocketManager.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../sharding/WorkerShardingStrategy.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class WorkerContextFetchingStrategy implements IContextFetchingStrategy {\n\tprivate readonly sessionPromises = new Collection<number, (session: SessionInfo | null) => void>();\n\n\tprivate readonly waitForIdentifyPromises = new Collection<\n\t\tnumber,\n\t\t{ reject(error: unknown): void; resolve(): void; signal: AbortSignal }\n\t>();\n\n\tpublic constructor(public readonly options: FetchingStrategyOptions) {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Cannot instantiate WorkerContextFetchingStrategy on the main thread');\n\t\t}\n\n\t\tparentPort!.on('message', (payload: WorkerSendPayload) => {\n\t\t\tif (payload.op === WorkerSendPayloadOp.SessionInfoResponse) {\n\t\t\t\tthis.sessionPromises.get(payload.nonce)?.(payload.session);\n\t\t\t\tthis.sessionPromises.delete(payload.nonce);\n\t\t\t}\n\n\t\t\tif (payload.op === WorkerSendPayloadOp.ShardIdentifyResponse) {\n\t\t\t\tconst promise = this.waitForIdentifyPromises.get(payload.nonce);\n\t\t\t\tif (payload.ok) {\n\t\t\t\t\tpromise?.resolve();\n\t\t\t\t} else {\n\t\t\t\t\t// We need to make sure we reject with an abort error\n\t\t\t\t\tpromise?.reject(promise.signal.reason);\n\t\t\t\t}\n\n\t\t\t\tthis.waitForIdentifyPromises.delete(payload.nonce);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\tconst nonce = Math.random();\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.RetrieveSessionInfo,\n\t\t\tshardId,\n\t\t\tnonce,\n\t\t};\n\t\t// eslint-disable-next-line no-promise-executor-return\n\t\tconst promise = new Promise<SessionInfo | null>((resolve) => this.sessionPromises.set(nonce, resolve));\n\t\tparentPort!.postMessage(payload);\n\t\treturn promise;\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.UpdateSessionInfo,\n\t\t\tshardId,\n\t\t\tsession: sessionInfo,\n\t\t};\n\t\tparentPort!.postMessage(payload);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst nonce = Math.random();\n\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WaitForIdentify,\n\t\t\tnonce,\n\t\t\tshardId,\n\t\t};\n\t\tconst promise = new Promise<void>((resolve, reject) =>\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tthis.waitForIdentifyPromises.set(nonce, { signal, resolve, reject }),\n\t\t);\n\n\t\tparentPort!.postMessage(payload);\n\n\t\tconst listener = () => {\n\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\top: WorkerReceivePayloadOp.CancelIdentify,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\tparentPort!.postMessage(payload);\n\t\t};\n\n\t\tsignal.addEventListener('abort', listener);\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} finally {\n\t\t\tsignal.removeEventListener('abort', listener);\n\t\t}\n\t}\n}\n","import { once } from 'node:events';\nimport { join, isAbsolute, resolve } from 'node:path';\nimport { Worker } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type {\n\tWebSocketShardDestroyOptions,\n\tWebSocketShardEvents,\n\tWebSocketShardStatus,\n} from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions, type FetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\nexport interface WorkerData extends FetchingStrategyOptions {\n\tshardIds: number[];\n}\n\nexport enum WorkerSendPayloadOp {\n\tConnect,\n\tDestroy,\n\tSend,\n\tSessionInfoResponse,\n\tShardIdentifyResponse,\n\tFetchStatus,\n}\n\nexport type WorkerSendPayload =\n\t| { nonce: number; ok: boolean; op: WorkerSendPayloadOp.ShardIdentifyResponse }\n\t| { nonce: number; op: WorkerSendPayloadOp.FetchStatus; shardId: number }\n\t| { nonce: number; op: WorkerSendPayloadOp.SessionInfoResponse; session: SessionInfo | null }\n\t| { op: WorkerSendPayloadOp.Connect; shardId: number }\n\t| { op: WorkerSendPayloadOp.Destroy; options?: WebSocketShardDestroyOptions; shardId: number }\n\t| { op: WorkerSendPayloadOp.Send; payload: GatewaySendPayload; shardId: number };\n\nexport enum WorkerReceivePayloadOp {\n\tConnected,\n\tDestroyed,\n\tEvent,\n\tRetrieveSessionInfo,\n\tUpdateSessionInfo,\n\tWaitForIdentify,\n\tFetchStatusResponse,\n\tWorkerReady,\n\tCancelIdentify,\n}\n\nexport type WorkerReceivePayload =\n\t// Can't seem to get a type-safe union based off of the event, so I'm sadly leaving data as any for now\n\t| { data: any; event: WebSocketShardEvents; op: WorkerReceivePayloadOp.Event; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.CancelIdentify }\n\t| { nonce: number; op: WorkerReceivePayloadOp.FetchStatusResponse; status: WebSocketShardStatus }\n\t| { nonce: number; op: WorkerReceivePayloadOp.RetrieveSessionInfo; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.WaitForIdentify; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Connected; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Destroyed; shardId: number }\n\t| { op: WorkerReceivePayloadOp.UpdateSessionInfo; session: SessionInfo | null; shardId: number }\n\t| { op: WorkerReceivePayloadOp.WorkerReady };\n\n/**\n * Options for a {@link WorkerShardingStrategy}\n */\nexport interface WorkerShardingStrategyOptions {\n\t/**\n\t * Dictates how many shards should be spawned per worker thread.\n\t */\n\tshardsPerWorker: number | 'all';\n\t/**\n\t * Path to the worker file to use. The worker requires quite a bit of setup, it is recommended you leverage the {@link WorkerBootstrapper} class.\n\t */\n\tworkerPath?: string;\n}\n\n/**\n * Strategy used to spawn threads in worker_threads\n */\nexport class WorkerShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly options: WorkerShardingStrategyOptions;\n\n\t#workers: Worker[] = [];\n\n\treadonly #workerByShardId = new Collection<number, Worker>();\n\n\tprivate readonly connectPromises = new Collection<number, () => void>();\n\n\tprivate readonly destroyPromises = new Collection<number, () => void>();\n\n\tprivate readonly fetchStatusPromises = new Collection<number, (status: WebSocketShardStatus) => void>();\n\n\tprivate readonly waitForIdentifyControllers = new Collection<number, AbortController>();\n\n\tprivate throttler?: IIdentifyThrottler;\n\n\tpublic constructor(manager: WebSocketManager, options: WorkerShardingStrategyOptions) {\n\t\tthis.manager = manager;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst shardsPerWorker = this.options.shardsPerWorker === 'all' ? shardIds.length : this.options.shardsPerWorker;\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tconst loops = Math.ceil(shardIds.length / shardsPerWorker);\n\t\tconst promises: Promise<void>[] = [];\n\n\t\tfor (let idx = 0; idx < loops; idx++) {\n\t\t\tconst slice = shardIds.slice(idx * shardsPerWorker, (idx + 1) * shardsPerWorker);\n\t\t\tconst workerData: WorkerData = {\n\t\t\t\t...strategyOptions,\n\t\t\t\tshardIds: slice,\n\t\t\t};\n\n\t\t\tpromises.push(this.setupWorker(workerData));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Connect,\n\t\t\t\tshardId,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<void>((resolve) => this.connectPromises.set(shardId, resolve));\n\t\t\tworker.postMessage(payload);\n\t\t\tpromises.push(promise);\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options: Omit<WebSocketShardDestroyOptions, 'recover'> = {}) {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Destroy,\n\t\t\t\tshardId,\n\t\t\t\toptions,\n\t\t\t};\n\n\t\t\tpromises.push(\n\t\t\t\t// eslint-disable-next-line no-promise-executor-return, promise/prefer-await-to-then\n\t\t\t\tnew Promise<void>((resolve) => this.destroyPromises.set(shardId, resolve)).then(async () => worker.terminate()),\n\t\t\t);\n\t\t\tworker.postMessage(payload);\n\t\t}\n\n\t\tthis.#workers = [];\n\t\tthis.#workerByShardId.clear();\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic send(shardId: number, data: GatewaySendPayload) {\n\t\tconst worker = this.#workerByShardId.get(shardId);\n\t\tif (!worker) {\n\t\t\tthrow new Error(`No worker found for shard ${shardId}`);\n\t\t}\n\n\t\tconst payload: WorkerSendPayload = {\n\t\t\top: WorkerSendPayloadOp.Send,\n\t\t\tshardId,\n\t\t\tpayload: data,\n\t\t};\n\t\tworker.postMessage(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\tconst statuses = new Collection<number, WebSocketShardStatus>();\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst nonce = Math.random();\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.FetchStatus,\n\t\t\t\tshardId,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<WebSocketShardStatus>((resolve) => this.fetchStatusPromises.set(nonce, resolve));\n\t\t\tworker.postMessage(payload);\n\n\t\t\tconst status = await promise;\n\t\t\tstatuses.set(shardId, status);\n\t\t}\n\n\t\treturn statuses;\n\t}\n\n\tprivate async setupWorker(workerData: WorkerData) {\n\t\tconst worker = new Worker(this.resolveWorkerPath(), { workerData });\n\n\t\tawait once(worker, 'online');\n\t\t// We do this in case the user has any potentially long running code in their worker\n\t\tawait this.waitForWorkerReady(worker);\n\n\t\tworker\n\t\t\t.on('error', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerReceivePayload) => this.onMessage(worker, payload));\n\n\t\tthis.#workers.push(worker);\n\t\tfor (const shardId of workerData.shardIds) {\n\t\t\tthis.#workerByShardId.set(shardId, worker);\n\t\t}\n\t}\n\n\tprivate resolveWorkerPath(): string {\n\t\tconst path = this.options.workerPath;\n\n\t\tif (!path) {\n\t\t\treturn join(__dirname, 'defaultWorker.js');\n\t\t}\n\n\t\tif (isAbsolute(path)) {\n\t\t\treturn path;\n\t\t}\n\n\t\tif (/^\\.\\.?[/\\\\]/.test(path)) {\n\t\t\treturn resolve(path);\n\t\t}\n\n\t\ttry {\n\t\t\treturn require.resolve(path);\n\t\t} catch {\n\t\t\treturn resolve(path);\n\t\t}\n\t}\n\n\tprivate async waitForWorkerReady(worker: Worker): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst handler = (payload: WorkerReceivePayload) => {\n\t\t\t\tif (payload.op === WorkerReceivePayloadOp.WorkerReady) {\n\t\t\t\t\tresolve();\n\t\t\t\t\tworker.off('message', handler);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tworker.on('message', handler);\n\t\t});\n\t}\n\n\tprivate async onMessage(worker: Worker, payload: WorkerReceivePayload) {\n\t\tswitch (payload.op) {\n\t\t\tcase WorkerReceivePayloadOp.Connected: {\n\t\t\t\tthis.connectPromises.get(payload.shardId)?.();\n\t\t\t\tthis.connectPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Destroyed: {\n\t\t\t\tthis.destroyPromises.get(payload.shardId)?.();\n\t\t\t\tthis.destroyPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Event: {\n\t\t\t\tthis.manager.emit(payload.event, { ...payload.data, shardId: payload.shardId });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.RetrieveSessionInfo: {\n\t\t\t\tconst session = await this.manager.options.retrieveSessionInfo(payload.shardId);\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.SessionInfoResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tsession,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.UpdateSessionInfo: {\n\t\t\t\tawait this.manager.options.updateSessionInfo(payload.shardId, payload.session);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WaitForIdentify: {\n\t\t\t\tconst throttler = await this.ensureThrottler();\n\n\t\t\t\t// If this rejects it means we aborted, in which case we reply elsewhere.\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.waitForIdentifyControllers.set(payload.nonce, controller);\n\t\t\t\t\tawait throttler.waitForIdentify(payload.shardId, controller.signal);\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: true,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.FetchStatusResponse: {\n\t\t\t\tthis.fetchStatusPromises.get(payload.nonce)?.(payload.status);\n\t\t\t\tthis.fetchStatusPromises.delete(payload.nonce);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WorkerReady: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.CancelIdentify: {\n\t\t\t\tthis.waitForIdentifyControllers.get(payload.nonce)?.abort();\n\t\t\t\tthis.waitForIdentifyControllers.delete(payload.nonce);\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: false,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async ensureThrottler(): Promise<IIdentifyThrottler> {\n\t\tthis.throttler ??= await this.manager.options.buildIdentifyThrottler(this.manager);\n\t\treturn this.throttler;\n\t}\n}\n","import { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { WebSocketManager } from '../../ws/WebSocketManager.js';\nimport { WebSocketShard, WebSocketShardEvents, type WebSocketShardDestroyOptions } from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport { SimpleContextFetchingStrategy } from '../context/SimpleContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\n/**\n * Simple strategy that just spawns shards in the current process\n */\nexport class SimpleShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor(manager: WebSocketManager) {\n\t\tthis.manager = manager;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tfor (const shardId of shardIds) {\n\t\t\tconst strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);\n\t\t\tconst shard = new WebSocketShard(strategy, shardId);\n\t\t\tfor (const event of Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Intentional\n\t\t\t\tshard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));\n\t\t\t}\n\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.connect());\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.destroy(options));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t\tthis.shards.clear();\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic async send(shardId: number, payload: GatewaySendPayload) {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} not found`);\n\t\t}\n\n\t\treturn shard.send(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\treturn this.shards.mapValues((shard) => shard.status);\n\t}\n}\n","/* eslint-disable id-length */\nimport { Buffer } from 'node:buffer';\nimport { once } from 'node:events';\nimport { clearInterval, clearTimeout, setInterval, setTimeout } from 'node:timers';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { URLSearchParams } from 'node:url';\nimport { TextDecoder } from 'node:util';\nimport { inflate } from 'node:zlib';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tGatewayCloseCodes,\n\tGatewayDispatchEvents,\n\tGatewayOpcodes,\n\ttype GatewayDispatchPayload,\n\ttype GatewayIdentifyData,\n\ttype GatewayReadyDispatchData,\n\ttype GatewayReceivePayload,\n\ttype GatewaySendPayload,\n} from 'discord-api-types/v10';\nimport { WebSocket, type Data } from 'ws';\nimport type { Inflate } from 'zlib-sync';\nimport type { IContextFetchingStrategy } from '../strategies/context/IContextFetchingStrategy.js';\nimport { ImportantGatewayOpcodes, getInitialSendRateLimitState } from '../utils/constants.js';\nimport type { SessionInfo } from './WebSocketManager.js';\n\n// eslint-disable-next-line promise/prefer-await-to-then\nconst getZlibSync = lazy(async () => import('zlib-sync').then((mod) => mod.default).catch(() => null));\n\nexport enum WebSocketShardEvents {\n\tClosed = 'closed',\n\tDebug = 'debug',\n\tDispatch = 'dispatch',\n\tError = 'error',\n\tHeartbeatComplete = 'heartbeat',\n\tHello = 'hello',\n\tReady = 'ready',\n\tResumed = 'resumed',\n}\n\nexport enum WebSocketShardStatus {\n\tIdle,\n\tConnecting,\n\tResuming,\n\tReady,\n}\n\nexport enum WebSocketShardDestroyRecovery {\n\tReconnect,\n\tResume,\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport type WebSocketShardEventsMap = {\n\t[WebSocketShardEvents.Closed]: [{ code: number }];\n\t[WebSocketShardEvents.Debug]: [payload: { message: string }];\n\t[WebSocketShardEvents.Dispatch]: [payload: { data: GatewayDispatchPayload }];\n\t[WebSocketShardEvents.Error]: [payload: { error: Error }];\n\t[WebSocketShardEvents.Hello]: [];\n\t[WebSocketShardEvents.Ready]: [payload: { data: GatewayReadyDispatchData }];\n\t[WebSocketShardEvents.Resumed]: [];\n\t[WebSocketShardEvents.HeartbeatComplete]: [payload: { ackAt: number; heartbeatAt: number; latency: number }];\n};\n\nexport interface WebSocketShardDestroyOptions {\n\tcode?: number;\n\treason?: string;\n\trecover?: WebSocketShardDestroyRecovery;\n}\n\nexport enum CloseCodes {\n\tNormal = 1_000,\n\tResuming = 4_200,\n}\n\nexport interface SendRateLimitState {\n\tremaining: number;\n\tresetAt: number;\n}\n\n// TODO(vladfrangu): enable this once https://github.com/oven-sh/bun/issues/3392 is solved\n// const WebSocketConstructor: typeof WebSocket = shouldUseGlobalFetchAndWebSocket()\n// \t? (globalThis as any).WebSocket\n// \t: WebSocket;\nconst WebSocketConstructor: typeof WebSocket = WebSocket;\n\nexport class WebSocketShard extends AsyncEventEmitter<WebSocketShardEventsMap> {\n\tprivate connection: WebSocket | null = null;\n\n\tprivate useIdentifyCompress = false;\n\n\tprivate inflate: Inflate | null = null;\n\n\tprivate readonly textDecoder = new TextDecoder();\n\n\tprivate replayedEvents = 0;\n\n\tprivate isAck = true;\n\n\tprivate sendRateLimitState: SendRateLimitState = getInitialSendRateLimitState();\n\n\tprivate initialHeartbeatTimeoutController: AbortController | null = null;\n\n\tprivate heartbeatInterval: NodeJS.Timer | null = null;\n\n\tprivate lastHeartbeatAt = -1;\n\n\t// Indicates whether the shard has already resolved its original connect() call\n\tprivate initialConnectResolved = false;\n\n\t// Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)\n\tprivate failedToConnectDueToNetworkError = false;\n\n\tprivate readonly sendQueue = new AsyncQueue();\n\n\tprivate readonly timeoutAbortControllers = new Collection<WebSocketShardEvents, AbortController>();\n\n\tprivate readonly strategy: IContextFetchingStrategy;\n\n\tpublic readonly id: number;\n\n\t#status: WebSocketShardStatus = WebSocketShardStatus.Idle;\n\n\tpublic get status(): WebSocketShardStatus {\n\t\treturn this.#status;\n\t}\n\n\tpublic constructor(strategy: IContextFetchingStrategy, id: number) {\n\t\tsuper();\n\t\tthis.strategy = strategy;\n\t\tthis.id = id;\n\t}\n\n\tpublic async connect() {\n\t\tconst controller = new AbortController();\n\t\tlet promise;\n\n\t\tif (!this.initialConnectResolved) {\n\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\tpromise = Promise.race([\n\t\t\t\tonce(this, WebSocketShardEvents.Ready, { signal: controller.signal }),\n\t\t\t\tonce(this, WebSocketShardEvents.Resumed, { signal: controller.signal }),\n\t\t\t]);\n\t\t}\n\n\t\tvoid this.internalConnect();\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} catch ({ error }: any) {\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// cleanup hanging listeners\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.initialConnectResolved = true;\n\t}\n\n\tprivate async internalConnect() {\n\t\tif (this.#status !== WebSocketShardStatus.Idle) {\n\t\t\tthrow new Error(\"Tried to connect a shard that wasn't idle\");\n\t\t}\n\n\t\tconst { version, encoding, compression } = this.strategy.options;\n\t\tconst params = new URLSearchParams({ v: version, encoding });\n\t\tif (compression) {\n\t\t\tconst zlib = await getZlibSync();\n\t\t\tif (zlib) {\n\t\t\t\tparams.append('compress', compression);\n\t\t\t\tthis.inflate = new zlib.Inflate({\n\t\t\t\t\tchunkSize: 65_535,\n\t\t\t\t\tto: 'string',\n\t\t\t\t});\n\t\t\t} else if (!this.useIdentifyCompress) {\n\t\t\t\tthis.useIdentifyCompress = true;\n\t\t\t\tconsole.warn(\n\t\t\t\t\t'WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress',\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tconst url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;\n\n\t\tthis.debug([`Connecting to ${url}`]);\n\n\t\tconst connection = new WebSocketConstructor(url, {\n\t\t\thandshakeTimeout: this.strategy.options.handshakeTimeout ?? undefined,\n\t\t});\n\n\t\tconnection.binaryType = 'arraybuffer';\n\n\t\tconnection.onmessage = (event) => {\n\t\t\tvoid this.onMessage(event.data, event.data instanceof ArrayBuffer);\n\t\t};\n\n\t\tconnection.onerror = (event) => {\n\t\t\tthis.onError(event.error);\n\t\t};\n\n\t\tconnection.onclose = (event) => {\n\t\t\tvoid this.onClose(event.code);\n\t\t};\n\n\t\tthis.connection = connection;\n\n\t\tthis.#status = WebSocketShardStatus.Connecting;\n\n\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\n\t\tconst { ok } = await this.waitForEvent(WebSocketShardEvents.Hello, this.strategy.options.helloTimeout);\n\t\tif (!ok) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (session?.shardCount === this.strategy.options.shardCount) {\n\t\t\tawait this.resume(session);\n\t\t} else {\n\t\t\tawait this.identify();\n\t\t}\n\t}\n\n\tpublic async destroy(options: WebSocketShardDestroyOptions = {}) {\n\t\tif (this.#status === WebSocketShardStatus.Idle) {\n\t\t\tthis.debug(['Tried to destroy a shard that was idle']);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!options.code) {\n\t\t\toptions.code = options.recover === WebSocketShardDestroyRecovery.Resume ? CloseCodes.Resuming : CloseCodes.Normal;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Destroying shard',\n\t\t\t`Reason: ${options.reason ?? 'none'}`,\n\t\t\t`Code: ${options.code}`,\n\t\t\t`Recover: ${options.recover === undefined ? 'none' : WebSocketShardDestroyRecovery[options.recover]!}`,\n\t\t]);\n\n\t\t// Reset state\n\t\tthis.isAck = true;\n\t\tif (this.heartbeatInterval) {\n\t\t\tclearInterval(this.heartbeatInterval);\n\t\t}\n\n\t\tif (this.initialHeartbeatTimeoutController) {\n\t\t\tthis.initialHeartbeatTimeoutController.abort();\n\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t}\n\n\t\tthis.lastHeartbeatAt = -1;\n\n\t\tfor (const controller of this.timeoutAbortControllers.values()) {\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.timeoutAbortControllers.clear();\n\n\t\tthis.failedToConnectDueToNetworkError = false;\n\n\t\t// Clear session state if applicable\n\t\tif (options.recover !== WebSocketShardDestroyRecovery.Resume) {\n\t\t\tawait this.strategy.updateSessionInfo(this.id, null);\n\t\t}\n\n\t\tif (this.connection) {\n\t\t\t// No longer need to listen to messages\n\t\t\tthis.connection.onmessage = null;\n\t\t\t// Prevent a reconnection loop by unbinding the main close event\n\t\t\tthis.connection.onclose = null;\n\n\t\t\tconst shouldClose = this.connection.readyState === WebSocket.OPEN;\n\n\t\t\tthis.debug([\n\t\t\t\t'Connection status during destroy',\n\t\t\t\t`Needs closing: ${shouldClose}`,\n\t\t\t\t`Ready state: ${this.connection.readyState}`,\n\t\t\t]);\n\n\t\t\tif (shouldClose) {\n\t\t\t\tlet outerResolve: () => void;\n\t\t\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\t\t\touterResolve = resolve;\n\t\t\t\t});\n\n\t\t\t\tthis.connection.onclose = outerResolve!;\n\n\t\t\t\tthis.connection.close(options.code, options.reason);\n\n\t\t\t\tawait promise;\n\t\t\t\tthis.emit(WebSocketShardEvents.Closed, { code: options.code });\n\t\t\t}\n\n\t\t\t// Lastly, remove the error event.\n\t\t\t// Doing this earlier would cause a hard crash in case an error event fired on our `close` call\n\t\t\tthis.connection.onerror = null;\n\t\t} else {\n\t\t\tthis.debug(['Destroying a shard that has no connection; please open an issue on GitHub']);\n\t\t}\n\n\t\tthis.#status = WebSocketShardStatus.Idle;\n\n\t\tif (options.recover !== undefined) {\n\t\t\t// There's cases (like no internet connection) where we immediately fail to connect,\n\t\t\t// causing a very fast and draining reconnection loop.\n\t\t\tawait sleep(500);\n\t\t\treturn this.internalConnect();\n\t\t}\n\t}\n\n\tprivate async waitForEvent(event: WebSocketShardEvents, timeoutDuration?: number | null): Promise<{ ok: boolean }> {\n\t\tthis.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : 'indefinitely'}`]);\n\t\tconst timeoutController = new AbortController();\n\t\tconst timeout = timeoutDuration ? setTimeout(() => timeoutController.abort(), timeoutDuration).unref() : null;\n\n\t\tthis.timeoutAbortControllers.set(event, timeoutController);\n\n\t\tconst closeController = new AbortController();\n\n\t\ttry {\n\t\t\t// If the first promise resolves, all is well. If the 2nd promise resolves,\n\t\t\t// the shard has meanwhile closed. In that case, a destroy is already ongoing, so we just need to\n\t\t\t// return false. Meanwhile, if something rejects (error event) or the first controller is aborted,\n\t\t\t// we enter the catch block and trigger a destroy there.\n\t\t\tconst closed = await Promise.race<boolean>([\n\t\t\t\tonce(this, event, { signal: timeoutController.signal }).then(() => false),\n\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: closeController.signal }).then(() => true),\n\t\t\t]);\n\n\t\t\treturn { ok: !closed };\n\t\t} catch {\n\t\t\t// If we're here because of other reasons, we need to destroy the shard\n\t\t\tvoid this.destroy({\n\t\t\t\tcode: CloseCodes.Normal,\n\t\t\t\treason: 'Something timed out or went wrong while waiting for an event',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t});\n\n\t\t\treturn { ok: false };\n\t\t} finally {\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\n\t\t\tthis.timeoutAbortControllers.delete(event);\n\n\t\t\t// Clean up the close listener to not leak memory\n\t\t\tif (!closeController.signal.aborted) {\n\t\t\t\tcloseController.abort();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async send(payload: GatewaySendPayload): Promise<void> {\n\t\tif (!this.connection) {\n\t\t\tthrow new Error(\"WebSocketShard wasn't connected\");\n\t\t}\n\n\t\tif (this.#status !== WebSocketShardStatus.Ready && !ImportantGatewayOpcodes.has(payload.op)) {\n\t\t\tthis.debug(['Tried to send a non-crucial payload before the shard was ready, waiting']);\n\t\t\t// This will throw if the shard throws an error event in the meantime, just requeue the payload\n\t\t\ttry {\n\t\t\t\tawait once(this, WebSocketShardEvents.Ready);\n\t\t\t} catch {\n\t\t\t\treturn this.send(payload);\n\t\t\t}\n\t\t}\n\n\t\tawait this.sendQueue.wait();\n\n\t\tif (--this.sendRateLimitState.remaining <= 0) {\n\t\t\tconst now = Date.now();\n\n\t\t\tif (this.sendRateLimitState.resetAt > now) {\n\t\t\t\tconst sleepFor = this.sendRateLimitState.resetAt - now;\n\n\t\t\t\tthis.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);\n\t\t\t\tconst controller = new AbortController();\n\n\t\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\t\tconst interrupted = await Promise.race([\n\t\t\t\t\tsleep(sleepFor).then(() => false),\n\t\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: controller.signal }).then(() => true),\n\t\t\t\t]);\n\n\t\t\t\tif (interrupted) {\n\t\t\t\t\tthis.debug(['Connection closed while waiting for the send rate limit to reset, re-queueing payload']);\n\t\t\t\t\tthis.sendQueue.shift();\n\t\t\t\t\treturn this.send(payload);\n\t\t\t\t}\n\n\t\t\t\t// This is so the listener from the `once` call is removed\n\t\t\t\tcontroller.abort();\n\t\t\t}\n\n\t\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\t\t}\n\n\t\tthis.sendQueue.shift();\n\t\tthis.connection.send(JSON.stringify(payload));\n\t}\n\n\tprivate async identify() {\n\t\tthis.debug(['Waiting for identify throttle']);\n\n\t\tconst controller = new AbortController();\n\t\tconst closeHandler = () => {\n\t\t\tcontroller.abort();\n\t\t};\n\n\t\tthis.on(WebSocketShardEvents.Closed, closeHandler);\n\n\t\ttry {\n\t\t\tawait this.strategy.waitForIdentify(this.id, controller.signal);\n\t\t} catch {\n\t\t\tif (controller.signal.aborted) {\n\t\t\t\tthis.debug(['Was waiting for an identify, but the shard closed in the meantime']);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.debug([\n\t\t\t\t'IContextFetchingStrategy#waitForIdentify threw an unknown error.',\n\t\t\t\t\"If you're using a custom strategy, this is probably nothing to worry about.\",\n\t\t\t\t\"If you're not, please open an issue on GitHub.\",\n\t\t\t]);\n\n\t\t\tawait this.destroy({\n\t\t\t\treason: 'Identify throttling logic failed',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t});\n\t\t} finally {\n\t\t\tthis.off(WebSocketShardEvents.Closed, closeHandler);\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Identifying',\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t\t`shard count: ${this.strategy.options.shardCount}`,\n\t\t\t`intents: ${this.strategy.options.intents}`,\n\t\t\t`compression: ${this.inflate ? 'zlib-stream' : this.useIdentifyCompress ? 'identify' : 'none'}`,\n\t\t]);\n\n\t\tconst d: GatewayIdentifyData = {\n\t\t\ttoken: this.strategy.options.token,\n\t\t\tproperties: this.strategy.options.identifyProperties,\n\t\t\tintents: this.strategy.options.intents,\n\t\t\tcompress: this.useIdentifyCompress,\n\t\t\tshard: [this.id, this.strategy.options.shardCount],\n\t\t};\n\n\t\tif (this.strategy.options.largeThreshold) {\n\t\t\td.large_threshold = this.strategy.options.largeThreshold;\n\t\t}\n\n\t\tif (this.strategy.options.initialPresence) {\n\t\t\td.presence = this.strategy.options.initialPresence;\n\t\t}\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Identify,\n\t\t\td,\n\t\t});\n\n\t\tawait this.waitForEvent(WebSocketShardEvents.Ready, this.strategy.options.readyTimeout);\n\t}\n\n\tprivate async resume(session: SessionInfo) {\n\t\tthis.debug([\n\t\t\t'Resuming session',\n\t\t\t`resume url: ${session.resumeURL}`,\n\t\t\t`sequence: ${session.sequence}`,\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t]);\n\n\t\tthis.#status = WebSocketShardStatus.Resuming;\n\t\tthis.replayedEvents = 0;\n\t\treturn this.send({\n\t\t\top: GatewayOpcodes.Resume,\n\t\t\td: {\n\t\t\t\ttoken: this.strategy.options.token,\n\t\t\t\tseq: session.sequence,\n\t\t\t\tsession_id: session.sessionId,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async heartbeat(requested = false) {\n\t\tif (!this.isAck && !requested) {\n\t\t\treturn this.destroy({ reason: 'Zombie connection', recover: WebSocketShardDestroyRecovery.Resume });\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Heartbeat,\n\t\t\td: session?.sequence ?? null,\n\t\t});\n\n\t\tthis.lastHeartbeatAt = Date.now();\n\t\tthis.isAck = false;\n\t}\n\n\tprivate async unpackMessage(data: Data, isBinary: boolean): Promise<GatewayReceivePayload | null> {\n\t\t// Deal with no compression\n\t\tif (!isBinary) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(data as string) as GatewayReceivePayload;\n\t\t\t} catch {\n\t\t\t\t// This is a non-JSON payload / (at the time of writing this comment) emitted by bun wrongly interpreting custom close codes https://github.com/oven-sh/bun/issues/3392\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tconst decompressable = new Uint8Array(data as ArrayBuffer);\n\n\t\t// Deal with identify compress\n\t\tif (this.useIdentifyCompress) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-callbacks\n\t\t\t\tinflate(decompressable, { chunkSize: 65_535 }, (err, result) => {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve(JSON.parse(this.textDecoder.decode(result)) as GatewayReceivePayload);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\t// Deal with gw wide zlib-stream compression\n\t\tif (this.inflate) {\n\t\t\tconst l = decompressable.length;\n\t\t\tconst flush =\n\t\t\t\tl >= 4 &&\n\t\t\t\tdecompressable[l - 4] === 0x00 &&\n\t\t\t\tdecompressable[l - 3] === 0x00 &&\n\t\t\t\tdecompressable[l - 2] === 0xff &&\n\t\t\t\tdecompressable[l - 1] === 0xff;\n\n\t\t\tconst zlib = (await getZlibSync())!;\n\t\t\tthis.inflate.push(Buffer.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);\n\n\t\t\tif (this.inflate.err) {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ''}`),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!flush) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { result } = this.inflate;\n\t\t\tif (!result) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn JSON.parse(typeof result === 'string' ? result : this.textDecoder.decode(result)) as GatewayReceivePayload;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Received a message we were unable to decompress',\n\t\t\t`isBinary: ${isBinary.toString()}`,\n\t\t\t`useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,\n\t\t\t`inflate: ${Boolean(this.inflate).toString()}`,\n\t\t]);\n\n\t\treturn null;\n\t}\n\n\tprivate async onMessage(data: Data, isBinary: boolean) {\n\t\tconst payload = await this.unpackMessage(data, isBinary);\n\t\tif (!payload) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (payload.op) {\n\t\t\tcase GatewayOpcodes.Dispatch: {\n\t\t\t\tif (this.#status === WebSocketShardStatus.Resuming) {\n\t\t\t\t\tthis.replayedEvents++;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line sonarjs/no-nested-switch\n\t\t\t\tswitch (payload.t) {\n\t\t\t\t\tcase GatewayDispatchEvents.Ready: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\n\t\t\t\t\t\tconst session = {\n\t\t\t\t\t\t\tsequence: payload.s,\n\t\t\t\t\t\t\tsessionId: payload.d.session_id,\n\t\t\t\t\t\t\tshardId: this.id,\n\t\t\t\t\t\t\tshardCount: this.strategy.options.shardCount,\n\t\t\t\t\t\t\tresumeURL: payload.d.resume_gateway_url,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, session);\n\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Ready, { data: payload.d });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase GatewayDispatchEvents.Resumed: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\t\t\t\t\t\tthis.debug([`Resumed and replayed ${this.replayedEvents} events`]);\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Resumed);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (session) {\n\t\t\t\t\tif (payload.s > session.sequence) {\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.debug([\n\t\t\t\t\t\t`Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`,\n\t\t\t\t\t]);\n\t\t\t\t}\n\n\t\t\t\tthis.emit(WebSocketShardEvents.Dispatch, { data: payload });\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Heartbeat: {\n\t\t\t\tawait this.heartbeat(true);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Reconnect: {\n\t\t\t\tawait this.destroy({\n\t\t\t\t\treason: 'Told to reconnect by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.InvalidSession: {\n\t\t\t\tthis.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (payload.d && session) {\n\t\t\t\t\tawait this.resume(session);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.destroy({\n\t\t\t\t\t\treason: 'Invalid session',\n\t\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Hello: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Hello);\n\t\t\t\tconst jitter = Math.random();\n\t\t\t\tconst firstWait = Math.floor(payload.d.heartbeat_interval * jitter);\n\t\t\t\tthis.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = controller;\n\t\t\t\t\tawait sleep(firstWait, undefined, { signal: controller.signal });\n\t\t\t\t} catch {\n\t\t\t\t\tthis.debug(['Cancelled initial heartbeat due to #destroy being called']);\n\t\t\t\t\treturn;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t\t\t}\n\n\t\t\t\tawait this.heartbeat();\n\n\t\t\t\tthis.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);\n\t\t\t\tthis.heartbeatInterval = setInterval(() => void this.heartbeat(), payload.d.heartbeat_interval);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.HeartbeatAck: {\n\t\t\t\tthis.isAck = true;\n\n\t\t\t\tconst ackAt = Date.now();\n\t\t\t\tthis.emit(WebSocketShardEvents.HeartbeatComplete, {\n\t\t\t\t\tackAt,\n\t\t\t\t\theartbeatAt: this.lastHeartbeatAt,\n\t\t\t\t\tlatency: ackAt - this.lastHeartbeatAt,\n\t\t\t\t});\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onError(error: Error) {\n\t\tif ('code' in error && ['ECONNRESET', 'ECONNREFUSED'].includes(error.code as string)) {\n\t\t\tthis.debug(['Failed to connect to the gateway URL specified due to a network error']);\n\t\t\tthis.failedToConnectDueToNetworkError = true;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit(WebSocketShardEvents.Error, { error });\n\t}\n\n\tprivate async onClose(code: number) {\n\t\tthis.emit(WebSocketShardEvents.Closed, { code });\n\n\t\tswitch (code) {\n\t\t\tcase CloseCodes.Normal: {\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\treason: 'Got disconnected by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tcase CloseCodes.Resuming: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownError: {\n\t\t\t\tthis.debug([`An unknown error occurred: ${code}`]);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownOpcode: {\n\t\t\t\tthis.debug(['An invalid opcode was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DecodeError: {\n\t\t\t\tthis.debug(['An invalid payload was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.NotAuthenticated: {\n\t\t\t\tthis.debug(['A request was somehow sent before the identify/resume payload.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AuthenticationFailed: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Authentication failed'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AlreadyAuthenticated: {\n\t\t\t\tthis.debug(['More than one auth payload was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidSeq: {\n\t\t\t\tthis.debug(['An invalid sequence was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.RateLimited: {\n\t\t\t\tthis.debug(['The WebSocket rate limit has been hit, this should never happen']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.SessionTimedOut: {\n\t\t\t\tthis.debug(['Session timed out.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidShard: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Invalid shard'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.ShardingRequired: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Sharding is required'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidAPIVersion: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used an invalid API version'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used invalid intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DisallowedIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used disallowed intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tthis.debug([\n\t\t\t\t\t`The gateway closed with an unexpected code ${code}, attempting to ${\n\t\t\t\t\t\tthis.failedToConnectDueToNetworkError ? 'reconnect' : 'resume'\n\t\t\t\t\t}.`,\n\t\t\t\t]);\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\trecover: this.failedToConnectDueToNetworkError\n\t\t\t\t\t\t? WebSocketShardDestroyRecovery.Reconnect\n\t\t\t\t\t\t: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate debug(messages: [string, ...string[]]) {\n\t\tconst message = `${messages[0]}${\n\t\t\tmessages.length > 1\n\t\t\t\t? `\\n${messages\n\t\t\t\t\t\t.slice(1)\n\t\t\t\t\t\t.map((m) => `\t${m}`)\n\t\t\t\t\t\t.join('\\n')}`\n\t\t\t\t: ''\n\t\t}`;\n\n\t\tthis.emit(WebSocketShardEvents.Debug, { message });\n\t}\n}\n","import process from 'node:process';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { APIVersion, GatewayOpcodes } from 'discord-api-types/v10';\nimport { SimpleShardingStrategy } from '../strategies/sharding/SimpleShardingStrategy.js';\nimport { SimpleIdentifyThrottler } from '../throttling/SimpleIdentifyThrottler.js';\nimport type { SessionInfo, OptionalWebSocketManagerOptions, WebSocketManager } from '../ws/WebSocketManager.js';\nimport type { SendRateLimitState } from '../ws/WebSocketShard.js';\n\n/**\n * Valid encoding types\n */\nexport enum Encoding {\n\tJSON = 'json',\n}\n\n/**\n * Valid compression methods\n */\nexport enum CompressionMethod {\n\tZlibStream = 'zlib-stream',\n}\n\nexport const DefaultDeviceProperty = `@discordjs/ws 1.0.1` as `@discordjs/ws ${string}`;\n\nconst getDefaultSessionStore = lazy(() => new Collection<number, SessionInfo | null>());\n\n/**\n * Default options used by the manager\n */\nexport const DefaultWebSocketManagerOptions = {\n\tasync buildIdentifyThrottler(manager: WebSocketManager) {\n\t\tconst info = await manager.fetchGatewayInformation();\n\t\treturn new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);\n\t},\n\tbuildStrategy: (manager) => new SimpleShardingStrategy(manager),\n\tshardCount: null,\n\tshardIds: null,\n\tlargeThreshold: null,\n\tinitialPresence: null,\n\tidentifyProperties: {\n\t\tbrowser: DefaultDeviceProperty,\n\t\tdevice: DefaultDeviceProperty,\n\t\tos: process.platform,\n\t},\n\tversion: APIVersion,\n\tencoding: Encoding.JSON,\n\tcompression: null,\n\tretrieveSessionInfo(shardId) {\n\t\tconst store = getDefaultSessionStore();\n\t\treturn store.get(shardId) ?? null;\n\t},\n\tupdateSessionInfo(shardId: number, info: SessionInfo | null) {\n\t\tconst store = getDefaultSessionStore();\n\t\tif (info) {\n\t\t\tstore.set(shardId, info);\n\t\t} else {\n\t\t\tstore.delete(shardId);\n\t\t}\n\t},\n\thandshakeTimeout: 30_000,\n\thelloTimeout: 60_000,\n\treadyTimeout: 15_000,\n} as const satisfies OptionalWebSocketManagerOptions;\n\nexport const ImportantGatewayOpcodes = new Set([\n\tGatewayOpcodes.Heartbeat,\n\tGatewayOpcodes.Identify,\n\tGatewayOpcodes.Resume,\n]);\n\nexport function getInitialSendRateLimitState(): SendRateLimitState {\n\treturn {\n\t\tremaining: 120,\n\t\tresetAt: Date.now() + 60_000,\n\t};\n}\n","import { setTimeout as sleep } from 'node:timers/promises';\nimport { Collection } from '@discordjs/collection';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport type { IIdentifyThrottler } from './IIdentifyThrottler.js';\n\n/**\n * The state of a rate limit key's identify queue.\n */\nexport interface IdentifyState {\n\tqueue: AsyncQueue;\n\tresetsAt: number;\n}\n\n/**\n * Local, in-memory identify throttler.\n */\nexport class SimpleIdentifyThrottler implements IIdentifyThrottler {\n\tprivate readonly states = new Collection<number, IdentifyState>();\n\n\tpublic constructor(private readonly maxConcurrency: number) {}\n\n\t/**\n\t * {@inheritDoc IIdentifyThrottler.waitForIdentify}\n\t */\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst key = shardId % this.maxConcurrency;\n\n\t\tconst state = this.states.ensure(key, () => {\n\t\t\treturn {\n\t\t\t\tqueue: new AsyncQueue(),\n\t\t\t\tresetsAt: Number.POSITIVE_INFINITY,\n\t\t\t};\n\t\t});\n\n\t\tawait state.queue.wait({ signal });\n\n\t\ttry {\n\t\t\tconst diff = state.resetsAt - Date.now();\n\t\t\tif (diff <= 5_000) {\n\t\t\t\t// To account for the latency the IDENTIFY payload goes through, we add a bit more wait time\n\t\t\t\tconst time = diff + Math.random() * 1_500;\n\t\t\t\tawait sleep(time);\n\t\t\t}\n\n\t\t\tstate.resetsAt = Date.now() + 5_000;\n\t\t} finally {\n\t\t\tstate.queue.shift();\n\t\t}\n\t}\n}\n","import { isMainThread, parentPort, workerData } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { Awaitable } from '@discordjs/util';\nimport { WorkerContextFetchingStrategy } from '../strategies/context/WorkerContextFetchingStrategy.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerData,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../strategies/sharding/WorkerShardingStrategy.js';\nimport type { WebSocketShardDestroyOptions } from '../ws/WebSocketShard.js';\nimport { WebSocketShardEvents, WebSocketShard } from '../ws/WebSocketShard.js';\n\n/**\n * Options for bootstrapping the worker\n */\nexport interface BootstrapOptions {\n\t/**\n\t * Shard events to just arbitrarily forward to the parent thread for the manager to emit\n\t * Note: By default, this will include ALL events\n\t * you most likely want to handle dispatch within the worker itself\n\t */\n\tforwardEvents?: WebSocketShardEvents[];\n\t/**\n\t * Function to call when a shard is created for additional setup\n\t */\n\tshardCallback?(shard: WebSocketShard): Awaitable<void>;\n}\n\n/**\n * Utility class for bootstrapping a worker thread to be used for sharding\n */\nexport class WorkerBootstrapper {\n\t/**\n\t * The data passed to the worker thread\n\t */\n\tprotected readonly data = workerData as WorkerData;\n\n\t/**\n\t * The shards that are managed by this worker\n\t */\n\tprotected readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor() {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Expected WorkerBootstrap to not be used within the main thread');\n\t\t}\n\t}\n\n\t/**\n\t * Helper method to initiate a shard's connection process\n\t */\n\tprotected async connect(shardId: number): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.connect();\n\t}\n\n\t/**\n\t * Helper method to destroy a shard\n\t */\n\tprotected async destroy(shardId: number, options?: WebSocketShardDestroyOptions): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.destroy(options);\n\t}\n\n\t/**\n\t * Helper method to attach event listeners to the parentPort\n\t */\n\tprotected setupThreadEvents(): void {\n\t\tparentPort!\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerSendPayload) => {\n\t\t\t\tswitch (payload.op) {\n\t\t\t\t\tcase WorkerSendPayloadOp.Connect: {\n\t\t\t\t\t\tawait this.connect(payload.shardId);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Connected,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Destroy: {\n\t\t\t\t\t\tawait this.destroy(payload.shardId, payload.options);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Destroyed,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Send: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new RangeError(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait shard.send(payload.payload);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.SessionInfoResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.ShardIdentifyResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.FetchStatus: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new Error(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.FetchStatusResponse,\n\t\t\t\t\t\t\tstatus: shard.status,\n\t\t\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Bootstraps the worker thread with the provided options\n\t */\n\tpublic async bootstrap(options: Readonly<BootstrapOptions> = {}): Promise<void> {\n\t\t// Start by initializing the shards\n\t\tfor (const shardId of this.data.shardIds) {\n\t\t\tconst shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);\n\t\t\tfor (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Event types incompatible\n\t\t\t\tshard.on(event, (data) => {\n\t\t\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\t\t\top: WorkerReceivePayloadOp.Event,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tshardId,\n\t\t\t\t\t};\n\t\t\t\t\tparentPort!.postMessage(payload);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Any additional setup the user might want to do\n\t\t\tawait options.shardCallback?.(shard);\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\n\t\t// Lastly, start listening to messages from the parent thread\n\t\tthis.setupThreadEvents();\n\n\t\tconst message: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WorkerReady,\n\t\t};\n\t\tparentPort!.postMessage(message);\n\t}\n}\n","import type { REST } from '@discordjs/rest';\nimport { range, type Awaitable } from '@discordjs/util';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tRoutes,\n\ttype APIGatewayBotInfo,\n\ttype GatewayIdentifyProperties,\n\ttype GatewayPresenceUpdateData,\n\ttype RESTGetAPIGatewayBotResult,\n\ttype GatewayIntentBits,\n\ttype GatewaySendPayload,\n} from 'discord-api-types/v10';\nimport type { IShardingStrategy } from '../strategies/sharding/IShardingStrategy.js';\nimport type { IIdentifyThrottler } from '../throttling/IIdentifyThrottler.js';\nimport { DefaultWebSocketManagerOptions, type CompressionMethod, type Encoding } from '../utils/constants.js';\nimport type { WebSocketShardDestroyOptions, WebSocketShardEventsMap } from './WebSocketShard.js';\n\n/**\n * Represents a range of shard ids\n */\nexport interface ShardRange {\n\tend: number;\n\tstart: number;\n}\n\n/**\n * Session information for a given shard, used to resume a session\n */\nexport interface SessionInfo {\n\t/**\n\t * URL to use when resuming\n\t */\n\tresumeURL: string;\n\t/**\n\t * The sequence number of the last message sent by the shard\n\t */\n\tsequence: number;\n\t/**\n\t * Session id for this shard\n\t */\n\tsessionId: string;\n\t/**\n\t * The total number of shards at the time of this shard identifying\n\t */\n\tshardCount: number;\n\t/**\n\t * The id of the shard\n\t */\n\tshardId: number;\n}\n\n/**\n * Required options for the WebSocketManager\n */\nexport interface RequiredWebSocketManagerOptions {\n\t/**\n\t * The intents to request\n\t */\n\tintents: GatewayIntentBits | 0;\n\t/**\n\t * The REST instance to use for fetching gateway information\n\t */\n\trest: REST;\n\t/**\n\t * The token to use for identifying with the gateway\n\t */\n\ttoken: string;\n}\n\n/**\n * Optional additional configuration for the WebSocketManager\n */\nexport interface OptionalWebSocketManagerOptions {\n\t/**\n\t * Builds an identify throttler to use for this manager's shards\n\t */\n\tbuildIdentifyThrottler(manager: WebSocketManager): Awaitable<IIdentifyThrottler>;\n\t/**\n\t * Builds the strategy to use for sharding\n\t *\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * token: process.env.DISCORD_TOKEN,\n\t * intents: 0, // for no intents\n\t * rest,\n\t * buildStrategy: (manager) => new WorkerShardingStrategy(manager, { shardsPerWorker: 2 }),\n\t * });\n\t * ```\n\t */\n\tbuildStrategy(manager: WebSocketManager): IShardingStrategy;\n\t/**\n\t * The compression method to use\n\t *\n\t * @defaultValue `null` (no compression)\n\t */\n\tcompression: CompressionMethod | null;\n\t/**\n\t * The encoding to use\n\t *\n\t * @defaultValue `'json'`\n\t */\n\tencoding: Encoding;\n\t/**\n\t * How long to wait for a shard to connect before giving up\n\t */\n\thandshakeTimeout: number | null;\n\t/**\n\t * How long to wait for a shard's HELLO packet before giving up\n\t */\n\thelloTimeout: number | null;\n\t/**\n\t * Properties to send to the gateway when identifying\n\t */\n\tidentifyProperties: GatewayIdentifyProperties;\n\t/**\n\t * Initial presence data to send to the gateway when identifying\n\t */\n\tinitialPresence: GatewayPresenceUpdateData | null;\n\t/**\n\t * Value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list\n\t */\n\tlargeThreshold: number | null;\n\t/**\n\t * How long to wait for a shard's READY packet before giving up\n\t */\n\treadyTimeout: number | null;\n\t/**\n\t * Function used to retrieve session information (and attempt to resume) for a given shard\n\t *\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * async retrieveSessionInfo(shardId): Awaitable<SessionInfo | null> {\n\t * // Fetch this info from redis or similar\n\t * return { sessionId: string, sequence: number };\n\t * // Return null if no information is found\n\t * },\n\t * });\n\t * ```\n\t */\n\tretrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;\n\t/**\n\t * The total number of shards across all WebsocketManagers you intend to instantiate.\n\t * Use `null` to use Discord's recommended shard count\n\t */\n\tshardCount: number | null;\n\t/**\n\t * The ids of the shards this WebSocketManager should manage.\n\t * Use `null` to simply spawn 0 through `shardCount - 1`\n\t *\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * shardIds: [1, 3, 7], // spawns shard 1, 3, and 7, nothing else\n\t * });\n\t * ```\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * shardIds: {\n\t * start: 3,\n\t * end: 6,\n\t * }, // spawns shards 3, 4, 5, and 6\n\t * });\n\t * ```\n\t */\n\tshardIds: number[] | ShardRange | null;\n\t/**\n\t * Function used to store session information for a given shard\n\t */\n\tupdateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;\n\t/**\n\t * The gateway version to use\n\t *\n\t * @defaultValue `'10'`\n\t */\n\tversion: string;\n}\n\nexport type WebSocketManagerOptions = OptionalWebSocketManagerOptions & RequiredWebSocketManagerOptions;\n\nexport type ManagerShardEventsMap = {\n\t[K in keyof WebSocketShardEventsMap]: [\n\t\tWebSocketShardEventsMap[K] extends [] ? { shardId: number } : WebSocketShardEventsMap[K][0] & { shardId: number },\n\t];\n};\n\nexport class WebSocketManager extends AsyncEventEmitter<ManagerShardEventsMap> {\n\t/**\n\t * The options being used by this manager\n\t */\n\tpublic readonly options: WebSocketManagerOptions;\n\n\t/**\n\t * Internal cache for a GET /gateway/bot result\n\t */\n\tprivate gatewayInformation: {\n\t\tdata: APIGatewayBotInfo;\n\t\texpiresAt: number;\n\t} | null = null;\n\n\t/**\n\t * Internal cache for the shard ids\n\t */\n\tprivate shardIds: number[] | null = null;\n\n\t/**\n\t * Strategy used to manage shards\n\t *\n\t * @defaultValue `SimpleShardingStrategy`\n\t */\n\tprivate readonly strategy: IShardingStrategy;\n\n\tpublic constructor(options: Partial<OptionalWebSocketManagerOptions> & RequiredWebSocketManagerOptions) {\n\t\tsuper();\n\t\tthis.options = { ...DefaultWebSocketManagerOptions, ...options };\n\t\tthis.strategy = this.options.buildStrategy(this);\n\t}\n\n\t/**\n\t * Fetches the gateway information from Discord - or returns it from cache if available\n\t *\n\t * @param force - Whether to ignore the cache and force a fresh fetch\n\t */\n\tpublic async fetchGatewayInformation(force = false) {\n\t\tif (this.gatewayInformation) {\n\t\t\tif (this.gatewayInformation.expiresAt <= Date.now()) {\n\t\t\t\tthis.gatewayInformation = null;\n\t\t\t} else if (!force) {\n\t\t\t\treturn this.gatewayInformation.data;\n\t\t\t}\n\t\t}\n\n\t\tconst data = (await this.options.rest.get(Routes.gatewayBot())) as RESTGetAPIGatewayBotResult;\n\n\t\t// For single sharded bots session_start_limit.reset_after will be 0, use 5 seconds as a minimum expiration time\n\t\tthis.gatewayInformation = { data, expiresAt: Date.now() + (data.session_start_limit.reset_after || 5_000) };\n\t\treturn this.gatewayInformation.data;\n\t}\n\n\t/**\n\t * Updates your total shard count on-the-fly, spawning shards as needed\n\t *\n\t * @param shardCount - The new shard count to use\n\t */\n\tpublic async updateShardCount(shardCount: number | null) {\n\t\tawait this.strategy.destroy({ reason: 'User is adjusting their shards' });\n\t\tthis.options.shardCount = shardCount;\n\n\t\tconst shardIds = await this.getShardIds(true);\n\t\tawait this.strategy.spawn(shardIds);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Yields the total number of shards across for your bot, accounting for Discord recommendations\n\t */\n\tpublic async getShardCount(): Promise<number> {\n\t\tif (this.options.shardCount) {\n\t\t\treturn this.options.shardCount;\n\t\t}\n\n\t\tconst shardIds = await this.getShardIds();\n\t\treturn Math.max(...shardIds) + 1;\n\t}\n\n\t/**\n\t * Yields the ids of the shards this manager should manage\n\t */\n\tpublic async getShardIds(force = false): Promise<number[]> {\n\t\tif (this.shardIds && !force) {\n\t\t\treturn this.shardIds;\n\t\t}\n\n\t\tlet shardIds: number[];\n\t\tif (this.options.shardIds) {\n\t\t\tif (Array.isArray(this.options.shardIds)) {\n\t\t\t\tshardIds = this.options.shardIds;\n\t\t\t} else {\n\t\t\t\tconst { start, end } = this.options.shardIds;\n\t\t\t\tshardIds = [...range({ start, end: end + 1 })];\n\t\t\t}\n\t\t} else {\n\t\t\tconst data = await this.fetchGatewayInformation();\n\t\t\tshardIds = [...range(this.options.shardCount ?? data.shards)];\n\t\t}\n\n\t\tthis.shardIds = shardIds;\n\t\treturn shardIds;\n\t}\n\n\tpublic async connect() {\n\t\tconst shardCount = await this.getShardCount();\n\n\t\tconst data = await this.fetchGatewayInformation();\n\t\tif (data.session_start_limit.remaining < shardCount) {\n\t\t\tthrow new Error(\n\t\t\t\t`Not enough sessions remaining to spawn ${shardCount} shards; only ${\n\t\t\t\t\tdata.session_start_limit.remaining\n\t\t\t\t} remaining; resets at ${new Date(Date.now() + data.session_start_limit.reset_after).toISOString()}`,\n\t\t\t);\n\t\t}\n\n\t\t// First, make sure all our shards are spawned\n\t\tawait this.updateShardCount(shardCount);\n\t\tawait this.strategy.connect();\n\t}\n\n\tpublic destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\treturn this.strategy.destroy(options);\n\t}\n\n\tpublic send(shardId: number, payload: GatewaySendPayload) {\n\t\treturn this.strategy.send(shardId, payload);\n\t}\n\n\tpublic fetchStatus() {\n\t\treturn this.strategy.fetchStatus();\n\t}\n}\n"],"mappings":"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","names":["import_node_worker_threads","import_collection","WorkerSendPayloadOp","WorkerReceivePayloadOp","workerData","resolve","resolve","payload","import_collection","import_node_events","import_promises","import_collection","import_util","import_async_queue","import_v10","import_collection","import_collection","sleep","Encoding","CompressionMethod","process","WebSocketShardEvents","WebSocketShardStatus","WebSocketShardDestroyRecovery","CloseCodes","version","resolve","sleep","session","import_node_worker_threads","import_collection","import_util","import_async_event_emitter","import_v10"]} \ No newline at end of file
diff --git a/node_modules/@discordjs/ws/dist/index.mjs b/node_modules/@discordjs/ws/dist/index.mjs
new file mode 100644
index 0000000..56e44e6
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/index.mjs
@@ -0,0 +1,1446 @@
+var __defProp = Object.defineProperty;
+var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
+var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
+}) : x)(function(x) {
+ if (typeof require !== "undefined")
+ return require.apply(this, arguments);
+ throw Error('Dynamic require of "' + x + '" is not supported');
+});
+
+// ../../node_modules/tsup/assets/esm_shims.js
+import { fileURLToPath } from "url";
+import path from "path";
+var getFilename = /* @__PURE__ */ __name(() => fileURLToPath(import.meta.url), "getFilename");
+var getDirname = /* @__PURE__ */ __name(() => path.dirname(getFilename()), "getDirname");
+var __dirname = /* @__PURE__ */ getDirname();
+
+// src/strategies/context/IContextFetchingStrategy.ts
+async function managerToFetchingStrategyOptions(manager) {
+ const {
+ buildIdentifyThrottler,
+ buildStrategy,
+ retrieveSessionInfo,
+ updateSessionInfo,
+ shardCount,
+ shardIds,
+ rest,
+ ...managerOptions
+ } = manager.options;
+ return {
+ ...managerOptions,
+ gatewayInformation: await manager.fetchGatewayInformation(),
+ shardCount: await manager.getShardCount()
+ };
+}
+__name(managerToFetchingStrategyOptions, "managerToFetchingStrategyOptions");
+
+// src/strategies/context/SimpleContextFetchingStrategy.ts
+var SimpleContextFetchingStrategy = class _SimpleContextFetchingStrategy {
+ constructor(manager, options) {
+ this.manager = manager;
+ this.options = options;
+ }
+ static {
+ __name(this, "SimpleContextFetchingStrategy");
+ }
+ // This strategy assumes every shard is running under the same process - therefore we need a single
+ // IdentifyThrottler per manager.
+ static throttlerCache = /* @__PURE__ */ new WeakMap();
+ static async ensureThrottler(manager) {
+ const throttler = _SimpleContextFetchingStrategy.throttlerCache.get(manager);
+ if (throttler) {
+ return throttler;
+ }
+ const newThrottler = await manager.options.buildIdentifyThrottler(manager);
+ _SimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);
+ return newThrottler;
+ }
+ async retrieveSessionInfo(shardId) {
+ return this.manager.options.retrieveSessionInfo(shardId);
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ return this.manager.options.updateSessionInfo(shardId, sessionInfo);
+ }
+ async waitForIdentify(shardId, signal) {
+ const throttler = await _SimpleContextFetchingStrategy.ensureThrottler(this.manager);
+ await throttler.waitForIdentify(shardId, signal);
+ }
+};
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+import { isMainThread, parentPort } from "node:worker_threads";
+import { Collection as Collection2 } from "@discordjs/collection";
+
+// src/strategies/sharding/WorkerShardingStrategy.ts
+import { once } from "node:events";
+import { join, isAbsolute, resolve } from "node:path";
+import { Worker } from "node:worker_threads";
+import { Collection } from "@discordjs/collection";
+var WorkerSendPayloadOp = /* @__PURE__ */ ((WorkerSendPayloadOp2) => {
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["Connect"] = 0] = "Connect";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["Destroy"] = 1] = "Destroy";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["Send"] = 2] = "Send";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["SessionInfoResponse"] = 3] = "SessionInfoResponse";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["ShardIdentifyResponse"] = 4] = "ShardIdentifyResponse";
+ WorkerSendPayloadOp2[WorkerSendPayloadOp2["FetchStatus"] = 5] = "FetchStatus";
+ return WorkerSendPayloadOp2;
+})(WorkerSendPayloadOp || {});
+var WorkerReceivePayloadOp = /* @__PURE__ */ ((WorkerReceivePayloadOp2) => {
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["Connected"] = 0] = "Connected";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["Destroyed"] = 1] = "Destroyed";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["Event"] = 2] = "Event";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["RetrieveSessionInfo"] = 3] = "RetrieveSessionInfo";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["UpdateSessionInfo"] = 4] = "UpdateSessionInfo";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["WaitForIdentify"] = 5] = "WaitForIdentify";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["FetchStatusResponse"] = 6] = "FetchStatusResponse";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["WorkerReady"] = 7] = "WorkerReady";
+ WorkerReceivePayloadOp2[WorkerReceivePayloadOp2["CancelIdentify"] = 8] = "CancelIdentify";
+ return WorkerReceivePayloadOp2;
+})(WorkerReceivePayloadOp || {});
+var WorkerShardingStrategy = class {
+ static {
+ __name(this, "WorkerShardingStrategy");
+ }
+ manager;
+ options;
+ #workers = [];
+ #workerByShardId = new Collection();
+ connectPromises = new Collection();
+ destroyPromises = new Collection();
+ fetchStatusPromises = new Collection();
+ waitForIdentifyControllers = new Collection();
+ throttler;
+ constructor(manager, options) {
+ this.manager = manager;
+ this.options = options;
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ async spawn(shardIds) {
+ const shardsPerWorker = this.options.shardsPerWorker === "all" ? shardIds.length : this.options.shardsPerWorker;
+ const strategyOptions = await managerToFetchingStrategyOptions(this.manager);
+ const loops = Math.ceil(shardIds.length / shardsPerWorker);
+ const promises = [];
+ for (let idx = 0; idx < loops; idx++) {
+ const slice = shardIds.slice(idx * shardsPerWorker, (idx + 1) * shardsPerWorker);
+ const workerData2 = {
+ ...strategyOptions,
+ shardIds: slice
+ };
+ promises.push(this.setupWorker(workerData2));
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ async connect() {
+ const promises = [];
+ for (const [shardId, worker] of this.#workerByShardId.entries()) {
+ const payload = {
+ op: 0 /* Connect */,
+ shardId
+ };
+ const promise = new Promise((resolve2) => this.connectPromises.set(shardId, resolve2));
+ worker.postMessage(payload);
+ promises.push(promise);
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ async destroy(options = {}) {
+ const promises = [];
+ for (const [shardId, worker] of this.#workerByShardId.entries()) {
+ const payload = {
+ op: 1 /* Destroy */,
+ shardId,
+ options
+ };
+ promises.push(
+ // eslint-disable-next-line no-promise-executor-return, promise/prefer-await-to-then
+ new Promise((resolve2) => this.destroyPromises.set(shardId, resolve2)).then(async () => worker.terminate())
+ );
+ worker.postMessage(payload);
+ }
+ this.#workers = [];
+ this.#workerByShardId.clear();
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ send(shardId, data) {
+ const worker = this.#workerByShardId.get(shardId);
+ if (!worker) {
+ throw new Error(`No worker found for shard ${shardId}`);
+ }
+ const payload = {
+ op: 2 /* Send */,
+ shardId,
+ payload: data
+ };
+ worker.postMessage(payload);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ async fetchStatus() {
+ const statuses = new Collection();
+ for (const [shardId, worker] of this.#workerByShardId.entries()) {
+ const nonce = Math.random();
+ const payload = {
+ op: 5 /* FetchStatus */,
+ shardId,
+ nonce
+ };
+ const promise = new Promise((resolve2) => this.fetchStatusPromises.set(nonce, resolve2));
+ worker.postMessage(payload);
+ const status = await promise;
+ statuses.set(shardId, status);
+ }
+ return statuses;
+ }
+ async setupWorker(workerData2) {
+ const worker = new Worker(this.resolveWorkerPath(), { workerData: workerData2 });
+ await once(worker, "online");
+ await this.waitForWorkerReady(worker);
+ worker.on("error", (err) => {
+ throw err;
+ }).on("messageerror", (err) => {
+ throw err;
+ }).on("message", async (payload) => this.onMessage(worker, payload));
+ this.#workers.push(worker);
+ for (const shardId of workerData2.shardIds) {
+ this.#workerByShardId.set(shardId, worker);
+ }
+ }
+ resolveWorkerPath() {
+ const path2 = this.options.workerPath;
+ if (!path2) {
+ return join(__dirname, "defaultWorker.js");
+ }
+ if (isAbsolute(path2)) {
+ return path2;
+ }
+ if (/^\.\.?[/\\]/.test(path2)) {
+ return resolve(path2);
+ }
+ try {
+ return __require.resolve(path2);
+ } catch {
+ return resolve(path2);
+ }
+ }
+ async waitForWorkerReady(worker) {
+ return new Promise((resolve2) => {
+ const handler = /* @__PURE__ */ __name((payload) => {
+ if (payload.op === 7 /* WorkerReady */) {
+ resolve2();
+ worker.off("message", handler);
+ }
+ }, "handler");
+ worker.on("message", handler);
+ });
+ }
+ async onMessage(worker, payload) {
+ switch (payload.op) {
+ case 0 /* Connected */: {
+ this.connectPromises.get(payload.shardId)?.();
+ this.connectPromises.delete(payload.shardId);
+ break;
+ }
+ case 1 /* Destroyed */: {
+ this.destroyPromises.get(payload.shardId)?.();
+ this.destroyPromises.delete(payload.shardId);
+ break;
+ }
+ case 2 /* Event */: {
+ this.manager.emit(payload.event, { ...payload.data, shardId: payload.shardId });
+ break;
+ }
+ case 3 /* RetrieveSessionInfo */: {
+ const session = await this.manager.options.retrieveSessionInfo(payload.shardId);
+ const response = {
+ op: 3 /* SessionInfoResponse */,
+ nonce: payload.nonce,
+ session
+ };
+ worker.postMessage(response);
+ break;
+ }
+ case 4 /* UpdateSessionInfo */: {
+ await this.manager.options.updateSessionInfo(payload.shardId, payload.session);
+ break;
+ }
+ case 5 /* WaitForIdentify */: {
+ const throttler = await this.ensureThrottler();
+ try {
+ const controller = new AbortController();
+ this.waitForIdentifyControllers.set(payload.nonce, controller);
+ await throttler.waitForIdentify(payload.shardId, controller.signal);
+ } catch {
+ return;
+ }
+ const response = {
+ op: 4 /* ShardIdentifyResponse */,
+ nonce: payload.nonce,
+ ok: true
+ };
+ worker.postMessage(response);
+ break;
+ }
+ case 6 /* FetchStatusResponse */: {
+ this.fetchStatusPromises.get(payload.nonce)?.(payload.status);
+ this.fetchStatusPromises.delete(payload.nonce);
+ break;
+ }
+ case 7 /* WorkerReady */: {
+ break;
+ }
+ case 8 /* CancelIdentify */: {
+ this.waitForIdentifyControllers.get(payload.nonce)?.abort();
+ this.waitForIdentifyControllers.delete(payload.nonce);
+ const response = {
+ op: 4 /* ShardIdentifyResponse */,
+ nonce: payload.nonce,
+ ok: false
+ };
+ worker.postMessage(response);
+ break;
+ }
+ }
+ }
+ async ensureThrottler() {
+ this.throttler ??= await this.manager.options.buildIdentifyThrottler(this.manager);
+ return this.throttler;
+ }
+};
+
+// src/strategies/context/WorkerContextFetchingStrategy.ts
+var WorkerContextFetchingStrategy = class {
+ constructor(options) {
+ this.options = options;
+ if (isMainThread) {
+ throw new Error("Cannot instantiate WorkerContextFetchingStrategy on the main thread");
+ }
+ parentPort.on("message", (payload) => {
+ if (payload.op === 3 /* SessionInfoResponse */) {
+ this.sessionPromises.get(payload.nonce)?.(payload.session);
+ this.sessionPromises.delete(payload.nonce);
+ }
+ if (payload.op === 4 /* ShardIdentifyResponse */) {
+ const promise = this.waitForIdentifyPromises.get(payload.nonce);
+ if (payload.ok) {
+ promise?.resolve();
+ } else {
+ promise?.reject(promise.signal.reason);
+ }
+ this.waitForIdentifyPromises.delete(payload.nonce);
+ }
+ });
+ }
+ static {
+ __name(this, "WorkerContextFetchingStrategy");
+ }
+ sessionPromises = new Collection2();
+ waitForIdentifyPromises = new Collection2();
+ async retrieveSessionInfo(shardId) {
+ const nonce = Math.random();
+ const payload = {
+ op: 3 /* RetrieveSessionInfo */,
+ shardId,
+ nonce
+ };
+ const promise = new Promise((resolve2) => this.sessionPromises.set(nonce, resolve2));
+ parentPort.postMessage(payload);
+ return promise;
+ }
+ updateSessionInfo(shardId, sessionInfo) {
+ const payload = {
+ op: 4 /* UpdateSessionInfo */,
+ shardId,
+ session: sessionInfo
+ };
+ parentPort.postMessage(payload);
+ }
+ async waitForIdentify(shardId, signal) {
+ const nonce = Math.random();
+ const payload = {
+ op: 5 /* WaitForIdentify */,
+ nonce,
+ shardId
+ };
+ const promise = new Promise(
+ (resolve2, reject) => (
+ // eslint-disable-next-line no-promise-executor-return
+ this.waitForIdentifyPromises.set(nonce, { signal, resolve: resolve2, reject })
+ )
+ );
+ parentPort.postMessage(payload);
+ const listener = /* @__PURE__ */ __name(() => {
+ const payload2 = {
+ op: 8 /* CancelIdentify */,
+ nonce
+ };
+ parentPort.postMessage(payload2);
+ }, "listener");
+ signal.addEventListener("abort", listener);
+ try {
+ await promise;
+ } finally {
+ signal.removeEventListener("abort", listener);
+ }
+ }
+};
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+import { Collection as Collection6 } from "@discordjs/collection";
+
+// src/ws/WebSocketShard.ts
+import { Buffer as Buffer2 } from "node:buffer";
+import { once as once2 } from "node:events";
+import { clearInterval, clearTimeout, setInterval, setTimeout } from "node:timers";
+import { setTimeout as sleep2 } from "node:timers/promises";
+import { URLSearchParams } from "node:url";
+import { TextDecoder } from "node:util";
+import { inflate } from "node:zlib";
+import { Collection as Collection5 } from "@discordjs/collection";
+import { lazy as lazy2 } from "@discordjs/util";
+import { AsyncQueue as AsyncQueue2 } from "@sapphire/async-queue";
+import { AsyncEventEmitter } from "@vladfrangu/async_event_emitter";
+import {
+ GatewayCloseCodes,
+ GatewayDispatchEvents,
+ GatewayOpcodes as GatewayOpcodes2
+} from "discord-api-types/v10";
+import { WebSocket } from "ws";
+
+// src/utils/constants.ts
+import process from "node:process";
+import { Collection as Collection4 } from "@discordjs/collection";
+import { lazy } from "@discordjs/util";
+import { APIVersion, GatewayOpcodes } from "discord-api-types/v10";
+
+// src/throttling/SimpleIdentifyThrottler.ts
+import { setTimeout as sleep } from "node:timers/promises";
+import { Collection as Collection3 } from "@discordjs/collection";
+import { AsyncQueue } from "@sapphire/async-queue";
+var SimpleIdentifyThrottler = class {
+ constructor(maxConcurrency) {
+ this.maxConcurrency = maxConcurrency;
+ }
+ static {
+ __name(this, "SimpleIdentifyThrottler");
+ }
+ states = new Collection3();
+ /**
+ * {@inheritDoc IIdentifyThrottler.waitForIdentify}
+ */
+ async waitForIdentify(shardId, signal) {
+ const key = shardId % this.maxConcurrency;
+ const state = this.states.ensure(key, () => {
+ return {
+ queue: new AsyncQueue(),
+ resetsAt: Number.POSITIVE_INFINITY
+ };
+ });
+ await state.queue.wait({ signal });
+ try {
+ const diff = state.resetsAt - Date.now();
+ if (diff <= 5e3) {
+ const time = diff + Math.random() * 1500;
+ await sleep(time);
+ }
+ state.resetsAt = Date.now() + 5e3;
+ } finally {
+ state.queue.shift();
+ }
+ }
+};
+
+// src/utils/constants.ts
+var Encoding = /* @__PURE__ */ ((Encoding2) => {
+ Encoding2["JSON"] = "json";
+ return Encoding2;
+})(Encoding || {});
+var CompressionMethod = /* @__PURE__ */ ((CompressionMethod2) => {
+ CompressionMethod2["ZlibStream"] = "zlib-stream";
+ return CompressionMethod2;
+})(CompressionMethod || {});
+var DefaultDeviceProperty = `@discordjs/ws 1.0.1`;
+var getDefaultSessionStore = lazy(() => new Collection4());
+var DefaultWebSocketManagerOptions = {
+ async buildIdentifyThrottler(manager) {
+ const info = await manager.fetchGatewayInformation();
+ return new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);
+ },
+ buildStrategy: (manager) => new SimpleShardingStrategy(manager),
+ shardCount: null,
+ shardIds: null,
+ largeThreshold: null,
+ initialPresence: null,
+ identifyProperties: {
+ browser: DefaultDeviceProperty,
+ device: DefaultDeviceProperty,
+ os: process.platform
+ },
+ version: APIVersion,
+ encoding: "json" /* JSON */,
+ compression: null,
+ retrieveSessionInfo(shardId) {
+ const store = getDefaultSessionStore();
+ return store.get(shardId) ?? null;
+ },
+ updateSessionInfo(shardId, info) {
+ const store = getDefaultSessionStore();
+ if (info) {
+ store.set(shardId, info);
+ } else {
+ store.delete(shardId);
+ }
+ },
+ handshakeTimeout: 3e4,
+ helloTimeout: 6e4,
+ readyTimeout: 15e3
+};
+var ImportantGatewayOpcodes = /* @__PURE__ */ new Set([
+ GatewayOpcodes.Heartbeat,
+ GatewayOpcodes.Identify,
+ GatewayOpcodes.Resume
+]);
+function getInitialSendRateLimitState() {
+ return {
+ remaining: 120,
+ resetAt: Date.now() + 6e4
+ };
+}
+__name(getInitialSendRateLimitState, "getInitialSendRateLimitState");
+
+// src/ws/WebSocketShard.ts
+var getZlibSync = lazy2(async () => import("zlib-sync").then((mod) => mod.default).catch(() => null));
+var WebSocketShardEvents = /* @__PURE__ */ ((WebSocketShardEvents2) => {
+ WebSocketShardEvents2["Closed"] = "closed";
+ WebSocketShardEvents2["Debug"] = "debug";
+ WebSocketShardEvents2["Dispatch"] = "dispatch";
+ WebSocketShardEvents2["Error"] = "error";
+ WebSocketShardEvents2["HeartbeatComplete"] = "heartbeat";
+ WebSocketShardEvents2["Hello"] = "hello";
+ WebSocketShardEvents2["Ready"] = "ready";
+ WebSocketShardEvents2["Resumed"] = "resumed";
+ return WebSocketShardEvents2;
+})(WebSocketShardEvents || {});
+var WebSocketShardStatus = /* @__PURE__ */ ((WebSocketShardStatus2) => {
+ WebSocketShardStatus2[WebSocketShardStatus2["Idle"] = 0] = "Idle";
+ WebSocketShardStatus2[WebSocketShardStatus2["Connecting"] = 1] = "Connecting";
+ WebSocketShardStatus2[WebSocketShardStatus2["Resuming"] = 2] = "Resuming";
+ WebSocketShardStatus2[WebSocketShardStatus2["Ready"] = 3] = "Ready";
+ return WebSocketShardStatus2;
+})(WebSocketShardStatus || {});
+var WebSocketShardDestroyRecovery = /* @__PURE__ */ ((WebSocketShardDestroyRecovery2) => {
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Reconnect"] = 0] = "Reconnect";
+ WebSocketShardDestroyRecovery2[WebSocketShardDestroyRecovery2["Resume"] = 1] = "Resume";
+ return WebSocketShardDestroyRecovery2;
+})(WebSocketShardDestroyRecovery || {});
+var CloseCodes = /* @__PURE__ */ ((CloseCodes2) => {
+ CloseCodes2[CloseCodes2["Normal"] = 1e3] = "Normal";
+ CloseCodes2[CloseCodes2["Resuming"] = 4200] = "Resuming";
+ return CloseCodes2;
+})(CloseCodes || {});
+var WebSocketConstructor = WebSocket;
+var WebSocketShard = class extends AsyncEventEmitter {
+ static {
+ __name(this, "WebSocketShard");
+ }
+ connection = null;
+ useIdentifyCompress = false;
+ inflate = null;
+ textDecoder = new TextDecoder();
+ replayedEvents = 0;
+ isAck = true;
+ sendRateLimitState = getInitialSendRateLimitState();
+ initialHeartbeatTimeoutController = null;
+ heartbeatInterval = null;
+ lastHeartbeatAt = -1;
+ // Indicates whether the shard has already resolved its original connect() call
+ initialConnectResolved = false;
+ // Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)
+ failedToConnectDueToNetworkError = false;
+ sendQueue = new AsyncQueue2();
+ timeoutAbortControllers = new Collection5();
+ strategy;
+ id;
+ #status = 0 /* Idle */;
+ get status() {
+ return this.#status;
+ }
+ constructor(strategy, id) {
+ super();
+ this.strategy = strategy;
+ this.id = id;
+ }
+ async connect() {
+ const controller = new AbortController();
+ let promise;
+ if (!this.initialConnectResolved) {
+ promise = Promise.race([
+ once2(this, "ready" /* Ready */, { signal: controller.signal }),
+ once2(this, "resumed" /* Resumed */, { signal: controller.signal })
+ ]);
+ }
+ void this.internalConnect();
+ try {
+ await promise;
+ } catch ({ error }) {
+ throw error;
+ } finally {
+ controller.abort();
+ }
+ this.initialConnectResolved = true;
+ }
+ async internalConnect() {
+ if (this.#status !== 0 /* Idle */) {
+ throw new Error("Tried to connect a shard that wasn't idle");
+ }
+ const { version: version2, encoding, compression } = this.strategy.options;
+ const params = new URLSearchParams({ v: version2, encoding });
+ if (compression) {
+ const zlib = await getZlibSync();
+ if (zlib) {
+ params.append("compress", compression);
+ this.inflate = new zlib.Inflate({
+ chunkSize: 65535,
+ to: "string"
+ });
+ } else if (!this.useIdentifyCompress) {
+ this.useIdentifyCompress = true;
+ console.warn(
+ "WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress"
+ );
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ const url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;
+ this.debug([`Connecting to ${url}`]);
+ const connection = new WebSocketConstructor(url, {
+ handshakeTimeout: this.strategy.options.handshakeTimeout ?? void 0
+ });
+ connection.binaryType = "arraybuffer";
+ connection.onmessage = (event) => {
+ void this.onMessage(event.data, event.data instanceof ArrayBuffer);
+ };
+ connection.onerror = (event) => {
+ this.onError(event.error);
+ };
+ connection.onclose = (event) => {
+ void this.onClose(event.code);
+ };
+ this.connection = connection;
+ this.#status = 1 /* Connecting */;
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ const { ok } = await this.waitForEvent("hello" /* Hello */, this.strategy.options.helloTimeout);
+ if (!ok) {
+ return;
+ }
+ if (session?.shardCount === this.strategy.options.shardCount) {
+ await this.resume(session);
+ } else {
+ await this.identify();
+ }
+ }
+ async destroy(options = {}) {
+ if (this.#status === 0 /* Idle */) {
+ this.debug(["Tried to destroy a shard that was idle"]);
+ return;
+ }
+ if (!options.code) {
+ options.code = options.recover === 1 /* Resume */ ? 4200 /* Resuming */ : 1e3 /* Normal */;
+ }
+ this.debug([
+ "Destroying shard",
+ `Reason: ${options.reason ?? "none"}`,
+ `Code: ${options.code}`,
+ `Recover: ${options.recover === void 0 ? "none" : WebSocketShardDestroyRecovery[options.recover]}`
+ ]);
+ this.isAck = true;
+ if (this.heartbeatInterval) {
+ clearInterval(this.heartbeatInterval);
+ }
+ if (this.initialHeartbeatTimeoutController) {
+ this.initialHeartbeatTimeoutController.abort();
+ this.initialHeartbeatTimeoutController = null;
+ }
+ this.lastHeartbeatAt = -1;
+ for (const controller of this.timeoutAbortControllers.values()) {
+ controller.abort();
+ }
+ this.timeoutAbortControllers.clear();
+ this.failedToConnectDueToNetworkError = false;
+ if (options.recover !== 1 /* Resume */) {
+ await this.strategy.updateSessionInfo(this.id, null);
+ }
+ if (this.connection) {
+ this.connection.onmessage = null;
+ this.connection.onclose = null;
+ const shouldClose = this.connection.readyState === WebSocket.OPEN;
+ this.debug([
+ "Connection status during destroy",
+ `Needs closing: ${shouldClose}`,
+ `Ready state: ${this.connection.readyState}`
+ ]);
+ if (shouldClose) {
+ let outerResolve;
+ const promise = new Promise((resolve2) => {
+ outerResolve = resolve2;
+ });
+ this.connection.onclose = outerResolve;
+ this.connection.close(options.code, options.reason);
+ await promise;
+ this.emit("closed" /* Closed */, { code: options.code });
+ }
+ this.connection.onerror = null;
+ } else {
+ this.debug(["Destroying a shard that has no connection; please open an issue on GitHub"]);
+ }
+ this.#status = 0 /* Idle */;
+ if (options.recover !== void 0) {
+ await sleep2(500);
+ return this.internalConnect();
+ }
+ }
+ async waitForEvent(event, timeoutDuration) {
+ this.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : "indefinitely"}`]);
+ const timeoutController = new AbortController();
+ const timeout = timeoutDuration ? setTimeout(() => timeoutController.abort(), timeoutDuration).unref() : null;
+ this.timeoutAbortControllers.set(event, timeoutController);
+ const closeController = new AbortController();
+ try {
+ const closed = await Promise.race([
+ once2(this, event, { signal: timeoutController.signal }).then(() => false),
+ once2(this, "closed" /* Closed */, { signal: closeController.signal }).then(() => true)
+ ]);
+ return { ok: !closed };
+ } catch {
+ void this.destroy({
+ code: 1e3 /* Normal */,
+ reason: "Something timed out or went wrong while waiting for an event",
+ recover: 0 /* Reconnect */
+ });
+ return { ok: false };
+ } finally {
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ this.timeoutAbortControllers.delete(event);
+ if (!closeController.signal.aborted) {
+ closeController.abort();
+ }
+ }
+ }
+ async send(payload) {
+ if (!this.connection) {
+ throw new Error("WebSocketShard wasn't connected");
+ }
+ if (this.#status !== 3 /* Ready */ && !ImportantGatewayOpcodes.has(payload.op)) {
+ this.debug(["Tried to send a non-crucial payload before the shard was ready, waiting"]);
+ try {
+ await once2(this, "ready" /* Ready */);
+ } catch {
+ return this.send(payload);
+ }
+ }
+ await this.sendQueue.wait();
+ if (--this.sendRateLimitState.remaining <= 0) {
+ const now = Date.now();
+ if (this.sendRateLimitState.resetAt > now) {
+ const sleepFor = this.sendRateLimitState.resetAt - now;
+ this.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);
+ const controller = new AbortController();
+ const interrupted = await Promise.race([
+ sleep2(sleepFor).then(() => false),
+ once2(this, "closed" /* Closed */, { signal: controller.signal }).then(() => true)
+ ]);
+ if (interrupted) {
+ this.debug(["Connection closed while waiting for the send rate limit to reset, re-queueing payload"]);
+ this.sendQueue.shift();
+ return this.send(payload);
+ }
+ controller.abort();
+ }
+ this.sendRateLimitState = getInitialSendRateLimitState();
+ }
+ this.sendQueue.shift();
+ this.connection.send(JSON.stringify(payload));
+ }
+ async identify() {
+ this.debug(["Waiting for identify throttle"]);
+ const controller = new AbortController();
+ const closeHandler = /* @__PURE__ */ __name(() => {
+ controller.abort();
+ }, "closeHandler");
+ this.on("closed" /* Closed */, closeHandler);
+ try {
+ await this.strategy.waitForIdentify(this.id, controller.signal);
+ } catch {
+ if (controller.signal.aborted) {
+ this.debug(["Was waiting for an identify, but the shard closed in the meantime"]);
+ return;
+ }
+ this.debug([
+ "IContextFetchingStrategy#waitForIdentify threw an unknown error.",
+ "If you're using a custom strategy, this is probably nothing to worry about.",
+ "If you're not, please open an issue on GitHub."
+ ]);
+ await this.destroy({
+ reason: "Identify throttling logic failed",
+ recover: 1 /* Resume */
+ });
+ } finally {
+ this.off("closed" /* Closed */, closeHandler);
+ }
+ this.debug([
+ "Identifying",
+ `shard id: ${this.id.toString()}`,
+ `shard count: ${this.strategy.options.shardCount}`,
+ `intents: ${this.strategy.options.intents}`,
+ `compression: ${this.inflate ? "zlib-stream" : this.useIdentifyCompress ? "identify" : "none"}`
+ ]);
+ const d = {
+ token: this.strategy.options.token,
+ properties: this.strategy.options.identifyProperties,
+ intents: this.strategy.options.intents,
+ compress: this.useIdentifyCompress,
+ shard: [this.id, this.strategy.options.shardCount]
+ };
+ if (this.strategy.options.largeThreshold) {
+ d.large_threshold = this.strategy.options.largeThreshold;
+ }
+ if (this.strategy.options.initialPresence) {
+ d.presence = this.strategy.options.initialPresence;
+ }
+ await this.send({
+ op: GatewayOpcodes2.Identify,
+ d
+ });
+ await this.waitForEvent("ready" /* Ready */, this.strategy.options.readyTimeout);
+ }
+ async resume(session) {
+ this.debug([
+ "Resuming session",
+ `resume url: ${session.resumeURL}`,
+ `sequence: ${session.sequence}`,
+ `shard id: ${this.id.toString()}`
+ ]);
+ this.#status = 2 /* Resuming */;
+ this.replayedEvents = 0;
+ return this.send({
+ op: GatewayOpcodes2.Resume,
+ d: {
+ token: this.strategy.options.token,
+ seq: session.sequence,
+ session_id: session.sessionId
+ }
+ });
+ }
+ async heartbeat(requested = false) {
+ if (!this.isAck && !requested) {
+ return this.destroy({ reason: "Zombie connection", recover: 1 /* Resume */ });
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ await this.send({
+ op: GatewayOpcodes2.Heartbeat,
+ d: session?.sequence ?? null
+ });
+ this.lastHeartbeatAt = Date.now();
+ this.isAck = false;
+ }
+ async unpackMessage(data, isBinary) {
+ if (!isBinary) {
+ try {
+ return JSON.parse(data);
+ } catch {
+ return null;
+ }
+ }
+ const decompressable = new Uint8Array(data);
+ if (this.useIdentifyCompress) {
+ return new Promise((resolve2, reject) => {
+ inflate(decompressable, { chunkSize: 65535 }, (err, result) => {
+ if (err) {
+ reject(err);
+ return;
+ }
+ resolve2(JSON.parse(this.textDecoder.decode(result)));
+ });
+ });
+ }
+ if (this.inflate) {
+ const l = decompressable.length;
+ const flush = l >= 4 && decompressable[l - 4] === 0 && decompressable[l - 3] === 0 && decompressable[l - 2] === 255 && decompressable[l - 1] === 255;
+ const zlib = await getZlibSync();
+ this.inflate.push(Buffer2.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);
+ if (this.inflate.err) {
+ this.emit("error" /* Error */, {
+ error: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ""}`)
+ });
+ }
+ if (!flush) {
+ return null;
+ }
+ const { result } = this.inflate;
+ if (!result) {
+ return null;
+ }
+ return JSON.parse(typeof result === "string" ? result : this.textDecoder.decode(result));
+ }
+ this.debug([
+ "Received a message we were unable to decompress",
+ `isBinary: ${isBinary.toString()}`,
+ `useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,
+ `inflate: ${Boolean(this.inflate).toString()}`
+ ]);
+ return null;
+ }
+ async onMessage(data, isBinary) {
+ const payload = await this.unpackMessage(data, isBinary);
+ if (!payload) {
+ return;
+ }
+ switch (payload.op) {
+ case GatewayOpcodes2.Dispatch: {
+ if (this.#status === 2 /* Resuming */) {
+ this.replayedEvents++;
+ }
+ switch (payload.t) {
+ case GatewayDispatchEvents.Ready: {
+ this.#status = 3 /* Ready */;
+ const session2 = {
+ sequence: payload.s,
+ sessionId: payload.d.session_id,
+ shardId: this.id,
+ shardCount: this.strategy.options.shardCount,
+ resumeURL: payload.d.resume_gateway_url
+ };
+ await this.strategy.updateSessionInfo(this.id, session2);
+ this.emit("ready" /* Ready */, { data: payload.d });
+ break;
+ }
+ case GatewayDispatchEvents.Resumed: {
+ this.#status = 3 /* Ready */;
+ this.debug([`Resumed and replayed ${this.replayedEvents} events`]);
+ this.emit("resumed" /* Resumed */);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (session) {
+ if (payload.s > session.sequence) {
+ await this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });
+ }
+ } else {
+ this.debug([
+ `Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`
+ ]);
+ }
+ this.emit("dispatch" /* Dispatch */, { data: payload });
+ break;
+ }
+ case GatewayOpcodes2.Heartbeat: {
+ await this.heartbeat(true);
+ break;
+ }
+ case GatewayOpcodes2.Reconnect: {
+ await this.destroy({
+ reason: "Told to reconnect by Discord",
+ recover: 1 /* Resume */
+ });
+ break;
+ }
+ case GatewayOpcodes2.InvalidSession: {
+ this.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);
+ const session = await this.strategy.retrieveSessionInfo(this.id);
+ if (payload.d && session) {
+ await this.resume(session);
+ } else {
+ await this.destroy({
+ reason: "Invalid session",
+ recover: 0 /* Reconnect */
+ });
+ }
+ break;
+ }
+ case GatewayOpcodes2.Hello: {
+ this.emit("hello" /* Hello */);
+ const jitter = Math.random();
+ const firstWait = Math.floor(payload.d.heartbeat_interval * jitter);
+ this.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);
+ try {
+ const controller = new AbortController();
+ this.initialHeartbeatTimeoutController = controller;
+ await sleep2(firstWait, void 0, { signal: controller.signal });
+ } catch {
+ this.debug(["Cancelled initial heartbeat due to #destroy being called"]);
+ return;
+ } finally {
+ this.initialHeartbeatTimeoutController = null;
+ }
+ await this.heartbeat();
+ this.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);
+ this.heartbeatInterval = setInterval(() => void this.heartbeat(), payload.d.heartbeat_interval);
+ break;
+ }
+ case GatewayOpcodes2.HeartbeatAck: {
+ this.isAck = true;
+ const ackAt = Date.now();
+ this.emit("heartbeat" /* HeartbeatComplete */, {
+ ackAt,
+ heartbeatAt: this.lastHeartbeatAt,
+ latency: ackAt - this.lastHeartbeatAt
+ });
+ break;
+ }
+ }
+ }
+ onError(error) {
+ if ("code" in error && ["ECONNRESET", "ECONNREFUSED"].includes(error.code)) {
+ this.debug(["Failed to connect to the gateway URL specified due to a network error"]);
+ this.failedToConnectDueToNetworkError = true;
+ return;
+ }
+ this.emit("error" /* Error */, { error });
+ }
+ async onClose(code) {
+ this.emit("closed" /* Closed */, { code });
+ switch (code) {
+ case 1e3 /* Normal */: {
+ return this.destroy({
+ code,
+ reason: "Got disconnected by Discord",
+ recover: 0 /* Reconnect */
+ });
+ }
+ case 4200 /* Resuming */: {
+ break;
+ }
+ case GatewayCloseCodes.UnknownError: {
+ this.debug([`An unknown error occurred: ${code}`]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.UnknownOpcode: {
+ this.debug(["An invalid opcode was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.DecodeError: {
+ this.debug(["An invalid payload was sent to Discord."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.NotAuthenticated: {
+ this.debug(["A request was somehow sent before the identify/resume payload."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.AuthenticationFailed: {
+ this.emit("error" /* Error */, {
+ error: new Error("Authentication failed")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.AlreadyAuthenticated: {
+ this.debug(["More than one auth payload was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.InvalidSeq: {
+ this.debug(["An invalid sequence was sent."]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.RateLimited: {
+ this.debug(["The WebSocket rate limit has been hit, this should never happen"]);
+ return this.destroy({ code, recover: 0 /* Reconnect */ });
+ }
+ case GatewayCloseCodes.SessionTimedOut: {
+ this.debug(["Session timed out."]);
+ return this.destroy({ code, recover: 1 /* Resume */ });
+ }
+ case GatewayCloseCodes.InvalidShard: {
+ this.emit("error" /* Error */, {
+ error: new Error("Invalid shard")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.ShardingRequired: {
+ this.emit("error" /* Error */, {
+ error: new Error("Sharding is required")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.InvalidAPIVersion: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used an invalid API version")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.InvalidIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used invalid intents")
+ });
+ return this.destroy({ code });
+ }
+ case GatewayCloseCodes.DisallowedIntents: {
+ this.emit("error" /* Error */, {
+ error: new Error("Used disallowed intents")
+ });
+ return this.destroy({ code });
+ }
+ default: {
+ this.debug([
+ `The gateway closed with an unexpected code ${code}, attempting to ${this.failedToConnectDueToNetworkError ? "reconnect" : "resume"}.`
+ ]);
+ return this.destroy({
+ code,
+ recover: this.failedToConnectDueToNetworkError ? 0 /* Reconnect */ : 1 /* Resume */
+ });
+ }
+ }
+ }
+ debug(messages) {
+ const message = `${messages[0]}${messages.length > 1 ? `
+${messages.slice(1).map((m) => ` ${m}`).join("\n")}` : ""}`;
+ this.emit("debug" /* Debug */, { message });
+ }
+};
+
+// src/strategies/sharding/SimpleShardingStrategy.ts
+var SimpleShardingStrategy = class {
+ static {
+ __name(this, "SimpleShardingStrategy");
+ }
+ manager;
+ shards = new Collection6();
+ constructor(manager) {
+ this.manager = manager;
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.spawn}
+ */
+ async spawn(shardIds) {
+ const strategyOptions = await managerToFetchingStrategyOptions(this.manager);
+ for (const shardId of shardIds) {
+ const strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);
+ const shard = new WebSocketShard(strategy, shardId);
+ for (const event of Object.values(WebSocketShardEvents)) {
+ shard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));
+ }
+ this.shards.set(shardId, shard);
+ }
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.connect}
+ */
+ async connect() {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.connect());
+ }
+ await Promise.all(promises);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.destroy}
+ */
+ async destroy(options) {
+ const promises = [];
+ for (const shard of this.shards.values()) {
+ promises.push(shard.destroy(options));
+ }
+ await Promise.all(promises);
+ this.shards.clear();
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.send}
+ */
+ async send(shardId, payload) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} not found`);
+ }
+ return shard.send(payload);
+ }
+ /**
+ * {@inheritDoc IShardingStrategy.fetchStatus}
+ */
+ async fetchStatus() {
+ return this.shards.mapValues((shard) => shard.status);
+ }
+};
+
+// src/utils/WorkerBootstrapper.ts
+import { isMainThread as isMainThread2, parentPort as parentPort2, workerData } from "node:worker_threads";
+import { Collection as Collection7 } from "@discordjs/collection";
+var WorkerBootstrapper = class {
+ static {
+ __name(this, "WorkerBootstrapper");
+ }
+ /**
+ * The data passed to the worker thread
+ */
+ data = workerData;
+ /**
+ * The shards that are managed by this worker
+ */
+ shards = new Collection7();
+ constructor() {
+ if (isMainThread2) {
+ throw new Error("Expected WorkerBootstrap to not be used within the main thread");
+ }
+ }
+ /**
+ * Helper method to initiate a shard's connection process
+ */
+ async connect(shardId) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.connect();
+ }
+ /**
+ * Helper method to destroy a shard
+ */
+ async destroy(shardId, options) {
+ const shard = this.shards.get(shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${shardId} does not exist`);
+ }
+ await shard.destroy(options);
+ }
+ /**
+ * Helper method to attach event listeners to the parentPort
+ */
+ setupThreadEvents() {
+ parentPort2.on("messageerror", (err) => {
+ throw err;
+ }).on("message", async (payload) => {
+ switch (payload.op) {
+ case 0 /* Connect */: {
+ await this.connect(payload.shardId);
+ const response = {
+ op: 0 /* Connected */,
+ shardId: payload.shardId
+ };
+ parentPort2.postMessage(response);
+ break;
+ }
+ case 1 /* Destroy */: {
+ await this.destroy(payload.shardId, payload.options);
+ const response = {
+ op: 1 /* Destroyed */,
+ shardId: payload.shardId
+ };
+ parentPort2.postMessage(response);
+ break;
+ }
+ case 2 /* Send */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new RangeError(`Shard ${payload.shardId} does not exist`);
+ }
+ await shard.send(payload.payload);
+ break;
+ }
+ case 3 /* SessionInfoResponse */: {
+ break;
+ }
+ case 4 /* ShardIdentifyResponse */: {
+ break;
+ }
+ case 5 /* FetchStatus */: {
+ const shard = this.shards.get(payload.shardId);
+ if (!shard) {
+ throw new Error(`Shard ${payload.shardId} does not exist`);
+ }
+ const response = {
+ op: 6 /* FetchStatusResponse */,
+ status: shard.status,
+ nonce: payload.nonce
+ };
+ parentPort2.postMessage(response);
+ break;
+ }
+ }
+ });
+ }
+ /**
+ * Bootstraps the worker thread with the provided options
+ */
+ async bootstrap(options = {}) {
+ for (const shardId of this.data.shardIds) {
+ const shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);
+ for (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {
+ shard.on(event, (data) => {
+ const payload = {
+ op: 2 /* Event */,
+ event,
+ data,
+ shardId
+ };
+ parentPort2.postMessage(payload);
+ });
+ }
+ await options.shardCallback?.(shard);
+ this.shards.set(shardId, shard);
+ }
+ this.setupThreadEvents();
+ const message = {
+ op: 7 /* WorkerReady */
+ };
+ parentPort2.postMessage(message);
+ }
+};
+
+// src/ws/WebSocketManager.ts
+import { range } from "@discordjs/util";
+import { AsyncEventEmitter as AsyncEventEmitter2 } from "@vladfrangu/async_event_emitter";
+import {
+ Routes
+} from "discord-api-types/v10";
+var WebSocketManager = class extends AsyncEventEmitter2 {
+ static {
+ __name(this, "WebSocketManager");
+ }
+ /**
+ * The options being used by this manager
+ */
+ options;
+ /**
+ * Internal cache for a GET /gateway/bot result
+ */
+ gatewayInformation = null;
+ /**
+ * Internal cache for the shard ids
+ */
+ shardIds = null;
+ /**
+ * Strategy used to manage shards
+ *
+ * @defaultValue `SimpleShardingStrategy`
+ */
+ strategy;
+ constructor(options) {
+ super();
+ this.options = { ...DefaultWebSocketManagerOptions, ...options };
+ this.strategy = this.options.buildStrategy(this);
+ }
+ /**
+ * Fetches the gateway information from Discord - or returns it from cache if available
+ *
+ * @param force - Whether to ignore the cache and force a fresh fetch
+ */
+ async fetchGatewayInformation(force = false) {
+ if (this.gatewayInformation) {
+ if (this.gatewayInformation.expiresAt <= Date.now()) {
+ this.gatewayInformation = null;
+ } else if (!force) {
+ return this.gatewayInformation.data;
+ }
+ }
+ const data = await this.options.rest.get(Routes.gatewayBot());
+ this.gatewayInformation = { data, expiresAt: Date.now() + (data.session_start_limit.reset_after || 5e3) };
+ return this.gatewayInformation.data;
+ }
+ /**
+ * Updates your total shard count on-the-fly, spawning shards as needed
+ *
+ * @param shardCount - The new shard count to use
+ */
+ async updateShardCount(shardCount) {
+ await this.strategy.destroy({ reason: "User is adjusting their shards" });
+ this.options.shardCount = shardCount;
+ const shardIds = await this.getShardIds(true);
+ await this.strategy.spawn(shardIds);
+ return this;
+ }
+ /**
+ * Yields the total number of shards across for your bot, accounting for Discord recommendations
+ */
+ async getShardCount() {
+ if (this.options.shardCount) {
+ return this.options.shardCount;
+ }
+ const shardIds = await this.getShardIds();
+ return Math.max(...shardIds) + 1;
+ }
+ /**
+ * Yields the ids of the shards this manager should manage
+ */
+ async getShardIds(force = false) {
+ if (this.shardIds && !force) {
+ return this.shardIds;
+ }
+ let shardIds;
+ if (this.options.shardIds) {
+ if (Array.isArray(this.options.shardIds)) {
+ shardIds = this.options.shardIds;
+ } else {
+ const { start, end } = this.options.shardIds;
+ shardIds = [...range({ start, end: end + 1 })];
+ }
+ } else {
+ const data = await this.fetchGatewayInformation();
+ shardIds = [...range(this.options.shardCount ?? data.shards)];
+ }
+ this.shardIds = shardIds;
+ return shardIds;
+ }
+ async connect() {
+ const shardCount = await this.getShardCount();
+ const data = await this.fetchGatewayInformation();
+ if (data.session_start_limit.remaining < shardCount) {
+ throw new Error(
+ `Not enough sessions remaining to spawn ${shardCount} shards; only ${data.session_start_limit.remaining} remaining; resets at ${new Date(Date.now() + data.session_start_limit.reset_after).toISOString()}`
+ );
+ }
+ await this.updateShardCount(shardCount);
+ await this.strategy.connect();
+ }
+ destroy(options) {
+ return this.strategy.destroy(options);
+ }
+ send(shardId, payload) {
+ return this.strategy.send(shardId, payload);
+ }
+ fetchStatus() {
+ return this.strategy.fetchStatus();
+ }
+};
+
+// src/index.ts
+var version = "1.0.1";
+export {
+ CloseCodes,
+ CompressionMethod,
+ DefaultDeviceProperty,
+ DefaultWebSocketManagerOptions,
+ Encoding,
+ ImportantGatewayOpcodes,
+ SimpleContextFetchingStrategy,
+ SimpleIdentifyThrottler,
+ SimpleShardingStrategy,
+ WebSocketManager,
+ WebSocketShard,
+ WebSocketShardDestroyRecovery,
+ WebSocketShardEvents,
+ WebSocketShardStatus,
+ WorkerBootstrapper,
+ WorkerContextFetchingStrategy,
+ WorkerReceivePayloadOp,
+ WorkerSendPayloadOp,
+ WorkerShardingStrategy,
+ getInitialSendRateLimitState,
+ managerToFetchingStrategyOptions,
+ version
+};
+//# sourceMappingURL=index.mjs.map \ No newline at end of file
diff --git a/node_modules/@discordjs/ws/dist/index.mjs.map b/node_modules/@discordjs/ws/dist/index.mjs.map
new file mode 100644
index 0000000..5c18bd5
--- /dev/null
+++ b/node_modules/@discordjs/ws/dist/index.mjs.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../../node_modules/tsup/assets/esm_shims.js","../src/strategies/context/IContextFetchingStrategy.ts","../src/strategies/context/SimpleContextFetchingStrategy.ts","../src/strategies/context/WorkerContextFetchingStrategy.ts","../src/strategies/sharding/WorkerShardingStrategy.ts","../src/strategies/sharding/SimpleShardingStrategy.ts","../src/ws/WebSocketShard.ts","../src/utils/constants.ts","../src/throttling/SimpleIdentifyThrottler.ts","../src/utils/WorkerBootstrapper.ts","../src/ws/WebSocketManager.ts","../src/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport { fileURLToPath } from 'url'\nimport path from 'path'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import type { Awaitable } from '@discordjs/util';\nimport type { APIGatewayBotInfo } from 'discord-api-types/v10';\nimport type { SessionInfo, WebSocketManager, WebSocketManagerOptions } from '../../ws/WebSocketManager.js';\n\nexport interface FetchingStrategyOptions\n\textends Omit<\n\t\tWebSocketManagerOptions,\n\t\t| 'buildIdentifyThrottler'\n\t\t| 'buildStrategy'\n\t\t| 'rest'\n\t\t| 'retrieveSessionInfo'\n\t\t| 'shardCount'\n\t\t| 'shardIds'\n\t\t| 'updateSessionInfo'\n\t> {\n\treadonly gatewayInformation: APIGatewayBotInfo;\n\treadonly shardCount: number;\n}\n\n/**\n * Strategies responsible solely for making manager information accessible\n */\nexport interface IContextFetchingStrategy {\n\treadonly options: FetchingStrategyOptions;\n\tretrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;\n\tupdateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;\n\t/**\n\t * Resolves once the given shard should be allowed to identify\n\t * This should correctly handle the signal and reject with an abort error if the operation is aborted.\n\t * Other errors will cause the shard to reconnect.\n\t */\n\twaitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;\n}\n\nexport async function managerToFetchingStrategyOptions(manager: WebSocketManager): Promise<FetchingStrategyOptions> {\n\t/* eslint-disable @typescript-eslint/unbound-method */\n\tconst {\n\t\tbuildIdentifyThrottler,\n\t\tbuildStrategy,\n\t\tretrieveSessionInfo,\n\t\tupdateSessionInfo,\n\t\tshardCount,\n\t\tshardIds,\n\t\trest,\n\t\t...managerOptions\n\t} = manager.options;\n\t/* eslint-enable @typescript-eslint/unbound-method */\n\n\treturn {\n\t\t...managerOptions,\n\t\tgatewayInformation: await manager.fetchGatewayInformation(),\n\t\tshardCount: await manager.getShardCount(),\n\t};\n}\n","import type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class SimpleContextFetchingStrategy implements IContextFetchingStrategy {\n\t// This strategy assumes every shard is running under the same process - therefore we need a single\n\t// IdentifyThrottler per manager.\n\tprivate static throttlerCache = new WeakMap<WebSocketManager, IIdentifyThrottler>();\n\n\tprivate static async ensureThrottler(manager: WebSocketManager): Promise<IIdentifyThrottler> {\n\t\tconst throttler = SimpleContextFetchingStrategy.throttlerCache.get(manager);\n\t\tif (throttler) {\n\t\t\treturn throttler;\n\t\t}\n\n\t\tconst newThrottler = await manager.options.buildIdentifyThrottler(manager);\n\t\tSimpleContextFetchingStrategy.throttlerCache.set(manager, newThrottler);\n\n\t\treturn newThrottler;\n\t}\n\n\tpublic constructor(private readonly manager: WebSocketManager, public readonly options: FetchingStrategyOptions) {}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\treturn this.manager.options.retrieveSessionInfo(shardId);\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\treturn this.manager.options.updateSessionInfo(shardId, sessionInfo);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst throttler = await SimpleContextFetchingStrategy.ensureThrottler(this.manager);\n\t\tawait throttler.waitForIdentify(shardId, signal);\n\t}\n}\n","import { isMainThread, parentPort } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { SessionInfo } from '../../ws/WebSocketManager.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../sharding/WorkerShardingStrategy.js';\nimport type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';\n\nexport class WorkerContextFetchingStrategy implements IContextFetchingStrategy {\n\tprivate readonly sessionPromises = new Collection<number, (session: SessionInfo | null) => void>();\n\n\tprivate readonly waitForIdentifyPromises = new Collection<\n\t\tnumber,\n\t\t{ reject(error: unknown): void; resolve(): void; signal: AbortSignal }\n\t>();\n\n\tpublic constructor(public readonly options: FetchingStrategyOptions) {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Cannot instantiate WorkerContextFetchingStrategy on the main thread');\n\t\t}\n\n\t\tparentPort!.on('message', (payload: WorkerSendPayload) => {\n\t\t\tif (payload.op === WorkerSendPayloadOp.SessionInfoResponse) {\n\t\t\t\tthis.sessionPromises.get(payload.nonce)?.(payload.session);\n\t\t\t\tthis.sessionPromises.delete(payload.nonce);\n\t\t\t}\n\n\t\t\tif (payload.op === WorkerSendPayloadOp.ShardIdentifyResponse) {\n\t\t\t\tconst promise = this.waitForIdentifyPromises.get(payload.nonce);\n\t\t\t\tif (payload.ok) {\n\t\t\t\t\tpromise?.resolve();\n\t\t\t\t} else {\n\t\t\t\t\t// We need to make sure we reject with an abort error\n\t\t\t\t\tpromise?.reject(promise.signal.reason);\n\t\t\t\t}\n\n\t\t\t\tthis.waitForIdentifyPromises.delete(payload.nonce);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n\t\tconst nonce = Math.random();\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.RetrieveSessionInfo,\n\t\t\tshardId,\n\t\t\tnonce,\n\t\t};\n\t\t// eslint-disable-next-line no-promise-executor-return\n\t\tconst promise = new Promise<SessionInfo | null>((resolve) => this.sessionPromises.set(nonce, resolve));\n\t\tparentPort!.postMessage(payload);\n\t\treturn promise;\n\t}\n\n\tpublic updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null) {\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.UpdateSessionInfo,\n\t\t\tshardId,\n\t\t\tsession: sessionInfo,\n\t\t};\n\t\tparentPort!.postMessage(payload);\n\t}\n\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst nonce = Math.random();\n\n\t\tconst payload: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WaitForIdentify,\n\t\t\tnonce,\n\t\t\tshardId,\n\t\t};\n\t\tconst promise = new Promise<void>((resolve, reject) =>\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tthis.waitForIdentifyPromises.set(nonce, { signal, resolve, reject }),\n\t\t);\n\n\t\tparentPort!.postMessage(payload);\n\n\t\tconst listener = () => {\n\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\top: WorkerReceivePayloadOp.CancelIdentify,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\tparentPort!.postMessage(payload);\n\t\t};\n\n\t\tsignal.addEventListener('abort', listener);\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} finally {\n\t\t\tsignal.removeEventListener('abort', listener);\n\t\t}\n\t}\n}\n","import { once } from 'node:events';\nimport { join, isAbsolute, resolve } from 'node:path';\nimport { Worker } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { IIdentifyThrottler } from '../../throttling/IIdentifyThrottler.js';\nimport type { SessionInfo, WebSocketManager } from '../../ws/WebSocketManager.js';\nimport type {\n\tWebSocketShardDestroyOptions,\n\tWebSocketShardEvents,\n\tWebSocketShardStatus,\n} from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions, type FetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\nexport interface WorkerData extends FetchingStrategyOptions {\n\tshardIds: number[];\n}\n\nexport enum WorkerSendPayloadOp {\n\tConnect,\n\tDestroy,\n\tSend,\n\tSessionInfoResponse,\n\tShardIdentifyResponse,\n\tFetchStatus,\n}\n\nexport type WorkerSendPayload =\n\t| { nonce: number; ok: boolean; op: WorkerSendPayloadOp.ShardIdentifyResponse }\n\t| { nonce: number; op: WorkerSendPayloadOp.FetchStatus; shardId: number }\n\t| { nonce: number; op: WorkerSendPayloadOp.SessionInfoResponse; session: SessionInfo | null }\n\t| { op: WorkerSendPayloadOp.Connect; shardId: number }\n\t| { op: WorkerSendPayloadOp.Destroy; options?: WebSocketShardDestroyOptions; shardId: number }\n\t| { op: WorkerSendPayloadOp.Send; payload: GatewaySendPayload; shardId: number };\n\nexport enum WorkerReceivePayloadOp {\n\tConnected,\n\tDestroyed,\n\tEvent,\n\tRetrieveSessionInfo,\n\tUpdateSessionInfo,\n\tWaitForIdentify,\n\tFetchStatusResponse,\n\tWorkerReady,\n\tCancelIdentify,\n}\n\nexport type WorkerReceivePayload =\n\t// Can't seem to get a type-safe union based off of the event, so I'm sadly leaving data as any for now\n\t| { data: any; event: WebSocketShardEvents; op: WorkerReceivePayloadOp.Event; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.CancelIdentify }\n\t| { nonce: number; op: WorkerReceivePayloadOp.FetchStatusResponse; status: WebSocketShardStatus }\n\t| { nonce: number; op: WorkerReceivePayloadOp.RetrieveSessionInfo; shardId: number }\n\t| { nonce: number; op: WorkerReceivePayloadOp.WaitForIdentify; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Connected; shardId: number }\n\t| { op: WorkerReceivePayloadOp.Destroyed; shardId: number }\n\t| { op: WorkerReceivePayloadOp.UpdateSessionInfo; session: SessionInfo | null; shardId: number }\n\t| { op: WorkerReceivePayloadOp.WorkerReady };\n\n/**\n * Options for a {@link WorkerShardingStrategy}\n */\nexport interface WorkerShardingStrategyOptions {\n\t/**\n\t * Dictates how many shards should be spawned per worker thread.\n\t */\n\tshardsPerWorker: number | 'all';\n\t/**\n\t * Path to the worker file to use. The worker requires quite a bit of setup, it is recommended you leverage the {@link WorkerBootstrapper} class.\n\t */\n\tworkerPath?: string;\n}\n\n/**\n * Strategy used to spawn threads in worker_threads\n */\nexport class WorkerShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly options: WorkerShardingStrategyOptions;\n\n\t#workers: Worker[] = [];\n\n\treadonly #workerByShardId = new Collection<number, Worker>();\n\n\tprivate readonly connectPromises = new Collection<number, () => void>();\n\n\tprivate readonly destroyPromises = new Collection<number, () => void>();\n\n\tprivate readonly fetchStatusPromises = new Collection<number, (status: WebSocketShardStatus) => void>();\n\n\tprivate readonly waitForIdentifyControllers = new Collection<number, AbortController>();\n\n\tprivate throttler?: IIdentifyThrottler;\n\n\tpublic constructor(manager: WebSocketManager, options: WorkerShardingStrategyOptions) {\n\t\tthis.manager = manager;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst shardsPerWorker = this.options.shardsPerWorker === 'all' ? shardIds.length : this.options.shardsPerWorker;\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tconst loops = Math.ceil(shardIds.length / shardsPerWorker);\n\t\tconst promises: Promise<void>[] = [];\n\n\t\tfor (let idx = 0; idx < loops; idx++) {\n\t\t\tconst slice = shardIds.slice(idx * shardsPerWorker, (idx + 1) * shardsPerWorker);\n\t\t\tconst workerData: WorkerData = {\n\t\t\t\t...strategyOptions,\n\t\t\t\tshardIds: slice,\n\t\t\t};\n\n\t\t\tpromises.push(this.setupWorker(workerData));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Connect,\n\t\t\t\tshardId,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<void>((resolve) => this.connectPromises.set(shardId, resolve));\n\t\t\tworker.postMessage(payload);\n\t\t\tpromises.push(promise);\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options: Omit<WebSocketShardDestroyOptions, 'recover'> = {}) {\n\t\tconst promises = [];\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.Destroy,\n\t\t\t\tshardId,\n\t\t\t\toptions,\n\t\t\t};\n\n\t\t\tpromises.push(\n\t\t\t\t// eslint-disable-next-line no-promise-executor-return, promise/prefer-await-to-then\n\t\t\t\tnew Promise<void>((resolve) => this.destroyPromises.set(shardId, resolve)).then(async () => worker.terminate()),\n\t\t\t);\n\t\t\tworker.postMessage(payload);\n\t\t}\n\n\t\tthis.#workers = [];\n\t\tthis.#workerByShardId.clear();\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic send(shardId: number, data: GatewaySendPayload) {\n\t\tconst worker = this.#workerByShardId.get(shardId);\n\t\tif (!worker) {\n\t\t\tthrow new Error(`No worker found for shard ${shardId}`);\n\t\t}\n\n\t\tconst payload: WorkerSendPayload = {\n\t\t\top: WorkerSendPayloadOp.Send,\n\t\t\tshardId,\n\t\t\tpayload: data,\n\t\t};\n\t\tworker.postMessage(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\tconst statuses = new Collection<number, WebSocketShardStatus>();\n\n\t\tfor (const [shardId, worker] of this.#workerByShardId.entries()) {\n\t\t\tconst nonce = Math.random();\n\t\t\tconst payload: WorkerSendPayload = {\n\t\t\t\top: WorkerSendPayloadOp.FetchStatus,\n\t\t\t\tshardId,\n\t\t\t\tnonce,\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-promise-executor-return\n\t\t\tconst promise = new Promise<WebSocketShardStatus>((resolve) => this.fetchStatusPromises.set(nonce, resolve));\n\t\t\tworker.postMessage(payload);\n\n\t\t\tconst status = await promise;\n\t\t\tstatuses.set(shardId, status);\n\t\t}\n\n\t\treturn statuses;\n\t}\n\n\tprivate async setupWorker(workerData: WorkerData) {\n\t\tconst worker = new Worker(this.resolveWorkerPath(), { workerData });\n\n\t\tawait once(worker, 'online');\n\t\t// We do this in case the user has any potentially long running code in their worker\n\t\tawait this.waitForWorkerReady(worker);\n\n\t\tworker\n\t\t\t.on('error', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerReceivePayload) => this.onMessage(worker, payload));\n\n\t\tthis.#workers.push(worker);\n\t\tfor (const shardId of workerData.shardIds) {\n\t\t\tthis.#workerByShardId.set(shardId, worker);\n\t\t}\n\t}\n\n\tprivate resolveWorkerPath(): string {\n\t\tconst path = this.options.workerPath;\n\n\t\tif (!path) {\n\t\t\treturn join(__dirname, 'defaultWorker.js');\n\t\t}\n\n\t\tif (isAbsolute(path)) {\n\t\t\treturn path;\n\t\t}\n\n\t\tif (/^\\.\\.?[/\\\\]/.test(path)) {\n\t\t\treturn resolve(path);\n\t\t}\n\n\t\ttry {\n\t\t\treturn require.resolve(path);\n\t\t} catch {\n\t\t\treturn resolve(path);\n\t\t}\n\t}\n\n\tprivate async waitForWorkerReady(worker: Worker): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst handler = (payload: WorkerReceivePayload) => {\n\t\t\t\tif (payload.op === WorkerReceivePayloadOp.WorkerReady) {\n\t\t\t\t\tresolve();\n\t\t\t\t\tworker.off('message', handler);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tworker.on('message', handler);\n\t\t});\n\t}\n\n\tprivate async onMessage(worker: Worker, payload: WorkerReceivePayload) {\n\t\tswitch (payload.op) {\n\t\t\tcase WorkerReceivePayloadOp.Connected: {\n\t\t\t\tthis.connectPromises.get(payload.shardId)?.();\n\t\t\t\tthis.connectPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Destroyed: {\n\t\t\t\tthis.destroyPromises.get(payload.shardId)?.();\n\t\t\t\tthis.destroyPromises.delete(payload.shardId);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.Event: {\n\t\t\t\tthis.manager.emit(payload.event, { ...payload.data, shardId: payload.shardId });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.RetrieveSessionInfo: {\n\t\t\t\tconst session = await this.manager.options.retrieveSessionInfo(payload.shardId);\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.SessionInfoResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tsession,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.UpdateSessionInfo: {\n\t\t\t\tawait this.manager.options.updateSessionInfo(payload.shardId, payload.session);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WaitForIdentify: {\n\t\t\t\tconst throttler = await this.ensureThrottler();\n\n\t\t\t\t// If this rejects it means we aborted, in which case we reply elsewhere.\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.waitForIdentifyControllers.set(payload.nonce, controller);\n\t\t\t\t\tawait throttler.waitForIdentify(payload.shardId, controller.signal);\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: true,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.FetchStatusResponse: {\n\t\t\t\tthis.fetchStatusPromises.get(payload.nonce)?.(payload.status);\n\t\t\t\tthis.fetchStatusPromises.delete(payload.nonce);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.WorkerReady: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WorkerReceivePayloadOp.CancelIdentify: {\n\t\t\t\tthis.waitForIdentifyControllers.get(payload.nonce)?.abort();\n\t\t\t\tthis.waitForIdentifyControllers.delete(payload.nonce);\n\n\t\t\t\tconst response: WorkerSendPayload = {\n\t\t\t\t\top: WorkerSendPayloadOp.ShardIdentifyResponse,\n\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\tok: false,\n\t\t\t\t};\n\t\t\t\tworker.postMessage(response);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async ensureThrottler(): Promise<IIdentifyThrottler> {\n\t\tthis.throttler ??= await this.manager.options.buildIdentifyThrottler(this.manager);\n\t\treturn this.throttler;\n\t}\n}\n","import { Collection } from '@discordjs/collection';\nimport type { GatewaySendPayload } from 'discord-api-types/v10';\nimport type { WebSocketManager } from '../../ws/WebSocketManager.js';\nimport { WebSocketShard, WebSocketShardEvents, type WebSocketShardDestroyOptions } from '../../ws/WebSocketShard.js';\nimport { managerToFetchingStrategyOptions } from '../context/IContextFetchingStrategy.js';\nimport { SimpleContextFetchingStrategy } from '../context/SimpleContextFetchingStrategy.js';\nimport type { IShardingStrategy } from './IShardingStrategy.js';\n\n/**\n * Simple strategy that just spawns shards in the current process\n */\nexport class SimpleShardingStrategy implements IShardingStrategy {\n\tprivate readonly manager: WebSocketManager;\n\n\tprivate readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor(manager: WebSocketManager) {\n\t\tthis.manager = manager;\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.spawn}\n\t */\n\tpublic async spawn(shardIds: number[]) {\n\t\tconst strategyOptions = await managerToFetchingStrategyOptions(this.manager);\n\n\t\tfor (const shardId of shardIds) {\n\t\t\tconst strategy = new SimpleContextFetchingStrategy(this.manager, strategyOptions);\n\t\t\tconst shard = new WebSocketShard(strategy, shardId);\n\t\t\tfor (const event of Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Intentional\n\t\t\t\tshard.on(event, (payload) => this.manager.emit(event, { ...payload, shardId }));\n\t\t\t}\n\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.connect}\n\t */\n\tpublic async connect() {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.connect());\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.destroy}\n\t */\n\tpublic async destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\tconst promises = [];\n\n\t\tfor (const shard of this.shards.values()) {\n\t\t\tpromises.push(shard.destroy(options));\n\t\t}\n\n\t\tawait Promise.all(promises);\n\t\tthis.shards.clear();\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.send}\n\t */\n\tpublic async send(shardId: number, payload: GatewaySendPayload) {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} not found`);\n\t\t}\n\n\t\treturn shard.send(payload);\n\t}\n\n\t/**\n\t * {@inheritDoc IShardingStrategy.fetchStatus}\n\t */\n\tpublic async fetchStatus() {\n\t\treturn this.shards.mapValues((shard) => shard.status);\n\t}\n}\n","/* eslint-disable id-length */\nimport { Buffer } from 'node:buffer';\nimport { once } from 'node:events';\nimport { clearInterval, clearTimeout, setInterval, setTimeout } from 'node:timers';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { URLSearchParams } from 'node:url';\nimport { TextDecoder } from 'node:util';\nimport { inflate } from 'node:zlib';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tGatewayCloseCodes,\n\tGatewayDispatchEvents,\n\tGatewayOpcodes,\n\ttype GatewayDispatchPayload,\n\ttype GatewayIdentifyData,\n\ttype GatewayReadyDispatchData,\n\ttype GatewayReceivePayload,\n\ttype GatewaySendPayload,\n} from 'discord-api-types/v10';\nimport { WebSocket, type Data } from 'ws';\nimport type { Inflate } from 'zlib-sync';\nimport type { IContextFetchingStrategy } from '../strategies/context/IContextFetchingStrategy.js';\nimport { ImportantGatewayOpcodes, getInitialSendRateLimitState } from '../utils/constants.js';\nimport type { SessionInfo } from './WebSocketManager.js';\n\n// eslint-disable-next-line promise/prefer-await-to-then\nconst getZlibSync = lazy(async () => import('zlib-sync').then((mod) => mod.default).catch(() => null));\n\nexport enum WebSocketShardEvents {\n\tClosed = 'closed',\n\tDebug = 'debug',\n\tDispatch = 'dispatch',\n\tError = 'error',\n\tHeartbeatComplete = 'heartbeat',\n\tHello = 'hello',\n\tReady = 'ready',\n\tResumed = 'resumed',\n}\n\nexport enum WebSocketShardStatus {\n\tIdle,\n\tConnecting,\n\tResuming,\n\tReady,\n}\n\nexport enum WebSocketShardDestroyRecovery {\n\tReconnect,\n\tResume,\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport type WebSocketShardEventsMap = {\n\t[WebSocketShardEvents.Closed]: [{ code: number }];\n\t[WebSocketShardEvents.Debug]: [payload: { message: string }];\n\t[WebSocketShardEvents.Dispatch]: [payload: { data: GatewayDispatchPayload }];\n\t[WebSocketShardEvents.Error]: [payload: { error: Error }];\n\t[WebSocketShardEvents.Hello]: [];\n\t[WebSocketShardEvents.Ready]: [payload: { data: GatewayReadyDispatchData }];\n\t[WebSocketShardEvents.Resumed]: [];\n\t[WebSocketShardEvents.HeartbeatComplete]: [payload: { ackAt: number; heartbeatAt: number; latency: number }];\n};\n\nexport interface WebSocketShardDestroyOptions {\n\tcode?: number;\n\treason?: string;\n\trecover?: WebSocketShardDestroyRecovery;\n}\n\nexport enum CloseCodes {\n\tNormal = 1_000,\n\tResuming = 4_200,\n}\n\nexport interface SendRateLimitState {\n\tremaining: number;\n\tresetAt: number;\n}\n\n// TODO(vladfrangu): enable this once https://github.com/oven-sh/bun/issues/3392 is solved\n// const WebSocketConstructor: typeof WebSocket = shouldUseGlobalFetchAndWebSocket()\n// \t? (globalThis as any).WebSocket\n// \t: WebSocket;\nconst WebSocketConstructor: typeof WebSocket = WebSocket;\n\nexport class WebSocketShard extends AsyncEventEmitter<WebSocketShardEventsMap> {\n\tprivate connection: WebSocket | null = null;\n\n\tprivate useIdentifyCompress = false;\n\n\tprivate inflate: Inflate | null = null;\n\n\tprivate readonly textDecoder = new TextDecoder();\n\n\tprivate replayedEvents = 0;\n\n\tprivate isAck = true;\n\n\tprivate sendRateLimitState: SendRateLimitState = getInitialSendRateLimitState();\n\n\tprivate initialHeartbeatTimeoutController: AbortController | null = null;\n\n\tprivate heartbeatInterval: NodeJS.Timer | null = null;\n\n\tprivate lastHeartbeatAt = -1;\n\n\t// Indicates whether the shard has already resolved its original connect() call\n\tprivate initialConnectResolved = false;\n\n\t// Indicates if we failed to connect to the ws url (ECONNREFUSED/ECONNRESET)\n\tprivate failedToConnectDueToNetworkError = false;\n\n\tprivate readonly sendQueue = new AsyncQueue();\n\n\tprivate readonly timeoutAbortControllers = new Collection<WebSocketShardEvents, AbortController>();\n\n\tprivate readonly strategy: IContextFetchingStrategy;\n\n\tpublic readonly id: number;\n\n\t#status: WebSocketShardStatus = WebSocketShardStatus.Idle;\n\n\tpublic get status(): WebSocketShardStatus {\n\t\treturn this.#status;\n\t}\n\n\tpublic constructor(strategy: IContextFetchingStrategy, id: number) {\n\t\tsuper();\n\t\tthis.strategy = strategy;\n\t\tthis.id = id;\n\t}\n\n\tpublic async connect() {\n\t\tconst controller = new AbortController();\n\t\tlet promise;\n\n\t\tif (!this.initialConnectResolved) {\n\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\tpromise = Promise.race([\n\t\t\t\tonce(this, WebSocketShardEvents.Ready, { signal: controller.signal }),\n\t\t\t\tonce(this, WebSocketShardEvents.Resumed, { signal: controller.signal }),\n\t\t\t]);\n\t\t}\n\n\t\tvoid this.internalConnect();\n\n\t\ttry {\n\t\t\tawait promise;\n\t\t} catch ({ error }: any) {\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// cleanup hanging listeners\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.initialConnectResolved = true;\n\t}\n\n\tprivate async internalConnect() {\n\t\tif (this.#status !== WebSocketShardStatus.Idle) {\n\t\t\tthrow new Error(\"Tried to connect a shard that wasn't idle\");\n\t\t}\n\n\t\tconst { version, encoding, compression } = this.strategy.options;\n\t\tconst params = new URLSearchParams({ v: version, encoding });\n\t\tif (compression) {\n\t\t\tconst zlib = await getZlibSync();\n\t\t\tif (zlib) {\n\t\t\t\tparams.append('compress', compression);\n\t\t\t\tthis.inflate = new zlib.Inflate({\n\t\t\t\t\tchunkSize: 65_535,\n\t\t\t\t\tto: 'string',\n\t\t\t\t});\n\t\t\t} else if (!this.useIdentifyCompress) {\n\t\t\t\tthis.useIdentifyCompress = true;\n\t\t\t\tconsole.warn(\n\t\t\t\t\t'WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress',\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tconst url = `${session?.resumeURL ?? this.strategy.options.gatewayInformation.url}?${params.toString()}`;\n\n\t\tthis.debug([`Connecting to ${url}`]);\n\n\t\tconst connection = new WebSocketConstructor(url, {\n\t\t\thandshakeTimeout: this.strategy.options.handshakeTimeout ?? undefined,\n\t\t});\n\n\t\tconnection.binaryType = 'arraybuffer';\n\n\t\tconnection.onmessage = (event) => {\n\t\t\tvoid this.onMessage(event.data, event.data instanceof ArrayBuffer);\n\t\t};\n\n\t\tconnection.onerror = (event) => {\n\t\t\tthis.onError(event.error);\n\t\t};\n\n\t\tconnection.onclose = (event) => {\n\t\t\tvoid this.onClose(event.code);\n\t\t};\n\n\t\tthis.connection = connection;\n\n\t\tthis.#status = WebSocketShardStatus.Connecting;\n\n\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\n\t\tconst { ok } = await this.waitForEvent(WebSocketShardEvents.Hello, this.strategy.options.helloTimeout);\n\t\tif (!ok) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (session?.shardCount === this.strategy.options.shardCount) {\n\t\t\tawait this.resume(session);\n\t\t} else {\n\t\t\tawait this.identify();\n\t\t}\n\t}\n\n\tpublic async destroy(options: WebSocketShardDestroyOptions = {}) {\n\t\tif (this.#status === WebSocketShardStatus.Idle) {\n\t\t\tthis.debug(['Tried to destroy a shard that was idle']);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!options.code) {\n\t\t\toptions.code = options.recover === WebSocketShardDestroyRecovery.Resume ? CloseCodes.Resuming : CloseCodes.Normal;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Destroying shard',\n\t\t\t`Reason: ${options.reason ?? 'none'}`,\n\t\t\t`Code: ${options.code}`,\n\t\t\t`Recover: ${options.recover === undefined ? 'none' : WebSocketShardDestroyRecovery[options.recover]!}`,\n\t\t]);\n\n\t\t// Reset state\n\t\tthis.isAck = true;\n\t\tif (this.heartbeatInterval) {\n\t\t\tclearInterval(this.heartbeatInterval);\n\t\t}\n\n\t\tif (this.initialHeartbeatTimeoutController) {\n\t\t\tthis.initialHeartbeatTimeoutController.abort();\n\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t}\n\n\t\tthis.lastHeartbeatAt = -1;\n\n\t\tfor (const controller of this.timeoutAbortControllers.values()) {\n\t\t\tcontroller.abort();\n\t\t}\n\n\t\tthis.timeoutAbortControllers.clear();\n\n\t\tthis.failedToConnectDueToNetworkError = false;\n\n\t\t// Clear session state if applicable\n\t\tif (options.recover !== WebSocketShardDestroyRecovery.Resume) {\n\t\t\tawait this.strategy.updateSessionInfo(this.id, null);\n\t\t}\n\n\t\tif (this.connection) {\n\t\t\t// No longer need to listen to messages\n\t\t\tthis.connection.onmessage = null;\n\t\t\t// Prevent a reconnection loop by unbinding the main close event\n\t\t\tthis.connection.onclose = null;\n\n\t\t\tconst shouldClose = this.connection.readyState === WebSocket.OPEN;\n\n\t\t\tthis.debug([\n\t\t\t\t'Connection status during destroy',\n\t\t\t\t`Needs closing: ${shouldClose}`,\n\t\t\t\t`Ready state: ${this.connection.readyState}`,\n\t\t\t]);\n\n\t\t\tif (shouldClose) {\n\t\t\t\tlet outerResolve: () => void;\n\t\t\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\t\t\touterResolve = resolve;\n\t\t\t\t});\n\n\t\t\t\tthis.connection.onclose = outerResolve!;\n\n\t\t\t\tthis.connection.close(options.code, options.reason);\n\n\t\t\t\tawait promise;\n\t\t\t\tthis.emit(WebSocketShardEvents.Closed, { code: options.code });\n\t\t\t}\n\n\t\t\t// Lastly, remove the error event.\n\t\t\t// Doing this earlier would cause a hard crash in case an error event fired on our `close` call\n\t\t\tthis.connection.onerror = null;\n\t\t} else {\n\t\t\tthis.debug(['Destroying a shard that has no connection; please open an issue on GitHub']);\n\t\t}\n\n\t\tthis.#status = WebSocketShardStatus.Idle;\n\n\t\tif (options.recover !== undefined) {\n\t\t\t// There's cases (like no internet connection) where we immediately fail to connect,\n\t\t\t// causing a very fast and draining reconnection loop.\n\t\t\tawait sleep(500);\n\t\t\treturn this.internalConnect();\n\t\t}\n\t}\n\n\tprivate async waitForEvent(event: WebSocketShardEvents, timeoutDuration?: number | null): Promise<{ ok: boolean }> {\n\t\tthis.debug([`Waiting for event ${event} ${timeoutDuration ? `for ${timeoutDuration}ms` : 'indefinitely'}`]);\n\t\tconst timeoutController = new AbortController();\n\t\tconst timeout = timeoutDuration ? setTimeout(() => timeoutController.abort(), timeoutDuration).unref() : null;\n\n\t\tthis.timeoutAbortControllers.set(event, timeoutController);\n\n\t\tconst closeController = new AbortController();\n\n\t\ttry {\n\t\t\t// If the first promise resolves, all is well. If the 2nd promise resolves,\n\t\t\t// the shard has meanwhile closed. In that case, a destroy is already ongoing, so we just need to\n\t\t\t// return false. Meanwhile, if something rejects (error event) or the first controller is aborted,\n\t\t\t// we enter the catch block and trigger a destroy there.\n\t\t\tconst closed = await Promise.race<boolean>([\n\t\t\t\tonce(this, event, { signal: timeoutController.signal }).then(() => false),\n\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: closeController.signal }).then(() => true),\n\t\t\t]);\n\n\t\t\treturn { ok: !closed };\n\t\t} catch {\n\t\t\t// If we're here because of other reasons, we need to destroy the shard\n\t\t\tvoid this.destroy({\n\t\t\t\tcode: CloseCodes.Normal,\n\t\t\t\treason: 'Something timed out or went wrong while waiting for an event',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t});\n\n\t\t\treturn { ok: false };\n\t\t} finally {\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\n\t\t\tthis.timeoutAbortControllers.delete(event);\n\n\t\t\t// Clean up the close listener to not leak memory\n\t\t\tif (!closeController.signal.aborted) {\n\t\t\t\tcloseController.abort();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async send(payload: GatewaySendPayload): Promise<void> {\n\t\tif (!this.connection) {\n\t\t\tthrow new Error(\"WebSocketShard wasn't connected\");\n\t\t}\n\n\t\tif (this.#status !== WebSocketShardStatus.Ready && !ImportantGatewayOpcodes.has(payload.op)) {\n\t\t\tthis.debug(['Tried to send a non-crucial payload before the shard was ready, waiting']);\n\t\t\t// This will throw if the shard throws an error event in the meantime, just requeue the payload\n\t\t\ttry {\n\t\t\t\tawait once(this, WebSocketShardEvents.Ready);\n\t\t\t} catch {\n\t\t\t\treturn this.send(payload);\n\t\t\t}\n\t\t}\n\n\t\tawait this.sendQueue.wait();\n\n\t\tif (--this.sendRateLimitState.remaining <= 0) {\n\t\t\tconst now = Date.now();\n\n\t\t\tif (this.sendRateLimitState.resetAt > now) {\n\t\t\t\tconst sleepFor = this.sendRateLimitState.resetAt - now;\n\n\t\t\t\tthis.debug([`Was about to hit the send rate limit, sleeping for ${sleepFor}ms`]);\n\t\t\t\tconst controller = new AbortController();\n\n\t\t\t\t// Sleep for the remaining time, but if the connection closes in the meantime, we shouldn't wait the remainder to avoid blocking the new conn\n\t\t\t\tconst interrupted = await Promise.race([\n\t\t\t\t\tsleep(sleepFor).then(() => false),\n\t\t\t\t\tonce(this, WebSocketShardEvents.Closed, { signal: controller.signal }).then(() => true),\n\t\t\t\t]);\n\n\t\t\t\tif (interrupted) {\n\t\t\t\t\tthis.debug(['Connection closed while waiting for the send rate limit to reset, re-queueing payload']);\n\t\t\t\t\tthis.sendQueue.shift();\n\t\t\t\t\treturn this.send(payload);\n\t\t\t\t}\n\n\t\t\t\t// This is so the listener from the `once` call is removed\n\t\t\t\tcontroller.abort();\n\t\t\t}\n\n\t\t\tthis.sendRateLimitState = getInitialSendRateLimitState();\n\t\t}\n\n\t\tthis.sendQueue.shift();\n\t\tthis.connection.send(JSON.stringify(payload));\n\t}\n\n\tprivate async identify() {\n\t\tthis.debug(['Waiting for identify throttle']);\n\n\t\tconst controller = new AbortController();\n\t\tconst closeHandler = () => {\n\t\t\tcontroller.abort();\n\t\t};\n\n\t\tthis.on(WebSocketShardEvents.Closed, closeHandler);\n\n\t\ttry {\n\t\t\tawait this.strategy.waitForIdentify(this.id, controller.signal);\n\t\t} catch {\n\t\t\tif (controller.signal.aborted) {\n\t\t\t\tthis.debug(['Was waiting for an identify, but the shard closed in the meantime']);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.debug([\n\t\t\t\t'IContextFetchingStrategy#waitForIdentify threw an unknown error.',\n\t\t\t\t\"If you're using a custom strategy, this is probably nothing to worry about.\",\n\t\t\t\t\"If you're not, please open an issue on GitHub.\",\n\t\t\t]);\n\n\t\t\tawait this.destroy({\n\t\t\t\treason: 'Identify throttling logic failed',\n\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t});\n\t\t} finally {\n\t\t\tthis.off(WebSocketShardEvents.Closed, closeHandler);\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Identifying',\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t\t`shard count: ${this.strategy.options.shardCount}`,\n\t\t\t`intents: ${this.strategy.options.intents}`,\n\t\t\t`compression: ${this.inflate ? 'zlib-stream' : this.useIdentifyCompress ? 'identify' : 'none'}`,\n\t\t]);\n\n\t\tconst d: GatewayIdentifyData = {\n\t\t\ttoken: this.strategy.options.token,\n\t\t\tproperties: this.strategy.options.identifyProperties,\n\t\t\tintents: this.strategy.options.intents,\n\t\t\tcompress: this.useIdentifyCompress,\n\t\t\tshard: [this.id, this.strategy.options.shardCount],\n\t\t};\n\n\t\tif (this.strategy.options.largeThreshold) {\n\t\t\td.large_threshold = this.strategy.options.largeThreshold;\n\t\t}\n\n\t\tif (this.strategy.options.initialPresence) {\n\t\t\td.presence = this.strategy.options.initialPresence;\n\t\t}\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Identify,\n\t\t\td,\n\t\t});\n\n\t\tawait this.waitForEvent(WebSocketShardEvents.Ready, this.strategy.options.readyTimeout);\n\t}\n\n\tprivate async resume(session: SessionInfo) {\n\t\tthis.debug([\n\t\t\t'Resuming session',\n\t\t\t`resume url: ${session.resumeURL}`,\n\t\t\t`sequence: ${session.sequence}`,\n\t\t\t`shard id: ${this.id.toString()}`,\n\t\t]);\n\n\t\tthis.#status = WebSocketShardStatus.Resuming;\n\t\tthis.replayedEvents = 0;\n\t\treturn this.send({\n\t\t\top: GatewayOpcodes.Resume,\n\t\t\td: {\n\t\t\t\ttoken: this.strategy.options.token,\n\t\t\t\tseq: session.sequence,\n\t\t\t\tsession_id: session.sessionId,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async heartbeat(requested = false) {\n\t\tif (!this.isAck && !requested) {\n\t\t\treturn this.destroy({ reason: 'Zombie connection', recover: WebSocketShardDestroyRecovery.Resume });\n\t\t}\n\n\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\n\t\tawait this.send({\n\t\t\top: GatewayOpcodes.Heartbeat,\n\t\t\td: session?.sequence ?? null,\n\t\t});\n\n\t\tthis.lastHeartbeatAt = Date.now();\n\t\tthis.isAck = false;\n\t}\n\n\tprivate async unpackMessage(data: Data, isBinary: boolean): Promise<GatewayReceivePayload | null> {\n\t\t// Deal with no compression\n\t\tif (!isBinary) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(data as string) as GatewayReceivePayload;\n\t\t\t} catch {\n\t\t\t\t// This is a non-JSON payload / (at the time of writing this comment) emitted by bun wrongly interpreting custom close codes https://github.com/oven-sh/bun/issues/3392\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tconst decompressable = new Uint8Array(data as ArrayBuffer);\n\n\t\t// Deal with identify compress\n\t\tif (this.useIdentifyCompress) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-callbacks\n\t\t\t\tinflate(decompressable, { chunkSize: 65_535 }, (err, result) => {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve(JSON.parse(this.textDecoder.decode(result)) as GatewayReceivePayload);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\t// Deal with gw wide zlib-stream compression\n\t\tif (this.inflate) {\n\t\t\tconst l = decompressable.length;\n\t\t\tconst flush =\n\t\t\t\tl >= 4 &&\n\t\t\t\tdecompressable[l - 4] === 0x00 &&\n\t\t\t\tdecompressable[l - 3] === 0x00 &&\n\t\t\t\tdecompressable[l - 2] === 0xff &&\n\t\t\t\tdecompressable[l - 1] === 0xff;\n\n\t\t\tconst zlib = (await getZlibSync())!;\n\t\t\tthis.inflate.push(Buffer.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);\n\n\t\t\tif (this.inflate.err) {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ''}`),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!flush) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { result } = this.inflate;\n\t\t\tif (!result) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn JSON.parse(typeof result === 'string' ? result : this.textDecoder.decode(result)) as GatewayReceivePayload;\n\t\t}\n\n\t\tthis.debug([\n\t\t\t'Received a message we were unable to decompress',\n\t\t\t`isBinary: ${isBinary.toString()}`,\n\t\t\t`useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,\n\t\t\t`inflate: ${Boolean(this.inflate).toString()}`,\n\t\t]);\n\n\t\treturn null;\n\t}\n\n\tprivate async onMessage(data: Data, isBinary: boolean) {\n\t\tconst payload = await this.unpackMessage(data, isBinary);\n\t\tif (!payload) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (payload.op) {\n\t\t\tcase GatewayOpcodes.Dispatch: {\n\t\t\t\tif (this.#status === WebSocketShardStatus.Resuming) {\n\t\t\t\t\tthis.replayedEvents++;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line sonarjs/no-nested-switch\n\t\t\t\tswitch (payload.t) {\n\t\t\t\t\tcase GatewayDispatchEvents.Ready: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\n\t\t\t\t\t\tconst session = {\n\t\t\t\t\t\t\tsequence: payload.s,\n\t\t\t\t\t\t\tsessionId: payload.d.session_id,\n\t\t\t\t\t\t\tshardId: this.id,\n\t\t\t\t\t\t\tshardCount: this.strategy.options.shardCount,\n\t\t\t\t\t\t\tresumeURL: payload.d.resume_gateway_url,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, session);\n\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Ready, { data: payload.d });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase GatewayDispatchEvents.Resumed: {\n\t\t\t\t\t\tthis.#status = WebSocketShardStatus.Ready;\n\t\t\t\t\t\tthis.debug([`Resumed and replayed ${this.replayedEvents} events`]);\n\t\t\t\t\t\tthis.emit(WebSocketShardEvents.Resumed);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (session) {\n\t\t\t\t\tif (payload.s > session.sequence) {\n\t\t\t\t\t\tawait this.strategy.updateSessionInfo(this.id, { ...session, sequence: payload.s });\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.debug([\n\t\t\t\t\t\t`Received a ${payload.t} event but no session is available. Session information cannot be re-constructed in this state without a full reconnect`,\n\t\t\t\t\t]);\n\t\t\t\t}\n\n\t\t\t\tthis.emit(WebSocketShardEvents.Dispatch, { data: payload });\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Heartbeat: {\n\t\t\t\tawait this.heartbeat(true);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Reconnect: {\n\t\t\t\tawait this.destroy({\n\t\t\t\t\treason: 'Told to reconnect by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.InvalidSession: {\n\t\t\t\tthis.debug([`Invalid session; will attempt to resume: ${payload.d.toString()}`]);\n\t\t\t\tconst session = await this.strategy.retrieveSessionInfo(this.id);\n\t\t\t\tif (payload.d && session) {\n\t\t\t\t\tawait this.resume(session);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.destroy({\n\t\t\t\t\t\treason: 'Invalid session',\n\t\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.Hello: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Hello);\n\t\t\t\tconst jitter = Math.random();\n\t\t\t\tconst firstWait = Math.floor(payload.d.heartbeat_interval * jitter);\n\t\t\t\tthis.debug([`Preparing first heartbeat of the connection with a jitter of ${jitter}; waiting ${firstWait}ms`]);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = controller;\n\t\t\t\t\tawait sleep(firstWait, undefined, { signal: controller.signal });\n\t\t\t\t} catch {\n\t\t\t\t\tthis.debug(['Cancelled initial heartbeat due to #destroy being called']);\n\t\t\t\t\treturn;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.initialHeartbeatTimeoutController = null;\n\t\t\t\t}\n\n\t\t\t\tawait this.heartbeat();\n\n\t\t\t\tthis.debug([`First heartbeat sent, starting to beat every ${payload.d.heartbeat_interval}ms`]);\n\t\t\t\tthis.heartbeatInterval = setInterval(() => void this.heartbeat(), payload.d.heartbeat_interval);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayOpcodes.HeartbeatAck: {\n\t\t\t\tthis.isAck = true;\n\n\t\t\t\tconst ackAt = Date.now();\n\t\t\t\tthis.emit(WebSocketShardEvents.HeartbeatComplete, {\n\t\t\t\t\tackAt,\n\t\t\t\t\theartbeatAt: this.lastHeartbeatAt,\n\t\t\t\t\tlatency: ackAt - this.lastHeartbeatAt,\n\t\t\t\t});\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onError(error: Error) {\n\t\tif ('code' in error && ['ECONNRESET', 'ECONNREFUSED'].includes(error.code as string)) {\n\t\t\tthis.debug(['Failed to connect to the gateway URL specified due to a network error']);\n\t\t\tthis.failedToConnectDueToNetworkError = true;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit(WebSocketShardEvents.Error, { error });\n\t}\n\n\tprivate async onClose(code: number) {\n\t\tthis.emit(WebSocketShardEvents.Closed, { code });\n\n\t\tswitch (code) {\n\t\t\tcase CloseCodes.Normal: {\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\treason: 'Got disconnected by Discord',\n\t\t\t\t\trecover: WebSocketShardDestroyRecovery.Reconnect,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tcase CloseCodes.Resuming: {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownError: {\n\t\t\t\tthis.debug([`An unknown error occurred: ${code}`]);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.UnknownOpcode: {\n\t\t\t\tthis.debug(['An invalid opcode was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DecodeError: {\n\t\t\t\tthis.debug(['An invalid payload was sent to Discord.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.NotAuthenticated: {\n\t\t\t\tthis.debug(['A request was somehow sent before the identify/resume payload.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AuthenticationFailed: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Authentication failed'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.AlreadyAuthenticated: {\n\t\t\t\tthis.debug(['More than one auth payload was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidSeq: {\n\t\t\t\tthis.debug(['An invalid sequence was sent.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.RateLimited: {\n\t\t\t\tthis.debug(['The WebSocket rate limit has been hit, this should never happen']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Reconnect });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.SessionTimedOut: {\n\t\t\t\tthis.debug(['Session timed out.']);\n\t\t\t\treturn this.destroy({ code, recover: WebSocketShardDestroyRecovery.Resume });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidShard: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Invalid shard'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.ShardingRequired: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Sharding is required'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidAPIVersion: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used an invalid API version'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.InvalidIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used invalid intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tcase GatewayCloseCodes.DisallowedIntents: {\n\t\t\t\tthis.emit(WebSocketShardEvents.Error, {\n\t\t\t\t\terror: new Error('Used disallowed intents'),\n\t\t\t\t});\n\t\t\t\treturn this.destroy({ code });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tthis.debug([\n\t\t\t\t\t`The gateway closed with an unexpected code ${code}, attempting to ${\n\t\t\t\t\t\tthis.failedToConnectDueToNetworkError ? 'reconnect' : 'resume'\n\t\t\t\t\t}.`,\n\t\t\t\t]);\n\t\t\t\treturn this.destroy({\n\t\t\t\t\tcode,\n\t\t\t\t\trecover: this.failedToConnectDueToNetworkError\n\t\t\t\t\t\t? WebSocketShardDestroyRecovery.Reconnect\n\t\t\t\t\t\t: WebSocketShardDestroyRecovery.Resume,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate debug(messages: [string, ...string[]]) {\n\t\tconst message = `${messages[0]}${\n\t\t\tmessages.length > 1\n\t\t\t\t? `\\n${messages\n\t\t\t\t\t\t.slice(1)\n\t\t\t\t\t\t.map((m) => `\t${m}`)\n\t\t\t\t\t\t.join('\\n')}`\n\t\t\t\t: ''\n\t\t}`;\n\n\t\tthis.emit(WebSocketShardEvents.Debug, { message });\n\t}\n}\n","import process from 'node:process';\nimport { Collection } from '@discordjs/collection';\nimport { lazy } from '@discordjs/util';\nimport { APIVersion, GatewayOpcodes } from 'discord-api-types/v10';\nimport { SimpleShardingStrategy } from '../strategies/sharding/SimpleShardingStrategy.js';\nimport { SimpleIdentifyThrottler } from '../throttling/SimpleIdentifyThrottler.js';\nimport type { SessionInfo, OptionalWebSocketManagerOptions, WebSocketManager } from '../ws/WebSocketManager.js';\nimport type { SendRateLimitState } from '../ws/WebSocketShard.js';\n\n/**\n * Valid encoding types\n */\nexport enum Encoding {\n\tJSON = 'json',\n}\n\n/**\n * Valid compression methods\n */\nexport enum CompressionMethod {\n\tZlibStream = 'zlib-stream',\n}\n\nexport const DefaultDeviceProperty = `@discordjs/ws 1.0.1` as `@discordjs/ws ${string}`;\n\nconst getDefaultSessionStore = lazy(() => new Collection<number, SessionInfo | null>());\n\n/**\n * Default options used by the manager\n */\nexport const DefaultWebSocketManagerOptions = {\n\tasync buildIdentifyThrottler(manager: WebSocketManager) {\n\t\tconst info = await manager.fetchGatewayInformation();\n\t\treturn new SimpleIdentifyThrottler(info.session_start_limit.max_concurrency);\n\t},\n\tbuildStrategy: (manager) => new SimpleShardingStrategy(manager),\n\tshardCount: null,\n\tshardIds: null,\n\tlargeThreshold: null,\n\tinitialPresence: null,\n\tidentifyProperties: {\n\t\tbrowser: DefaultDeviceProperty,\n\t\tdevice: DefaultDeviceProperty,\n\t\tos: process.platform,\n\t},\n\tversion: APIVersion,\n\tencoding: Encoding.JSON,\n\tcompression: null,\n\tretrieveSessionInfo(shardId) {\n\t\tconst store = getDefaultSessionStore();\n\t\treturn store.get(shardId) ?? null;\n\t},\n\tupdateSessionInfo(shardId: number, info: SessionInfo | null) {\n\t\tconst store = getDefaultSessionStore();\n\t\tif (info) {\n\t\t\tstore.set(shardId, info);\n\t\t} else {\n\t\t\tstore.delete(shardId);\n\t\t}\n\t},\n\thandshakeTimeout: 30_000,\n\thelloTimeout: 60_000,\n\treadyTimeout: 15_000,\n} as const satisfies OptionalWebSocketManagerOptions;\n\nexport const ImportantGatewayOpcodes = new Set([\n\tGatewayOpcodes.Heartbeat,\n\tGatewayOpcodes.Identify,\n\tGatewayOpcodes.Resume,\n]);\n\nexport function getInitialSendRateLimitState(): SendRateLimitState {\n\treturn {\n\t\tremaining: 120,\n\t\tresetAt: Date.now() + 60_000,\n\t};\n}\n","import { setTimeout as sleep } from 'node:timers/promises';\nimport { Collection } from '@discordjs/collection';\nimport { AsyncQueue } from '@sapphire/async-queue';\nimport type { IIdentifyThrottler } from './IIdentifyThrottler.js';\n\n/**\n * The state of a rate limit key's identify queue.\n */\nexport interface IdentifyState {\n\tqueue: AsyncQueue;\n\tresetsAt: number;\n}\n\n/**\n * Local, in-memory identify throttler.\n */\nexport class SimpleIdentifyThrottler implements IIdentifyThrottler {\n\tprivate readonly states = new Collection<number, IdentifyState>();\n\n\tpublic constructor(private readonly maxConcurrency: number) {}\n\n\t/**\n\t * {@inheritDoc IIdentifyThrottler.waitForIdentify}\n\t */\n\tpublic async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n\t\tconst key = shardId % this.maxConcurrency;\n\n\t\tconst state = this.states.ensure(key, () => {\n\t\t\treturn {\n\t\t\t\tqueue: new AsyncQueue(),\n\t\t\t\tresetsAt: Number.POSITIVE_INFINITY,\n\t\t\t};\n\t\t});\n\n\t\tawait state.queue.wait({ signal });\n\n\t\ttry {\n\t\t\tconst diff = state.resetsAt - Date.now();\n\t\t\tif (diff <= 5_000) {\n\t\t\t\t// To account for the latency the IDENTIFY payload goes through, we add a bit more wait time\n\t\t\t\tconst time = diff + Math.random() * 1_500;\n\t\t\t\tawait sleep(time);\n\t\t\t}\n\n\t\t\tstate.resetsAt = Date.now() + 5_000;\n\t\t} finally {\n\t\t\tstate.queue.shift();\n\t\t}\n\t}\n}\n","import { isMainThread, parentPort, workerData } from 'node:worker_threads';\nimport { Collection } from '@discordjs/collection';\nimport type { Awaitable } from '@discordjs/util';\nimport { WorkerContextFetchingStrategy } from '../strategies/context/WorkerContextFetchingStrategy.js';\nimport {\n\tWorkerReceivePayloadOp,\n\tWorkerSendPayloadOp,\n\ttype WorkerData,\n\ttype WorkerReceivePayload,\n\ttype WorkerSendPayload,\n} from '../strategies/sharding/WorkerShardingStrategy.js';\nimport type { WebSocketShardDestroyOptions } from '../ws/WebSocketShard.js';\nimport { WebSocketShardEvents, WebSocketShard } from '../ws/WebSocketShard.js';\n\n/**\n * Options for bootstrapping the worker\n */\nexport interface BootstrapOptions {\n\t/**\n\t * Shard events to just arbitrarily forward to the parent thread for the manager to emit\n\t * Note: By default, this will include ALL events\n\t * you most likely want to handle dispatch within the worker itself\n\t */\n\tforwardEvents?: WebSocketShardEvents[];\n\t/**\n\t * Function to call when a shard is created for additional setup\n\t */\n\tshardCallback?(shard: WebSocketShard): Awaitable<void>;\n}\n\n/**\n * Utility class for bootstrapping a worker thread to be used for sharding\n */\nexport class WorkerBootstrapper {\n\t/**\n\t * The data passed to the worker thread\n\t */\n\tprotected readonly data = workerData as WorkerData;\n\n\t/**\n\t * The shards that are managed by this worker\n\t */\n\tprotected readonly shards = new Collection<number, WebSocketShard>();\n\n\tpublic constructor() {\n\t\tif (isMainThread) {\n\t\t\tthrow new Error('Expected WorkerBootstrap to not be used within the main thread');\n\t\t}\n\t}\n\n\t/**\n\t * Helper method to initiate a shard's connection process\n\t */\n\tprotected async connect(shardId: number): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.connect();\n\t}\n\n\t/**\n\t * Helper method to destroy a shard\n\t */\n\tprotected async destroy(shardId: number, options?: WebSocketShardDestroyOptions): Promise<void> {\n\t\tconst shard = this.shards.get(shardId);\n\t\tif (!shard) {\n\t\t\tthrow new RangeError(`Shard ${shardId} does not exist`);\n\t\t}\n\n\t\tawait shard.destroy(options);\n\t}\n\n\t/**\n\t * Helper method to attach event listeners to the parentPort\n\t */\n\tprotected setupThreadEvents(): void {\n\t\tparentPort!\n\t\t\t.on('messageerror', (err) => {\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.on('message', async (payload: WorkerSendPayload) => {\n\t\t\t\tswitch (payload.op) {\n\t\t\t\t\tcase WorkerSendPayloadOp.Connect: {\n\t\t\t\t\t\tawait this.connect(payload.shardId);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Connected,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Destroy: {\n\t\t\t\t\t\tawait this.destroy(payload.shardId, payload.options);\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.Destroyed,\n\t\t\t\t\t\t\tshardId: payload.shardId,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.Send: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new RangeError(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait shard.send(payload.payload);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.SessionInfoResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.ShardIdentifyResponse: {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase WorkerSendPayloadOp.FetchStatus: {\n\t\t\t\t\t\tconst shard = this.shards.get(payload.shardId);\n\t\t\t\t\t\tif (!shard) {\n\t\t\t\t\t\t\tthrow new Error(`Shard ${payload.shardId} does not exist`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst response: WorkerReceivePayload = {\n\t\t\t\t\t\t\top: WorkerReceivePayloadOp.FetchStatusResponse,\n\t\t\t\t\t\t\tstatus: shard.status,\n\t\t\t\t\t\t\tnonce: payload.nonce,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tparentPort!.postMessage(response);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Bootstraps the worker thread with the provided options\n\t */\n\tpublic async bootstrap(options: Readonly<BootstrapOptions> = {}): Promise<void> {\n\t\t// Start by initializing the shards\n\t\tfor (const shardId of this.data.shardIds) {\n\t\t\tconst shard = new WebSocketShard(new WorkerContextFetchingStrategy(this.data), shardId);\n\t\t\tfor (const event of options.forwardEvents ?? Object.values(WebSocketShardEvents)) {\n\t\t\t\t// @ts-expect-error: Event types incompatible\n\t\t\t\tshard.on(event, (data) => {\n\t\t\t\t\tconst payload: WorkerReceivePayload = {\n\t\t\t\t\t\top: WorkerReceivePayloadOp.Event,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tshardId,\n\t\t\t\t\t};\n\t\t\t\t\tparentPort!.postMessage(payload);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Any additional setup the user might want to do\n\t\t\tawait options.shardCallback?.(shard);\n\t\t\tthis.shards.set(shardId, shard);\n\t\t}\n\n\t\t// Lastly, start listening to messages from the parent thread\n\t\tthis.setupThreadEvents();\n\n\t\tconst message: WorkerReceivePayload = {\n\t\t\top: WorkerReceivePayloadOp.WorkerReady,\n\t\t};\n\t\tparentPort!.postMessage(message);\n\t}\n}\n","import type { REST } from '@discordjs/rest';\nimport { range, type Awaitable } from '@discordjs/util';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tRoutes,\n\ttype APIGatewayBotInfo,\n\ttype GatewayIdentifyProperties,\n\ttype GatewayPresenceUpdateData,\n\ttype RESTGetAPIGatewayBotResult,\n\ttype GatewayIntentBits,\n\ttype GatewaySendPayload,\n} from 'discord-api-types/v10';\nimport type { IShardingStrategy } from '../strategies/sharding/IShardingStrategy.js';\nimport type { IIdentifyThrottler } from '../throttling/IIdentifyThrottler.js';\nimport { DefaultWebSocketManagerOptions, type CompressionMethod, type Encoding } from '../utils/constants.js';\nimport type { WebSocketShardDestroyOptions, WebSocketShardEventsMap } from './WebSocketShard.js';\n\n/**\n * Represents a range of shard ids\n */\nexport interface ShardRange {\n\tend: number;\n\tstart: number;\n}\n\n/**\n * Session information for a given shard, used to resume a session\n */\nexport interface SessionInfo {\n\t/**\n\t * URL to use when resuming\n\t */\n\tresumeURL: string;\n\t/**\n\t * The sequence number of the last message sent by the shard\n\t */\n\tsequence: number;\n\t/**\n\t * Session id for this shard\n\t */\n\tsessionId: string;\n\t/**\n\t * The total number of shards at the time of this shard identifying\n\t */\n\tshardCount: number;\n\t/**\n\t * The id of the shard\n\t */\n\tshardId: number;\n}\n\n/**\n * Required options for the WebSocketManager\n */\nexport interface RequiredWebSocketManagerOptions {\n\t/**\n\t * The intents to request\n\t */\n\tintents: GatewayIntentBits | 0;\n\t/**\n\t * The REST instance to use for fetching gateway information\n\t */\n\trest: REST;\n\t/**\n\t * The token to use for identifying with the gateway\n\t */\n\ttoken: string;\n}\n\n/**\n * Optional additional configuration for the WebSocketManager\n */\nexport interface OptionalWebSocketManagerOptions {\n\t/**\n\t * Builds an identify throttler to use for this manager's shards\n\t */\n\tbuildIdentifyThrottler(manager: WebSocketManager): Awaitable<IIdentifyThrottler>;\n\t/**\n\t * Builds the strategy to use for sharding\n\t *\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * token: process.env.DISCORD_TOKEN,\n\t * intents: 0, // for no intents\n\t * rest,\n\t * buildStrategy: (manager) => new WorkerShardingStrategy(manager, { shardsPerWorker: 2 }),\n\t * });\n\t * ```\n\t */\n\tbuildStrategy(manager: WebSocketManager): IShardingStrategy;\n\t/**\n\t * The compression method to use\n\t *\n\t * @defaultValue `null` (no compression)\n\t */\n\tcompression: CompressionMethod | null;\n\t/**\n\t * The encoding to use\n\t *\n\t * @defaultValue `'json'`\n\t */\n\tencoding: Encoding;\n\t/**\n\t * How long to wait for a shard to connect before giving up\n\t */\n\thandshakeTimeout: number | null;\n\t/**\n\t * How long to wait for a shard's HELLO packet before giving up\n\t */\n\thelloTimeout: number | null;\n\t/**\n\t * Properties to send to the gateway when identifying\n\t */\n\tidentifyProperties: GatewayIdentifyProperties;\n\t/**\n\t * Initial presence data to send to the gateway when identifying\n\t */\n\tinitialPresence: GatewayPresenceUpdateData | null;\n\t/**\n\t * Value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list\n\t */\n\tlargeThreshold: number | null;\n\t/**\n\t * How long to wait for a shard's READY packet before giving up\n\t */\n\treadyTimeout: number | null;\n\t/**\n\t * Function used to retrieve session information (and attempt to resume) for a given shard\n\t *\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * async retrieveSessionInfo(shardId): Awaitable<SessionInfo | null> {\n\t * // Fetch this info from redis or similar\n\t * return { sessionId: string, sequence: number };\n\t * // Return null if no information is found\n\t * },\n\t * });\n\t * ```\n\t */\n\tretrieveSessionInfo(shardId: number): Awaitable<SessionInfo | null>;\n\t/**\n\t * The total number of shards across all WebsocketManagers you intend to instantiate.\n\t * Use `null` to use Discord's recommended shard count\n\t */\n\tshardCount: number | null;\n\t/**\n\t * The ids of the shards this WebSocketManager should manage.\n\t * Use `null` to simply spawn 0 through `shardCount - 1`\n\t *\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * shardIds: [1, 3, 7], // spawns shard 1, 3, and 7, nothing else\n\t * });\n\t * ```\n\t * @example\n\t * ```ts\n\t * const manager = new WebSocketManager({\n\t * shardIds: {\n\t * start: 3,\n\t * end: 6,\n\t * }, // spawns shards 3, 4, 5, and 6\n\t * });\n\t * ```\n\t */\n\tshardIds: number[] | ShardRange | null;\n\t/**\n\t * Function used to store session information for a given shard\n\t */\n\tupdateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Awaitable<void>;\n\t/**\n\t * The gateway version to use\n\t *\n\t * @defaultValue `'10'`\n\t */\n\tversion: string;\n}\n\nexport type WebSocketManagerOptions = OptionalWebSocketManagerOptions & RequiredWebSocketManagerOptions;\n\nexport type ManagerShardEventsMap = {\n\t[K in keyof WebSocketShardEventsMap]: [\n\t\tWebSocketShardEventsMap[K] extends [] ? { shardId: number } : WebSocketShardEventsMap[K][0] & { shardId: number },\n\t];\n};\n\nexport class WebSocketManager extends AsyncEventEmitter<ManagerShardEventsMap> {\n\t/**\n\t * The options being used by this manager\n\t */\n\tpublic readonly options: WebSocketManagerOptions;\n\n\t/**\n\t * Internal cache for a GET /gateway/bot result\n\t */\n\tprivate gatewayInformation: {\n\t\tdata: APIGatewayBotInfo;\n\t\texpiresAt: number;\n\t} | null = null;\n\n\t/**\n\t * Internal cache for the shard ids\n\t */\n\tprivate shardIds: number[] | null = null;\n\n\t/**\n\t * Strategy used to manage shards\n\t *\n\t * @defaultValue `SimpleShardingStrategy`\n\t */\n\tprivate readonly strategy: IShardingStrategy;\n\n\tpublic constructor(options: Partial<OptionalWebSocketManagerOptions> & RequiredWebSocketManagerOptions) {\n\t\tsuper();\n\t\tthis.options = { ...DefaultWebSocketManagerOptions, ...options };\n\t\tthis.strategy = this.options.buildStrategy(this);\n\t}\n\n\t/**\n\t * Fetches the gateway information from Discord - or returns it from cache if available\n\t *\n\t * @param force - Whether to ignore the cache and force a fresh fetch\n\t */\n\tpublic async fetchGatewayInformation(force = false) {\n\t\tif (this.gatewayInformation) {\n\t\t\tif (this.gatewayInformation.expiresAt <= Date.now()) {\n\t\t\t\tthis.gatewayInformation = null;\n\t\t\t} else if (!force) {\n\t\t\t\treturn this.gatewayInformation.data;\n\t\t\t}\n\t\t}\n\n\t\tconst data = (await this.options.rest.get(Routes.gatewayBot())) as RESTGetAPIGatewayBotResult;\n\n\t\t// For single sharded bots session_start_limit.reset_after will be 0, use 5 seconds as a minimum expiration time\n\t\tthis.gatewayInformation = { data, expiresAt: Date.now() + (data.session_start_limit.reset_after || 5_000) };\n\t\treturn this.gatewayInformation.data;\n\t}\n\n\t/**\n\t * Updates your total shard count on-the-fly, spawning shards as needed\n\t *\n\t * @param shardCount - The new shard count to use\n\t */\n\tpublic async updateShardCount(shardCount: number | null) {\n\t\tawait this.strategy.destroy({ reason: 'User is adjusting their shards' });\n\t\tthis.options.shardCount = shardCount;\n\n\t\tconst shardIds = await this.getShardIds(true);\n\t\tawait this.strategy.spawn(shardIds);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Yields the total number of shards across for your bot, accounting for Discord recommendations\n\t */\n\tpublic async getShardCount(): Promise<number> {\n\t\tif (this.options.shardCount) {\n\t\t\treturn this.options.shardCount;\n\t\t}\n\n\t\tconst shardIds = await this.getShardIds();\n\t\treturn Math.max(...shardIds) + 1;\n\t}\n\n\t/**\n\t * Yields the ids of the shards this manager should manage\n\t */\n\tpublic async getShardIds(force = false): Promise<number[]> {\n\t\tif (this.shardIds && !force) {\n\t\t\treturn this.shardIds;\n\t\t}\n\n\t\tlet shardIds: number[];\n\t\tif (this.options.shardIds) {\n\t\t\tif (Array.isArray(this.options.shardIds)) {\n\t\t\t\tshardIds = this.options.shardIds;\n\t\t\t} else {\n\t\t\t\tconst { start, end } = this.options.shardIds;\n\t\t\t\tshardIds = [...range({ start, end: end + 1 })];\n\t\t\t}\n\t\t} else {\n\t\t\tconst data = await this.fetchGatewayInformation();\n\t\t\tshardIds = [...range(this.options.shardCount ?? data.shards)];\n\t\t}\n\n\t\tthis.shardIds = shardIds;\n\t\treturn shardIds;\n\t}\n\n\tpublic async connect() {\n\t\tconst shardCount = await this.getShardCount();\n\n\t\tconst data = await this.fetchGatewayInformation();\n\t\tif (data.session_start_limit.remaining < shardCount) {\n\t\t\tthrow new Error(\n\t\t\t\t`Not enough sessions remaining to spawn ${shardCount} shards; only ${\n\t\t\t\t\tdata.session_start_limit.remaining\n\t\t\t\t} remaining; resets at ${new Date(Date.now() + data.session_start_limit.reset_after).toISOString()}`,\n\t\t\t);\n\t\t}\n\n\t\t// First, make sure all our shards are spawned\n\t\tawait this.updateShardCount(shardCount);\n\t\tawait this.strategy.connect();\n\t}\n\n\tpublic destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\treturn this.strategy.destroy(options);\n\t}\n\n\tpublic send(shardId: number, payload: GatewaySendPayload) {\n\t\treturn this.strategy.send(shardId, payload);\n\t}\n\n\tpublic fetchStatus() {\n\t\treturn this.strategy.fetchStatus();\n\t}\n}\n","export * from './strategies/context/IContextFetchingStrategy.js';\nexport * from './strategies/context/SimpleContextFetchingStrategy.js';\nexport * from './strategies/context/WorkerContextFetchingStrategy.js';\n\nexport * from './strategies/sharding/IShardingStrategy.js';\nexport * from './strategies/sharding/SimpleShardingStrategy.js';\nexport * from './strategies/sharding/WorkerShardingStrategy.js';\n\nexport * from './throttling/IIdentifyThrottler.js';\nexport * from './throttling/SimpleIdentifyThrottler.js';\n\nexport * from './utils/constants.js';\nexport * from './utils/WorkerBootstrapper.js';\n\nexport * from './ws/WebSocketManager.js';\nexport * from './ws/WebSocketShard.js';\n\n/**\n * The {@link https://github.com/discordjs/discord.js/blob/main/packages/ws/#readme | @discordjs/ws} version\n * that you are currently using.\n */\n// This needs to explicitly be `string` so it is not typed as a \"const string\" that gets injected by esbuild\nexport const version = '1.0.1' as string;\n"],"mappings":"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","names":["Collection","WorkerSendPayloadOp","WorkerReceivePayloadOp","workerData","resolve","path","Collection","resolve","payload","Collection","Buffer","once","sleep","Collection","lazy","AsyncQueue","GatewayOpcodes","Collection","Collection","Collection","Encoding","CompressionMethod","Collection","lazy","WebSocketShardEvents","WebSocketShardStatus","WebSocketShardDestroyRecovery","CloseCodes","AsyncQueue","Collection","once","version","resolve","sleep","GatewayOpcodes","Buffer","session","Collection","isMainThread","parentPort","Collection","Collection","isMainThread","parentPort","AsyncEventEmitter","AsyncEventEmitter"]} \ No newline at end of file