feat: file types for discord.js (#11580)

* feat: file types

* fix(ApplicationCommandNonOptions): make it actually work
This commit is contained in:
Jiralite
2026-07-19 23:48:19 +01:00
parent 75a5eaadc1
commit cffb0b588f
5 changed files with 77 additions and 2 deletions
@@ -264,6 +264,9 @@ class ApplicationCommand extends Base {
* @property {ApplicationCommandOptionData[]} [options] Additional options if this option is a subcommand (group)
* @property {ChannelType[]} [channelTypes] When the option type is channel,
* the allowed types of channels that can be selected
* @property {FileUploadType[]} [fileTypes] When the option type is attachment,
* the allowed types of files that can be uploaded. When only using extensions, include `.jpg`
* for images and both `.mp4` and `.mov` for videos for mobile compatibility
* @property {number} [minValue] The minimum value for an {@link ApplicationCommandOptionType.Integer} or
* {@link ApplicationCommandOptionType.Number} option
* @property {number} [maxValue] The maximum value for an {@link ApplicationCommandOptionType.Integer} or
@@ -495,6 +498,7 @@ class ApplicationCommand extends Base {
option.choices?.length !== existing.choices?.length ||
option.options?.length !== existing.options?.length ||
(option.channelTypes ?? option.channel_types)?.length !== existing.channelTypes?.length ||
(option.fileTypes ?? option.file_types)?.length !== existing.fileTypes?.length ||
(option.minValue ?? option.min_value) !== existing.minValue ||
(option.maxValue ?? option.max_value) !== existing.maxValue ||
(option.minLength ?? option.min_length) !== existing.minLength ||
@@ -539,6 +543,13 @@ class ApplicationCommand extends Base {
}
}
if (existing.fileTypes) {
const newTypes = option.fileTypes ?? option.file_types;
for (const type of existing.fileTypes) {
if (!newTypes.includes(type)) return false;
}
}
if (existing.options) {
return this.optionsEqual(existing.options, option.options, enforceOptionOrder);
}
@@ -563,6 +574,9 @@ class ApplicationCommand extends Base {
* @property {ApplicationCommandOption[]} [options] Additional options if this option is a subcommand (group)
* @property {ApplicationCommandOptionAllowedChannelTypes[]} [channelTypes] When the option type is channel,
* the allowed types of channels that can be selected
* @property {FileUploadType[]} [fileTypes] When the option type is attachment,
* the allowed types of files that can be uploaded. When only using extensions, include `.jpg`
* for images and both `.mp4` and `.mov` for videos for mobile compatibility
* @property {number} [minValue] The minimum value for an {@link ApplicationCommandOptionType.Integer} or
* {@link ApplicationCommandOptionType.Number} option
* @property {number} [maxValue] The maximum value for an {@link ApplicationCommandOptionType.Integer} or
@@ -591,6 +605,7 @@ class ApplicationCommand extends Base {
*/
static transformOption(option, received) {
const channelTypesKey = received ? 'channelTypes' : 'channel_types';
const fileTypesKey = received ? 'fileTypes' : 'file_types';
const minValueKey = received ? 'minValue' : 'min_value';
const maxValueKey = received ? 'maxValue' : 'max_value';
const minLengthKey = received ? 'minLength' : 'min_length';
@@ -622,6 +637,7 @@ class ApplicationCommand extends Base {
})),
options: option.options?.map(opt => this.transformOption(opt, received)),
[channelTypesKey]: option.channelTypes ?? option.channel_types,
[fileTypesKey]: option.fileTypes ?? option.file_types,
[minValueKey]: option.minValue ?? option.min_value,
[maxValueKey]: option.maxValue ?? option.max_value,
[minLengthKey]: option.minLength ?? option.min_length,
+5
View File
@@ -385,6 +385,11 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/EntryPointCommandHandlerType}
*/
/**
* @external FileUploadType
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10#FileUploadType}
*/
/**
* @external ForumLayoutType
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ForumLayoutType}
@@ -50,6 +50,8 @@ const { ComponentType } = require('discord-api-types/v10');
* @property {string} customId The custom id of the file upload
* @property {number} [minValues] The minimum number of files that must be uploaded (0-10)
* @property {number} [maxValues] The maximum number of files that can be uploaded (1-10)
* @property {FileUploadType[]} [fileTypes] The allowed types of files that can be uploaded (maximum of 10).
* When only using extensions, include `.jpg` for images and both `.mp4` and `.mov` for videos for mobile compatibility
* @property {boolean} [required] Whether this component is required in modals
*/
+12 -2
View File
@@ -82,6 +82,7 @@ import {
ButtonStyle,
ChannelType,
ComponentType,
FileUploadType,
GatewayDispatchEvents,
GatewayVoiceServerUpdateDispatchData,
GatewayVoiceStateUpdateDispatchData,
@@ -5671,7 +5672,14 @@ export interface ApplicationCommandMentionableOption extends BaseApplicationComm
type: ApplicationCommandOptionType.Mentionable;
}
export interface ApplicationCommandAttachmentOptionData extends BaseApplicationCommandOptionsData {
fileTypes?: readonly FileUploadType[];
file_types?: readonly FileUploadType[];
type: ApplicationCommandOptionType.Attachment;
}
export interface ApplicationCommandAttachmentOption extends BaseApplicationCommandOptionsData {
fileTypes?: readonly FileUploadType[];
type: ApplicationCommandOptionType.Attachment;
}
@@ -5797,15 +5805,16 @@ export interface ApplicationCommandSubCommand extends Omit<BaseApplicationComman
}
export interface ApplicationCommandNonOptionsData extends BaseApplicationCommandOptionsData {
type: CommandOptionNonChoiceResolvableType;
type: Exclude<CommandOptionNonChoiceResolvableType, ApplicationCommandOptionType.Attachment>;
}
export interface ApplicationCommandNonOptions extends BaseApplicationCommandOptionsData {
type: Exclude<CommandOptionNonChoiceResolvableType, ApplicationCommandOptionType>;
type: Exclude<CommandOptionNonChoiceResolvableType, ApplicationCommandOptionType.Attachment>;
}
export type ApplicationCommandOptionData =
| ApplicationCommandSubGroupData
| ApplicationCommandAttachmentOptionData
| ApplicationCommandNonOptionsData
| ApplicationCommandChannelOptionData
| ApplicationCommandAutocompleteNumericOptionData
@@ -7545,6 +7554,7 @@ export interface TextInputComponentData extends BaseComponentData {
export interface FileUploadComponentData extends BaseComponentData {
customId: string;
fileTypes?: readonly FileUploadType[];
maxValues?: number;
minValues?: number;
required?: boolean;
@@ -41,6 +41,8 @@ import {
} from 'discord-api-types/v10';
import {
ApplicationCommand,
ApplicationCommandAttachmentOption,
ApplicationCommandAttachmentOptionData,
ApplicationCommandData,
ApplicationCommandManager,
ApplicationCommandOptionData,
@@ -62,6 +64,7 @@ import {
CommandOptionNonChoiceResolvableType,
ContextMenuCommandInteraction,
DMChannel,
FileUploadComponentData,
Guild,
GuildApplicationCommandManager,
GuildChannelManager,
@@ -1641,6 +1644,21 @@ declare const applicationCommandChannelOption: ApplicationCommandChannelOption;
applicationCommandChannelOption.channelTypes = [] as const;
}
declare const applicationCommandAttachmentOptionData: ApplicationCommandAttachmentOptionData;
declare const applicationCommandAttachmentOption: ApplicationCommandAttachmentOption;
{
applicationCommandAttachmentOptionData.fileTypes = ['image', '.pdf'] as const;
applicationCommandAttachmentOptionData.file_types = ['video', '.mov'] as const;
applicationCommandAttachmentOption.fileTypes = ['audio', '.flac'] as const;
expectNotAssignable<ApplicationCommandOptionData>({
description: 'Upload a file',
fileTypes: ['pdf'],
name: 'file',
type: ApplicationCommandOptionType.Attachment,
});
}
declare const applicationNonChoiceOptionData: ApplicationCommandOptionData & {
type: CommandOptionNonChoiceResolvableType;
};
@@ -2579,6 +2597,15 @@ chatInputInteraction.showModal({
],
type: ComponentType.ActionRow,
},
{
component: {
type: ComponentType.FileUpload,
custom_id: 'upload',
file_types: ['image', '.pdf'],
},
type: ComponentType.Label,
label: 'upload',
},
],
});
@@ -2632,6 +2659,15 @@ chatInputInteraction.showModal({
type: ComponentType.RoleSelect,
},
},
{
type: ComponentType.Label,
component: {
type: ComponentType.FileUpload,
customId: 'upload',
fileTypes: ['video', '.mp4', '.mov'],
},
label: 'upload',
},
],
});
@@ -2650,6 +2686,12 @@ ChannelSelectMenuBuilder.from(channelSelectMenuData);
declare const mentionableSelectMenuData: APIMentionableSelectComponent;
MentionableSelectMenuBuilder.from(mentionableSelectMenuData);
expectNotAssignable<FileUploadComponentData>({
customId: 'upload',
fileTypes: ['pdf'],
type: ComponentType.FileUpload,
});
declare const stringSelectMenuComp: StringSelectMenuComponent;
StringSelectMenuBuilder.from(stringSelectMenuComp);