discord.js 14.24.1 → 14.25.0
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 +5 -5
- package/src/client/websocket/handlers/RATE_LIMITED.js +25 -0
- package/src/client/websocket/handlers/index.js +1 -0
- package/src/managers/GuildBanManager.js +3 -3
- package/src/managers/GuildEmojiRoleManager.js +9 -1
- package/src/managers/GuildMemberManager.js +45 -20
- package/src/managers/GuildMemberRoleManager.js +11 -2
- package/src/managers/MessageManager.js +9 -9
- package/src/structures/GuildMember.js +12 -8
- 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 +1 -1
- package/typings/index.d.mts +2 -2
- package/typings/index.d.ts +2 -2
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": "14.
|
|
4
|
+
"version": "14.25.0",
|
|
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",
|
|
@@ -53,19 +53,19 @@
|
|
|
53
53
|
"homepage": "https://discord.js.org",
|
|
54
54
|
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@discordjs/builders": "^1.13.0",
|
|
57
56
|
"@discordjs/collection": "1.5.3",
|
|
58
|
-
"@discordjs/formatters": "^0.6.1",
|
|
59
57
|
"@discordjs/ws": "^1.2.3",
|
|
60
58
|
"@sapphire/snowflake": "3.5.3",
|
|
61
|
-
"discord-api-types": "^0.38.
|
|
59
|
+
"discord-api-types": "^0.38.33",
|
|
62
60
|
"fast-deep-equal": "3.1.3",
|
|
63
61
|
"lodash.snakecase": "4.1.1",
|
|
64
62
|
"magic-bytes.js": "^1.10.0",
|
|
65
63
|
"tslib": "^2.6.3",
|
|
66
64
|
"undici": "6.21.3",
|
|
65
|
+
"@discordjs/builders": "^1.13.0",
|
|
66
|
+
"@discordjs/formatters": "^0.6.2",
|
|
67
67
|
"@discordjs/rest": "^2.6.0",
|
|
68
|
-
"@discordjs/util": "^1.
|
|
68
|
+
"@discordjs/util": "^1.2.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@favware/cliff-jumper": "^4.1.0",
|
|
@@ -0,0 +1,25 @@
|
|
|
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 = (_, { 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
|
+
// eslint-disable-next-line max-len
|
|
18
|
+
`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.`,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
emittedFor.add(data.opcode);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -52,6 +52,7 @@ const handlers = Object.fromEntries([
|
|
|
52
52
|
['MESSAGE_REACTION_REMOVE_EMOJI', require('./MESSAGE_REACTION_REMOVE_EMOJI')],
|
|
53
53
|
['MESSAGE_UPDATE', require('./MESSAGE_UPDATE')],
|
|
54
54
|
['PRESENCE_UPDATE', require('./PRESENCE_UPDATE')],
|
|
55
|
+
['RATE_LIMITED', require('./RATE_LIMITED')],
|
|
55
56
|
['READY', require('./READY')],
|
|
56
57
|
['RESUMED', require('./RESUMED')],
|
|
57
58
|
['SOUNDBOARD_SOUNDS', require('./SOUNDBOARD_SOUNDS')],
|
|
@@ -120,12 +120,12 @@ class GuildBanManager extends CachedManager {
|
|
|
120
120
|
return this._add(data, cache);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
async _fetchMany(
|
|
123
|
+
async _fetchMany({ cache, ...apiOptions } = {}) {
|
|
124
124
|
const data = await this.client.rest.get(Routes.guildBans(this.guild.id), {
|
|
125
|
-
query: makeURLSearchParams(
|
|
125
|
+
query: makeURLSearchParams(apiOptions),
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban,
|
|
128
|
+
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, cache)), new Collection());
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/**
|
|
@@ -31,7 +31,15 @@ class GuildEmojiRoleManager extends DataManager {
|
|
|
31
31
|
* @readonly
|
|
32
32
|
*/
|
|
33
33
|
get cache() {
|
|
34
|
-
|
|
34
|
+
const cache = new Collection();
|
|
35
|
+
for (const roleId of this.emoji._roles) {
|
|
36
|
+
const role = this.guild.roles.cache.get(roleId);
|
|
37
|
+
if (role !== undefined) {
|
|
38
|
+
cache.set(roleId, role);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return cache;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
/**
|
|
@@ -4,8 +4,9 @@ const { process } = require('node:process');
|
|
|
4
4
|
const { setTimeout, clearTimeout } = require('node:timers');
|
|
5
5
|
const { Collection } = require('@discordjs/collection');
|
|
6
6
|
const { makeURLSearchParams } = require('@discordjs/rest');
|
|
7
|
+
const { GatewayRateLimitError } = require('@discordjs/util');
|
|
7
8
|
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
|
8
|
-
const { Routes, GatewayOpcodes } = require('discord-api-types/v10');
|
|
9
|
+
const { Routes, GatewayOpcodes, GatewayDispatchEvents } = require('discord-api-types/v10');
|
|
9
10
|
const CachedManager = require('./CachedManager');
|
|
10
11
|
const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } = require('../errors');
|
|
11
12
|
const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
|
|
@@ -239,19 +240,25 @@ class GuildMemberManager extends CachedManager {
|
|
|
239
240
|
|
|
240
241
|
return new Promise((resolve, reject) => {
|
|
241
242
|
if (!query && !users) query = '';
|
|
242
|
-
this.guild.shard.send({
|
|
243
|
-
op: GatewayOpcodes.RequestGuildMembers,
|
|
244
|
-
d: {
|
|
245
|
-
guild_id: this.guild.id,
|
|
246
|
-
presences,
|
|
247
|
-
user_ids: users,
|
|
248
|
-
query,
|
|
249
|
-
nonce,
|
|
250
|
-
limit,
|
|
251
|
-
},
|
|
252
|
-
});
|
|
253
243
|
const fetchedMembers = new Collection();
|
|
254
244
|
let i = 0;
|
|
245
|
+
|
|
246
|
+
const cleanup = () => {
|
|
247
|
+
/* eslint-disable no-use-before-define */
|
|
248
|
+
clearTimeout(timeout);
|
|
249
|
+
|
|
250
|
+
this.client.removeListener(Events.Raw, rateLimitHandler);
|
|
251
|
+
this.client.decrementMaxListeners();
|
|
252
|
+
this.client.removeListener(Events.GuildMembersChunk, handler);
|
|
253
|
+
this.client.decrementMaxListeners();
|
|
254
|
+
/* eslint-enable no-use-before-define */
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const timeout = setTimeout(() => {
|
|
258
|
+
cleanup();
|
|
259
|
+
reject(new DiscordjsError(ErrorCodes.GuildMembersTimeout));
|
|
260
|
+
}, time).unref();
|
|
261
|
+
|
|
255
262
|
const handler = (members, _, chunk) => {
|
|
256
263
|
if (chunk.nonce !== nonce) return;
|
|
257
264
|
timeout.refresh();
|
|
@@ -260,19 +267,37 @@ class GuildMemberManager extends CachedManager {
|
|
|
260
267
|
fetchedMembers.set(member.id, member);
|
|
261
268
|
}
|
|
262
269
|
if (members.size < 1_000 || (limit && fetchedMembers.size >= limit) || i === chunk.count) {
|
|
263
|
-
|
|
264
|
-
this.client.removeListener(Events.GuildMembersChunk, handler);
|
|
265
|
-
this.client.decrementMaxListeners();
|
|
270
|
+
cleanup();
|
|
266
271
|
resolve(users && !Array.isArray(users) && fetchedMembers.size ? fetchedMembers.first() : fetchedMembers);
|
|
267
272
|
}
|
|
268
273
|
};
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
this.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
|
|
275
|
+
const requestData = {
|
|
276
|
+
guild_id: this.guild.id,
|
|
277
|
+
presences,
|
|
278
|
+
user_ids: users,
|
|
279
|
+
query,
|
|
280
|
+
nonce,
|
|
281
|
+
limit,
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const rateLimitHandler = payload => {
|
|
285
|
+
if (payload.t === GatewayDispatchEvents.RateLimited && payload.d.meta.nonce === nonce) {
|
|
286
|
+
cleanup();
|
|
287
|
+
reject(new GatewayRateLimitError(payload.d, requestData));
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
this.client.incrementMaxListeners();
|
|
292
|
+
this.client.on(Events.Raw, rateLimitHandler);
|
|
293
|
+
|
|
274
294
|
this.client.incrementMaxListeners();
|
|
275
295
|
this.client.on(Events.GuildMembersChunk, handler);
|
|
296
|
+
|
|
297
|
+
this.guild.shard.send({
|
|
298
|
+
op: GatewayOpcodes.RequestGuildMembers,
|
|
299
|
+
d: requestData,
|
|
300
|
+
});
|
|
276
301
|
});
|
|
277
302
|
}
|
|
278
303
|
|
|
@@ -33,8 +33,17 @@ class GuildMemberRoleManager extends DataManager {
|
|
|
33
33
|
* @readonly
|
|
34
34
|
*/
|
|
35
35
|
get cache() {
|
|
36
|
-
const
|
|
37
|
-
|
|
36
|
+
const cache = new Collection();
|
|
37
|
+
cache.set(this.guild.id, this.guild.roles.everyone);
|
|
38
|
+
|
|
39
|
+
for (const roleId of this.member._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;
|
|
38
47
|
}
|
|
39
48
|
|
|
40
49
|
/**
|
|
@@ -111,12 +111,12 @@ class MessageManager extends CachedManager {
|
|
|
111
111
|
return this._add(data, cache);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
async _fetchMany(
|
|
114
|
+
async _fetchMany({ cache, ...apiOptions } = {}) {
|
|
115
115
|
const data = await this.client.rest.get(Routes.channelMessages(this.channel.id), {
|
|
116
|
-
query: makeURLSearchParams(
|
|
116
|
+
query: makeURLSearchParams(apiOptions),
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
return data.reduce((_data, message) => _data.set(message.id, this._add(message,
|
|
119
|
+
return data.reduce((_data, message) => _data.set(message.id, this._add(message, cache)), new Collection());
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
@@ -146,8 +146,8 @@ class MessageManager extends CachedManager {
|
|
|
146
146
|
*/
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
|
-
* Fetches the pinned messages of this channel
|
|
150
|
-
* <info>The returned
|
|
149
|
+
* Fetches the pinned messages of this channel, returning a paginated result.
|
|
150
|
+
* <info>The returned messages do not contain any reaction data.
|
|
151
151
|
* Those need to be fetched separately.</info>
|
|
152
152
|
*
|
|
153
153
|
* @param {FetchPinnedMessagesOptions} [options={}] Options for fetching pinned messages
|
|
@@ -158,11 +158,11 @@ class MessageManager extends CachedManager {
|
|
|
158
158
|
* .then(messages => console.log(`Received ${messages.items.length} messages`))
|
|
159
159
|
* .catch(console.error);
|
|
160
160
|
*/
|
|
161
|
-
async fetchPins(
|
|
161
|
+
async fetchPins({ cache, ...apiOptions } = {}) {
|
|
162
162
|
const data = await this.client.rest.get(Routes.channelMessagesPins(this.channel.id), {
|
|
163
163
|
query: makeURLSearchParams({
|
|
164
|
-
...
|
|
165
|
-
before:
|
|
164
|
+
...apiOptions,
|
|
165
|
+
before: apiOptions.before && new Date(apiOptions.before).toISOString(),
|
|
166
166
|
}),
|
|
167
167
|
});
|
|
168
168
|
|
|
@@ -172,7 +172,7 @@ class MessageManager extends CachedManager {
|
|
|
172
172
|
get pinnedAt() {
|
|
173
173
|
return new Date(this.pinnedTimestamp);
|
|
174
174
|
},
|
|
175
|
-
message: this._add(item.message,
|
|
175
|
+
message: this._add(item.message, cache),
|
|
176
176
|
})),
|
|
177
177
|
hasMore: data.has_more,
|
|
178
178
|
};
|
|
@@ -24,12 +24,6 @@ class GuildMember extends Base {
|
|
|
24
24
|
*/
|
|
25
25
|
this.guild = guild;
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* The timestamp the member joined the guild at
|
|
29
|
-
* @type {?number}
|
|
30
|
-
*/
|
|
31
|
-
this.joinedTimestamp = null;
|
|
32
|
-
|
|
33
27
|
/**
|
|
34
28
|
* The last timestamp this member started boosting the guild
|
|
35
29
|
* @type {?number}
|
|
@@ -62,7 +56,7 @@ class GuildMember extends Base {
|
|
|
62
56
|
*/
|
|
63
57
|
Object.defineProperty(this, '_roles', { value: [], writable: true });
|
|
64
58
|
|
|
65
|
-
|
|
59
|
+
this._patch(data);
|
|
66
60
|
}
|
|
67
61
|
|
|
68
62
|
_patch(data) {
|
|
@@ -95,7 +89,17 @@ class GuildMember extends Base {
|
|
|
95
89
|
this.banner ??= null;
|
|
96
90
|
}
|
|
97
91
|
|
|
98
|
-
if ('joined_at' in data)
|
|
92
|
+
if ('joined_at' in data) {
|
|
93
|
+
/**
|
|
94
|
+
* The timestamp the member joined the guild at
|
|
95
|
+
*
|
|
96
|
+
* @type {?number}
|
|
97
|
+
*/
|
|
98
|
+
this.joinedTimestamp = data.joined_at && Date.parse(data.joined_at);
|
|
99
|
+
} else {
|
|
100
|
+
this.joinedTimestamp ??= null;
|
|
101
|
+
}
|
|
102
|
+
|
|
99
103
|
if ('premium_since' in data) {
|
|
100
104
|
this.premiumSinceTimestamp = data.premium_since ? Date.parse(data.premium_since) : null;
|
|
101
105
|
}
|
package/src/structures/Role.js
CHANGED
package/typings/index.d.mts
CHANGED
|
@@ -3841,7 +3841,7 @@ export interface PrivateThreadChannel extends ThreadChannel<false> {
|
|
|
3841
3841
|
export interface ThreadChannel<ThreadOnly extends boolean = boolean>
|
|
3842
3842
|
extends Omit<TextBasedChannelFields<true>, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> {}
|
|
3843
3843
|
export class ThreadChannel<ThreadOnly extends boolean = boolean> extends BaseChannel {
|
|
3844
|
-
private constructor(guild: Guild, data
|
|
3844
|
+
private constructor(guild: Guild, data: RawThreadChannelData, client?: Client<true>);
|
|
3845
3845
|
public archived: boolean | null;
|
|
3846
3846
|
public get archivedAt(): Date | null;
|
|
3847
3847
|
public archiveTimestamp: number | null;
|
|
@@ -4234,7 +4234,7 @@ export class VoiceState extends Base {
|
|
|
4234
4234
|
// tslint:disable-next-line no-empty-interface
|
|
4235
4235
|
export interface Webhook<Type extends WebhookType = WebhookType> extends WebhookFields {}
|
|
4236
4236
|
export class Webhook<Type extends WebhookType = WebhookType> {
|
|
4237
|
-
private constructor(client: Client<true>, data
|
|
4237
|
+
private constructor(client: Client<true>, data: RawWebhookData);
|
|
4238
4238
|
public avatar: string | null;
|
|
4239
4239
|
public avatarURL(options?: ImageURLOptions): string | null;
|
|
4240
4240
|
public channelId: Snowflake;
|
package/typings/index.d.ts
CHANGED
|
@@ -3841,7 +3841,7 @@ export interface PrivateThreadChannel extends ThreadChannel<false> {
|
|
|
3841
3841
|
export interface ThreadChannel<ThreadOnly extends boolean = boolean>
|
|
3842
3842
|
extends Omit<TextBasedChannelFields<true>, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> {}
|
|
3843
3843
|
export class ThreadChannel<ThreadOnly extends boolean = boolean> extends BaseChannel {
|
|
3844
|
-
private constructor(guild: Guild, data
|
|
3844
|
+
private constructor(guild: Guild, data: RawThreadChannelData, client?: Client<true>);
|
|
3845
3845
|
public archived: boolean | null;
|
|
3846
3846
|
public get archivedAt(): Date | null;
|
|
3847
3847
|
public archiveTimestamp: number | null;
|
|
@@ -4234,7 +4234,7 @@ export class VoiceState extends Base {
|
|
|
4234
4234
|
// tslint:disable-next-line no-empty-interface
|
|
4235
4235
|
export interface Webhook<Type extends WebhookType = WebhookType> extends WebhookFields {}
|
|
4236
4236
|
export class Webhook<Type extends WebhookType = WebhookType> {
|
|
4237
|
-
private constructor(client: Client<true>, data
|
|
4237
|
+
private constructor(client: Client<true>, data: RawWebhookData);
|
|
4238
4238
|
public avatar: string | null;
|
|
4239
4239
|
public avatarURL(options?: ImageURLOptions): string | null;
|
|
4240
4240
|
public channelId: Snowflake;
|