@discordeno/gateway 19.0.0-next.a6c3ffe → 19.0.0-next.a8f9e5e

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/Shard.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import type { AtLeastOne, BigString, Camelize, DiscordGatewayPayload, DiscordMember, RequestGuildMembers } from '@discordeno/types';
2
- import { Collection, LeakyBucket } from '@discordeno/utils';
3
- import WebSocket from 'ws';
4
- import type { RequestMemberRequest } from './manager.js';
5
- import type { BotStatusUpdate, ShardEvents, ShardGatewayConfig, ShardHeart, ShardSocketRequest, StatusUpdate, UpdateVoiceState } from './types.js';
1
+ import type { DiscordGatewayPayload } from '@discordeno/types';
2
+ import { LeakyBucket } from '@discordeno/utils';
3
+ import NodeWebSocket from 'ws';
4
+ import type { BotStatusUpdate, ShardEvents, ShardGatewayConfig, ShardHeart, ShardSocketRequest } from './types.js';
6
5
  import { ShardState } from './types.js';
7
6
  export declare class DiscordenoShard {
8
7
  /** The id of the shard */
@@ -20,7 +19,7 @@ export declare class DiscordenoShard {
20
19
  /** Current session id of the shard if present. */
21
20
  sessionId?: string;
22
21
  /** This contains the WebSocket connection to Discord, if currently connected. */
23
- socket?: WebSocket;
22
+ socket?: NodeWebSocket;
24
23
  /** Current internal state of the this. */
25
24
  state: ShardState;
26
25
  /** The url provided by discord to use when resuming a connection for this this. */
@@ -33,22 +32,10 @@ export declare class DiscordenoShard {
33
32
  resolves: Map<"READY" | "RESUMED" | "INVALID_SESSION", (payload: DiscordGatewayPayload) => void>;
34
33
  /** Shard bucket. Only access this if you know what you are doing. Bucket for handling shard request rate limits. */
35
34
  bucket: LeakyBucket;
36
- /** This managers cache related settings. */
37
- cache: {
38
- requestMembers: {
39
- /**
40
- * Whether or not request member requests should be cached.
41
- * @default false
42
- */
43
- enabled: boolean;
44
- /** The pending requests. */
45
- pending: Collection<string, RequestMemberRequest>;
46
- };
47
- };
48
35
  constructor(options: ShardCreateOptions);
49
36
  /** The gateway configuration which is used to connect to Discord. */
50
37
  get gatewayConfig(): ShardGatewayConfig;
51
- /** The url to connect to. Intially this is the discord gateway url, and then is switched to resume gateway url once a READY is received. */
38
+ /** The url to connect to. Initially this is the discord gateway url, and then is switched to resume gateway url once a READY is received. */
52
39
  get connectionUrl(): string;
53
40
  /** Calculate the amount of requests which can safely be made per rate limit interval, before the gateway gets disconnected due to an exceeded rate limit. */
54
41
  calculateSafeRequests(): number;
@@ -70,11 +57,12 @@ export declare class DiscordenoShard {
70
57
  /** Shutdown the this. Forcefully disconnect the shard from Discord. The shard may not attempt to reconnect with Discord. */
71
58
  shutdown(): Promise<void>;
72
59
  /** Handle a gateway connection close. */
73
- handleClose(close: WebSocket.CloseEvent): Promise<void>;
60
+ handleClose(close: NodeWebSocket.CloseEvent): Promise<void>;
74
61
  /** Handles a incoming gateway packet. */
75
62
  handleDiscordPacket(packet: DiscordGatewayPayload): Promise<void>;
63
+ forwardToBot(packet: DiscordGatewayPayload): void;
76
64
  /** Handle an incoming gateway message. */
77
- handleMessage(message: WebSocket.MessageEvent): Promise<void>;
65
+ handleMessage(message: NodeWebSocket.MessageEvent): Promise<void>;
78
66
  /**
79
67
  * Override in order to make the shards presence.
80
68
  * async in case devs create the presence based on eg. database values.
@@ -89,74 +77,6 @@ export declare class DiscordenoShard {
89
77
  startHeartbeating(interval: number): void;
90
78
  /** Stop the heartbeating process with discord. */
91
79
  stopHeartbeating(): void;
92
- /**
93
- * Connects the bot user to a voice or stage channel.
94
- *
95
- * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.
96
- *
97
- * @param guildId - The ID of the guild the voice channel to leave is in.
98
- * @param channelId - The ID of the channel you want to join.
99
- *
100
- * @remarks
101
- * Requires the `CONNECT` permission.
102
- *
103
- * Fires a _Voice State Update_ gateway event.
104
- *
105
- * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}
106
- */
107
- joinVoiceChannel(guildId: BigString, channelId: BigString, options?: AtLeastOne<Omit<UpdateVoiceState, 'guildId' | 'channelId'>>): Promise<void>;
108
- /**
109
- * Edits the bot status in all shards that this gateway manages.
110
- *
111
- * @param data The status data to set the bots status to.
112
- * @returns Promise<void>
113
- */
114
- editBotStatus(data: StatusUpdate): Promise<void>;
115
- /**
116
- * Edits the bot's status on one shard.
117
- *
118
- * @param shardId The shard id to edit the status for.
119
- * @param data The status data to set the bots status to.
120
- * @returns Promise<void>
121
- */
122
- editShardStatus(data: StatusUpdate): Promise<void>;
123
- /**
124
- * Fetches the list of members for a guild over the gateway.
125
- *
126
- * @param guildId - The ID of the guild to get the list of members for.
127
- * @param options - The parameters for the fetching of the members.
128
- *
129
- * @remarks
130
- * If requesting the entire member list:
131
- * - Requires the `GUILD_MEMBERS` intent.
132
- *
133
- * If requesting presences ({@link RequestGuildMembers.presences | presences} set to `true`):
134
- * - Requires the `GUILD_PRESENCES` intent.
135
- *
136
- * If requesting a prefix ({@link RequestGuildMembers.query | query} non-`undefined`):
137
- * - Returns a maximum of 100 members.
138
- *
139
- * If requesting a users by ID ({@link RequestGuildMembers.userIds | userIds} non-`undefined`):
140
- * - Returns a maximum of 100 members.
141
- *
142
- * Fires a _Guild Members Chunk_ gateway event for every 1000 members fetched.
143
- *
144
- * @see {@link https://discord.com/developers/docs/topics/gateway#request-guild-members}
145
- */
146
- requestMembers(guildId: BigString, options?: Omit<RequestGuildMembers, 'guildId'>): Promise<Camelize<DiscordMember[]>>;
147
- /**
148
- * Leaves the voice channel the bot user is currently in.
149
- *
150
- * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.
151
- *
152
- * @param guildId - The ID of the guild the voice channel to leave is in.
153
- *
154
- * @remarks
155
- * Fires a _Voice State Update_ gateway event.
156
- *
157
- * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}
158
- */
159
- leaveVoiceChannel(guildId: BigString): Promise<void>;
160
80
  }
161
81
  export interface ShardCreateOptions {
162
82
  /** The shard id */
@@ -1 +1 @@
1
- {"version":3,"file":"Shard.d.ts","sourceRoot":"","sources":["../src/Shard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Shard.d.ts","sourceRoot":"","sources":["../src/Shard.ts"],"names":[],"mappings":"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"}
package/dist/Shard.js CHANGED
@@ -1,7 +1,7 @@
1
- /* eslint-disable @typescript-eslint/no-confusing-void-expression */ import { GatewayCloseEventCodes, GatewayIntents, GatewayOpcodes } from '@discordeno/types';
2
- import { camelize, Collection, delay, LeakyBucket, logger } from '@discordeno/utils';
1
+ /* eslint-disable @typescript-eslint/no-confusing-void-expression */ import { GatewayCloseEventCodes, GatewayOpcodes } from '@discordeno/types';
2
+ import { camelize, delay, LeakyBucket, logger } from '@discordeno/utils';
3
3
  import { inflateSync } from 'node:zlib';
4
- import WebSocket from 'ws';
4
+ import NodeWebSocket from 'ws';
5
5
  import { ShardSocketCloseCodes, ShardState } from './types.js';
6
6
  export class DiscordenoShard {
7
7
  constructor(options){
@@ -13,15 +13,6 @@ export class DiscordenoShard {
13
13
  /** The shard related event handlers. */ this.events = {};
14
14
  /** Cache for pending gateway requests which should have been send while the gateway went offline. */ this.offlineSendQueue = [];
15
15
  /** Resolve internal waiting states. Mapped by SelectedEvents => ResolveFunction */ this.resolves = new Map();
16
- /** This managers cache related settings. */ this.cache = {
17
- requestMembers: {
18
- /**
19
- * Whether or not request member requests should be cached.
20
- * @default false
21
- */ enabled: false,
22
- /** The pending requests. */ pending: new Collection()
23
- }
24
- };
25
16
  this.id = options.id;
26
17
  this.connection = options.connection;
27
18
  this.events = options.events;
@@ -40,7 +31,7 @@ export class DiscordenoShard {
40
31
  /** The gateway configuration which is used to connect to Discord. */ get gatewayConfig() {
41
32
  return this.connection;
42
33
  }
43
- /** The url to connect to. Intially this is the discord gateway url, and then is switched to resume gateway url once a READY is received. */ get connectionUrl() {
34
+ /** The url to connect to. Initially this is the discord gateway url, and then is switched to resume gateway url once a READY is received. */ get connectionUrl() {
44
35
  // Use || and not ?? here. ?? will cause a bug.
45
36
  return this.resumeGatewayUrl || this.gatewayConfig.url;
46
37
  }
@@ -59,7 +50,7 @@ export class DiscordenoShard {
59
50
  }
60
51
  }
61
52
  /** Close the socket connection to discord if present. */ close(code, reason) {
62
- if (this.socket?.readyState !== WebSocket.OPEN) return;
53
+ if (this.socket?.readyState !== NodeWebSocket.OPEN) return;
63
54
  this.socket?.close(code, reason);
64
55
  }
65
56
  /** Connect the shard with the gateway and start heartbeating. This will not identify the shard to the gateway. */ async connect() {
@@ -75,7 +66,8 @@ export class DiscordenoShard {
75
66
  const url = new URL(this.connectionUrl);
76
67
  url.searchParams.set('v', this.gatewayConfig.version.toString());
77
68
  url.searchParams.set('encoding', 'json');
78
- const socket = new WebSocket(url.toString());
69
+ const socket = // @ts-expect-error Deno
70
+ globalThis.Deno !== undefined && Reflect.has(globalThis, 'Deno') ? new WebSocket(url.toString()) : new NodeWebSocket(url.toString());
79
71
  this.socket = socket;
80
72
  // TODO: proper event handling
81
73
  socket.onerror = (event)=>console.log({
@@ -145,13 +137,14 @@ export class DiscordenoShard {
145
137
  });
146
138
  }
147
139
  /** Check whether the connection to Discord is currently open. */ isOpen() {
148
- return this.socket?.readyState === WebSocket.OPEN;
140
+ return this.socket?.readyState === NodeWebSocket.OPEN;
149
141
  }
150
142
  /** Attempt to resume the previous shards session with the gateway. */ async resume() {
151
143
  logger.debug(`[Gateway] Resuming Shard #${this.id}`);
152
144
  // It has been requested to resume the Shards session.
153
145
  // It's possible that the shard is still connected with Discord's gateway therefore we need to forcefully close it.
154
146
  if (this.isOpen()) {
147
+ logger.debug(`[Gateway] Resuming Shard #${this.id} in isOpen`);
155
148
  this.close(ShardSocketCloseCodes.ResumeClosingOldConnection, 'Reconnecting the shard, closing old connection.');
156
149
  }
157
150
  // Shard has never identified, so we cannot resume.
@@ -160,8 +153,11 @@ export class DiscordenoShard {
160
153
  return await this.identify();
161
154
  }
162
155
  this.state = ShardState.Resuming;
156
+ logger.debug(`[Gateway] Resuming Shard #${this.id}, before connecting`);
163
157
  // Before we can resume, we need to create a new connection with Discord's gateway.
164
158
  await this.connect();
159
+ logger.debug(// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
160
+ `[Gateway] Resuming Shard #${this.id}, after connecting. ${this.gatewayConfig.token} | ${this.sessionId} | ${this.previousSequenceNumber}`);
165
161
  this.send({
166
162
  op: GatewayOpcodes.Resume,
167
163
  d: {
@@ -170,6 +166,7 @@ export class DiscordenoShard {
170
166
  seq: this.previousSequenceNumber ?? 0
171
167
  }
172
168
  }, true);
169
+ logger.debug(`[Gateway] Resuming Shard #${this.id} after send resumg`);
173
170
  return await new Promise((resolve)=>{
174
171
  this.resolves.set('RESUMED', ()=>resolve());
175
172
  // If it is attempted to resume with an invalid session id,
@@ -249,6 +246,7 @@ export class DiscordenoShard {
249
246
  case GatewayCloseEventCodes.AlreadyAuthenticated:
250
247
  default:
251
248
  {
249
+ logger.info(`[Shard] closed shard #${this.id}. Resuming...`);
252
250
  this.state = ShardState.Resuming;
253
251
  this.events.disconnected?.(this);
254
252
  return await this.resume();
@@ -282,6 +280,7 @@ export class DiscordenoShard {
282
280
  case GatewayOpcodes.Hello:
283
281
  {
284
282
  const interval = packet.d.heartbeat_interval;
283
+ logger.debug(`[Gateway] Hello on Shard #${this.id}`);
285
284
  this.startHeartbeating(interval);
286
285
  if (this.state !== ShardState.Resuming) {
287
286
  const currentQueue = [
@@ -333,25 +332,33 @@ export class DiscordenoShard {
333
332
  break;
334
333
  }
335
334
  }
336
- if (packet.t === 'RESUMED') {
337
- // gateway.debug("GW RESUMED", { shardId });
338
- this.state = ShardState.Connected;
339
- this.events.resumed?.(this);
340
- // Continue the requests which have been queued since the shard went offline.
341
- this.offlineSendQueue.map((resolve)=>resolve());
342
- this.resolves.get('RESUMED')?.(packet);
343
- this.resolves.delete('RESUMED');
344
- } else if (packet.t === 'READY') {
345
- // Important for future resumes.
346
- const payload = packet.d;
347
- this.resumeGatewayUrl = payload.resume_gateway_url;
348
- this.sessionId = payload.session_id;
349
- this.state = ShardState.Connected;
350
- // Continue the requests which have been queued since the shard went offline.
351
- // Important when this is a re-identify
352
- this.offlineSendQueue.map((resolve)=>resolve());
353
- this.resolves.get('READY')?.(packet);
354
- this.resolves.delete('READY');
335
+ switch(packet.t){
336
+ case 'RESUMED':
337
+ this.state = ShardState.Connected;
338
+ this.events.resumed?.(this);
339
+ // Continue the requests which have been queued since the shard went offline.
340
+ this.offlineSendQueue.map((resolve)=>resolve());
341
+ this.resolves.get('RESUMED')?.(packet);
342
+ this.resolves.delete('RESUMED');
343
+ break;
344
+ case 'READY':
345
+ {
346
+ // Important for future resumes.
347
+ const payload = packet.d;
348
+ this.resumeGatewayUrl = payload.resume_gateway_url;
349
+ this.sessionId = payload.session_id;
350
+ this.state = ShardState.Connected;
351
+ // Continue the requests which have been queued since the shard went offline.
352
+ // Important when this is a re-identify
353
+ this.offlineSendQueue.map((resolve)=>resolve());
354
+ this.resolves.get('READY')?.(packet);
355
+ this.resolves.delete('READY');
356
+ break;
357
+ }
358
+ case 'GUILD_MEMBERS_CHUNK':
359
+ {
360
+ this.events.guildMemberChunk?.(packet.d);
361
+ }
355
362
  }
356
363
  // Update the sequence number if it is present
357
364
  // `s` can be either `null` or a `number`.
@@ -359,6 +366,9 @@ export class DiscordenoShard {
359
366
  if (packet.s !== null) {
360
367
  this.previousSequenceNumber = packet.s;
361
368
  }
369
+ this.forwardToBot(packet);
370
+ }
371
+ forwardToBot(packet) {
362
372
  // The necessary handling required for the Shards connection has been finished.
363
373
  // Now the event can be safely forwarded.
364
374
  this.events.message?.(this, camelize(packet));
@@ -385,6 +395,7 @@ export class DiscordenoShard {
385
395
  /** This function communicates with the management process, in order to know whether its free to identify. When this function resolves, this means that the shard is allowed to send an identify payload to discord. */ async requestIdentify() {}
386
396
  /** This function communicates with the management process, in order to tell it can identify the next shard. */ async shardIsReady() {}
387
397
  /** Start sending heartbeat payloads to Discord in the provided interval. */ startHeartbeating(interval) {
398
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id}`);
388
399
  // If old heartbeast exist like after resume, clear the old ones.
389
400
  if (this.heart.intervalId) clearInterval(this.heart.intervalId);
390
401
  if (this.heart.timeoutId) clearTimeout(this.heart.timeoutId);
@@ -395,6 +406,7 @@ export class DiscordenoShard {
395
406
  ShardState.Disconnected,
396
407
  ShardState.Offline
397
408
  ].includes(this.state)) {
409
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} a`);
398
410
  this.state = ShardState.Unidentified;
399
411
  }
400
412
  // The first heartbeat needs to be send with a random delay between `0` and `interval`
@@ -403,17 +415,22 @@ export class DiscordenoShard {
403
415
  // Reference: https://discord.com/developers/docs/topics/gateway#heartbeating
404
416
  const jitter = Math.ceil(this.heart.interval * (Math.random() || 0.5));
405
417
  this.heart.timeoutId = setTimeout(()=>{
418
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} b`);
406
419
  if (!this.isOpen()) return;
420
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} c ${this.previousSequenceNumber}`);
407
421
  // Using a direct socket.send call here because heartbeat requests are reserved by us.
408
422
  this.socket?.send(JSON.stringify({
409
423
  op: GatewayOpcodes.Heartbeat,
410
424
  d: this.previousSequenceNumber
411
425
  }));
426
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} d`);
412
427
  this.heart.lastBeat = Date.now();
413
428
  this.heart.acknowledged = false;
414
429
  // After the random heartbeat jitter we can start a normal interval.
415
430
  this.heart.intervalId = setInterval(async ()=>{
431
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} e`);
416
432
  if (!this.isOpen()) return;
433
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} f`);
417
434
  // gateway.debug("GW DEBUG", `Running setInterval in heartbeat file. Shard: ${shardId}`);
418
435
  // gateway.debug("GW HEARTBEATING", { shardId, shard: currentShard });
419
436
  // The Shard did not receive a heartbeat ACK from Discord in time,
@@ -426,11 +443,13 @@ export class DiscordenoShard {
426
443
  return await this.identify();
427
444
  }
428
445
  this.heart.acknowledged = false;
446
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} g`);
429
447
  // Using a direct socket.send call here because heartbeat requests are reserved by us.
430
448
  this.socket?.send(JSON.stringify({
431
449
  op: GatewayOpcodes.Heartbeat,
432
450
  d: this.previousSequenceNumber
433
451
  }));
452
+ logger.debug(`[Gateway] Start Heartbeating Shard #${this.id} h`);
434
453
  this.heart.lastBeat = Date.now();
435
454
  this.events.heartbeat?.(this);
436
455
  }, this.heart.interval);
@@ -443,153 +462,6 @@ export class DiscordenoShard {
443
462
  // To go safe we should clear the related timeout too.
444
463
  clearTimeout(this.heart.timeoutId);
445
464
  }
446
- /**
447
- * Connects the bot user to a voice or stage channel.
448
- *
449
- * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.
450
- *
451
- * @param guildId - The ID of the guild the voice channel to leave is in.
452
- * @param channelId - The ID of the channel you want to join.
453
- *
454
- * @remarks
455
- * Requires the `CONNECT` permission.
456
- *
457
- * Fires a _Voice State Update_ gateway event.
458
- *
459
- * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}
460
- */ async joinVoiceChannel(guildId, channelId, options) {
461
- logger.debug(`[Shard] joinVoiceChannel guildId: ${guildId} channelId: ${channelId}`);
462
- await this.send({
463
- op: GatewayOpcodes.VoiceStateUpdate,
464
- d: {
465
- guild_id: guildId.toString(),
466
- channel_id: channelId.toString(),
467
- self_mute: Boolean(options?.selfMute),
468
- self_deaf: options?.selfDeaf ?? true
469
- }
470
- });
471
- }
472
- /**
473
- * Edits the bot status in all shards that this gateway manages.
474
- *
475
- * @param data The status data to set the bots status to.
476
- * @returns Promise<void>
477
- */ async editBotStatus(data) {
478
- logger.debug(`[Shard] editBotStatus data: ${JSON.stringify(data)}`);
479
- await this.editShardStatus(data);
480
- }
481
- /**
482
- * Edits the bot's status on one shard.
483
- *
484
- * @param shardId The shard id to edit the status for.
485
- * @param data The status data to set the bots status to.
486
- * @returns Promise<void>
487
- */ async editShardStatus(data) {
488
- logger.debug(`[Shard] editShardStatus shardId: ${this.id} -> data: ${JSON.stringify(data)}`);
489
- await this.send({
490
- op: GatewayOpcodes.PresenceUpdate,
491
- d: {
492
- since: null,
493
- afk: false,
494
- activities: data.activities,
495
- status: data.status
496
- }
497
- });
498
- }
499
- /**
500
- * Fetches the list of members for a guild over the gateway.
501
- *
502
- * @param guildId - The ID of the guild to get the list of members for.
503
- * @param options - The parameters for the fetching of the members.
504
- *
505
- * @remarks
506
- * If requesting the entire member list:
507
- * - Requires the `GUILD_MEMBERS` intent.
508
- *
509
- * If requesting presences ({@link RequestGuildMembers.presences | presences} set to `true`):
510
- * - Requires the `GUILD_PRESENCES` intent.
511
- *
512
- * If requesting a prefix ({@link RequestGuildMembers.query | query} non-`undefined`):
513
- * - Returns a maximum of 100 members.
514
- *
515
- * If requesting a users by ID ({@link RequestGuildMembers.userIds | userIds} non-`undefined`):
516
- * - Returns a maximum of 100 members.
517
- *
518
- * Fires a _Guild Members Chunk_ gateway event for every 1000 members fetched.
519
- *
520
- * @see {@link https://discord.com/developers/docs/topics/gateway#request-guild-members}
521
- */ async requestMembers(guildId, options) {
522
- // You can request 1 member without the intent
523
- // Check if intents is not 0 as proxy ws won't set intents in other instances
524
- if (this.connection.intents && (!options?.limit || options.limit > 1) && !(this.connection.intents & GatewayIntents.GuildMembers)) {
525
- throw new Error('MISSING_INTENT_GUILD_MEMBERS');
526
- }
527
- if (options?.userIds?.length) {
528
- logger.debug(`[Shard] requestMembers guildId: ${guildId} -> setting user limit based on userIds length: ${options.userIds.length}`);
529
- options.limit = options.userIds.length;
530
- }
531
- const nonce = `${guildId}-${Date.now()}`;
532
- // Gateway does not require caching these requests so directly send and return
533
- if (!this.cache.requestMembers?.enabled) {
534
- logger.debug(`[Shard] requestMembers guildId: ${guildId} -> skipping cache -> options ${JSON.stringify(options)}`);
535
- await this.send({
536
- op: GatewayOpcodes.RequestGuildMembers,
537
- d: {
538
- guild_id: guildId.toString(),
539
- // If a query is provided use it, OR if a limit is NOT provided use ""
540
- query: options?.query ?? (options?.limit ? undefined : ''),
541
- limit: options?.limit ?? 0,
542
- presences: options?.presences ?? false,
543
- user_ids: options?.userIds?.map((id)=>id.toString()),
544
- nonce
545
- }
546
- });
547
- return [];
548
- }
549
- return await new Promise((resolve)=>{
550
- this.cache.requestMembers?.pending.set(nonce, {
551
- nonce,
552
- resolve,
553
- members: []
554
- });
555
- logger.debug(`[Shard] requestMembers guildId: ${guildId} -> requesting members -> data: ${JSON.stringify(options)}`);
556
- this.send({
557
- op: GatewayOpcodes.RequestGuildMembers,
558
- d: {
559
- guild_id: guildId.toString(),
560
- // If a query is provided use it, OR if a limit is NOT provided use ""
561
- query: options?.query ?? (options?.limit ? undefined : ''),
562
- limit: options?.limit ?? 0,
563
- presences: options?.presences ?? false,
564
- user_ids: options?.userIds?.map((id)=>id.toString()),
565
- nonce
566
- }
567
- });
568
- });
569
- }
570
- /**
571
- * Leaves the voice channel the bot user is currently in.
572
- *
573
- * This function sends the _Update Voice State_ gateway command over the gateway behind the scenes.
574
- *
575
- * @param guildId - The ID of the guild the voice channel to leave is in.
576
- *
577
- * @remarks
578
- * Fires a _Voice State Update_ gateway event.
579
- *
580
- * @see {@link https://discord.com/developers/docs/topics/gateway#update-voice-state}
581
- */ async leaveVoiceChannel(guildId) {
582
- logger.debug(`[Shard] leaveVoiceChannel guildId: ${guildId} Shard ${this.id}`);
583
- await this.send({
584
- op: GatewayOpcodes.VoiceStateUpdate,
585
- d: {
586
- guild_id: guildId.toString(),
587
- channel_id: null,
588
- self_mute: false,
589
- self_deaf: false
590
- }
591
- });
592
- }
593
465
  }
594
466
  export default DiscordenoShard;
595
467