discord.js 15.0.0-dev.1757851336-b66f52f9a → 15.0.0-dev.1758542541-beed098bf

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.1757851336-b66f52f9a",
4
+ "version": "15.0.0-dev.1758542541-beed098bf",
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.11.0",
64
- "@discordjs/builders": "^2.0.0-dev.1757851336-b66f52f9a",
65
- "@discordjs/collection": "^3.0.0-dev.1757851336-b66f52f9a",
66
- "@discordjs/util": "^2.0.0-dev.1757851336-b66f52f9a",
67
- "@discordjs/rest": "^3.0.0-dev.1757851336-b66f52f9a",
68
- "@discordjs/ws": "^3.0.0-dev.1757851336-b66f52f9a",
69
- "@discordjs/formatters": "^1.0.0-dev.1757851336-b66f52f9a"
64
+ "@discordjs/collection": "^3.0.0-dev.1758542541-beed098bf",
65
+ "@discordjs/formatters": "^1.0.0-dev.1758542541-beed098bf",
66
+ "@discordjs/builders": "^2.0.0-dev.1758542541-beed098bf",
67
+ "@discordjs/util": "^2.0.0-dev.1758542541-beed098bf",
68
+ "@discordjs/rest": "^3.0.0-dev.1758542541-beed098bf",
69
+ "@discordjs/ws": "^3.0.0-dev.1758542541-beed098bf"
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.6",
84
84
  "typescript": "~5.9.2",
85
- "@discordjs/docgen": "^0.12.1",
86
85
  "@discordjs/api-extractor": "^7.52.7",
87
- "@discordjs/scripts": "^0.1.0"
86
+ "@discordjs/scripts": "^0.1.0",
87
+ "@discordjs/docgen": "^0.12.1"
88
88
  },
89
89
  "engines": {
90
90
  "node": ">=22.12.0"
@@ -114,8 +114,10 @@
114
114
  * @property {'CommandInteractionOptionInvalidChannelType'} CommandInteractionOptionInvalidChannelType
115
115
  * @property {'AutocompleteInteractionOptionNoFocusedOption'} AutocompleteInteractionOptionNoFocusedOption
116
116
  *
117
- * @property {'ModalSubmitInteractionFieldNotFound'} ModalSubmitInteractionFieldNotFound
118
- * @property {'ModalSubmitInteractionFieldType'} ModalSubmitInteractionFieldType
117
+ * @property {'ModalSubmitInteractionComponentNotFound'} ModalSubmitInteractionComponentNotFound
118
+ * @property {'ModalSubmitInteractionComponentType'} ModalSubmitInteractionComponentType
119
+ * @property {'ModalSubmitInteractionComponentEmpty'} ModalSubmitInteractionComponentEmpty
120
+ * @property {'ModalSubmitInteractionComponentInvalidChannelType'} ModalSubmitInteractionComponentInvalidChannelType
119
121
  *
120
122
  * @property {'InvalidMissingScopes'} InvalidMissingScopes
121
123
  * @property {'InvalidScopesWithPermissions'} InvalidScopesWithPermissions
@@ -248,8 +250,10 @@ const keys = [
248
250
  'CommandInteractionOptionInvalidChannelType',
249
251
  'AutocompleteInteractionOptionNoFocusedOption',
250
252
 
251
- 'ModalSubmitInteractionFieldNotFound',
252
- 'ModalSubmitInteractionFieldType',
253
+ 'ModalSubmitInteractionComponentNotFound',
254
+ 'ModalSubmitInteractionComponentType',
255
+ 'ModalSubmitInteractionComponentEmpty',
256
+ 'ModalSubmitInteractionComponentInvalidChannelType',
253
257
 
254
258
  'InvalidMissingScopes',
255
259
  'InvalidScopesWithPermissions',
@@ -127,10 +127,14 @@ const Messages = {
127
127
  `The type of channel of the option "${name}" is: ${type}; expected ${expected}.`,
128
128
  [ErrorCodes.AutocompleteInteractionOptionNoFocusedOption]: 'No focused option for autocomplete interaction.',
129
129
 
130
- [ErrorCodes.ModalSubmitInteractionFieldNotFound]: customId =>
131
- `Required field with custom id "${customId}" not found.`,
132
- [ErrorCodes.ModalSubmitInteractionFieldType]: (customId, type, expected) =>
133
- `Field with custom id "${customId}" is of type: ${type}; expected ${expected}.`,
130
+ [ErrorCodes.ModalSubmitInteractionComponentNotFound]: customId =>
131
+ `Required component with custom id "${customId}" not found.`,
132
+ [ErrorCodes.ModalSubmitInteractionComponentType]: (customId, type, expected) =>
133
+ `Component with custom id "${customId}" is of type: ${type}; expected ${expected}.`,
134
+ [ErrorCodes.ModalSubmitInteractionComponentEmpty]: (customId, type) =>
135
+ `Required component with custom id "${customId}" is of type: ${type}; expected a non-empty value.`,
136
+ [ErrorCodes.ModalSubmitInteractionComponentInvalidChannelType]: (customId, type, expected) =>
137
+ `The type of channel of the component with custom id "${customId}" is: ${type}; expected ${expected}.`,
134
138
 
135
139
  [ErrorCodes.InvalidMissingScopes]: 'At least one valid scope must be provided for the invite',
136
140
  [ErrorCodes.InvalidScopesWithPermissions]: 'Permissions cannot be set without the bot scope.',
package/src/index.js CHANGED
@@ -199,7 +199,7 @@ exports.MessageContextMenuCommandInteraction =
199
199
  exports.MessageMentions = require('./structures/MessageMentions.js').MessageMentions;
200
200
  exports.MessagePayload = require('./structures/MessagePayload.js').MessagePayload;
201
201
  exports.MessageReaction = require('./structures/MessageReaction.js').MessageReaction;
202
- exports.ModalSubmitFields = require('./structures/ModalSubmitFields.js').ModalSubmitFields;
202
+ exports.ModalComponentResolver = require('./structures/ModalComponentResolver.js').ModalComponentResolver;
203
203
  exports.ModalSubmitInteraction = require('./structures/ModalSubmitInteraction.js').ModalSubmitInteraction;
204
204
  exports.OAuth2Guild = require('./structures/OAuth2Guild.js').OAuth2Guild;
205
205
  exports.PartialGroupDMChannel = require('./structures/PartialGroupDMChannel.js').PartialGroupDMChannel;
@@ -9,6 +9,7 @@ const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } =
9
9
  const { BaseGuildVoiceChannel } = require('../structures/BaseGuildVoiceChannel.js');
10
10
  const { GuildMember } = require('../structures/GuildMember.js');
11
11
  const { Role } = require('../structures/Role.js');
12
+ const { resolveImage } = require('../util/DataResolver.js');
12
13
  const { Events } = require('../util/Events.js');
13
14
  const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField.js');
14
15
  const { Partials } = require('../util/Partials.js');
@@ -358,8 +359,7 @@ class GuildMemberManager extends CachedManager {
358
359
  */
359
360
 
360
361
  /**
361
- * Edits a member of the guild.
362
- * <info>The user must be a member of the guild</info>
362
+ * Edits a member of a guild.
363
363
  *
364
364
  * @param {UserResolvable} user The member to edit
365
365
  * @param {GuildMemberEditOptions} options The options to provide
@@ -396,18 +396,40 @@ class GuildMemberManager extends CachedManager {
396
396
  options.flags = GuildMemberFlagsBitField.resolve(options.flags);
397
397
  }
398
398
 
399
- let endpoint;
400
- if (id === this.client.user.id) {
401
- const keys = Object.keys(options);
402
- if (keys.length === 1 && keys[0] === 'nick') endpoint = Routes.guildMember(this.guild.id);
403
- else endpoint = Routes.guildMember(this.guild.id, id);
404
- } else {
405
- endpoint = Routes.guildMember(this.guild.id, id);
406
- }
399
+ const data = await this.client.rest.patch(Routes.guildMember(this.guild.id, id), { body: options, reason });
400
+ const clone = this.cache.get(id)?._clone();
401
+ clone?._patch(data);
402
+ return clone ?? this._add(data, false);
403
+ }
404
+
405
+ /**
406
+ * The data for editing the current application's guild member.
407
+ *
408
+ * @typedef {Object} GuildMemberEditMeOptions
409
+ * @property {?string} [nick] The nickname to set
410
+ * @property {?(BufferResolvable|Base64Resolvable)} [banner] The banner to set
411
+ * @property {?(BufferResolvable|Base64Resolvable)} [avatar] The avatar to set
412
+ * @property {?string} [bio] The bio to set
413
+ * @property {string} [reason] The reason to use
414
+ */
407
415
 
408
- const data = await this.client.rest.patch(endpoint, { body: options, reason });
416
+ /**
417
+ * Edits the current application's guild member in a guild.
418
+ *
419
+ * @param {GuildMemberEditMeOptions} options The options to provide
420
+ * @returns {Promise<GuildMember>}
421
+ */
422
+ async editMe({ reason, ...options }) {
423
+ const data = await this.client.rest.patch(Routes.guildMember(this.guild.id, '@me'), {
424
+ body: {
425
+ ...options,
426
+ banner: options.banner && (await resolveImage(options.banner)),
427
+ avatar: options.avatar && (await resolveImage(options.avatar)),
428
+ },
429
+ reason,
430
+ });
409
431
 
410
- const clone = this.cache.get(id)?._clone();
432
+ const clone = this.me?._clone();
411
433
  clone?._patch(data);
412
434
  return clone ?? this._add(data, false);
413
435
  }
@@ -91,13 +91,17 @@ class CommandInteraction extends BaseInteraction {
91
91
  }
92
92
 
93
93
  /**
94
- * Represents the resolved data of a received command interaction.
95
- *
96
- * @typedef {Object} CommandInteractionResolvedData
94
+ * @typedef {Object} BaseInteractionResolvedData
97
95
  * @property {Collection<Snowflake, User>} [users] The resolved users
98
96
  * @property {Collection<Snowflake, GuildMember|APIGuildMember>} [members] The resolved guild members
99
97
  * @property {Collection<Snowflake, Role|APIRole>} [roles] The resolved roles
100
98
  * @property {Collection<Snowflake, BaseChannel|APIChannel>} [channels] The resolved channels
99
+ */
100
+
101
+ /**
102
+ * Represents the resolved data of a received command interaction.
103
+ *
104
+ * @typedef {BaseInteractionResolvedData} CommandInteractionResolvedData
101
105
  * @property {Collection<Snowflake, Message|APIMessage>} [messages] The resolved messages
102
106
  * @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
103
107
  */
@@ -634,7 +634,7 @@ class Message extends Base {
634
634
  * Resolves with a collection of reactions that pass the specified filter.
635
635
  *
636
636
  * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector
637
- * @returns {Promise<Collection<string | Snowflake, MessageReaction>>}
637
+ * @returns {Promise<Collection<string|Snowflake, MessageReaction>>}
638
638
  * @example
639
639
  * // Create a reaction collector
640
640
  * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someId'
@@ -0,0 +1,228 @@
1
+ 'use strict';
2
+
3
+ const { Collection } = require('@discordjs/collection');
4
+ const { ComponentType } = require('discord-api-types/v10');
5
+ const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
6
+
7
+ /**
8
+ * @typedef {Object} ModalSelectedMentionables
9
+ * @property {Collection<Snowflake, User>} users The selected users
10
+ * @property {Collection<Snowflake, GuildMember | APIGuildMember>} members The selected members
11
+ * @property {Collection<Snowflake, Role | APIRole>} roles The selected roles
12
+ */
13
+
14
+ /**
15
+ * A resolver for modal submit components
16
+ */
17
+ class ModalComponentResolver {
18
+ constructor(client, components, resolved) {
19
+ /**
20
+ * The client that instantiated this.
21
+ *
22
+ * @name ModalComponentResolver#client
23
+ * @type {Client}
24
+ * @readonly
25
+ */
26
+ Object.defineProperty(this, 'client', { value: client });
27
+
28
+ /**
29
+ * The interaction resolved data
30
+ *
31
+ * @name ModalComponentResolver#resolved
32
+ * @type {?Readonly<BaseInteractionResolvedData>}
33
+ */
34
+ Object.defineProperty(this, 'resolved', { value: resolved ? Object.freeze(resolved) : null });
35
+
36
+ /**
37
+ * The components within the modal
38
+ *
39
+ * @type {Array<ActionRowModalData|LabelModalData|TextDisplayModalData>}
40
+ */
41
+ this.data = components;
42
+
43
+ /**
44
+ * The bottom-level components of the interaction
45
+ *
46
+ * @type {Collection<string, ModalData>}
47
+ */
48
+ this.hoistedComponents = components.reduce((accumulator, next) => {
49
+ // For legacy support of action rows
50
+ if ('components' in next) {
51
+ for (const component of next.components) accumulator.set(component.customId, component);
52
+ }
53
+
54
+ // For label components
55
+ if ('component' in next) {
56
+ accumulator.set(next.component.customId, next.component);
57
+ }
58
+
59
+ return accumulator;
60
+ }, new Collection());
61
+ }
62
+
63
+ /**
64
+ * Gets a component by custom id.
65
+ *
66
+ * @property {string} customId The custom id of the component.
67
+ * @returns {ModalData}
68
+ */
69
+ getComponent(customId) {
70
+ const component = this.hoistedComponents.get(customId);
71
+
72
+ if (!component) throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionComponentNotFound, customId);
73
+
74
+ return component;
75
+ }
76
+
77
+ /**
78
+ * Gets a component by custom id and property and checks its type.
79
+ *
80
+ * @param {string} customId The custom id of the component.
81
+ * @param {ComponentType[]} allowedTypes The allowed types of the component.
82
+ * @param {string[]} properties The properties to check for for `required`.
83
+ * @param {boolean} required Whether to throw an error if the component value(s) are not found.
84
+ * @returns {ModalData} The option, if found.
85
+ * @private
86
+ */
87
+ _getTypedComponent(customId, allowedTypes, properties, required) {
88
+ const component = this.getComponent(customId);
89
+ if (!allowedTypes.includes(component.type)) {
90
+ throw new DiscordjsTypeError(
91
+ ErrorCodes.ModalSubmitInteractionComponentType,
92
+ customId,
93
+ component.type,
94
+ allowedTypes.join(', '),
95
+ );
96
+ } else if (required && properties.every(prop => component[prop] === null || component[prop] === undefined)) {
97
+ throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionComponentEmpty, customId, component.type);
98
+ }
99
+
100
+ return component;
101
+ }
102
+
103
+ /**
104
+ * Gets the value of a text input component
105
+ *
106
+ * @param {string} customId The custom id of the text input component
107
+ * @param {?boolean} required Whether to throw an error if the component value is not found or empty
108
+ * @returns {?string}
109
+ */
110
+ getTextInputValue(customId, required = false) {
111
+ return this._getTypedComponent(customId, [ComponentType.TextInput], ['value'], required).value ?? null;
112
+ }
113
+
114
+ /**
115
+ * Gets the values of a string select component
116
+ *
117
+ * @param {string} customId The custom id of the string select component
118
+ * @returns {string[]}
119
+ */
120
+ getStringSelectValues(customId) {
121
+ return this._getTypedComponent(customId, [ComponentType.StringSelect]).values;
122
+ }
123
+
124
+ /**
125
+ * Gets users component
126
+ *
127
+ * @param {string} customId The custom id of the component
128
+ * @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
129
+ * @returns {?Collection<Snowflake, User>} The selected users, or null if none were selected and not required
130
+ */
131
+ getSelectedUsers(customId, required = false) {
132
+ const component = this._getTypedComponent(
133
+ customId,
134
+ [ComponentType.UserSelect, ComponentType.MentionableSelect],
135
+ ['users'],
136
+ required,
137
+ );
138
+ return component.users ?? null;
139
+ }
140
+
141
+ /**
142
+ * Gets roles component
143
+ *
144
+ * @param {string} customId The custom id of the component
145
+ * @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
146
+ * @returns {?Collection<Snowflake, Role|APIRole>} The selected roles, or null if none were selected and not required
147
+ */
148
+ getSelectedRoles(customId, required = false) {
149
+ const component = this._getTypedComponent(
150
+ customId,
151
+ [ComponentType.RoleSelect, ComponentType.MentionableSelect],
152
+ ['roles'],
153
+ required,
154
+ );
155
+ return component.roles ?? null;
156
+ }
157
+
158
+ /**
159
+ * Gets channels component
160
+ *
161
+ * @param {string} customId The custom id of the component
162
+ * @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
163
+ * @param {ChannelType[]} [channelTypes=[]] The allowed types of channels. If empty, all channel types are allowed.
164
+ * @returns {?Collection<Snowflake, GuildChannel|ThreadChannel|APIChannel>} The selected channels, or null if none were selected and not required
165
+ */
166
+ getSelectedChannels(customId, required = false, channelTypes = []) {
167
+ const component = this._getTypedComponent(customId, [ComponentType.ChannelSelect], ['channels'], required);
168
+ const channels = component.channels;
169
+ if (channels && channelTypes.length > 0) {
170
+ for (const channel of channels.values()) {
171
+ if (!channelTypes.includes(channel.type)) {
172
+ throw new DiscordjsTypeError(
173
+ ErrorCodes.ModalSubmitInteractionComponentInvalidChannelType,
174
+ customId,
175
+ channel.type,
176
+ channelTypes.join(', '),
177
+ );
178
+ }
179
+ }
180
+ }
181
+
182
+ return channels ?? null;
183
+ }
184
+
185
+ /**
186
+ * Gets members component
187
+ *
188
+ * @param {string} customId The custom id of the component
189
+ * @returns {?Collection<Snowflake, GuildMember|APIGuildMember>} The selected members, or null if none were selected or the users were not present in the guild
190
+ */
191
+ getSelectedMembers(customId) {
192
+ const component = this._getTypedComponent(
193
+ customId,
194
+ [ComponentType.UserSelect, ComponentType.MentionableSelect],
195
+ ['members'],
196
+ false,
197
+ );
198
+ return component.members ?? null;
199
+ }
200
+
201
+ /**
202
+ * Gets mentionables component
203
+ *
204
+ * @param {string} customId The custom id of the component
205
+ * @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
206
+ * @returns {?ModalSelectedMentionables} The selected mentionables, or null if none were selected and not required
207
+ */
208
+ getSelectedMentionables(customId, required = false) {
209
+ const component = this._getTypedComponent(
210
+ customId,
211
+ [ComponentType.MentionableSelect],
212
+ ['users', 'members', 'roles'],
213
+ required,
214
+ );
215
+
216
+ if (component.users || component.members || component.roles) {
217
+ return {
218
+ users: component.users ?? new Collection(),
219
+ members: component.members ?? new Collection(),
220
+ roles: component.roles ?? new Collection(),
221
+ };
222
+ }
223
+
224
+ return null;
225
+ }
226
+ }
227
+
228
+ exports.ModalComponentResolver = ModalComponentResolver;
@@ -1,46 +1,53 @@
1
1
  'use strict';
2
2
 
3
+ const { Collection } = require('@discordjs/collection');
3
4
  const { lazy } = require('@discordjs/util');
5
+ const { transformResolved } = require('../util/Util.js');
4
6
  const { BaseInteraction } = require('./BaseInteraction.js');
5
7
  const { InteractionWebhook } = require('./InteractionWebhook.js');
6
- const { ModalSubmitFields } = require('./ModalSubmitFields.js');
8
+ const { ModalComponentResolver } = require('./ModalComponentResolver.js');
7
9
  const { InteractionResponses } = require('./interfaces/InteractionResponses.js');
8
10
 
9
11
  const getMessage = lazy(() => require('./Message.js').Message);
10
12
 
11
13
  /**
12
14
  * @typedef {Object} BaseModalData
13
- * @property {ComponentType} type The component type of the field
14
- * @property {string} customId The custom id of the field
15
- * @property {number} id The id of the field
15
+ * @property {ComponentType} type The component type of the component
16
+ * @property {number} id The id of the component
17
+ */
18
+
19
+ /**
20
+ * @typedef {BaseModalData} SelectMenuModalData
21
+ * @property {string} customId The custom id of the component
22
+ * @property {string[]} values The values of the component
23
+ * @property {Collection<string, GuildMember|APIGuildMember>} [members] The resolved members
24
+ * @property {Collection<string, User|APIUser>} [users] The resolved users
25
+ * @property {Collection<string, Role|APIRole>} [roles] The resolved roles
26
+ * @property {Collection<string, BaseChannel|APIChannel>} [channels] The resolved channels
16
27
  */
17
28
 
18
29
  /**
19
30
  * @typedef {BaseModalData} TextInputModalData
20
- * @property {string} value The value of the field
31
+ * @property {string} customId The custom id of the component
32
+ * @property {string} value The value of the component
21
33
  */
22
34
 
23
35
  /**
24
- * @typedef {BaseModalData} StringSelectModalData
25
- * @property {string[]} values The values of the field
36
+ * @typedef {BaseModalData} TextDisplayModalData
26
37
  */
27
38
 
28
39
  /**
29
- * @typedef {TextInputModalData | StringSelectModalData} ModalData
40
+ * @typedef {SelectMenuModalData|TextInputModalData} ModalData
30
41
  */
31
42
 
32
43
  /**
33
- * @typedef {Object} LabelModalData
44
+ * @typedef {BaseModalData} LabelModalData
34
45
  * @property {ModalData} component The component within the label
35
- * @property {ComponentType} type The component type of the label
36
- * @property {number} id The id of the label
37
46
  */
38
47
 
39
48
  /**
40
- * @typedef {Object} ActionRowModalData
49
+ * @typedef {BaseModalData} ActionRowModalData
41
50
  * @property {TextInputModalData[]} components The components of this action row
42
- * @property {ComponentType} type The component type of the action row
43
- * @property {number} id The id of the action row
44
51
  */
45
52
 
46
53
  /**
@@ -73,16 +80,13 @@ class ModalSubmitInteraction extends BaseInteraction {
73
80
  /**
74
81
  * The components within the modal
75
82
  *
76
- * @type {Array<ActionRowModalData | LabelModalData>}
77
- */
78
- this.components = data.data.components?.map(component => ModalSubmitInteraction.transformComponent(component));
79
-
80
- /**
81
- * The fields within the modal
82
- *
83
- * @type {ModalSubmitFields}
83
+ * @type {ModalComponentResolver}
84
84
  */
85
- this.fields = new ModalSubmitFields(this.components);
85
+ this.components = new ModalComponentResolver(
86
+ this.client,
87
+ data.data.components?.map(component => this.transformComponent(component, data.data.resolved)),
88
+ transformResolved({ client: this.client, guild: this.guild, channel: this.channel }, data.data.resolved),
89
+ );
86
90
 
87
91
  /**
88
92
  * Whether the reply to this interaction has been deferred
@@ -117,15 +121,16 @@ class ModalSubmitInteraction extends BaseInteraction {
117
121
  * Transforms component data to discord.js-compatible data
118
122
  *
119
123
  * @param {*} rawComponent The data to transform
124
+ * @param {APIInteractionDataResolved} resolved The resolved data for the interaction
120
125
  * @returns {ModalData[]}
121
126
  * @private
122
127
  */
123
- static transformComponent(rawComponent) {
128
+ transformComponent(rawComponent, resolved) {
124
129
  if ('components' in rawComponent) {
125
130
  return {
126
131
  type: rawComponent.type,
127
132
  id: rawComponent.id,
128
- components: rawComponent.components.map(component => this.transformComponent(component)),
133
+ components: rawComponent.components.map(component => this.transformComponent(component, resolved)),
129
134
  };
130
135
  }
131
136
 
@@ -133,18 +138,50 @@ class ModalSubmitInteraction extends BaseInteraction {
133
138
  return {
134
139
  type: rawComponent.type,
135
140
  id: rawComponent.id,
136
- component: this.transformComponent(rawComponent.component),
141
+ component: this.transformComponent(rawComponent.component, resolved),
137
142
  };
138
143
  }
139
144
 
140
145
  const data = {
141
146
  type: rawComponent.type,
142
- customId: rawComponent.custom_id,
143
147
  id: rawComponent.id,
144
148
  };
145
149
 
150
+ // Text display components do not have custom ids.
151
+ if (rawComponent.custom_id) data.customId = rawComponent.custom_id;
152
+
146
153
  if (rawComponent.value) data.value = rawComponent.value;
147
- if (rawComponent.values) data.values = rawComponent.values;
154
+
155
+ if (rawComponent.values) {
156
+ data.values = rawComponent.values;
157
+ if (resolved) {
158
+ const resolveCollection = (resolvedData, resolver) => {
159
+ const collection = new Collection();
160
+ for (const value of data.values) {
161
+ if (resolvedData?.[value]) {
162
+ collection.set(value, resolver(resolvedData[value]));
163
+ }
164
+ }
165
+
166
+ return collection.size ? collection : null;
167
+ };
168
+
169
+ const users = resolveCollection(resolved.users, user => this.client.users._add(user));
170
+ if (users) data.users = users;
171
+
172
+ const channels = resolveCollection(
173
+ resolved.channels,
174
+ channel => this.client.channels._add(channel, this.guild) ?? channel,
175
+ );
176
+ if (channels) data.channels = channels;
177
+
178
+ const members = resolveCollection(resolved.members, member => this.guild?.members._add(member) ?? member);
179
+ if (members) data.members = members;
180
+
181
+ const roles = resolveCollection(resolved.roles, role => this.guild?.roles._add(role) ?? role);
182
+ if (roles) data.roles = roles;
183
+ }
184
+ }
148
185
 
149
186
  return data;
150
187
  }
@@ -19,11 +19,12 @@ const { ComponentType } = require('discord-api-types/v10');
19
19
  * @typedef {Object} ModalComponentData
20
20
  * @property {string} title The title of the modal
21
21
  * @property {string} customId The custom id of the modal
22
- * @property {LabelData[]} components The components within this modal
22
+ * @property {Array<TextDisplayComponentData|LabelData>} components The components within this modal
23
23
  */
24
24
 
25
25
  /**
26
- * @typedef {StringSelectMenuComponentData|TextInputComponentData} ComponentInLabelData
26
+ * @typedef {StringSelectMenuComponentData|TextInputComponentData|UserSelectMenuComponentData|
27
+ * RoleSelectMenuComponentData|MentionableSelectMenuComponentData|ChannelSelectMenuComponentData} ComponentInLabelData
27
28
  */
28
29
 
29
30
  /**
@@ -44,16 +45,41 @@ const { ComponentType } = require('discord-api-types/v10');
44
45
  */
45
46
 
46
47
  /**
47
- * @typedef {BaseComponentData} StringSelectMenuComponentData
48
+ * @typedef {BaseComponentData} BaseSelectMenuComponentData
48
49
  * @property {string} customId The custom id of the select menu
49
50
  * @property {boolean} [disabled] Whether the select menu is disabled or not
50
51
  * @property {number} [maxValues] The maximum amount of options that can be selected
51
52
  * @property {number} [minValues] The minimum amount of options that can be selected
52
- * @property {SelectMenuComponentOptionData[]} [options] The options in this select menu
53
53
  * @property {string} [placeholder] The placeholder of the select menu
54
54
  * @property {boolean} [required] Whether this component is required in modals
55
55
  */
56
56
 
57
+ /**
58
+ * @typedef {BaseSelectMenuComponentData} StringSelectMenuComponentData
59
+ * @property {SelectMenuComponentOptionData[]} [options] The options in this select menu
60
+ */
61
+
62
+ /**
63
+ * @typedef {BaseSelectMenuComponentData} UserSelectMenuComponentData
64
+ * @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
65
+ */
66
+
67
+ /**
68
+ * @typedef {BaseSelectMenuComponentData} RoleSelectMenuComponentData
69
+ * @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
70
+ */
71
+
72
+ /**
73
+ * @typedef {BaseSelectMenuComponentData} MentionableSelectMenuComponentData
74
+ * @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
75
+ */
76
+
77
+ /**
78
+ * @typedef {BaseSelectMenuComponentData} ChannelSelectMenuComponentData
79
+ * @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
80
+ * @property {ChannelType[]} [channelTypes] The types of channels that can be selected
81
+ */
82
+
57
83
  /**
58
84
  * @typedef {Object} SelectMenuComponentOptionData
59
85
  * @property {string} label The label of the option
@@ -272,7 +272,13 @@ export interface ActionRowData<ComponentType extends ActionRowComponentData | JS
272
272
  components: readonly ComponentType[];
273
273
  }
274
274
 
275
- export type ComponentInLabelData = StringSelectMenuComponentData | TextInputComponentData;
275
+ export type ComponentInLabelData =
276
+ | ChannelSelectMenuComponentData
277
+ | MentionableSelectMenuComponentData
278
+ | RoleSelectMenuComponentData
279
+ | StringSelectMenuComponentData
280
+ | TextInputComponentData
281
+ | UserSelectMenuComponentData;
276
282
  export interface LabelData extends BaseComponentData {
277
283
  component: ComponentInLabelData;
278
284
  description?: string;
@@ -2540,48 +2546,114 @@ export interface MessageReactionEventDetails {
2540
2546
  }
2541
2547
 
2542
2548
  export interface ModalComponentData {
2543
- components: readonly LabelData[];
2549
+ components: readonly (LabelData | TextDisplayComponentData)[];
2544
2550
  customId: string;
2545
2551
  title: string;
2546
2552
  }
2547
2553
 
2548
2554
  export interface BaseModalData<Type extends ComponentType> {
2549
- customId: string;
2550
2555
  id: number;
2551
2556
  type: Type;
2552
2557
  }
2553
2558
 
2554
2559
  export interface TextInputModalData extends BaseModalData<ComponentType.TextInput> {
2560
+ customId: string;
2555
2561
  value: string;
2556
2562
  }
2557
2563
 
2558
- export interface StringSelectModalData extends BaseModalData<ComponentType.StringSelect> {
2564
+ export interface SelectMenuModalData<Cached extends CacheType = CacheType>
2565
+ extends BaseModalData<
2566
+ | ComponentType.ChannelSelect
2567
+ | ComponentType.MentionableSelect
2568
+ | ComponentType.RoleSelect
2569
+ | ComponentType.StringSelect
2570
+ | ComponentType.UserSelect
2571
+ > {
2572
+ channels?: ReadonlyCollection<
2573
+ Snowflake,
2574
+ CacheTypeReducer<Cached, GuildBasedChannel, APIInteractionDataResolvedChannel>
2575
+ >;
2576
+ customId: string;
2577
+ members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
2578
+ roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
2579
+ users?: ReadonlyCollection<Snowflake, User>;
2559
2580
  values: readonly string[];
2560
2581
  }
2561
2582
 
2562
- export type ModalData = StringSelectModalData | TextInputModalData;
2583
+ export type ModalData = SelectMenuModalData | TextInputModalData;
2563
2584
 
2564
- export interface LabelModalData {
2585
+ export interface LabelModalData extends BaseModalData<ComponentType.Label> {
2565
2586
  component: readonly ModalData[];
2566
- id: number;
2567
- type: ComponentType.Label;
2568
2587
  }
2569
- export interface ActionRowModalData {
2588
+ export interface ActionRowModalData extends BaseModalData<ComponentType.ActionRow> {
2570
2589
  components: readonly TextInputModalData[];
2571
- type: ComponentType.ActionRow;
2572
2590
  }
2573
2591
 
2574
- export class ModalSubmitFields {
2575
- private constructor(components: readonly (ActionRowModalData | LabelModalData)[]);
2576
- public components: (ActionRowModalData | LabelModalData)[];
2577
- public fields: Collection<string, StringSelectModalData | TextInputModalData>;
2578
- public getField<Type extends ComponentType>(
2592
+ export interface TextDisplayModalData extends BaseModalData<ComponentType.TextDisplay> {}
2593
+
2594
+ export interface ModalSelectedMentionables<Cached extends CacheType = CacheType> {
2595
+ members: NonNullable<SelectMenuModalData<Cached>['members']>;
2596
+ roles: NonNullable<SelectMenuModalData<Cached>['roles']>;
2597
+ users: NonNullable<SelectMenuModalData<Cached>['users']>;
2598
+ }
2599
+ export class ModalComponentResolver<Cached extends CacheType = CacheType> {
2600
+ private constructor(client: Client<true>, components: readonly ModalData[], resolved: BaseInteractionResolvedData);
2601
+ public readonly client: Client<true>;
2602
+ public readonly data: readonly (ActionRowModalData | LabelModalData | TextDisplayModalData)[];
2603
+ public readonly resolved: Readonly<BaseInteractionResolvedData<Cached>> | null;
2604
+ public readonly hoistedComponents: ReadonlyCollection<string, ModalData>;
2605
+ public getComponent(customId: string): ModalData;
2606
+ private _getTypedComponent(
2579
2607
  customId: string,
2580
- type: Type,
2581
- ): { type: Type } & (StringSelectModalData | TextInputModalData);
2582
- public getField(customId: string, type?: ComponentType): StringSelectModalData | TextInputModalData;
2583
- public getTextInputValue(customId: string): string;
2608
+ allowedTypes: readonly ComponentType[],
2609
+ properties: string,
2610
+ required: boolean,
2611
+ ): ModalData;
2612
+ public getTextInputValue(customId: string, required: true): string;
2613
+ public getTextInputValue(customId: string, required?: boolean): string | null;
2584
2614
  public getStringSelectValues(customId: string): readonly string[];
2615
+ public getSelectedUsers(customId: string, required: true): ReadonlyCollection<Snowflake, User>;
2616
+ public getSelectedUsers(customId: string, required?: boolean): ReadonlyCollection<Snowflake, User> | null;
2617
+ public getSelectedMembers(customId: string): NonNullable<SelectMenuModalData<Cached>['members']> | null;
2618
+ public getSelectedChannels<const Type extends ChannelType = ChannelType>(
2619
+ customId: string,
2620
+ required: true,
2621
+ channelTypes?: readonly Type[],
2622
+ ): ReadonlyCollection<
2623
+ Snowflake,
2624
+ Extract<
2625
+ NonNullable<CommandInteractionOption<Cached>['channel']>,
2626
+ {
2627
+ type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
2628
+ ? ChannelType.AnnouncementThread | ChannelType.PublicThread
2629
+ : Type;
2630
+ }
2631
+ >
2632
+ >;
2633
+ public getSelectedChannels<const Type extends ChannelType = ChannelType>(
2634
+ customId: string,
2635
+ required?: boolean,
2636
+ channelTypes?: readonly Type[],
2637
+ ): ReadonlyCollection<
2638
+ Snowflake,
2639
+ Extract<
2640
+ NonNullable<CommandInteractionOption<Cached>['channel']>,
2641
+ {
2642
+ type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
2643
+ ? ChannelType.AnnouncementThread | ChannelType.PublicThread
2644
+ : Type;
2645
+ }
2646
+ >
2647
+ > | null;
2648
+
2649
+ public getSelectedRoles(customId: string, required: true): NonNullable<SelectMenuModalData<Cached>['roles']>;
2650
+ public getSelectedRoles(
2651
+ customId: string,
2652
+ required?: boolean,
2653
+ ): NonNullable<SelectMenuModalData<Cached>['roles']> | null;
2654
+
2655
+ public getSelectedMentionables(customId: string, required: true): ModalSelectedMentionables<Cached>;
2656
+ public getSelectedMentionables(customId: string, required?: boolean): ModalSelectedMentionables<Cached> | null;
2585
2657
  }
2586
2658
 
2587
2659
  export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = CacheType>
@@ -2604,8 +2676,7 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
2604
2676
  private constructor(client: Client<true>, data: APIModalSubmitInteraction);
2605
2677
  public type: InteractionType.ModalSubmit;
2606
2678
  public readonly customId: string;
2607
- public readonly components: (ActionRowModalData | LabelModalData)[];
2608
- public readonly fields: ModalSubmitFields;
2679
+ public readonly components: ModalComponentResolver<Cached>;
2609
2680
  public deferred: boolean;
2610
2681
  public ephemeral: boolean | null;
2611
2682
  public message: Message<BooleanCache<Cached>> | null;
@@ -4021,8 +4092,10 @@ export enum DiscordjsErrorCodes {
4021
4092
  CommandInteractionOptionNoSubcommandGroup = 'CommandInteractionOptionNoSubcommandGroup',
4022
4093
  AutocompleteInteractionOptionNoFocusedOption = 'AutocompleteInteractionOptionNoFocusedOption',
4023
4094
 
4024
- ModalSubmitInteractionFieldNotFound = 'ModalSubmitInteractionFieldNotFound',
4025
- ModalSubmitInteractionFieldType = 'ModalSubmitInteractionFieldType',
4095
+ ModalSubmitInteractionComponentNotFound = 'ModalSubmitInteractionComponentNotFound',
4096
+ ModalSubmitInteractionComponentType = 'ModalSubmitInteractionComponentType',
4097
+ ModalSubmitInteractionComponentEmpty = 'ModalSubmitInteractionComponentEmpty',
4098
+ ModalSubmitInteractionComponentInvalidChannelType = 'ModalSubmitInteractionComponentInvalidChannelType',
4026
4099
 
4027
4100
  InvalidMissingScopes = 'InvalidMissingScopes',
4028
4101
  InvalidScopesWithPermissions = 'InvalidScopesWithPermissions',
@@ -4413,6 +4486,7 @@ export class GuildMemberManager extends CachedManager<Snowflake, GuildMember, Us
4413
4486
  options?: BanOptions,
4414
4487
  ): Promise<BulkBanResult>;
4415
4488
  public edit(user: UserResolvable, options: GuildMemberEditOptions): Promise<GuildMember>;
4489
+ public editMe(options: GuildMemberEditMeOptions): Promise<GuildMember>;
4416
4490
  public fetch(
4417
4491
  options: FetchMemberOptions | UserResolvable | (FetchMembersOptions & { user: UserResolvable }),
4418
4492
  ): Promise<GuildMember>;
@@ -5548,15 +5622,19 @@ export interface CommandInteractionOption<Cached extends CacheType = CacheType>
5548
5622
  value?: boolean | number | string;
5549
5623
  }
5550
5624
 
5551
- export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType> {
5552
- attachments?: ReadonlyCollection<Snowflake, Attachment>;
5625
+ export interface BaseInteractionResolvedData<Cached extends CacheType = CacheType> {
5553
5626
  channels?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
5554
5627
  members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
5555
- messages?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
5556
5628
  roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
5557
5629
  users?: ReadonlyCollection<Snowflake, User>;
5558
5630
  }
5559
5631
 
5632
+ export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType>
5633
+ extends BaseInteractionResolvedData<Cached> {
5634
+ attachments?: ReadonlyCollection<Snowflake, Attachment>;
5635
+ messages?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
5636
+ }
5637
+
5560
5638
  export interface AutocompleteFocusedOption {
5561
5639
  focused: true;
5562
5640
  name: string;
@@ -6216,6 +6294,14 @@ export interface GuildMemberEditOptions {
6216
6294
  roles?: ReadonlyCollection<Snowflake, Role> | readonly RoleResolvable[];
6217
6295
  }
6218
6296
 
6297
+ export interface GuildMemberEditMeOptions {
6298
+ avatar?: Base64Resolvable | BufferResolvable | null;
6299
+ banner?: Base64Resolvable | BufferResolvable | null;
6300
+ bio?: string | null;
6301
+ nick?: string | null;
6302
+ reason?: string;
6303
+ }
6304
+
6219
6305
  export type GuildResolvable =
6220
6306
  | Guild
6221
6307
  | GuildEmoji
@@ -6691,11 +6777,11 @@ export interface BaseSelectMenuComponentData extends BaseComponentData {
6691
6777
  maxValues?: number;
6692
6778
  minValues?: number;
6693
6779
  placeholder?: string;
6780
+ required?: boolean;
6694
6781
  }
6695
6782
 
6696
6783
  export interface StringSelectMenuComponentData extends BaseSelectMenuComponentData {
6697
6784
  options: readonly SelectMenuComponentOptionData[];
6698
- required?: boolean;
6699
6785
  type: ComponentType.StringSelect;
6700
6786
  }
6701
6787
 
@@ -272,7 +272,13 @@ export interface ActionRowData<ComponentType extends ActionRowComponentData | JS
272
272
  components: readonly ComponentType[];
273
273
  }
274
274
 
275
- export type ComponentInLabelData = StringSelectMenuComponentData | TextInputComponentData;
275
+ export type ComponentInLabelData =
276
+ | ChannelSelectMenuComponentData
277
+ | MentionableSelectMenuComponentData
278
+ | RoleSelectMenuComponentData
279
+ | StringSelectMenuComponentData
280
+ | TextInputComponentData
281
+ | UserSelectMenuComponentData;
276
282
  export interface LabelData extends BaseComponentData {
277
283
  component: ComponentInLabelData;
278
284
  description?: string;
@@ -2540,48 +2546,114 @@ export interface MessageReactionEventDetails {
2540
2546
  }
2541
2547
 
2542
2548
  export interface ModalComponentData {
2543
- components: readonly LabelData[];
2549
+ components: readonly (LabelData | TextDisplayComponentData)[];
2544
2550
  customId: string;
2545
2551
  title: string;
2546
2552
  }
2547
2553
 
2548
2554
  export interface BaseModalData<Type extends ComponentType> {
2549
- customId: string;
2550
2555
  id: number;
2551
2556
  type: Type;
2552
2557
  }
2553
2558
 
2554
2559
  export interface TextInputModalData extends BaseModalData<ComponentType.TextInput> {
2560
+ customId: string;
2555
2561
  value: string;
2556
2562
  }
2557
2563
 
2558
- export interface StringSelectModalData extends BaseModalData<ComponentType.StringSelect> {
2564
+ export interface SelectMenuModalData<Cached extends CacheType = CacheType>
2565
+ extends BaseModalData<
2566
+ | ComponentType.ChannelSelect
2567
+ | ComponentType.MentionableSelect
2568
+ | ComponentType.RoleSelect
2569
+ | ComponentType.StringSelect
2570
+ | ComponentType.UserSelect
2571
+ > {
2572
+ channels?: ReadonlyCollection<
2573
+ Snowflake,
2574
+ CacheTypeReducer<Cached, GuildBasedChannel, APIInteractionDataResolvedChannel>
2575
+ >;
2576
+ customId: string;
2577
+ members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
2578
+ roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
2579
+ users?: ReadonlyCollection<Snowflake, User>;
2559
2580
  values: readonly string[];
2560
2581
  }
2561
2582
 
2562
- export type ModalData = StringSelectModalData | TextInputModalData;
2583
+ export type ModalData = SelectMenuModalData | TextInputModalData;
2563
2584
 
2564
- export interface LabelModalData {
2585
+ export interface LabelModalData extends BaseModalData<ComponentType.Label> {
2565
2586
  component: readonly ModalData[];
2566
- id: number;
2567
- type: ComponentType.Label;
2568
2587
  }
2569
- export interface ActionRowModalData {
2588
+ export interface ActionRowModalData extends BaseModalData<ComponentType.ActionRow> {
2570
2589
  components: readonly TextInputModalData[];
2571
- type: ComponentType.ActionRow;
2572
2590
  }
2573
2591
 
2574
- export class ModalSubmitFields {
2575
- private constructor(components: readonly (ActionRowModalData | LabelModalData)[]);
2576
- public components: (ActionRowModalData | LabelModalData)[];
2577
- public fields: Collection<string, StringSelectModalData | TextInputModalData>;
2578
- public getField<Type extends ComponentType>(
2592
+ export interface TextDisplayModalData extends BaseModalData<ComponentType.TextDisplay> {}
2593
+
2594
+ export interface ModalSelectedMentionables<Cached extends CacheType = CacheType> {
2595
+ members: NonNullable<SelectMenuModalData<Cached>['members']>;
2596
+ roles: NonNullable<SelectMenuModalData<Cached>['roles']>;
2597
+ users: NonNullable<SelectMenuModalData<Cached>['users']>;
2598
+ }
2599
+ export class ModalComponentResolver<Cached extends CacheType = CacheType> {
2600
+ private constructor(client: Client<true>, components: readonly ModalData[], resolved: BaseInteractionResolvedData);
2601
+ public readonly client: Client<true>;
2602
+ public readonly data: readonly (ActionRowModalData | LabelModalData | TextDisplayModalData)[];
2603
+ public readonly resolved: Readonly<BaseInteractionResolvedData<Cached>> | null;
2604
+ public readonly hoistedComponents: ReadonlyCollection<string, ModalData>;
2605
+ public getComponent(customId: string): ModalData;
2606
+ private _getTypedComponent(
2579
2607
  customId: string,
2580
- type: Type,
2581
- ): { type: Type } & (StringSelectModalData | TextInputModalData);
2582
- public getField(customId: string, type?: ComponentType): StringSelectModalData | TextInputModalData;
2583
- public getTextInputValue(customId: string): string;
2608
+ allowedTypes: readonly ComponentType[],
2609
+ properties: string,
2610
+ required: boolean,
2611
+ ): ModalData;
2612
+ public getTextInputValue(customId: string, required: true): string;
2613
+ public getTextInputValue(customId: string, required?: boolean): string | null;
2584
2614
  public getStringSelectValues(customId: string): readonly string[];
2615
+ public getSelectedUsers(customId: string, required: true): ReadonlyCollection<Snowflake, User>;
2616
+ public getSelectedUsers(customId: string, required?: boolean): ReadonlyCollection<Snowflake, User> | null;
2617
+ public getSelectedMembers(customId: string): NonNullable<SelectMenuModalData<Cached>['members']> | null;
2618
+ public getSelectedChannels<const Type extends ChannelType = ChannelType>(
2619
+ customId: string,
2620
+ required: true,
2621
+ channelTypes?: readonly Type[],
2622
+ ): ReadonlyCollection<
2623
+ Snowflake,
2624
+ Extract<
2625
+ NonNullable<CommandInteractionOption<Cached>['channel']>,
2626
+ {
2627
+ type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
2628
+ ? ChannelType.AnnouncementThread | ChannelType.PublicThread
2629
+ : Type;
2630
+ }
2631
+ >
2632
+ >;
2633
+ public getSelectedChannels<const Type extends ChannelType = ChannelType>(
2634
+ customId: string,
2635
+ required?: boolean,
2636
+ channelTypes?: readonly Type[],
2637
+ ): ReadonlyCollection<
2638
+ Snowflake,
2639
+ Extract<
2640
+ NonNullable<CommandInteractionOption<Cached>['channel']>,
2641
+ {
2642
+ type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
2643
+ ? ChannelType.AnnouncementThread | ChannelType.PublicThread
2644
+ : Type;
2645
+ }
2646
+ >
2647
+ > | null;
2648
+
2649
+ public getSelectedRoles(customId: string, required: true): NonNullable<SelectMenuModalData<Cached>['roles']>;
2650
+ public getSelectedRoles(
2651
+ customId: string,
2652
+ required?: boolean,
2653
+ ): NonNullable<SelectMenuModalData<Cached>['roles']> | null;
2654
+
2655
+ public getSelectedMentionables(customId: string, required: true): ModalSelectedMentionables<Cached>;
2656
+ public getSelectedMentionables(customId: string, required?: boolean): ModalSelectedMentionables<Cached> | null;
2585
2657
  }
2586
2658
 
2587
2659
  export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = CacheType>
@@ -2604,8 +2676,7 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
2604
2676
  private constructor(client: Client<true>, data: APIModalSubmitInteraction);
2605
2677
  public type: InteractionType.ModalSubmit;
2606
2678
  public readonly customId: string;
2607
- public readonly components: (ActionRowModalData | LabelModalData)[];
2608
- public readonly fields: ModalSubmitFields;
2679
+ public readonly components: ModalComponentResolver<Cached>;
2609
2680
  public deferred: boolean;
2610
2681
  public ephemeral: boolean | null;
2611
2682
  public message: Message<BooleanCache<Cached>> | null;
@@ -4021,8 +4092,10 @@ export enum DiscordjsErrorCodes {
4021
4092
  CommandInteractionOptionNoSubcommandGroup = 'CommandInteractionOptionNoSubcommandGroup',
4022
4093
  AutocompleteInteractionOptionNoFocusedOption = 'AutocompleteInteractionOptionNoFocusedOption',
4023
4094
 
4024
- ModalSubmitInteractionFieldNotFound = 'ModalSubmitInteractionFieldNotFound',
4025
- ModalSubmitInteractionFieldType = 'ModalSubmitInteractionFieldType',
4095
+ ModalSubmitInteractionComponentNotFound = 'ModalSubmitInteractionComponentNotFound',
4096
+ ModalSubmitInteractionComponentType = 'ModalSubmitInteractionComponentType',
4097
+ ModalSubmitInteractionComponentEmpty = 'ModalSubmitInteractionComponentEmpty',
4098
+ ModalSubmitInteractionComponentInvalidChannelType = 'ModalSubmitInteractionComponentInvalidChannelType',
4026
4099
 
4027
4100
  InvalidMissingScopes = 'InvalidMissingScopes',
4028
4101
  InvalidScopesWithPermissions = 'InvalidScopesWithPermissions',
@@ -4413,6 +4486,7 @@ export class GuildMemberManager extends CachedManager<Snowflake, GuildMember, Us
4413
4486
  options?: BanOptions,
4414
4487
  ): Promise<BulkBanResult>;
4415
4488
  public edit(user: UserResolvable, options: GuildMemberEditOptions): Promise<GuildMember>;
4489
+ public editMe(options: GuildMemberEditMeOptions): Promise<GuildMember>;
4416
4490
  public fetch(
4417
4491
  options: FetchMemberOptions | UserResolvable | (FetchMembersOptions & { user: UserResolvable }),
4418
4492
  ): Promise<GuildMember>;
@@ -5548,15 +5622,19 @@ export interface CommandInteractionOption<Cached extends CacheType = CacheType>
5548
5622
  value?: boolean | number | string;
5549
5623
  }
5550
5624
 
5551
- export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType> {
5552
- attachments?: ReadonlyCollection<Snowflake, Attachment>;
5625
+ export interface BaseInteractionResolvedData<Cached extends CacheType = CacheType> {
5553
5626
  channels?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
5554
5627
  members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
5555
- messages?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
5556
5628
  roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
5557
5629
  users?: ReadonlyCollection<Snowflake, User>;
5558
5630
  }
5559
5631
 
5632
+ export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType>
5633
+ extends BaseInteractionResolvedData<Cached> {
5634
+ attachments?: ReadonlyCollection<Snowflake, Attachment>;
5635
+ messages?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
5636
+ }
5637
+
5560
5638
  export interface AutocompleteFocusedOption {
5561
5639
  focused: true;
5562
5640
  name: string;
@@ -6216,6 +6294,14 @@ export interface GuildMemberEditOptions {
6216
6294
  roles?: ReadonlyCollection<Snowflake, Role> | readonly RoleResolvable[];
6217
6295
  }
6218
6296
 
6297
+ export interface GuildMemberEditMeOptions {
6298
+ avatar?: Base64Resolvable | BufferResolvable | null;
6299
+ banner?: Base64Resolvable | BufferResolvable | null;
6300
+ bio?: string | null;
6301
+ nick?: string | null;
6302
+ reason?: string;
6303
+ }
6304
+
6219
6305
  export type GuildResolvable =
6220
6306
  | Guild
6221
6307
  | GuildEmoji
@@ -6691,11 +6777,11 @@ export interface BaseSelectMenuComponentData extends BaseComponentData {
6691
6777
  maxValues?: number;
6692
6778
  minValues?: number;
6693
6779
  placeholder?: string;
6780
+ required?: boolean;
6694
6781
  }
6695
6782
 
6696
6783
  export interface StringSelectMenuComponentData extends BaseSelectMenuComponentData {
6697
6784
  options: readonly SelectMenuComponentOptionData[];
6698
- required?: boolean;
6699
6785
  type: ComponentType.StringSelect;
6700
6786
  }
6701
6787
 
@@ -1,78 +0,0 @@
1
- 'use strict';
2
-
3
- const { Collection } = require('@discordjs/collection');
4
- const { ComponentType } = require('discord-api-types/v10');
5
- const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
6
-
7
- /**
8
- * Represents the serialized fields from a modal submit interaction
9
- */
10
- class ModalSubmitFields {
11
- constructor(components) {
12
- /**
13
- * The components within the modal
14
- *
15
- * @type {Array<ActionRowModalData | LabelModalData>}
16
- */
17
- this.components = components;
18
-
19
- /**
20
- * The extracted fields from the modal
21
- *
22
- * @type {Collection<string, ModalData>}
23
- */
24
- this.fields = components.reduce((accumulator, next) => {
25
- // NOTE: for legacy support of action rows in modals, which has `components`
26
- if ('components' in next) {
27
- for (const component of next.components) accumulator.set(component.customId, component);
28
- }
29
-
30
- // For label component
31
- if ('component' in next) {
32
- accumulator.set(next.component.customId, next.component);
33
- }
34
-
35
- return accumulator;
36
- }, new Collection());
37
- }
38
-
39
- /**
40
- * Gets a field given a custom id from a component
41
- *
42
- * @param {string} customId The custom id of the component
43
- * @param {ComponentType} [type] The type of the component
44
- * @returns {ModalData}
45
- */
46
- getField(customId, type) {
47
- const field = this.fields.get(customId);
48
- if (!field) throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionFieldNotFound, customId);
49
-
50
- if (type !== undefined && type !== field.type) {
51
- throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionFieldType, customId, field.type, type);
52
- }
53
-
54
- return field;
55
- }
56
-
57
- /**
58
- * Gets the value of a text input component given a custom id
59
- *
60
- * @param {string} customId The custom id of the text input component
61
- * @returns {string}
62
- */
63
- getTextInputValue(customId) {
64
- return this.getField(customId, ComponentType.TextInput).value;
65
- }
66
-
67
- /**
68
- * Gets the values of a string select component given a custom id
69
- *
70
- * @param {string} customId The custom id of the string select component
71
- * @returns {string[]}
72
- */
73
- getStringSelectValues(customId) {
74
- return this.getField(customId, ComponentType.StringSelect).values;
75
- }
76
- }
77
-
78
- exports.ModalSubmitFields = ModalSubmitFields;