@discordeno/gateway 19.0.0-next.fd357ae → 19.0.0-next.fd518cb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/manager.js CHANGED
@@ -32,7 +32,7 @@ export function createGatewayManager(options) {
32
32
  totalWorkers: options.totalWorkers ?? 4,
33
33
  shardsPerWorker: options.shardsPerWorker ?? 25,
34
34
  spawnShardDelay: options.spawnShardDelay ?? 5300,
35
- preferSnakeCase: false,
35
+ preferSnakeCase: options.preferSnakeCase ?? false,
36
36
  shards: new Map(),
37
37
  buckets: new Map(),
38
38
  cache: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/manager.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-confusing-void-expression */\nimport type { AtLeastOne, BigString, Camelize, DiscordGetGatewayBot, DiscordMember, RequestGuildMembers } from '@discordeno/types'\nimport { Collection, delay, logger } from '@discordeno/utils'\nimport Shard from './Shard.js'\nimport type { ShardEvents, StatusUpdate, UpdateVoiceState } from './types.js'\n\nexport function createGatewayManager(options: CreateGatewayManagerOptions): GatewayManager {\n if (!options.connection) {\n options.connection = {\n url: 'wss://gateway.discord.gg',\n shards: 1,\n sessionStartLimit: {\n maxConcurrency: 1,\n remaining: 1000,\n total: 1000,\n resetAfter: 1000 * 60 * 60 * 24,\n },\n }\n }\n\n const gateway: GatewayManager = {\n events: options.events,\n compress: options.compress ?? false,\n intents: options.intents ?? 0,\n properties: {\n os: options.properties?.os ?? process.platform,\n browser: options.properties?.browser ?? 'Discordeno',\n device: options.properties?.device ?? 'Discordeno',\n },\n token: options.token,\n url: options.url ?? options.connection.url ?? 'wss://gateway.discord.gg',\n version: options.version ?? 10,\n connection: options.connection,\n totalShards: options.totalShards ?? options.connection.shards ?? 1,\n lastShardId: options.lastShardId ?? 0,\n firstShardId: options.firstShardId ?? 0,\n totalWorkers: options.totalWorkers ?? 4,\n shardsPerWorker: options.shardsPerWorker ?? 25,\n spawnShardDelay: options.spawnShardDelay ?? 5300,\n preferSnakeCase: false,\n shards: new Map(),\n buckets: new Map(),\n cache: {\n requestMembers: {\n enabled: options.cache?.requestMembers?.enabled ?? false,\n pending: new Collection(),\n },\n },\n\n calculateTotalShards() {\n // Bots under 100k servers do not have access to total shards.\n if (gateway.totalShards < 100) {\n logger.debug(`[Gateway] Calculating total shards: ${gateway.totalShards}`)\n return gateway.totalShards\n }\n\n logger.debug(`[Gateway] Calculating total shards`, gateway.totalShards, gateway.connection.sessionStartLimit.maxConcurrency)\n // Calculate a multiple of `maxConcurrency` which can be used to connect to the gateway.\n return (\n Math.ceil(\n gateway.totalShards /\n // If `maxConcurrency` is 1 we can safely use 16.\n (gateway.connection.sessionStartLimit.maxConcurrency === 1 ? 16 : gateway.connection.sessionStartLimit.maxConcurrency),\n ) * gateway.connection.sessionStartLimit.maxConcurrency\n )\n },\n calculateWorkerId(shardId) {\n const workerId = shardId % gateway.shardsPerWorker\n logger.debug(\n `[Gateway] Calculating workerId: Shard: ${shardId} -> Worker: ${workerId} -> Per Worker: ${gateway.shardsPerWorker} -> Total: ${gateway.totalWorkers}`,\n )\n return workerId\n },\n prepareBuckets() {\n for (let i = 0; i < gateway.connection.sessionStartLimit.maxConcurrency; ++i) {\n logger.debug(`[Gateway] Preparing buckets for concurrency: ${i}`)\n gateway.buckets.set(i, {\n workers: [],\n identifyRequests: [],\n })\n }\n\n // ORGANIZE ALL SHARDS INTO THEIR OWN BUCKETS\n for (let shardId = gateway.firstShardId; shardId <= gateway.lastShardId; ++shardId) {\n logger.debug(`[Gateway] Preparing buckets for shard: ${shardId}`)\n if (shardId >= gateway.totalShards) {\n throw new Error(`Shard (id: ${shardId}) is bigger or equal to the used amount of used shards which is ${gateway.totalShards}`)\n }\n\n const bucketId = shardId % gateway.connection.sessionStartLimit.maxConcurrency\n const bucket = gateway.buckets.get(bucketId)\n if (!bucket) {\n throw new Error(\n `Shard (id: ${shardId}) got assigned to an illegal bucket id: ${bucketId}, expected a bucket id between 0 and ${\n gateway.connection.sessionStartLimit.maxConcurrency - 1\n }`,\n )\n }\n\n // FIND A QUEUE IN THIS BUCKET THAT HAS SPACE\n // const worker = bucket.workers.find((w) => w.queue.length < gateway.shardsPerWorker);\n const workerId = gateway.calculateWorkerId(shardId)\n const worker = bucket.workers.find((w) => w.id === workerId)\n if (worker) {\n // IF THE QUEUE HAS SPACE JUST ADD IT TO THIS QUEUE\n worker.queue.push(shardId)\n } else {\n bucket.workers.push({ id: workerId, queue: [shardId] })\n }\n }\n\n for (const bucket of gateway.buckets.values()) {\n for (const worker of bucket.workers.values()) {\n // eslint-disable-next-line @typescript-eslint/require-array-sort-compare\n worker.queue = worker.queue.sort((a, b) => a - b)\n }\n }\n },\n async spawnShards() {\n // PREPARES ALL SHARDS IN SPECIFIC BUCKETS\n gateway.prepareBuckets()\n\n // Prefer concurrency of forEach instead of forof\n await Promise.all(\n [...gateway.buckets.entries()].map(async ([bucketId, bucket]) => {\n for (const worker of bucket.workers) {\n for (const shardId of worker.queue) {\n await gateway.tellWorkerToIdentify(worker.id, shardId, bucketId)\n }\n }\n }),\n )\n },\n async shutdown(code, reason) {\n gateway.shards.forEach((shard) => shard.close(code, reason))\n\n await delay(5000)\n },\n async tellWorkerToIdentify(workerId, shardId, bucketId) {\n logger.debug(`[Gateway] tell worker to identify (${workerId}, ${shardId}, ${bucketId})`)\n await gateway.identify(shardId)\n },\n async identify(shardId: number) {\n let shard = this.shards.get(shardId)\n logger.debug(`[Gateway] identifying ${shard ? 'existing' : 'new'} shard (${shardId})`)\n\n if (!shard) {\n shard = new Shard({\n id: shardId,\n connection: {\n compress: this.compress,\n intents: this.intents,\n properties: this.properties,\n token: this.token,\n totalShards: this.totalShards,\n url: this.url,\n version: this.version,\n },\n events: options.events,\n requestIdentify: async () => {\n await gateway.identify(shardId)\n },\n shardIsReady: async () => {\n logger.debug(`[Shard] Shard #${shardId} is ready`)\n await delay(gateway.spawnShardDelay)\n logger.debug(`[Shard] Resolving shard identify request`)\n gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency)!.identifyRequests.shift()?.()\n },\n })\n\n if (this.preferSnakeCase) {\n shard.forwardToBot = async (payload) => {\n options.events.message?.(shard!, payload)\n }\n }\n\n this.shards.set(shardId, shard)\n }\n\n const bucket = gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency)\n if (!bucket) return\n\n return await new Promise((resolve) => {\n // Mark that we are making an identify request so another is not made.\n bucket.identifyRequests.push(resolve)\n logger.debug(`[Gateway] identifying shard #(${shardId}).`)\n // This will trigger identify and when READY is received it will resolve the above request.\n shard?.identify()\n })\n },\n async kill(shardId: number) {\n const shard = this.shards.get(shardId)\n if (!shard) {\n return logger.debug(`[Gateway] kill shard but not found (${shardId})`)\n }\n\n logger.debug(`[Gateway] kill shard (${shardId})`)\n this.shards.delete(shardId)\n await shard.shutdown()\n },\n\n async requestIdentify(shardId: number) {\n logger.debug(`[Gateway] requesting identify`)\n // const bucket = gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency)\n // if (!bucket) return\n\n // return await new Promise((resolve) => {\n // bucket.identifyRequests.push(resolve)\n // })\n },\n\n // Helpers methods below this\n\n calculateShardId(guildId, totalShards) {\n // If none is provided, use the total shards number from gateway object.\n if (!totalShards) totalShards = gateway.totalShards\n // If it is only 1 shard, it will always be shard id 0\n if (totalShards === 1) {\n logger.debug(`[Gateway] calculateShardId (1 shard)`)\n return 0\n }\n\n logger.debug(`[Gateway] calculateShardId (guildId: ${guildId}, totalShards: ${totalShards})`)\n return Number((BigInt(guildId) >> 22n) % BigInt(totalShards))\n },\n\n async joinVoiceChannel(guildId, channelId, options) {\n const shardId = gateway.calculateShardId(guildId)\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId} not found`)\n }\n\n logger.debug(`[Gateway] joinVoiceChannel guildId: ${guildId} channelId: ${channelId}`)\n shard.joinVoiceChannel(guildId, channelId, options)\n },\n\n async editBotStatus(data) {\n logger.debug(`[Gateway] editBotStatus data: ${JSON.stringify(data)}`)\n await Promise.all(\n [...gateway.shards.values()].map(async (shard) => {\n gateway.editShardStatus(shard.id, data)\n }),\n )\n },\n\n async editShardStatus(shardId, data) {\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId}) not found.`)\n }\n\n logger.debug(`[Gateway] editShardStatus shardId: ${shardId} -> data: ${JSON.stringify(data)}`)\n await shard.editShardStatus(data)\n },\n\n async requestMembers(guildId, options) {\n const shardId = gateway.calculateShardId(guildId)\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId}) not found.`)\n }\n\n logger.debug(`[Gateway] requestMembers guildId: ${guildId} -> options ${JSON.stringify(options)}`)\n return await shard.requestMembers(guildId, options)\n },\n\n async leaveVoiceChannel(guildId) {\n const shardId = gateway.calculateShardId(guildId)\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId} not found`)\n }\n\n logger.debug(`[Gateway] leaveVoiceChannel guildId: ${guildId} Shard ${shardId}`)\n await shard.leaveVoiceChannel(guildId)\n },\n }\n\n return gateway\n}\n\nexport interface CreateGatewayManagerOptions {\n /**\n * Id of the first Shard which should get controlled by this manager.\n * @default 0\n */\n firstShardId?: number\n /**\n * Id of the last Shard which should get controlled by this manager.\n * @default 0\n */\n lastShardId?: number\n /**\n * Delay in milliseconds to wait before spawning next shard. OPTIMAL IS ABOVE 5100. YOU DON'T WANT TO HIT THE RATE LIMIT!!!\n * @default 5300\n */\n spawnShardDelay?: number\n /**\n * Whether to send the discord packets in snake case form.\n * @default false\n */\n preferSnakeCase?: boolean\n /**\n * Total amount of shards your bot uses. Useful for zero-downtime updates or resharding.\n * @default 1\n */\n totalShards?: number\n /**\n * The amount of shards to load per worker.\n * @default 25\n */\n shardsPerWorker?: number\n /**\n * The total amount of workers to use for your bot.\n * @default 4\n */\n totalWorkers?: number\n /** Important data which is used by the manager to connect shards to the gateway. */\n connection?: Camelize<DiscordGetGatewayBot>\n /** Whether incoming payloads are compressed using zlib.\n *\n * @default false\n */\n compress?: boolean\n /** The calculated intent value of the events which the shard should receive.\n *\n * @default 0\n */\n intents?: number\n /** Identify properties to use */\n properties?: {\n /** Operating system the shard runs on.\n *\n * @default \"darwin\" | \"linux\" | \"windows\"\n */\n os: string\n /** The \"browser\" where this shard is running on.\n *\n * @default \"Discordeno\"\n */\n browser: string\n /** The device on which the shard is running.\n *\n * @default \"Discordeno\"\n */\n device: string\n }\n /** Bot token which is used to connect to Discord */\n token: string\n /** The URL of the gateway which should be connected to.\n *\n * @default \"wss://gateway.discord.gg\"\n */\n url?: string\n /** The gateway version which should be used.\n *\n * @default 10\n */\n version?: number\n /** The events handlers */\n events: ShardEvents\n /** This managers cache related settings. */\n cache?: {\n requestMembers?: {\n /**\n * Whether or not request member requests should be cached.\n * @default false\n */\n enabled?: boolean\n /** The pending requests. */\n pending: Collection<string, RequestMemberRequest>\n }\n }\n}\n\nexport interface GatewayManager extends Required<CreateGatewayManagerOptions> {\n /** The max concurrency buckets. Those will be created when the `spawnShards` (which calls `prepareBuckets` under the hood) function gets called. */\n buckets: Map<\n number,\n {\n workers: Array<{ id: number; queue: number[] }>\n /** Requests to identify shards are made based on whether it is available to be made. */\n identifyRequests: Array<(value: void | PromiseLike<void>) => void>\n }\n >\n /** The shards that are created. */\n shards: Map<number, Shard>\n /** Determine max number of shards to use based upon the max concurrency. */\n calculateTotalShards: () => number\n /** Determine the id of the worker which is handling a shard. */\n calculateWorkerId: (shardId: number) => number\n /** Prepares all the buckets that are available for identifying the shards. */\n prepareBuckets: () => void\n /** Start identifying all the shards. */\n spawnShards: () => Promise<void>\n /** Shutdown all shards. */\n shutdown: (code: number, reason: string) => Promise<void>\n /** Allows users to hook in and change to communicate to different workers across different servers or anything they like. For example using redis pubsub to talk to other servers. */\n tellWorkerToIdentify: (workerId: number, shardId: number, bucketId: number) => Promise<void>\n /** Tell the manager to identify a Shard. If this Shard is not already managed this will also add the Shard to the manager. */\n identify: (shardId: number) => Promise<void>\n /** Kill a shard. Close a shards connection to Discord's gateway (if any) and remove it from the manager. */\n kill: (shardId: number) => Promise<void>\n /** This function makes sure that the bucket is allowed to make the next identify request. */\n requestIdentify: (shardId: number) => Promise<void>\n /** Calculates the number of shards based on the guild id and total shards. */\n calculateShardId: (guildId: BigString, totalShards?: number) => number\n /**\n * Connects the bot user to a voice or stage channel.\n *\n * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.\n *\n * @param guildId - The ID of the guild the voice channel to leave is in.\n * @param channelId - The ID of the channel you want to join.\n *\n * @remarks\n * Requires the `CONNECT` permission.\n *\n * Fires a _Voice State Update_ gateway event.\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}\n */\n joinVoiceChannel: (guildId: BigString, channelId: BigString, options?: AtLeastOne<Omit<UpdateVoiceState, 'guildId' | 'channelId'>>) => Promise<void>\n /**\n * Edits the bot status in all shards that this gateway manages.\n *\n * @param data The status data to set the bots status to.\n * @returns Promise<void>\n */\n editBotStatus: (data: StatusUpdate) => Promise<void>\n /**\n * Edits the bot's status on one shard.\n *\n * @param shardId The shard id to edit the status for.\n * @param data The status data to set the bots status to.\n * @returns Promise<void>\n */\n editShardStatus: (shardId: number, data: StatusUpdate) => Promise<void>\n /**\n * Fetches the list of members for a guild over the gateway.\n *\n * @param guildId - The ID of the guild to get the list of members for.\n * @param options - The parameters for the fetching of the members.\n *\n * @remarks\n * If requesting the entire member list:\n * - Requires the `GUILD_MEMBERS` intent.\n *\n * If requesting presences ({@link RequestGuildMembers.presences | presences} set to `true`):\n * - Requires the `GUILD_PRESENCES` intent.\n *\n * If requesting a prefix ({@link RequestGuildMembers.query | query} non-`undefined`):\n * - Returns a maximum of 100 members.\n *\n * If requesting a users by ID ({@link RequestGuildMembers.userIds | userIds} non-`undefined`):\n * - Returns a maximum of 100 members.\n *\n * Fires a _Guild Members Chunk_ gateway event for every 1000 members fetched.\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#request-guild-members}\n */\n requestMembers: (guildId: BigString, options?: Omit<RequestGuildMembers, 'guildId'>) => Promise<Camelize<DiscordMember[]>>\n /**\n * Leaves the voice channel the bot user is currently in.\n *\n * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.\n *\n * @param guildId - The ID of the guild the voice channel to leave is in.\n *\n * @remarks\n * Fires a _Voice State Update_ gateway event.\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}\n */\n leaveVoiceChannel: (guildId: BigString) => Promise<void>\n}\n\nexport interface RequestMemberRequest {\n /** The unique nonce for this request. */\n nonce: string\n /** The resolver handler to run when all members arrive. */\n resolve: (value: Camelize<DiscordMember[]> | PromiseLike<Camelize<DiscordMember[]>>) => void\n /** The members that have already arrived for this request. */\n members: Camelize<DiscordMember[]>\n}\n"],"names":["Collection","delay","logger","Shard","createGatewayManager","options","connection","url","shards","sessionStartLimit","maxConcurrency","remaining","total","resetAfter","gateway","events","compress","intents","properties","os","process","platform","browser","device","token","version","totalShards","lastShardId","firstShardId","totalWorkers","shardsPerWorker","spawnShardDelay","preferSnakeCase","Map","buckets","cache","requestMembers","enabled","pending","calculateTotalShards","debug","Math","ceil","calculateWorkerId","shardId","workerId","prepareBuckets","i","set","workers","identifyRequests","Error","bucketId","bucket","get","worker","find","w","id","queue","push","values","sort","a","b","spawnShards","Promise","all","entries","map","tellWorkerToIdentify","shutdown","code","reason","forEach","shard","close","identify","requestIdentify","shardIsReady","shift","forwardToBot","payload","message","resolve","kill","delete","calculateShardId","guildId","Number","BigInt","joinVoiceChannel","channelId","editBotStatus","data","JSON","stringify","editShardStatus","leaveVoiceChannel"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/manager.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-confusing-void-expression */\nimport type { AtLeastOne, BigString, Camelize, DiscordGetGatewayBot, DiscordMember, RequestGuildMembers } from '@discordeno/types'\nimport { Collection, delay, logger } from '@discordeno/utils'\nimport Shard from './Shard.js'\nimport type { ShardEvents, StatusUpdate, UpdateVoiceState } from './types.js'\n\nexport function createGatewayManager(options: CreateGatewayManagerOptions): GatewayManager {\n if (!options.connection) {\n options.connection = {\n url: 'wss://gateway.discord.gg',\n shards: 1,\n sessionStartLimit: {\n maxConcurrency: 1,\n remaining: 1000,\n total: 1000,\n resetAfter: 1000 * 60 * 60 * 24,\n },\n }\n }\n\n const gateway: GatewayManager = {\n events: options.events,\n compress: options.compress ?? false,\n intents: options.intents ?? 0,\n properties: {\n os: options.properties?.os ?? process.platform,\n browser: options.properties?.browser ?? 'Discordeno',\n device: options.properties?.device ?? 'Discordeno',\n },\n token: options.token,\n url: options.url ?? options.connection.url ?? 'wss://gateway.discord.gg',\n version: options.version ?? 10,\n connection: options.connection,\n totalShards: options.totalShards ?? options.connection.shards ?? 1,\n lastShardId: options.lastShardId ?? 0,\n firstShardId: options.firstShardId ?? 0,\n totalWorkers: options.totalWorkers ?? 4,\n shardsPerWorker: options.shardsPerWorker ?? 25,\n spawnShardDelay: options.spawnShardDelay ?? 5300,\n preferSnakeCase: options.preferSnakeCase ?? false,\n shards: new Map(),\n buckets: new Map(),\n cache: {\n requestMembers: {\n enabled: options.cache?.requestMembers?.enabled ?? false,\n pending: new Collection(),\n },\n },\n\n calculateTotalShards() {\n // Bots under 100k servers do not have access to total shards.\n if (gateway.totalShards < 100) {\n logger.debug(`[Gateway] Calculating total shards: ${gateway.totalShards}`)\n return gateway.totalShards\n }\n\n logger.debug(`[Gateway] Calculating total shards`, gateway.totalShards, gateway.connection.sessionStartLimit.maxConcurrency)\n // Calculate a multiple of `maxConcurrency` which can be used to connect to the gateway.\n return (\n Math.ceil(\n gateway.totalShards /\n // If `maxConcurrency` is 1 we can safely use 16.\n (gateway.connection.sessionStartLimit.maxConcurrency === 1 ? 16 : gateway.connection.sessionStartLimit.maxConcurrency),\n ) * gateway.connection.sessionStartLimit.maxConcurrency\n )\n },\n calculateWorkerId(shardId) {\n const workerId = shardId % gateway.shardsPerWorker\n logger.debug(\n `[Gateway] Calculating workerId: Shard: ${shardId} -> Worker: ${workerId} -> Per Worker: ${gateway.shardsPerWorker} -> Total: ${gateway.totalWorkers}`,\n )\n return workerId\n },\n prepareBuckets() {\n for (let i = 0; i < gateway.connection.sessionStartLimit.maxConcurrency; ++i) {\n logger.debug(`[Gateway] Preparing buckets for concurrency: ${i}`)\n gateway.buckets.set(i, {\n workers: [],\n identifyRequests: [],\n })\n }\n\n // ORGANIZE ALL SHARDS INTO THEIR OWN BUCKETS\n for (let shardId = gateway.firstShardId; shardId <= gateway.lastShardId; ++shardId) {\n logger.debug(`[Gateway] Preparing buckets for shard: ${shardId}`)\n if (shardId >= gateway.totalShards) {\n throw new Error(`Shard (id: ${shardId}) is bigger or equal to the used amount of used shards which is ${gateway.totalShards}`)\n }\n\n const bucketId = shardId % gateway.connection.sessionStartLimit.maxConcurrency\n const bucket = gateway.buckets.get(bucketId)\n if (!bucket) {\n throw new Error(\n `Shard (id: ${shardId}) got assigned to an illegal bucket id: ${bucketId}, expected a bucket id between 0 and ${\n gateway.connection.sessionStartLimit.maxConcurrency - 1\n }`,\n )\n }\n\n // FIND A QUEUE IN THIS BUCKET THAT HAS SPACE\n // const worker = bucket.workers.find((w) => w.queue.length < gateway.shardsPerWorker);\n const workerId = gateway.calculateWorkerId(shardId)\n const worker = bucket.workers.find((w) => w.id === workerId)\n if (worker) {\n // IF THE QUEUE HAS SPACE JUST ADD IT TO THIS QUEUE\n worker.queue.push(shardId)\n } else {\n bucket.workers.push({ id: workerId, queue: [shardId] })\n }\n }\n\n for (const bucket of gateway.buckets.values()) {\n for (const worker of bucket.workers.values()) {\n // eslint-disable-next-line @typescript-eslint/require-array-sort-compare\n worker.queue = worker.queue.sort((a, b) => a - b)\n }\n }\n },\n async spawnShards() {\n // PREPARES ALL SHARDS IN SPECIFIC BUCKETS\n gateway.prepareBuckets()\n\n // Prefer concurrency of forEach instead of forof\n await Promise.all(\n [...gateway.buckets.entries()].map(async ([bucketId, bucket]) => {\n for (const worker of bucket.workers) {\n for (const shardId of worker.queue) {\n await gateway.tellWorkerToIdentify(worker.id, shardId, bucketId)\n }\n }\n }),\n )\n },\n async shutdown(code, reason) {\n gateway.shards.forEach((shard) => shard.close(code, reason))\n\n await delay(5000)\n },\n async tellWorkerToIdentify(workerId, shardId, bucketId) {\n logger.debug(`[Gateway] tell worker to identify (${workerId}, ${shardId}, ${bucketId})`)\n await gateway.identify(shardId)\n },\n async identify(shardId: number) {\n let shard = this.shards.get(shardId)\n logger.debug(`[Gateway] identifying ${shard ? 'existing' : 'new'} shard (${shardId})`)\n\n if (!shard) {\n shard = new Shard({\n id: shardId,\n connection: {\n compress: this.compress,\n intents: this.intents,\n properties: this.properties,\n token: this.token,\n totalShards: this.totalShards,\n url: this.url,\n version: this.version,\n },\n events: options.events,\n requestIdentify: async () => {\n await gateway.identify(shardId)\n },\n shardIsReady: async () => {\n logger.debug(`[Shard] Shard #${shardId} is ready`)\n await delay(gateway.spawnShardDelay)\n logger.debug(`[Shard] Resolving shard identify request`)\n gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency)!.identifyRequests.shift()?.()\n },\n })\n\n if (this.preferSnakeCase) {\n shard.forwardToBot = async (payload) => {\n options.events.message?.(shard!, payload)\n }\n }\n\n this.shards.set(shardId, shard)\n }\n\n const bucket = gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency)\n if (!bucket) return\n\n return await new Promise((resolve) => {\n // Mark that we are making an identify request so another is not made.\n bucket.identifyRequests.push(resolve)\n logger.debug(`[Gateway] identifying shard #(${shardId}).`)\n // This will trigger identify and when READY is received it will resolve the above request.\n shard?.identify()\n })\n },\n async kill(shardId: number) {\n const shard = this.shards.get(shardId)\n if (!shard) {\n return logger.debug(`[Gateway] kill shard but not found (${shardId})`)\n }\n\n logger.debug(`[Gateway] kill shard (${shardId})`)\n this.shards.delete(shardId)\n await shard.shutdown()\n },\n\n async requestIdentify(shardId: number) {\n logger.debug(`[Gateway] requesting identify`)\n // const bucket = gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency)\n // if (!bucket) return\n\n // return await new Promise((resolve) => {\n // bucket.identifyRequests.push(resolve)\n // })\n },\n\n // Helpers methods below this\n\n calculateShardId(guildId, totalShards) {\n // If none is provided, use the total shards number from gateway object.\n if (!totalShards) totalShards = gateway.totalShards\n // If it is only 1 shard, it will always be shard id 0\n if (totalShards === 1) {\n logger.debug(`[Gateway] calculateShardId (1 shard)`)\n return 0\n }\n\n logger.debug(`[Gateway] calculateShardId (guildId: ${guildId}, totalShards: ${totalShards})`)\n return Number((BigInt(guildId) >> 22n) % BigInt(totalShards))\n },\n\n async joinVoiceChannel(guildId, channelId, options) {\n const shardId = gateway.calculateShardId(guildId)\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId} not found`)\n }\n\n logger.debug(`[Gateway] joinVoiceChannel guildId: ${guildId} channelId: ${channelId}`)\n shard.joinVoiceChannel(guildId, channelId, options)\n },\n\n async editBotStatus(data) {\n logger.debug(`[Gateway] editBotStatus data: ${JSON.stringify(data)}`)\n await Promise.all(\n [...gateway.shards.values()].map(async (shard) => {\n gateway.editShardStatus(shard.id, data)\n }),\n )\n },\n\n async editShardStatus(shardId, data) {\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId}) not found.`)\n }\n\n logger.debug(`[Gateway] editShardStatus shardId: ${shardId} -> data: ${JSON.stringify(data)}`)\n await shard.editShardStatus(data)\n },\n\n async requestMembers(guildId, options) {\n const shardId = gateway.calculateShardId(guildId)\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId}) not found.`)\n }\n\n logger.debug(`[Gateway] requestMembers guildId: ${guildId} -> options ${JSON.stringify(options)}`)\n return await shard.requestMembers(guildId, options)\n },\n\n async leaveVoiceChannel(guildId) {\n const shardId = gateway.calculateShardId(guildId)\n const shard = gateway.shards.get(shardId)\n if (!shard) {\n throw new Error(`Shard (id: ${shardId} not found`)\n }\n\n logger.debug(`[Gateway] leaveVoiceChannel guildId: ${guildId} Shard ${shardId}`)\n await shard.leaveVoiceChannel(guildId)\n },\n }\n\n return gateway\n}\n\nexport interface CreateGatewayManagerOptions {\n /**\n * Id of the first Shard which should get controlled by this manager.\n * @default 0\n */\n firstShardId?: number\n /**\n * Id of the last Shard which should get controlled by this manager.\n * @default 0\n */\n lastShardId?: number\n /**\n * Delay in milliseconds to wait before spawning next shard. OPTIMAL IS ABOVE 5100. YOU DON'T WANT TO HIT THE RATE LIMIT!!!\n * @default 5300\n */\n spawnShardDelay?: number\n /**\n * Whether to send the discord packets in snake case form.\n * @default false\n */\n preferSnakeCase?: boolean\n /**\n * Total amount of shards your bot uses. Useful for zero-downtime updates or resharding.\n * @default 1\n */\n totalShards?: number\n /**\n * The amount of shards to load per worker.\n * @default 25\n */\n shardsPerWorker?: number\n /**\n * The total amount of workers to use for your bot.\n * @default 4\n */\n totalWorkers?: number\n /** Important data which is used by the manager to connect shards to the gateway. */\n connection?: Camelize<DiscordGetGatewayBot>\n /** Whether incoming payloads are compressed using zlib.\n *\n * @default false\n */\n compress?: boolean\n /** The calculated intent value of the events which the shard should receive.\n *\n * @default 0\n */\n intents?: number\n /** Identify properties to use */\n properties?: {\n /** Operating system the shard runs on.\n *\n * @default \"darwin\" | \"linux\" | \"windows\"\n */\n os: string\n /** The \"browser\" where this shard is running on.\n *\n * @default \"Discordeno\"\n */\n browser: string\n /** The device on which the shard is running.\n *\n * @default \"Discordeno\"\n */\n device: string\n }\n /** Bot token which is used to connect to Discord */\n token: string\n /** The URL of the gateway which should be connected to.\n *\n * @default \"wss://gateway.discord.gg\"\n */\n url?: string\n /** The gateway version which should be used.\n *\n * @default 10\n */\n version?: number\n /** The events handlers */\n events: ShardEvents\n /** This managers cache related settings. */\n cache?: {\n requestMembers?: {\n /**\n * Whether or not request member requests should be cached.\n * @default false\n */\n enabled?: boolean\n /** The pending requests. */\n pending: Collection<string, RequestMemberRequest>\n }\n }\n}\n\nexport interface GatewayManager extends Required<CreateGatewayManagerOptions> {\n /** The max concurrency buckets. Those will be created when the `spawnShards` (which calls `prepareBuckets` under the hood) function gets called. */\n buckets: Map<\n number,\n {\n workers: Array<{ id: number; queue: number[] }>\n /** Requests to identify shards are made based on whether it is available to be made. */\n identifyRequests: Array<(value: void | PromiseLike<void>) => void>\n }\n >\n /** The shards that are created. */\n shards: Map<number, Shard>\n /** Determine max number of shards to use based upon the max concurrency. */\n calculateTotalShards: () => number\n /** Determine the id of the worker which is handling a shard. */\n calculateWorkerId: (shardId: number) => number\n /** Prepares all the buckets that are available for identifying the shards. */\n prepareBuckets: () => void\n /** Start identifying all the shards. */\n spawnShards: () => Promise<void>\n /** Shutdown all shards. */\n shutdown: (code: number, reason: string) => Promise<void>\n /** Allows users to hook in and change to communicate to different workers across different servers or anything they like. For example using redis pubsub to talk to other servers. */\n tellWorkerToIdentify: (workerId: number, shardId: number, bucketId: number) => Promise<void>\n /** Tell the manager to identify a Shard. If this Shard is not already managed this will also add the Shard to the manager. */\n identify: (shardId: number) => Promise<void>\n /** Kill a shard. Close a shards connection to Discord's gateway (if any) and remove it from the manager. */\n kill: (shardId: number) => Promise<void>\n /** This function makes sure that the bucket is allowed to make the next identify request. */\n requestIdentify: (shardId: number) => Promise<void>\n /** Calculates the number of shards based on the guild id and total shards. */\n calculateShardId: (guildId: BigString, totalShards?: number) => number\n /**\n * Connects the bot user to a voice or stage channel.\n *\n * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.\n *\n * @param guildId - The ID of the guild the voice channel to leave is in.\n * @param channelId - The ID of the channel you want to join.\n *\n * @remarks\n * Requires the `CONNECT` permission.\n *\n * Fires a _Voice State Update_ gateway event.\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}\n */\n joinVoiceChannel: (guildId: BigString, channelId: BigString, options?: AtLeastOne<Omit<UpdateVoiceState, 'guildId' | 'channelId'>>) => Promise<void>\n /**\n * Edits the bot status in all shards that this gateway manages.\n *\n * @param data The status data to set the bots status to.\n * @returns Promise<void>\n */\n editBotStatus: (data: StatusUpdate) => Promise<void>\n /**\n * Edits the bot's status on one shard.\n *\n * @param shardId The shard id to edit the status for.\n * @param data The status data to set the bots status to.\n * @returns Promise<void>\n */\n editShardStatus: (shardId: number, data: StatusUpdate) => Promise<void>\n /**\n * Fetches the list of members for a guild over the gateway.\n *\n * @param guildId - The ID of the guild to get the list of members for.\n * @param options - The parameters for the fetching of the members.\n *\n * @remarks\n * If requesting the entire member list:\n * - Requires the `GUILD_MEMBERS` intent.\n *\n * If requesting presences ({@link RequestGuildMembers.presences | presences} set to `true`):\n * - Requires the `GUILD_PRESENCES` intent.\n *\n * If requesting a prefix ({@link RequestGuildMembers.query | query} non-`undefined`):\n * - Returns a maximum of 100 members.\n *\n * If requesting a users by ID ({@link RequestGuildMembers.userIds | userIds} non-`undefined`):\n * - Returns a maximum of 100 members.\n *\n * Fires a _Guild Members Chunk_ gateway event for every 1000 members fetched.\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#request-guild-members}\n */\n requestMembers: (guildId: BigString, options?: Omit<RequestGuildMembers, 'guildId'>) => Promise<Camelize<DiscordMember[]>>\n /**\n * Leaves the voice channel the bot user is currently in.\n *\n * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.\n *\n * @param guildId - The ID of the guild the voice channel to leave is in.\n *\n * @remarks\n * Fires a _Voice State Update_ gateway event.\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}\n */\n leaveVoiceChannel: (guildId: BigString) => Promise<void>\n}\n\nexport interface RequestMemberRequest {\n /** The unique nonce for this request. */\n nonce: string\n /** The resolver handler to run when all members arrive. */\n resolve: (value: Camelize<DiscordMember[]> | PromiseLike<Camelize<DiscordMember[]>>) => void\n /** The members that have already arrived for this request. */\n members: Camelize<DiscordMember[]>\n}\n"],"names":["Collection","delay","logger","Shard","createGatewayManager","options","connection","url","shards","sessionStartLimit","maxConcurrency","remaining","total","resetAfter","gateway","events","compress","intents","properties","os","process","platform","browser","device","token","version","totalShards","lastShardId","firstShardId","totalWorkers","shardsPerWorker","spawnShardDelay","preferSnakeCase","Map","buckets","cache","requestMembers","enabled","pending","calculateTotalShards","debug","Math","ceil","calculateWorkerId","shardId","workerId","prepareBuckets","i","set","workers","identifyRequests","Error","bucketId","bucket","get","worker","find","w","id","queue","push","values","sort","a","b","spawnShards","Promise","all","entries","map","tellWorkerToIdentify","shutdown","code","reason","forEach","shard","close","identify","requestIdentify","shardIsReady","shift","forwardToBot","payload","message","resolve","kill","delete","calculateShardId","guildId","Number","BigInt","joinVoiceChannel","channelId","editBotStatus","data","JSON","stringify","editShardStatus","leaveVoiceChannel"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@discordeno/gateway",
3
- "version": "19.0.0-next.fd357ae",
3
+ "version": "19.0.0-next.fd518cb",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "type": "module",
@@ -24,8 +24,8 @@
24
24
  "test:test-type": "tsc --project tsconfig.test.json"
25
25
  },
26
26
  "dependencies": {
27
- "@discordeno/types": "19.0.0-next.fd357ae",
28
- "@discordeno/utils": "19.0.0-next.fd357ae",
27
+ "@discordeno/types": "19.0.0-next.fd518cb",
28
+ "@discordeno/utils": "19.0.0-next.fd518cb",
29
29
  "ws": "^8.13.0"
30
30
  },
31
31
  "devDependencies": {