discord.js 15.0.0-dev.1762992116-837af56cf → 15.0.0-dev.1763164928-7349a6ee3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "discord.js",
4
- "version": "15.0.0-dev.1762992116-837af56cf",
4
+ "version": "15.0.0-dev.1763164928-7349a6ee3",
5
5
  "description": "A powerful library for interacting with the Discord API",
6
6
  "main": "./src/index.js",
7
7
  "types": "./typings/index.d.ts",
@@ -61,12 +61,12 @@
61
61
  "magic-bytes.js": "^1.12.1",
62
62
  "tslib": "^2.8.1",
63
63
  "undici": "7.16.0",
64
- "@discordjs/builders": "2.0.0-dev.1762992116-837af56cf",
65
- "@discordjs/formatters": "1.0.0-dev.1762992116-837af56cf",
66
- "@discordjs/rest": "3.0.0-dev.1762992116-837af56cf",
67
- "@discordjs/util": "2.0.0-dev.1762992116-837af56cf",
68
- "@discordjs/ws": "3.0.0-dev.1762992116-837af56cf",
69
- "@discordjs/collection": "3.0.0-dev.1762992116-837af56cf"
64
+ "@discordjs/builders": "2.0.0-dev.1763164928-7349a6ee3",
65
+ "@discordjs/collection": "3.0.0-dev.1763164928-7349a6ee3",
66
+ "@discordjs/rest": "3.0.0-dev.1763164928-7349a6ee3",
67
+ "@discordjs/util": "2.0.0-dev.1763164928-7349a6ee3",
68
+ "@discordjs/ws": "3.0.0-dev.1763164928-7349a6ee3",
69
+ "@discordjs/formatters": "1.0.0-dev.1763164928-7349a6ee3"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@favware/cliff-jumper": "^4.1.0",
@@ -82,9 +82,9 @@
82
82
  "tsd": "^0.33.0",
83
83
  "turbo": "^2.5.8",
84
84
  "typescript": "~5.9.3",
85
+ "@discordjs/api-extractor": "7.52.7",
85
86
  "@discordjs/docgen": "0.12.1",
86
- "@discordjs/scripts": "0.1.0",
87
- "@discordjs/api-extractor": "7.52.7"
87
+ "@discordjs/scripts": "0.1.0"
88
88
  },
89
89
  "engines": {
90
90
  "node": ">=22.12.0"
@@ -3,8 +3,9 @@
3
3
  const process = require('node:process');
4
4
  const { clearTimeout, setImmediate, setTimeout } = require('node:timers');
5
5
  const { Collection } = require('@discordjs/collection');
6
- const { makeURLSearchParams } = require('@discordjs/rest');
6
+ const { REST, RESTEvents, makeURLSearchParams } = require('@discordjs/rest');
7
7
  const { WebSocketManager, WebSocketShardEvents, WebSocketShardStatus } = require('@discordjs/ws');
8
+ const { AsyncEventEmitter } = require('@vladfrangu/async_event_emitter');
8
9
  const { GatewayDispatchEvents, GatewayIntentBits, OAuth2Scopes, Routes } = require('discord-api-types/v10');
9
10
  const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
10
11
  const { ChannelManager } = require('../managers/ChannelManager.js');
@@ -28,7 +29,7 @@ const { Options } = require('../util/Options.js');
28
29
  const { PermissionsBitField } = require('../util/PermissionsBitField.js');
29
30
  const { Status } = require('../util/Status.js');
30
31
  const { Sweepers } = require('../util/Sweepers.js');
31
- const { BaseClient } = require('./BaseClient.js');
32
+ const { flatten } = require('../util/Util.js');
32
33
  const { ActionsManager } = require('./actions/ActionsManager.js');
33
34
  const { ClientVoiceManager } = require('./voice/ClientVoiceManager.js');
34
35
  const { PacketHandlers } = require('./websocket/handlers/index.js');
@@ -47,24 +48,66 @@ const BeforeReadyWhitelist = [
47
48
  /**
48
49
  * The main hub for interacting with the Discord API, and the starting point for any bot.
49
50
  *
50
- * @extends {BaseClient}
51
+ * @extends {AsyncEventEmitter}
51
52
  */
52
- class Client extends BaseClient {
53
+ class Client extends AsyncEventEmitter {
53
54
  /**
54
55
  * @param {ClientOptions} options Options for the client
55
56
  */
56
57
  constructor(options) {
57
- super(options);
58
+ super();
59
+
60
+ if (typeof options !== 'object' || options === null) {
61
+ throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
62
+ }
63
+
64
+ const defaultOptions = Options.createDefault();
65
+ /**
66
+ * The options the client was instantiated with
67
+ *
68
+ * @type {ClientOptions}
69
+ */
70
+ this.options = {
71
+ ...defaultOptions,
72
+ ...options,
73
+ presence: {
74
+ ...defaultOptions.presence,
75
+ ...options.presence,
76
+ },
77
+ sweepers: {
78
+ ...defaultOptions.sweepers,
79
+ ...options.sweepers,
80
+ },
81
+ ws: {
82
+ ...defaultOptions.ws,
83
+ ...options.ws,
84
+ },
85
+ rest: {
86
+ ...defaultOptions.rest,
87
+ ...options.rest,
88
+ userAgentAppendix: options.rest?.userAgentAppendix
89
+ ? `${Options.userAgentAppendix} ${options.rest.userAgentAppendix}`
90
+ : Options.userAgentAppendix,
91
+ },
92
+ };
93
+
94
+ /**
95
+ * The REST manager of the client
96
+ *
97
+ * @type {REST}
98
+ */
99
+ this.rest = new REST(this.options.rest);
100
+
101
+ this.rest.on(RESTEvents.Debug, message => this.emit(Events.Debug, message));
58
102
 
59
103
  const data = require('node:worker_threads').workerData ?? process.env;
60
- const defaults = Options.createDefault();
61
104
 
62
- if (this.options.ws.shardIds === defaults.ws.shardIds && 'SHARDS' in data) {
105
+ if (this.options.ws.shardIds === defaultOptions.ws.shardIds && 'SHARDS' in data) {
63
106
  const shards = JSON.parse(data.SHARDS);
64
107
  this.options.ws.shardIds = Array.isArray(shards) ? shards : [shards];
65
108
  }
66
109
 
67
- if (this.options.ws.shardCount === defaults.ws.shardCount && 'SHARD_COUNT' in data) {
110
+ if (this.options.ws.shardCount === defaultOptions.ws.shardCount && 'SHARD_COUNT' in data) {
68
111
  this.options.ws.shardCount = Number(data.SHARD_COUNT);
69
112
  }
70
113
 
@@ -442,12 +485,56 @@ class Client extends BaseClient {
442
485
  }
443
486
 
444
487
  /**
445
- * Logs out, terminates the connection to Discord, and destroys the client.
488
+ * Options used for deleting a webhook.
489
+ *
490
+ * @typedef {Object} WebhookDeleteOptions
491
+ * @property {string} [token] Token of the webhook
492
+ * @property {string} [reason] The reason for deleting the webhook
493
+ */
494
+
495
+ /**
496
+ * Deletes a webhook.
497
+ *
498
+ * @param {Snowflake} id The webhook's id
499
+ * @param {WebhookDeleteOptions} [options] Options for deleting the webhook
500
+ * @returns {Promise<void>}
501
+ */
502
+ async deleteWebhook(id, { token, reason } = {}) {
503
+ await this.rest.delete(Routes.webhook(id, token), { auth: !token, reason });
504
+ }
505
+
506
+ /**
507
+ * Increments max listeners by one, if they are not zero.
508
+ *
509
+ * @private
510
+ */
511
+ incrementMaxListeners() {
512
+ const maxListeners = this.getMaxListeners();
513
+ if (maxListeners !== 0) {
514
+ this.setMaxListeners(maxListeners + 1);
515
+ }
516
+ }
517
+
518
+ /**
519
+ * Decrements max listeners by one, if they are not zero.
520
+ *
521
+ * @private
522
+ */
523
+ decrementMaxListeners() {
524
+ const maxListeners = this.getMaxListeners();
525
+ if (maxListeners !== 0) {
526
+ this.setMaxListeners(maxListeners - 1);
527
+ }
528
+ }
529
+
530
+ /**
531
+ * Destroys all assets used by the client.
446
532
  *
447
533
  * @returns {Promise<void>}
448
534
  */
449
535
  async destroy() {
450
- super.destroy();
536
+ this.rest.clearHashSweeper();
537
+ this.rest.clearHandlerSweeper();
451
538
 
452
539
  this.sweepers.destroy();
453
540
  await this.ws.destroy();
@@ -701,10 +788,7 @@ class Client extends BaseClient {
701
788
  }
702
789
 
703
790
  toJSON() {
704
- return super.toJSON({
705
- actions: false,
706
- presence: false,
707
- });
791
+ return flatten(this, { actions: false, presence: false });
708
792
  }
709
793
 
710
794
  /**
@@ -797,6 +881,10 @@ class Client extends BaseClient {
797
881
  throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'jsonTransformer', 'a function');
798
882
  }
799
883
  }
884
+
885
+ async [Symbol.asyncDispose]() {
886
+ await this.destroy();
887
+ }
800
888
  }
801
889
 
802
890
  exports.Client = Client;
@@ -846,6 +934,11 @@ exports.Client = Client;
846
934
  * @see {@link https://discord.js.org/docs/packages/collection/stable/Collection:Class}
847
935
  */
848
936
 
937
+ /**
938
+ * @external REST
939
+ * @see {@link https://discord.js.org/docs/packages/rest/stable/REST:Class}
940
+ */
941
+
849
942
  /**
850
943
  * @external ImageURLOptions
851
944
  * @see {@link https://discord.js.org/docs/packages/rest/stable/ImageURLOptions:Interface}
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ const process = require('node:process');
4
+ const { GatewayOpcodes } = require('discord-api-types/v10');
5
+
6
+ const emittedFor = new Set();
7
+
8
+ module.exports = (client, { d: data }) => {
9
+ switch (data.opcode) {
10
+ case GatewayOpcodes.RequestGuildMembers: {
11
+ break;
12
+ }
13
+
14
+ default: {
15
+ if (!emittedFor.has(data.opcode)) {
16
+ process.emitWarning(
17
+ `Hit a gateway rate limit on opcode ${data.opcode} (${GatewayOpcodes[data.opcode]}). If the discord.js version you're using is up-to-date, please open an issue on GitHub.`,
18
+ );
19
+
20
+ emittedFor.add(data.opcode);
21
+ }
22
+ }
23
+ }
24
+ };
@@ -52,6 +52,7 @@ const PacketHandlers = Object.fromEntries([
52
52
  ['MESSAGE_REACTION_REMOVE_EMOJI', require('./MESSAGE_REACTION_REMOVE_EMOJI.js')],
53
53
  ['MESSAGE_UPDATE', require('./MESSAGE_UPDATE.js')],
54
54
  ['PRESENCE_UPDATE', require('./PRESENCE_UPDATE.js')],
55
+ ['RATE_LIMITED', require('./RATE_LIMITED.js')],
55
56
  ['READY', require('./READY.js')],
56
57
  ['SOUNDBOARD_SOUNDS', require('./SOUNDBOARD_SOUNDS.js')],
57
58
  ['STAGE_INSTANCE_CREATE', require('./STAGE_INSTANCE_CREATE.js')],
@@ -77,7 +77,6 @@
77
77
  *
78
78
  * @property {'WebhookMessage'} WebhookMessage
79
79
  * @property {'WebhookTokenUnavailable'} WebhookTokenUnavailable
80
- * @property {'WebhookURLInvalid'} WebhookURLInvalid
81
80
  * @property {'WebhookApplication'} WebhookApplication
82
81
  *
83
82
  * @property {'MessageReferenceMissing'} MessageReferenceMissing
@@ -212,7 +211,6 @@ const keys = [
212
211
 
213
212
  'WebhookMessage',
214
213
  'WebhookTokenUnavailable',
215
- 'WebhookURLInvalid',
216
214
  'WebhookApplication',
217
215
 
218
216
  'MessageReferenceMissing',
@@ -82,7 +82,6 @@ const Messages = {
82
82
 
83
83
  [ErrorCodes.WebhookMessage]: 'The message was not sent by a webhook.',
84
84
  [ErrorCodes.WebhookTokenUnavailable]: 'This action requires a webhook token, but none is available.',
85
- [ErrorCodes.WebhookURLInvalid]: 'The provided webhook URL is not valid.',
86
85
  [ErrorCodes.WebhookApplication]: 'This message webhook belongs to an application and cannot be fetched.',
87
86
 
88
87
  [ErrorCodes.MessageReferenceMissing]: 'The message does not reference another message',
package/src/index.js CHANGED
@@ -3,12 +3,10 @@
3
3
  const { __exportStar } = require('tslib');
4
4
 
5
5
  // "Root" classes (starting points)
6
- exports.BaseClient = require('./client/BaseClient.js').BaseClient;
7
6
  exports.Client = require('./client/Client.js').Client;
8
7
  exports.Shard = require('./sharding/Shard.js').Shard;
9
8
  exports.ShardClientUtil = require('./sharding/ShardClientUtil.js').ShardClientUtil;
10
9
  exports.ShardingManager = require('./sharding/ShardingManager.js').ShardingManager;
11
- exports.WebhookClient = require('./client/WebhookClient.js').WebhookClient;
12
10
 
13
11
  // Errors
14
12
  exports.DiscordjsError = require('./errors/DJSError.js').DiscordjsError;
@@ -3,8 +3,10 @@
3
3
  const { setTimeout, clearTimeout } = require('node:timers');
4
4
  const { Collection } = require('@discordjs/collection');
5
5
  const { makeURLSearchParams } = require('@discordjs/rest');
6
+ const { GatewayRateLimitError } = require('@discordjs/util');
7
+ const { WebSocketShardEvents } = require('@discordjs/ws');
6
8
  const { DiscordSnowflake } = require('@sapphire/snowflake');
7
- const { Routes, GatewayOpcodes } = require('discord-api-types/v10');
9
+ const { Routes, GatewayOpcodes, GatewayDispatchEvents } = require('discord-api-types/v10');
8
10
  const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } = require('../errors/index.js');
9
11
  const { BaseGuildVoiceChannel } = require('../structures/BaseGuildVoiceChannel.js');
10
12
  const { GuildMember } = require('../structures/GuildMember.js');
@@ -246,24 +248,27 @@ class GuildMemberManager extends CachedManager {
246
248
  const query = initialQuery ?? (users ? undefined : '');
247
249
 
248
250
  return new Promise((resolve, reject) => {
249
- this.guild.client.ws.send(this.guild.shardId, {
250
- op: GatewayOpcodes.RequestGuildMembers,
251
- // eslint-disable-next-line id-length
252
- d: {
253
- guild_id: this.guild.id,
254
- presences,
255
- user_ids: users,
256
- query,
257
- nonce,
258
- limit,
259
- },
260
- });
261
251
  const fetchedMembers = new Collection();
262
252
  let index = 0;
253
+
254
+ const cleanup = () => {
255
+ /* eslint-disable no-use-before-define */
256
+ clearTimeout(timeout);
257
+
258
+ this.client.ws.removeListener(WebSocketShardEvents.Dispatch, rateLimitHandler);
259
+ this.client.removeListener(Events.GuildMembersChunk, handler);
260
+ this.client.decrementMaxListeners();
261
+ /* eslint-enable no-use-before-define */
262
+ };
263
+
264
+ const timeout = setTimeout(() => {
265
+ cleanup();
266
+ reject(new DiscordjsError(ErrorCodes.GuildMembersTimeout));
267
+ }, time).unref();
268
+
263
269
  const handler = (members, _, chunk) => {
264
270
  if (chunk.nonce !== nonce) return;
265
271
 
266
- // eslint-disable-next-line no-use-before-define
267
272
  timeout.refresh();
268
273
  index++;
269
274
  for (const member of members.values()) {
@@ -271,21 +276,37 @@ class GuildMemberManager extends CachedManager {
271
276
  }
272
277
 
273
278
  if (members.size < 1_000 || (limit && fetchedMembers.size >= limit) || index === chunk.count) {
274
- // eslint-disable-next-line no-use-before-define
275
- clearTimeout(timeout);
276
- this.client.removeListener(Events.GuildMembersChunk, handler);
277
- this.client.decrementMaxListeners();
279
+ cleanup();
278
280
  resolve(users && !Array.isArray(users) && fetchedMembers.size ? fetchedMembers.first() : fetchedMembers);
279
281
  }
280
282
  };
281
283
 
282
- const timeout = setTimeout(() => {
283
- this.client.removeListener(Events.GuildMembersChunk, handler);
284
- this.client.decrementMaxListeners();
285
- reject(new DiscordjsError(ErrorCodes.GuildMembersTimeout));
286
- }, time).unref();
284
+ const requestData = {
285
+ guild_id: this.guild.id,
286
+ presences,
287
+ user_ids: users,
288
+ query,
289
+ nonce,
290
+ limit,
291
+ };
292
+
293
+ const rateLimitHandler = payload => {
294
+ if (payload.t === GatewayDispatchEvents.RateLimited && payload.d.meta.nonce === nonce) {
295
+ cleanup();
296
+ reject(new GatewayRateLimitError(payload.d, requestData));
297
+ }
298
+ };
299
+
300
+ this.client.ws.on(WebSocketShardEvents.Dispatch, rateLimitHandler);
301
+
287
302
  this.client.incrementMaxListeners();
288
303
  this.client.on(Events.GuildMembersChunk, handler);
304
+
305
+ this.guild.client.ws.send(this.guild.shardId, {
306
+ op: GatewayOpcodes.RequestGuildMembers,
307
+ // eslint-disable-next-line id-length
308
+ d: requestData,
309
+ });
289
310
  });
290
311
  }
291
312
 
@@ -150,8 +150,8 @@ class MessageManager extends CachedManager {
150
150
  */
151
151
 
152
152
  /**
153
- * Fetches the pinned messages of this channel and returns a collection of them.
154
- * <info>The returned Collection does not contain any reaction data of the messages.
153
+ * Fetches the pinned messages of this channel, returning a paginated result.
154
+ * <info>The returned messages do not contain any reaction data.
155
155
  * Those need to be fetched separately.</info>
156
156
  *
157
157
  * @param {FetchPinnedMessagesOptions} [options={}] Options for fetching pinned messages
@@ -47,15 +47,14 @@ class MessagePayload {
47
47
  }
48
48
 
49
49
  /**
50
- * Whether or not the target is a {@link Webhook} or a {@link WebhookClient}
50
+ * Whether or not the target is a {@link Webhook}
51
51
  *
52
52
  * @type {boolean}
53
53
  * @readonly
54
54
  */
55
55
  get isWebhook() {
56
56
  const { Webhook } = require('./Webhook.js');
57
- const { WebhookClient } = require('../client/WebhookClient.js');
58
- return this.target instanceof Webhook || this.target instanceof WebhookClient;
57
+ return this.target instanceof Webhook;
59
58
  }
60
59
 
61
60
  /**
@@ -302,7 +301,7 @@ exports.MessagePayload = MessagePayload;
302
301
  /**
303
302
  * A target for a message.
304
303
  *
305
- * @typedef {TextBasedChannels|ChannelManager|Webhook|WebhookClient|BaseInteraction|InteractionWebhook|
304
+ * @typedef {TextBasedChannels|ChannelManager|Webhook|BaseInteraction|InteractionWebhook|
306
305
  * Message|MessageManager} MessageTarget
307
306
  */
308
307
 
@@ -95,9 +95,9 @@ class Webhook {
95
95
  /**
96
96
  * The owner of the webhook
97
97
  *
98
- * @type {?(User|APIUser)}
98
+ * @type {?User}
99
99
  */
100
- this.owner = this.client.users?._add(data.user) ?? data.user;
100
+ this.owner = this.client.users._add(data.user);
101
101
  } else {
102
102
  this.owner ??= null;
103
103
  }
@@ -119,7 +119,7 @@ class Webhook {
119
119
  *
120
120
  * @type {?(Guild|APIGuild)}
121
121
  */
122
- this.sourceGuild = this.client.guilds?.cache.get(data.source_guild.id) ?? data.source_guild;
122
+ this.sourceGuild = this.client.guilds.cache.get(data.source_guild.id) ?? data.source_guild;
123
123
  } else {
124
124
  this.sourceGuild ??= null;
125
125
  }
@@ -130,7 +130,7 @@ class Webhook {
130
130
  *
131
131
  * @type {?(AnnouncementChannel|APIChannel)}
132
132
  */
133
- this.sourceChannel = this.client.channels?.cache.get(data.source_channel?.id) ?? data.source_channel;
133
+ this.sourceChannel = this.client.channels.cache.get(data.source_channel?.id) ?? data.source_channel;
134
134
  } else {
135
135
  this.sourceChannel ??= null;
136
136
  }
@@ -248,7 +248,6 @@ class Webhook {
248
248
  auth: false,
249
249
  });
250
250
 
251
- if (!this.client.channels) return data;
252
251
  return (
253
252
  this.client.channels.cache.get(data.channel_id)?.messages._add(data, false) ??
254
253
  new (getMessage())(this.client, data)
@@ -345,7 +344,6 @@ class Webhook {
345
344
  auth: false,
346
345
  });
347
346
 
348
- if (!this.client.channels) return data;
349
347
  return (
350
348
  this.client.channels.cache.get(data.channel_id)?.messages._add(data, false) ??
351
349
  new (getMessage())(this.client, data)
@@ -384,10 +382,7 @@ class Webhook {
384
382
  },
385
383
  );
386
384
 
387
- const channelManager = this.client.channels;
388
- if (!channelManager) return data;
389
-
390
- const messageManager = channelManager.cache.get(data.channel_id)?.messages;
385
+ const messageManager = this.client.channels.cache.get(data.channel_id)?.messages;
391
386
  if (!messageManager) return new (getMessage())(this.client, data);
392
387
 
393
388
  const existing = messageManager.cache.get(data.id);
package/src/util/Util.js CHANGED
@@ -469,11 +469,19 @@ function cleanCodeBlockContent(text) {
469
469
  return text.replaceAll('```', '`\u200B``');
470
470
  }
471
471
 
472
+ /**
473
+ * Represents the credentials used for a webhook in the form of its id and token.
474
+ *
475
+ * @typedef {Object} WebhookDataIdWithToken
476
+ * @property {Snowflake} id The webhook's id
477
+ * @property {string} token The webhook's token
478
+ */
479
+
472
480
  /**
473
481
  * Parses a webhook URL for the id and token.
474
482
  *
475
483
  * @param {string} url The URL to parse
476
- * @returns {?WebhookClientDataIdWithToken} `null` if the URL is invalid, otherwise the id and the token
484
+ * @returns {?WebhookDataIdWithToken} `null` if the URL is invalid, otherwise the id and the token
477
485
  */
478
486
  function parseWebhookURL(url) {
479
487
  const matches =
@@ -492,18 +492,6 @@ export abstract class Base {
492
492
  public valueOf(): string;
493
493
  }
494
494
 
495
- export class BaseClient<Events extends {}> extends AsyncEventEmitter<Events> implements AsyncDisposable {
496
- public constructor(options?: ClientOptions | WebhookClientOptions);
497
- private decrementMaxListeners(): void;
498
- private incrementMaxListeners(): void;
499
-
500
- public options: ClientOptions | WebhookClientOptions;
501
- public rest: REST;
502
- public destroy(): void;
503
- public toJSON(...props: Record<string, boolean | string>[]): unknown;
504
- public [Symbol.asyncDispose](): Promise<void>;
505
- }
506
-
507
495
  export type GuildCacheMessage<Cached extends CacheType> = CacheTypeReducer<
508
496
  Cached,
509
497
  Message<true>,
@@ -913,7 +901,10 @@ export type If<Value extends boolean, TrueResult, FalseResult = null> = Value ex
913
901
  ? FalseResult
914
902
  : FalseResult | TrueResult;
915
903
 
916
- export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEventTypes> {
904
+ export class Client<Ready extends boolean = boolean>
905
+ extends AsyncEventEmitter<ClientEventTypes>
906
+ implements AsyncDisposable
907
+ {
917
908
  public constructor(options: ClientOptions);
918
909
  private readonly actions: unknown;
919
910
  private readonly expectedGuilds: Set<Snowflake>;
@@ -928,6 +919,8 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
928
919
  private _triggerClientReady(): void;
929
920
  private _validateOptions(options: ClientOptions): void;
930
921
  private get _censoredToken(): string | null;
922
+ private decrementMaxListeners(): void;
923
+ private incrementMaxListeners(): void;
931
924
  // This a technique used to brand the ready state. Or else we'll get `never` errors on typeguard checks.
932
925
  private readonly _ready: Ready;
933
926
 
@@ -939,6 +932,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
939
932
  public get ping(): number | null;
940
933
  public get readyAt(): If<Ready, Date>;
941
934
  public readyTimestamp: If<Ready, number>;
935
+ public rest: REST;
942
936
  public sweepers: Sweepers;
943
937
  public shard: ShardClientUtil | null;
944
938
  public status: Status;
@@ -969,6 +963,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
969
963
  public login(token?: string): Promise<string>;
970
964
  public isReady(): this is Client<true>;
971
965
  public toJSON(): unknown;
966
+ public [Symbol.asyncDispose](): Promise<void>;
972
967
  }
973
968
 
974
969
  export interface StickerPackFetchOptions {
@@ -3742,7 +3737,7 @@ export function fetchRecommendedShardCount(token: string, options?: FetchRecomme
3742
3737
  export function flatten(obj: unknown, ...props: Record<string, boolean | string>[]): unknown;
3743
3738
 
3744
3739
  export function parseEmoji(text: string): PartialEmoji | null;
3745
- export function parseWebhookURL(url: string): WebhookClientDataIdWithToken | null;
3740
+ export function parseWebhookURL(url: string): WebhookDataIdWithToken | null;
3746
3741
  export function resolveColor(color: ColorResolvable): number;
3747
3742
  export function resolveSKUId(resolvable: SKUResolvable): Snowflake | null;
3748
3743
  export function verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string;
@@ -3828,7 +3823,7 @@ export class Webhook<Type extends WebhookType = WebhookType> {
3828
3823
  public readonly client: Client;
3829
3824
  public guildId: Snowflake;
3830
3825
  public name: string;
3831
- public owner: Type extends WebhookType.Incoming ? APIUser | User | null : APIUser | User;
3826
+ public owner: Type extends WebhookType.Incoming ? User | null : User;
3832
3827
  public sourceGuild: Type extends WebhookType.ChannelFollower ? APIPartialGuild | Guild : null;
3833
3828
  public sourceChannel: Type extends WebhookType.ChannelFollower ? AnnouncementChannel | APIPartialChannel : null;
3834
3829
  public token: Type extends WebhookType.Incoming
@@ -3847,7 +3842,7 @@ export class Webhook<Type extends WebhookType = WebhookType> {
3847
3842
  | VoiceChannel
3848
3843
  | null;
3849
3844
  public isUserCreated(): this is Webhook<WebhookType.Incoming> & {
3850
- owner: APIUser | User;
3845
+ owner: User;
3851
3846
  };
3852
3847
  public isApplicationCreated(): this is Webhook<WebhookType.Application>;
3853
3848
  public isIncoming(): this is Webhook<WebhookType.Incoming>;
@@ -3861,20 +3856,6 @@ export class Webhook<Type extends WebhookType = WebhookType> {
3861
3856
  public send(options: MessagePayload | WebhookMessageCreateOptions | string): Promise<Message<true>>;
3862
3857
  }
3863
3858
 
3864
- export interface WebhookClient extends WebhookFields, BaseClient<{}> {}
3865
- export class WebhookClient extends BaseClient<{}> {
3866
- public constructor(data: WebhookClientData, options?: WebhookClientOptions);
3867
- public readonly client: this;
3868
- public options: WebhookClientOptions;
3869
- public token: string;
3870
- public editMessage(
3871
- message: MessageResolvable,
3872
- options: MessagePayload | WebhookMessageEditOptions | string,
3873
- ): Promise<APIMessage>;
3874
- public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise<APIMessage>;
3875
- public send(options: MessagePayload | WebhookMessageCreateOptions | string): Promise<APIMessage>;
3876
- }
3877
-
3878
3859
  export class Widget extends Base {
3879
3860
  private constructor(client: Client<true>, data: APIGuildWidget);
3880
3861
  private _patch(data: APIGuildWidget): void;
@@ -4064,7 +4045,6 @@ export enum DiscordjsErrorCodes {
4064
4045
 
4065
4046
  WebhookMessage = 'WebhookMessage',
4066
4047
  WebhookTokenUnavailable = 'WebhookTokenUnavailable',
4067
- WebhookURLInvalid = 'WebhookURLInvalid',
4068
4048
  WebhookApplication = 'WebhookApplication',
4069
4049
 
4070
4050
  MessageReferenceMissing = 'MessageReferenceMissing',
@@ -5576,7 +5556,8 @@ export interface ClientFetchInviteOptions {
5576
5556
  withCounts?: boolean;
5577
5557
  }
5578
5558
 
5579
- export interface ClientOptions extends WebhookClientOptions {
5559
+ export interface ClientOptions {
5560
+ allowedMentions?: MessageMentionOptions;
5580
5561
  closeTimeout?: number;
5581
5562
  enforceNonce?: boolean;
5582
5563
  failIfNotExists?: boolean;
@@ -5585,6 +5566,7 @@ export interface ClientOptions extends WebhookClientOptions {
5585
5566
  makeCache?: CacheFactory;
5586
5567
  partials?: readonly Partials[];
5587
5568
  presence?: PresenceData;
5569
+ rest?: Partial<RESTOptions>;
5588
5570
  sweepers?: SweeperOptions;
5589
5571
  waitGuildTimeout?: number;
5590
5572
  ws?: Partial<WebSocketManagerOptions>;
@@ -6873,8 +6855,7 @@ export type MessageTarget =
6873
6855
  | Message
6874
6856
  | MessageManager
6875
6857
  | TextBasedChannel
6876
- | Webhook<WebhookType.Incoming>
6877
- | WebhookClient;
6858
+ | Webhook<WebhookType.Incoming>;
6878
6859
 
6879
6860
  export interface MultipleShardRespawnOptions {
6880
6861
  respawnDelay?: number;
@@ -7248,22 +7229,11 @@ export interface VoiceStateEditOptions {
7248
7229
  suppressed?: boolean;
7249
7230
  }
7250
7231
 
7251
- export type WebhookClientData = WebhookClientDataIdWithToken | WebhookClientDataURL;
7252
-
7253
- export interface WebhookClientDataIdWithToken {
7232
+ export interface WebhookDataIdWithToken {
7254
7233
  id: Snowflake;
7255
7234
  token: string;
7256
7235
  }
7257
7236
 
7258
- export interface WebhookClientDataURL {
7259
- url: string;
7260
- }
7261
-
7262
- export interface WebhookClientOptions {
7263
- allowedMentions?: MessageMentionOptions;
7264
- rest?: Partial<RESTOptions>;
7265
- }
7266
-
7267
7237
  export interface WebhookDeleteOptions {
7268
7238
  reason?: string;
7269
7239
  token?: string;
@@ -492,18 +492,6 @@ export abstract class Base {
492
492
  public valueOf(): string;
493
493
  }
494
494
 
495
- export class BaseClient<Events extends {}> extends AsyncEventEmitter<Events> implements AsyncDisposable {
496
- public constructor(options?: ClientOptions | WebhookClientOptions);
497
- private decrementMaxListeners(): void;
498
- private incrementMaxListeners(): void;
499
-
500
- public options: ClientOptions | WebhookClientOptions;
501
- public rest: REST;
502
- public destroy(): void;
503
- public toJSON(...props: Record<string, boolean | string>[]): unknown;
504
- public [Symbol.asyncDispose](): Promise<void>;
505
- }
506
-
507
495
  export type GuildCacheMessage<Cached extends CacheType> = CacheTypeReducer<
508
496
  Cached,
509
497
  Message<true>,
@@ -913,7 +901,10 @@ export type If<Value extends boolean, TrueResult, FalseResult = null> = Value ex
913
901
  ? FalseResult
914
902
  : FalseResult | TrueResult;
915
903
 
916
- export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEventTypes> {
904
+ export class Client<Ready extends boolean = boolean>
905
+ extends AsyncEventEmitter<ClientEventTypes>
906
+ implements AsyncDisposable
907
+ {
917
908
  public constructor(options: ClientOptions);
918
909
  private readonly actions: unknown;
919
910
  private readonly expectedGuilds: Set<Snowflake>;
@@ -928,6 +919,8 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
928
919
  private _triggerClientReady(): void;
929
920
  private _validateOptions(options: ClientOptions): void;
930
921
  private get _censoredToken(): string | null;
922
+ private decrementMaxListeners(): void;
923
+ private incrementMaxListeners(): void;
931
924
  // This a technique used to brand the ready state. Or else we'll get `never` errors on typeguard checks.
932
925
  private readonly _ready: Ready;
933
926
 
@@ -939,6 +932,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
939
932
  public get ping(): number | null;
940
933
  public get readyAt(): If<Ready, Date>;
941
934
  public readyTimestamp: If<Ready, number>;
935
+ public rest: REST;
942
936
  public sweepers: Sweepers;
943
937
  public shard: ShardClientUtil | null;
944
938
  public status: Status;
@@ -969,6 +963,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
969
963
  public login(token?: string): Promise<string>;
970
964
  public isReady(): this is Client<true>;
971
965
  public toJSON(): unknown;
966
+ public [Symbol.asyncDispose](): Promise<void>;
972
967
  }
973
968
 
974
969
  export interface StickerPackFetchOptions {
@@ -3742,7 +3737,7 @@ export function fetchRecommendedShardCount(token: string, options?: FetchRecomme
3742
3737
  export function flatten(obj: unknown, ...props: Record<string, boolean | string>[]): unknown;
3743
3738
 
3744
3739
  export function parseEmoji(text: string): PartialEmoji | null;
3745
- export function parseWebhookURL(url: string): WebhookClientDataIdWithToken | null;
3740
+ export function parseWebhookURL(url: string): WebhookDataIdWithToken | null;
3746
3741
  export function resolveColor(color: ColorResolvable): number;
3747
3742
  export function resolveSKUId(resolvable: SKUResolvable): Snowflake | null;
3748
3743
  export function verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string;
@@ -3828,7 +3823,7 @@ export class Webhook<Type extends WebhookType = WebhookType> {
3828
3823
  public readonly client: Client;
3829
3824
  public guildId: Snowflake;
3830
3825
  public name: string;
3831
- public owner: Type extends WebhookType.Incoming ? APIUser | User | null : APIUser | User;
3826
+ public owner: Type extends WebhookType.Incoming ? User | null : User;
3832
3827
  public sourceGuild: Type extends WebhookType.ChannelFollower ? APIPartialGuild | Guild : null;
3833
3828
  public sourceChannel: Type extends WebhookType.ChannelFollower ? AnnouncementChannel | APIPartialChannel : null;
3834
3829
  public token: Type extends WebhookType.Incoming
@@ -3847,7 +3842,7 @@ export class Webhook<Type extends WebhookType = WebhookType> {
3847
3842
  | VoiceChannel
3848
3843
  | null;
3849
3844
  public isUserCreated(): this is Webhook<WebhookType.Incoming> & {
3850
- owner: APIUser | User;
3845
+ owner: User;
3851
3846
  };
3852
3847
  public isApplicationCreated(): this is Webhook<WebhookType.Application>;
3853
3848
  public isIncoming(): this is Webhook<WebhookType.Incoming>;
@@ -3861,20 +3856,6 @@ export class Webhook<Type extends WebhookType = WebhookType> {
3861
3856
  public send(options: MessagePayload | WebhookMessageCreateOptions | string): Promise<Message<true>>;
3862
3857
  }
3863
3858
 
3864
- export interface WebhookClient extends WebhookFields, BaseClient<{}> {}
3865
- export class WebhookClient extends BaseClient<{}> {
3866
- public constructor(data: WebhookClientData, options?: WebhookClientOptions);
3867
- public readonly client: this;
3868
- public options: WebhookClientOptions;
3869
- public token: string;
3870
- public editMessage(
3871
- message: MessageResolvable,
3872
- options: MessagePayload | WebhookMessageEditOptions | string,
3873
- ): Promise<APIMessage>;
3874
- public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise<APIMessage>;
3875
- public send(options: MessagePayload | WebhookMessageCreateOptions | string): Promise<APIMessage>;
3876
- }
3877
-
3878
3859
  export class Widget extends Base {
3879
3860
  private constructor(client: Client<true>, data: APIGuildWidget);
3880
3861
  private _patch(data: APIGuildWidget): void;
@@ -4064,7 +4045,6 @@ export enum DiscordjsErrorCodes {
4064
4045
 
4065
4046
  WebhookMessage = 'WebhookMessage',
4066
4047
  WebhookTokenUnavailable = 'WebhookTokenUnavailable',
4067
- WebhookURLInvalid = 'WebhookURLInvalid',
4068
4048
  WebhookApplication = 'WebhookApplication',
4069
4049
 
4070
4050
  MessageReferenceMissing = 'MessageReferenceMissing',
@@ -5576,7 +5556,8 @@ export interface ClientFetchInviteOptions {
5576
5556
  withCounts?: boolean;
5577
5557
  }
5578
5558
 
5579
- export interface ClientOptions extends WebhookClientOptions {
5559
+ export interface ClientOptions {
5560
+ allowedMentions?: MessageMentionOptions;
5580
5561
  closeTimeout?: number;
5581
5562
  enforceNonce?: boolean;
5582
5563
  failIfNotExists?: boolean;
@@ -5585,6 +5566,7 @@ export interface ClientOptions extends WebhookClientOptions {
5585
5566
  makeCache?: CacheFactory;
5586
5567
  partials?: readonly Partials[];
5587
5568
  presence?: PresenceData;
5569
+ rest?: Partial<RESTOptions>;
5588
5570
  sweepers?: SweeperOptions;
5589
5571
  waitGuildTimeout?: number;
5590
5572
  ws?: Partial<WebSocketManagerOptions>;
@@ -6873,8 +6855,7 @@ export type MessageTarget =
6873
6855
  | Message
6874
6856
  | MessageManager
6875
6857
  | TextBasedChannel
6876
- | Webhook<WebhookType.Incoming>
6877
- | WebhookClient;
6858
+ | Webhook<WebhookType.Incoming>;
6878
6859
 
6879
6860
  export interface MultipleShardRespawnOptions {
6880
6861
  respawnDelay?: number;
@@ -7248,22 +7229,11 @@ export interface VoiceStateEditOptions {
7248
7229
  suppressed?: boolean;
7249
7230
  }
7250
7231
 
7251
- export type WebhookClientData = WebhookClientDataIdWithToken | WebhookClientDataURL;
7252
-
7253
- export interface WebhookClientDataIdWithToken {
7232
+ export interface WebhookDataIdWithToken {
7254
7233
  id: Snowflake;
7255
7234
  token: string;
7256
7235
  }
7257
7236
 
7258
- export interface WebhookClientDataURL {
7259
- url: string;
7260
- }
7261
-
7262
- export interface WebhookClientOptions {
7263
- allowedMentions?: MessageMentionOptions;
7264
- rest?: Partial<RESTOptions>;
7265
- }
7266
-
7267
7237
  export interface WebhookDeleteOptions {
7268
7238
  reason?: string;
7269
7239
  token?: string;
@@ -1,131 +0,0 @@
1
- 'use strict';
2
-
3
- const { REST, RESTEvents } = require('@discordjs/rest');
4
- const { AsyncEventEmitter } = require('@vladfrangu/async_event_emitter');
5
- const { Routes } = require('discord-api-types/v10');
6
- const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
7
- const { Events } = require('../util/Events.js');
8
- const { Options } = require('../util/Options.js');
9
- const { flatten } = require('../util/Util.js');
10
-
11
- /**
12
- * The base class for all clients.
13
- *
14
- * @extends {AsyncEventEmitter}
15
- */
16
- class BaseClient extends AsyncEventEmitter {
17
- constructor(options = {}) {
18
- super();
19
-
20
- if (typeof options !== 'object' || options === null) {
21
- throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
22
- }
23
-
24
- const defaultOptions = Options.createDefault();
25
- /**
26
- * The options the client was instantiated with
27
- *
28
- * @type {ClientOptions}
29
- */
30
- this.options = {
31
- ...defaultOptions,
32
- ...options,
33
- presence: {
34
- ...defaultOptions.presence,
35
- ...options.presence,
36
- },
37
- sweepers: {
38
- ...defaultOptions.sweepers,
39
- ...options.sweepers,
40
- },
41
- ws: {
42
- ...defaultOptions.ws,
43
- ...options.ws,
44
- },
45
- rest: {
46
- ...defaultOptions.rest,
47
- ...options.rest,
48
- userAgentAppendix: options.rest?.userAgentAppendix
49
- ? `${Options.userAgentAppendix} ${options.rest.userAgentAppendix}`
50
- : Options.userAgentAppendix,
51
- },
52
- };
53
-
54
- /**
55
- * The REST manager of the client
56
- *
57
- * @type {REST}
58
- */
59
- this.rest = new REST(this.options.rest);
60
-
61
- this.rest.on(RESTEvents.Debug, message => this.emit(Events.Debug, message));
62
- }
63
-
64
- /**
65
- * Destroys all assets used by the base client.
66
- *
67
- * @returns {void}
68
- */
69
- destroy() {
70
- this.rest.clearHashSweeper();
71
- this.rest.clearHandlerSweeper();
72
- }
73
-
74
- /**
75
- * Options used for deleting a webhook.
76
- *
77
- * @typedef {Object} WebhookDeleteOptions
78
- * @property {string} [token] Token of the webhook
79
- * @property {string} [reason] The reason for deleting the webhook
80
- */
81
-
82
- /**
83
- * Deletes a webhook.
84
- *
85
- * @param {Snowflake} id The webhook's id
86
- * @param {WebhookDeleteOptions} [options] Options for deleting the webhook
87
- * @returns {Promise<void>}
88
- */
89
- async deleteWebhook(id, { token, reason } = {}) {
90
- await this.rest.delete(Routes.webhook(id, token), { auth: !token, reason });
91
- }
92
-
93
- /**
94
- * Increments max listeners by one, if they are not zero.
95
- *
96
- * @private
97
- */
98
- incrementMaxListeners() {
99
- const maxListeners = this.getMaxListeners();
100
- if (maxListeners !== 0) {
101
- this.setMaxListeners(maxListeners + 1);
102
- }
103
- }
104
-
105
- /**
106
- * Decrements max listeners by one, if they are not zero.
107
- *
108
- * @private
109
- */
110
- decrementMaxListeners() {
111
- const maxListeners = this.getMaxListeners();
112
- if (maxListeners !== 0) {
113
- this.setMaxListeners(maxListeners - 1);
114
- }
115
- }
116
-
117
- toJSON(...props) {
118
- return flatten(this, ...props);
119
- }
120
-
121
- async [Symbol.asyncDispose]() {
122
- await this.destroy();
123
- }
124
- }
125
-
126
- exports.BaseClient = BaseClient;
127
-
128
- /**
129
- * @external REST
130
- * @see {@link https://discord.js.org/docs/packages/rest/stable/REST:Class}
131
- */
@@ -1,119 +0,0 @@
1
- 'use strict';
2
-
3
- const { DiscordjsError, ErrorCodes } = require('../errors/index.js');
4
- const { Webhook } = require('../structures/Webhook.js');
5
- const { parseWebhookURL } = require('../util/Util.js');
6
- const { BaseClient } = require('./BaseClient.js');
7
-
8
- /**
9
- * The webhook client.
10
- *
11
- * @implements {Webhook}
12
- * @extends {BaseClient}
13
- */
14
- class WebhookClient extends BaseClient {
15
- /**
16
- * Represents the credentials used for a webhook in the form of its id and token.
17
- *
18
- * @typedef {Object} WebhookClientDataIdWithToken
19
- * @property {Snowflake} id The webhook's id
20
- * @property {string} token The webhook's token
21
- */
22
-
23
- /**
24
- * Represents the credentials used for a webhook in the form of a URL.
25
- *
26
- * @typedef {Object} WebhookClientDataURL
27
- * @property {string} url The full URL for the webhook
28
- */
29
-
30
- /**
31
- * Represents the credentials used for a webhook.
32
- *
33
- * @typedef {WebhookClientDataIdWithToken|WebhookClientDataURL} WebhookClientData
34
- */
35
-
36
- /**
37
- * Options for a webhook client.
38
- *
39
- * @typedef {Object} WebhookClientOptions
40
- * @property {MessageMentionOptions} [allowedMentions] Default value for {@link BaseMessageOptions#allowedMentions}
41
- * @property {RESTOptions} [rest] Options for the REST manager
42
- */
43
-
44
- /**
45
- * @param {WebhookClientData} data The data of the webhook
46
- * @param {WebhookClientOptions} [options] Options for the webhook client
47
- */
48
- constructor(data, options) {
49
- super(options);
50
- Object.defineProperty(this, 'client', { value: this });
51
- let { id, token } = data;
52
-
53
- if ('url' in data) {
54
- const parsed = parseWebhookURL(data.url);
55
- if (!parsed) {
56
- throw new DiscordjsError(ErrorCodes.WebhookURLInvalid);
57
- }
58
-
59
- ({ id, token } = parsed);
60
- }
61
-
62
- this.id = id;
63
- Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
64
- }
65
-
66
- /**
67
- * The options the webhook client was instantiated with.
68
- *
69
- * @type {WebhookClientOptions}
70
- * @name WebhookClient#options
71
- */
72
-
73
- // These are here only for documentation purposes - they are implemented by Webhook
74
-
75
- /* eslint-disable jsdoc/check-param-names, getter-return */
76
- /**
77
- * Sends a message with this webhook.
78
- *
79
- * @param {string|MessagePayload|WebhookMessageCreateOptions} options The content for the reply
80
- * @returns {Promise<APIMessage>}
81
- */
82
- async send() {}
83
-
84
- /**
85
- * Gets a message that was sent by this webhook.
86
- *
87
- * @param {Snowflake} message The id of the message to fetch
88
- * @param {WebhookFetchMessageOptions} [options] The options to provide to fetch the message.
89
- * @returns {Promise<APIMessage>} Returns the message sent by this webhook
90
- */
91
- async fetchMessage() {}
92
-
93
- /**
94
- * Edits a message that was sent by this webhook.
95
- *
96
- * @param {MessageResolvable} message The message to edit
97
- * @param {string|MessagePayload|WebhookMessageEditOptions} options The options to provide
98
- * @returns {Promise<APIMessage>} Returns the message edited by this webhook
99
- */
100
- async editMessage() {}
101
-
102
- sendSlackMessage() {}
103
-
104
- edit() {}
105
-
106
- delete() {}
107
-
108
- deleteMessage() {}
109
-
110
- get createdTimestamp() {}
111
-
112
- get createdAt() {}
113
-
114
- get url() {}
115
- }
116
-
117
- Webhook.applyToClass(WebhookClient);
118
-
119
- exports.WebhookClient = WebhookClient;