Skip to content

Commit 104ad75

Browse files
imnaiyarJiralite
andauthored
feat: handle file upload component for v14 (#11179)
* feat: handle file upload component * chore: fix import * chore: typings * fix: `Snowflake` --------- Co-authored-by: Jiralite <[email protected]>
1 parent 0ff239a commit 104ad75

File tree

5 files changed

+60
-7
lines changed

5 files changed

+60
-7
lines changed

packages/discord.js/src/structures/CommandInteraction.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,14 @@ class CommandInteraction extends BaseInteraction {
8585
* @property {Collection<Snowflake, GuildMember|APIGuildMember>} [members] The resolved guild members
8686
* @property {Collection<Snowflake, Role|APIRole>} [roles] The resolved roles
8787
* @property {Collection<Snowflake, BaseChannel|APIChannel>} [channels] The resolved channels
88+
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
8889
*/
8990

9091
/**
9192
* Represents the resolved data of a received command interaction.
9293
*
9394
* @typedef {BaseInteractionResolvedData} CommandInteractionResolvedData
9495
* @property {Collection<Snowflake, Message|APIMessage>} [messages] The resolved messages
95-
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
9696
*/
9797

9898
/**

packages/discord.js/src/structures/ModalSubmitFields.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,17 @@ class ModalSubmitFields {
216216

217217
return null;
218218
}
219+
220+
/**
221+
* Gets file upload component
222+
*
223+
* @param {string} customId The custom id of the component
224+
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
225+
* @returns {?Collection<Snowflake, Attachment>} The uploaded files, or null if none were uploaded and not required
226+
*/
227+
getUploadedFiles(customId, required = false) {
228+
return this._getTypedComponent(customId, [ComponentType.FileUpload], ['attachments'], required).attachments ?? null;
229+
}
219230
}
220231

221232
module.exports = ModalSubmitFields;

packages/discord.js/src/structures/ModalSubmitInteraction.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@ const InteractionResponses = require('./interfaces/InteractionResponses');
99
const { transformResolved } = require('../util/Util');
1010

1111
const getMessage = lazy(() => require('./Message').Message);
12+
const getAttachment = lazy(() => require('./Attachment'));
1213

1314
/**
1415
* @typedef {Object} BaseModalData
1516
* @property {ComponentType} type The component type of the field
1617
* @property {number} id The id of the field
1718
*/
1819

20+
/**
21+
* @typedef {BaseModalData} FileUploadModalData
22+
* @property {string} customId The custom id of the file upload
23+
* @property {string[]} values The values of the file upload
24+
* @property {Collection<string, Attachment>} [attachments] The resolved attachments
25+
*/
26+
1927
/**
2028
* @typedef {BaseModalData} TextInputModalData
2129
* @property {string} customId The custom id of the field
@@ -37,7 +45,7 @@ const getMessage = lazy(() => require('./Message').Message);
3745
*/
3846

3947
/**
40-
* @typedef {SelectMenuModalData|TextInputModalData} ModalData
48+
* @typedef {SelectMenuModalData|TextInputModalData|FileUploadModalData} ModalData
4149
*/
4250

4351
/**
@@ -161,7 +169,7 @@ class ModalSubmitInteraction extends BaseInteraction {
161169

162170
/* eslint-disable max-depth */
163171
if (resolved) {
164-
const { members, users, channels, roles } = resolved;
172+
const { members, users, channels, roles, attachments } = resolved;
165173
const valueSet = new Set(rawComponent.values);
166174

167175
if (users) {
@@ -204,6 +212,15 @@ class ModalSubmitInteraction extends BaseInteraction {
204212
}
205213
}
206214
}
215+
216+
if (attachments) {
217+
data.attachments = new Collection();
218+
for (const [id, attachment] of Object.entries(attachments)) {
219+
if (valueSet.has(id)) {
220+
data.attachments.set(id, new (getAttachment())(attachment));
221+
}
222+
}
223+
}
207224
}
208225

209226
/* eslint-enable max-depth */

packages/discord.js/src/util/Components.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ const { ComponentType } = require('discord-api-types/v10');
2323

2424
/**
2525
* @typedef {StringSelectMenuComponentData|TextInputComponentData|UserSelectMenuComponentData|
26-
* RoleSelectMenuComponentData|MentionableSelectMenuComponentData|ChannelSelectMenuComponentData} ComponentInLabelData
26+
* RoleSelectMenuComponentData|MentionableSelectMenuComponentData|ChannelSelectMenuComponentData|
27+
* FileUploadComponentData} ComponentInLabelData
2728
*/
2829

2930
/**
@@ -43,6 +44,14 @@ const { ComponentType } = require('discord-api-types/v10');
4344
* @property {string} [url] The URL of the button
4445
*/
4546

47+
/**
48+
* @typedef {BaseComponentData} FileUploadComponentData
49+
* @property {string} customId The custom id of the file upload
50+
* @property {number} [minValues] The minimum number of files that can be uploaded (0-10)
51+
* @property {number} [maxValues] The maximum number of files that can be uploaded (1-10)
52+
* @property {boolean} [required] Whether this component is required in modals
53+
*/
54+
4655
/**
4756
* @typedef {BaseComponentData} BaseSelectMenuComponentData
4857
* @property {string} customId The custom id of the select menu

packages/discord.js/typings/index.d.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,8 @@ export type ComponentInLabelData =
367367
| UserSelectMenuComponentData
368368
| ChannelSelectMenuComponentData
369369
| RoleSelectMenuComponentData
370-
| MentionableSelectMenuComponentData;
370+
| MentionableSelectMenuComponentData
371+
| FileUploadComponentData;
371372

372373
export interface LabelComponentData extends BaseComponentData {
373374
type: ComponentType.Label;
@@ -2823,7 +2824,12 @@ export interface SelectMenuModalData<Cached extends CacheType = CacheType>
28232824
values: readonly string[];
28242825
}
28252826

2826-
export type ModalData = SelectMenuModalData | TextInputModalData;
2827+
export interface FileUploadModalData extends BaseModalData<ComponentType.FileUpload> {
2828+
customId: string;
2829+
files: readonly Attachment[];
2830+
}
2831+
2832+
export type ModalData = FileUploadModalData | SelectMenuModalData | TextInputModalData;
28272833

28282834
export interface LabelModalData extends BaseModalData<ComponentType.Label> {
28292835
component: readonly ModalData[];
@@ -2900,6 +2906,8 @@ export class ModalSubmitFields<Cached extends CacheType = CacheType> {
29002906

29012907
public getSelectedMentionables(customId: string, required: true): ModalSelectedMentionables<Cached>;
29022908
public getSelectedMentionables(customId: string, required?: boolean): ModalSelectedMentionables<Cached> | null;
2909+
public getUploadedFiles(customId: string, required: true): ReadonlyCollection<Snowflake, Attachment>;
2910+
public getUploadedFiles(customId: string, required?: boolean): ReadonlyCollection<Snowflake, Attachment> | null;
29032911
}
29042912

29052913
export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = CacheType>
@@ -6184,6 +6192,7 @@ export interface CommandInteractionOption<Cached extends CacheType = CacheType>
61846192
}
61856193

61866194
export interface BaseInteractionResolvedData<Cached extends CacheType = CacheType> {
6195+
attachments?: ReadonlyCollection<Snowflake, Attachment>;
61876196
channels?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
61886197
members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
61896198
roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
@@ -6192,7 +6201,6 @@ export interface BaseInteractionResolvedData<Cached extends CacheType = CacheTyp
61926201

61936202
export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType>
61946203
extends BaseInteractionResolvedData<Cached> {
6195-
attachments?: ReadonlyCollection<Snowflake, Attachment>;
61966204
messages?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
61976205
}
61986206

@@ -7430,6 +7438,14 @@ export interface TextInputComponentData extends BaseComponentData {
74307438
placeholder?: string;
74317439
}
74327440

7441+
export interface FileUploadComponentData extends BaseComponentData {
7442+
customId: string;
7443+
maxValues?: number;
7444+
minValues?: number;
7445+
required?: number;
7446+
type: ComponentType.FileUpload;
7447+
}
7448+
74337449
export type MessageTarget =
74347450
| Interaction
74357451
| InteractionWebhook

0 commit comments

Comments
 (0)