discord.js 15.0.0-djs-file-upload.1761302390-5ae769c9e → 15.0.0-pr-11006.1765450224-e636950b2
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 +18 -20
- package/src/client/Client.js +110 -24
- package/src/client/websocket/handlers/RATE_LIMITED.js +24 -0
- package/src/client/websocket/handlers/READY.js +4 -0
- package/src/client/websocket/handlers/index.js +1 -0
- package/src/errors/DJSError.js +7 -3
- package/src/errors/ErrorCodes.js +2 -4
- package/src/errors/Messages.js +2 -3
- package/src/index.js +0 -3
- package/src/managers/CachedManager.js +5 -5
- package/src/managers/ChannelManager.js +10 -7
- package/src/managers/GuildBanManager.js +3 -3
- package/src/managers/GuildEmojiManager.js +2 -2
- package/src/managers/GuildEmojiRoleManager.js +9 -1
- package/src/managers/GuildMemberManager.js +44 -23
- package/src/managers/GuildMemberRoleManager.js +11 -2
- package/src/managers/MessageManager.js +25 -18
- package/src/structures/ApplicationCommand.js +4 -5
- package/src/structures/ClientApplication.js +2 -0
- package/src/structures/Embed.js +1 -1
- package/src/structures/Guild.js +11 -1
- package/src/structures/GuildInvite.js +1 -1
- package/src/structures/GuildMember.js +12 -9
- package/src/structures/Message.js +18 -15
- package/src/structures/MessagePayload.js +21 -17
- package/src/structures/ModalComponentResolver.js +1 -1
- package/src/structures/ModalSubmitInteraction.js +6 -6
- package/src/structures/PermissionOverwrites.js +1 -1
- package/src/structures/Role.js +1 -1
- package/src/structures/ThreadChannel.js +1 -1
- package/src/structures/Webhook.js +6 -11
- package/src/structures/interfaces/TextBasedChannel.js +7 -9
- package/src/util/APITypes.js +10 -0
- package/src/util/Components.js +52 -42
- package/src/util/Constants.js +2 -0
- package/src/util/DataResolver.js +5 -2
- package/src/util/GuildMemberFlagsBitField.js +1 -1
- package/src/util/Options.js +9 -5
- package/src/util/Util.js +18 -13
- package/typings/index.d.mts +148 -173
- package/typings/index.d.ts +148 -173
- package/src/client/BaseClient.js +0 -131
- package/src/client/WebhookClient.js +0 -119
- package/src/structures/AttachmentBuilder.js +0 -185
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-
|
|
4
|
+
"version": "15.0.0-pr-11006.1765450224-e636950b2",
|
|
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",
|
|
@@ -55,36 +55,34 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@sapphire/snowflake": "3.5.5",
|
|
57
57
|
"@vladfrangu/async_event_emitter": "^2.4.7",
|
|
58
|
-
"discord-api-types": "^0.38.
|
|
58
|
+
"discord-api-types": "^0.38.36",
|
|
59
59
|
"fast-deep-equal": "3.1.3",
|
|
60
60
|
"lodash.snakecase": "4.1.1",
|
|
61
61
|
"magic-bytes.js": "^1.12.1",
|
|
62
62
|
"tslib": "^2.8.1",
|
|
63
63
|
"undici": "7.16.0",
|
|
64
|
-
"@discordjs/
|
|
65
|
-
"@discordjs/
|
|
66
|
-
"@discordjs/
|
|
67
|
-
"@discordjs/
|
|
68
|
-
"@discordjs/
|
|
69
|
-
"@discordjs/ws": "
|
|
64
|
+
"@discordjs/builders": "2.0.0-pr-11006.1765450224-e636950b2",
|
|
65
|
+
"@discordjs/formatters": "1.0.0-pr-11006.1765450224-e636950b2",
|
|
66
|
+
"@discordjs/collection": "3.0.0-pr-11006.1765450224-e636950b2",
|
|
67
|
+
"@discordjs/rest": "3.0.0-pr-11006.1765450224-e636950b2",
|
|
68
|
+
"@discordjs/util": "2.0.0-pr-11006.1765450224-e636950b2",
|
|
69
|
+
"@discordjs/ws": "3.0.0-pr-11006.1765450224-e636950b2"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@favware/cliff-jumper": "^
|
|
73
|
-
"@types/node": "^22.
|
|
72
|
+
"@favware/cliff-jumper": "^6.0.0",
|
|
73
|
+
"@types/node": "^22.19.1",
|
|
74
74
|
"cross-env": "^10.1.0",
|
|
75
|
-
"eslint": "^9.
|
|
76
|
-
"eslint-config-neon": "^0.2.
|
|
77
|
-
"eslint-formatter-compact": "^
|
|
75
|
+
"eslint": "^9.39.1",
|
|
76
|
+
"eslint-config-neon": "^0.2.9",
|
|
77
|
+
"eslint-formatter-compact": "^9.0.1",
|
|
78
78
|
"eslint-formatter-pretty": "^7.0.0",
|
|
79
|
-
"
|
|
80
|
-
"eslint-plugin-jsdoc": "^54.7.0",
|
|
81
|
-
"prettier": "^3.6.2",
|
|
79
|
+
"prettier": "^3.7.4",
|
|
82
80
|
"tsd": "^0.33.0",
|
|
83
|
-
"turbo": "^2.
|
|
81
|
+
"turbo": "^2.6.3",
|
|
84
82
|
"typescript": "~5.9.3",
|
|
85
|
-
"@discordjs/api-extractor": "
|
|
86
|
-
"@discordjs/
|
|
87
|
-
"@discordjs/
|
|
83
|
+
"@discordjs/api-extractor": "7.52.7",
|
|
84
|
+
"@discordjs/docgen": "0.12.1",
|
|
85
|
+
"@discordjs/scripts": "0.1.0"
|
|
88
86
|
},
|
|
89
87
|
"engines": {
|
|
90
88
|
"node": ">=22.12.0"
|
package/src/client/Client.js
CHANGED
|
@@ -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 {
|
|
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 {
|
|
51
|
+
* @extends {AsyncEventEmitter}
|
|
51
52
|
*/
|
|
52
|
-
class Client extends
|
|
53
|
+
class Client extends AsyncEventEmitter {
|
|
53
54
|
/**
|
|
54
55
|
* @param {ClientOptions} options Options for the client
|
|
55
56
|
*/
|
|
56
57
|
constructor(options) {
|
|
57
|
-
super(
|
|
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 ===
|
|
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 ===
|
|
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
|
|
|
@@ -346,15 +389,6 @@ class Client extends BaseClient {
|
|
|
346
389
|
);
|
|
347
390
|
this.ws.on(WebSocketShardEvents.Dispatch, this._handlePacket.bind(this));
|
|
348
391
|
|
|
349
|
-
this.ws.on(WebSocketShardEvents.Ready, async data => {
|
|
350
|
-
for (const guild of data.guilds) {
|
|
351
|
-
this.expectedGuilds.add(guild.id);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
this.status = Status.WaitingForGuilds;
|
|
355
|
-
await this._checkReady();
|
|
356
|
-
});
|
|
357
|
-
|
|
358
392
|
this.ws.on(WebSocketShardEvents.HeartbeatComplete, ({ heartbeatAt, latency }, shardId) => {
|
|
359
393
|
this.emit(Events.Debug, `[WS => Shard ${shardId}] Heartbeat acknowledged, latency of ${latency}ms.`);
|
|
360
394
|
this.lastPingTimestamps.set(shardId, heartbeatAt);
|
|
@@ -384,7 +418,9 @@ class Client extends BaseClient {
|
|
|
384
418
|
PacketHandlers[packet.t](this, packet, shardId);
|
|
385
419
|
}
|
|
386
420
|
|
|
387
|
-
if (
|
|
421
|
+
if (packet.t === GatewayDispatchEvents.Ready) {
|
|
422
|
+
await this._checkReady();
|
|
423
|
+
} else if (this.status === Status.WaitingForGuilds && WaitingForGuildEvents.includes(packet.t)) {
|
|
388
424
|
this.expectedGuilds.delete(packet.d.id);
|
|
389
425
|
await this._checkReady();
|
|
390
426
|
}
|
|
@@ -442,12 +478,56 @@ class Client extends BaseClient {
|
|
|
442
478
|
}
|
|
443
479
|
|
|
444
480
|
/**
|
|
445
|
-
*
|
|
481
|
+
* Options used for deleting a webhook.
|
|
482
|
+
*
|
|
483
|
+
* @typedef {Object} WebhookDeleteOptions
|
|
484
|
+
* @property {string} [token] Token of the webhook
|
|
485
|
+
* @property {string} [reason] The reason for deleting the webhook
|
|
486
|
+
*/
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Deletes a webhook.
|
|
490
|
+
*
|
|
491
|
+
* @param {Snowflake} id The webhook's id
|
|
492
|
+
* @param {WebhookDeleteOptions} [options] Options for deleting the webhook
|
|
493
|
+
* @returns {Promise<void>}
|
|
494
|
+
*/
|
|
495
|
+
async deleteWebhook(id, { token, reason } = {}) {
|
|
496
|
+
await this.rest.delete(Routes.webhook(id, token), { auth: !token, reason });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Increments max listeners by one, if they are not zero.
|
|
501
|
+
*
|
|
502
|
+
* @private
|
|
503
|
+
*/
|
|
504
|
+
incrementMaxListeners() {
|
|
505
|
+
const maxListeners = this.getMaxListeners();
|
|
506
|
+
if (maxListeners !== 0) {
|
|
507
|
+
this.setMaxListeners(maxListeners + 1);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Decrements max listeners by one, if they are not zero.
|
|
513
|
+
*
|
|
514
|
+
* @private
|
|
515
|
+
*/
|
|
516
|
+
decrementMaxListeners() {
|
|
517
|
+
const maxListeners = this.getMaxListeners();
|
|
518
|
+
if (maxListeners !== 0) {
|
|
519
|
+
this.setMaxListeners(maxListeners - 1);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Destroys all assets used by the client.
|
|
446
525
|
*
|
|
447
526
|
* @returns {Promise<void>}
|
|
448
527
|
*/
|
|
449
528
|
async destroy() {
|
|
450
|
-
|
|
529
|
+
this.rest.clearHashSweeper();
|
|
530
|
+
this.rest.clearHandlerSweeper();
|
|
451
531
|
|
|
452
532
|
this.sweepers.destroy();
|
|
453
533
|
await this.ws.destroy();
|
|
@@ -701,10 +781,7 @@ class Client extends BaseClient {
|
|
|
701
781
|
}
|
|
702
782
|
|
|
703
783
|
toJSON() {
|
|
704
|
-
return
|
|
705
|
-
actions: false,
|
|
706
|
-
presence: false,
|
|
707
|
-
});
|
|
784
|
+
return flatten(this, { actions: false, presence: false });
|
|
708
785
|
}
|
|
709
786
|
|
|
710
787
|
/**
|
|
@@ -797,6 +874,10 @@ class Client extends BaseClient {
|
|
|
797
874
|
throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'jsonTransformer', 'a function');
|
|
798
875
|
}
|
|
799
876
|
}
|
|
877
|
+
|
|
878
|
+
async [Symbol.asyncDispose]() {
|
|
879
|
+
await this.destroy();
|
|
880
|
+
}
|
|
800
881
|
}
|
|
801
882
|
|
|
802
883
|
exports.Client = Client;
|
|
@@ -846,6 +927,11 @@ exports.Client = Client;
|
|
|
846
927
|
* @see {@link https://discord.js.org/docs/packages/collection/stable/Collection:Class}
|
|
847
928
|
*/
|
|
848
929
|
|
|
930
|
+
/**
|
|
931
|
+
* @external REST
|
|
932
|
+
* @see {@link https://discord.js.org/docs/packages/rest/stable/REST:Class}
|
|
933
|
+
*/
|
|
934
|
+
|
|
849
935
|
/**
|
|
850
936
|
* @external ImageURLOptions
|
|
851
937
|
* @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
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { ClientApplication } = require('../../../structures/ClientApplication.js');
|
|
4
|
+
const { Status } = require('../../../util/Status.js');
|
|
4
5
|
|
|
5
6
|
let ClientUser;
|
|
6
7
|
|
|
@@ -14,6 +15,7 @@ module.exports = (client, { d: data }, shardId) => {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
for (const guild of data.guilds) {
|
|
18
|
+
client.expectedGuilds.add(guild.id);
|
|
17
19
|
guild.shardId = shardId;
|
|
18
20
|
client.guilds._add(guild);
|
|
19
21
|
}
|
|
@@ -23,4 +25,6 @@ module.exports = (client, { d: data }, shardId) => {
|
|
|
23
25
|
} else {
|
|
24
26
|
client.application = new ClientApplication(client, data.application);
|
|
25
27
|
}
|
|
28
|
+
|
|
29
|
+
client.status = Status.WaitingForGuilds;
|
|
26
30
|
};
|
|
@@ -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')],
|
package/src/errors/DJSError.js
CHANGED
|
@@ -12,15 +12,19 @@ const { Messages } = require('./Messages.js');
|
|
|
12
12
|
* @ignore
|
|
13
13
|
*/
|
|
14
14
|
function makeDiscordjsError(Base) {
|
|
15
|
-
return class
|
|
15
|
+
return class extends Base {
|
|
16
|
+
static {
|
|
17
|
+
Object.defineProperty(this, 'name', { value: `Discordjs${Base.name}` });
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
constructor(code, ...args) {
|
|
17
21
|
super(message(code, args));
|
|
18
22
|
this.code = code;
|
|
19
|
-
Error.captureStackTrace
|
|
23
|
+
Error.captureStackTrace(this, this.constructor);
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
get name() {
|
|
23
|
-
return `${
|
|
27
|
+
return `${this.constructor.name} [${this.code}]`;
|
|
24
28
|
}
|
|
25
29
|
};
|
|
26
30
|
}
|
package/src/errors/ErrorCodes.js
CHANGED
|
@@ -77,14 +77,13 @@
|
|
|
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
|
|
84
83
|
*
|
|
85
84
|
* @property {'EmojiType'} EmojiType
|
|
86
85
|
* @property {'EmojiManaged'} EmojiManaged
|
|
87
|
-
* @property {'
|
|
86
|
+
* @property {'MissingGuildExpressionsPermission'} MissingGuildExpressionsPermission
|
|
88
87
|
*
|
|
89
88
|
* @property {'NotGuildSoundboardSound'} NotGuildSoundboardSound
|
|
90
89
|
* @property {'NotGuildSticker'} NotGuildSticker
|
|
@@ -212,14 +211,13 @@ const keys = [
|
|
|
212
211
|
|
|
213
212
|
'WebhookMessage',
|
|
214
213
|
'WebhookTokenUnavailable',
|
|
215
|
-
'WebhookURLInvalid',
|
|
216
214
|
'WebhookApplication',
|
|
217
215
|
|
|
218
216
|
'MessageReferenceMissing',
|
|
219
217
|
|
|
220
218
|
'EmojiType',
|
|
221
219
|
'EmojiManaged',
|
|
222
|
-
'
|
|
220
|
+
'MissingGuildExpressionsPermission',
|
|
223
221
|
|
|
224
222
|
'NotGuildSoundboardSound',
|
|
225
223
|
'NotGuildSticker',
|
package/src/errors/Messages.js
CHANGED
|
@@ -82,15 +82,14 @@ 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',
|
|
89
88
|
|
|
90
89
|
[ErrorCodes.EmojiType]: 'Emoji must be a string or GuildEmoji/ReactionEmoji',
|
|
91
90
|
[ErrorCodes.EmojiManaged]: 'Emoji is managed and has no Author.',
|
|
92
|
-
[ErrorCodes.
|
|
93
|
-
`Client must have Manage Guild Expressions permission in guild ${guild} to see emoji authors.`,
|
|
91
|
+
[ErrorCodes.MissingGuildExpressionsPermission]: guild =>
|
|
92
|
+
`Client must have Create Guild Expressions or Manage Guild Expressions permission in guild ${guild} to see emoji authors.`,
|
|
94
93
|
|
|
95
94
|
[ErrorCodes.NotGuildSoundboardSound]: action =>
|
|
96
95
|
`Soundboard sound is a default (non-guild) soundboard sound and can't be ${action}.`,
|
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;
|
|
@@ -113,7 +111,6 @@ exports.ApplicationEmoji = require('./structures/ApplicationEmoji.js').Applicati
|
|
|
113
111
|
exports.ApplicationRoleConnectionMetadata =
|
|
114
112
|
require('./structures/ApplicationRoleConnectionMetadata.js').ApplicationRoleConnectionMetadata;
|
|
115
113
|
exports.Attachment = require('./structures/Attachment.js').Attachment;
|
|
116
|
-
exports.AttachmentBuilder = require('./structures/AttachmentBuilder.js').AttachmentBuilder;
|
|
117
114
|
exports.AutocompleteInteraction = require('./structures/AutocompleteInteraction.js').AutocompleteInteraction;
|
|
118
115
|
exports.AutoModerationActionExecution =
|
|
119
116
|
require('./structures/AutoModerationActionExecution.js').AutoModerationActionExecution;
|
|
@@ -22,11 +22,11 @@ class CachedManager extends DataManager {
|
|
|
22
22
|
* @name CachedManager#_cache
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(this, '_cache', {
|
|
25
|
-
value: this.client.options.makeCache(
|
|
26
|
-
|
|
27
|
-
this.
|
|
28
|
-
this.constructor,
|
|
29
|
-
),
|
|
25
|
+
value: this.client.options.makeCache({
|
|
26
|
+
holds: this.holds,
|
|
27
|
+
manager: this.constructor,
|
|
28
|
+
managerType: this.constructor[MakeCacheOverrideSymbol] ?? this.constructor,
|
|
29
|
+
}),
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
if (iterable) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const process = require('node:process');
|
|
4
|
-
const { lazy } = require('@discordjs/util');
|
|
4
|
+
const { lazy, isFileBodyEncodable, isJSONEncodable } = require('@discordjs/util');
|
|
5
5
|
const { Routes } = require('discord-api-types/v10');
|
|
6
6
|
const { BaseChannel } = require('../structures/BaseChannel.js');
|
|
7
7
|
const { MessagePayload } = require('../structures/MessagePayload.js');
|
|
@@ -147,7 +147,7 @@ class ChannelManager extends CachedManager {
|
|
|
147
147
|
* Creates a message in a channel.
|
|
148
148
|
*
|
|
149
149
|
* @param {TextChannelResolvable} channel The channel to send the message to
|
|
150
|
-
* @param {string|MessagePayload|MessageCreateOptions} options The options to provide
|
|
150
|
+
* @param {string|MessagePayload|MessageCreateOptions|JSONEncodable<RESTPostAPIChannelMessageJSONBody>|FileBodyEncodable<RESTPostAPIChannelMessageJSONBody>} options The options to provide
|
|
151
151
|
* @returns {Promise<Message>}
|
|
152
152
|
* @example
|
|
153
153
|
* // Send a basic message
|
|
@@ -174,18 +174,21 @@ class ChannelManager extends CachedManager {
|
|
|
174
174
|
* .catch(console.error);
|
|
175
175
|
*/
|
|
176
176
|
async createMessage(channel, options) {
|
|
177
|
-
let
|
|
177
|
+
let payload;
|
|
178
178
|
|
|
179
179
|
if (options instanceof MessagePayload) {
|
|
180
|
-
|
|
180
|
+
payload = await options.resolveBody().resolveFiles();
|
|
181
|
+
} else if (isFileBodyEncodable(options)) {
|
|
182
|
+
payload = options.toFileBody();
|
|
183
|
+
} else if (isJSONEncodable(options)) {
|
|
184
|
+
payload = { body: options.toJSON() };
|
|
181
185
|
} else {
|
|
182
|
-
|
|
186
|
+
payload = await MessagePayload.create(this, options).resolveBody().resolveFiles();
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
const resolvedChannelId = this.resolveId(channel);
|
|
186
190
|
const resolvedChannel = this.resolve(channel);
|
|
187
|
-
const
|
|
188
|
-
const data = await this.client.rest.post(Routes.channelMessages(resolvedChannelId), { body, files });
|
|
191
|
+
const data = await this.client.rest.post(Routes.channelMessages(resolvedChannelId), payload);
|
|
189
192
|
|
|
190
193
|
return resolvedChannel?.messages._add(data) ?? new (getMessage())(this.client, data);
|
|
191
194
|
}
|
|
@@ -124,12 +124,12 @@ class GuildBanManager extends CachedManager {
|
|
|
124
124
|
return this._add(data, cache);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
async _fetchMany(
|
|
127
|
+
async _fetchMany({ cache, ...apiOptions } = {}) {
|
|
128
128
|
const data = await this.client.rest.get(Routes.guildBans(this.guild.id), {
|
|
129
|
-
query: makeURLSearchParams(
|
|
129
|
+
query: makeURLSearchParams(apiOptions),
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
-
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban,
|
|
132
|
+
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, cache)), new Collection());
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
/**
|
|
@@ -251,8 +251,8 @@ class GuildEmojiManager extends CachedManager {
|
|
|
251
251
|
|
|
252
252
|
const { me } = this.guild.members;
|
|
253
253
|
if (!me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
|
|
254
|
-
if (!me.permissions.
|
|
255
|
-
throw new DiscordjsError(ErrorCodes.
|
|
254
|
+
if (!me.permissions.any(PermissionFlagsBits.CreateGuildExpressions | PermissionFlagsBits.ManageGuildExpressions)) {
|
|
255
|
+
throw new DiscordjsError(ErrorCodes.MissingGuildExpressionsPermission, this.guild);
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
const data = await this.client.rest.get(Routes.guildEmoji(this.guild.id, resolvedEmoji.id));
|
|
@@ -35,7 +35,15 @@ class GuildEmojiRoleManager extends DataManager {
|
|
|
35
35
|
* @readonly
|
|
36
36
|
*/
|
|
37
37
|
get cache() {
|
|
38
|
-
|
|
38
|
+
const cache = new Collection();
|
|
39
|
+
for (const roleId of this.emoji._roles) {
|
|
40
|
+
const role = this.guild.roles.cache.get(roleId);
|
|
41
|
+
if (role !== undefined) {
|
|
42
|
+
cache.set(roleId, role);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return cache;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
/**
|
|
@@ -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
|
-
|
|
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
|
|
283
|
-
this.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
|
|
@@ -37,8 +37,17 @@ class GuildMemberRoleManager extends DataManager {
|
|
|
37
37
|
* @readonly
|
|
38
38
|
*/
|
|
39
39
|
get cache() {
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
const cache = new Collection();
|
|
41
|
+
cache.set(this.guild.id, this.guild.roles.everyone);
|
|
42
|
+
|
|
43
|
+
for (const roleId of this.member._roles) {
|
|
44
|
+
const role = this.guild.roles.cache.get(roleId);
|
|
45
|
+
if (role !== undefined) {
|
|
46
|
+
cache.set(roleId, role);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return cache;
|
|
42
51
|
}
|
|
43
52
|
|
|
44
53
|
/**
|