From 213acd799738b888d550cdf3f08906764f8288e0 Mon Sep 17 00:00:00 2001 From: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com> Date: Wed, 19 Jan 2022 08:11:10 -0500 Subject: [PATCH] feat: Enum resolvers & internal enum string removal (#7290) Co-authored-by: Almeida --- .../src/client/actions/ChannelUpdate.js | 3 +- packages/discord.js/src/index.js | 1 + .../src/managers/ApplicationCommandManager.js | 3 +- .../ApplicationCommandPermissionsManager.js | 23 +- .../src/managers/GuildChannelManager.js | 2 +- .../discord.js/src/managers/GuildManager.js | 21 +- .../managers/GuildScheduledEventManager.js | 12 +- .../src/managers/StageInstanceManager.js | 2 +- .../discord.js/src/managers/ThreadManager.js | 9 +- .../discord.js/src/managers/UserManager.js | 3 +- .../src/structures/AnonymousGuild.js | 9 +- .../src/structures/ApplicationCommand.js | 29 +- .../src/structures/AutocompleteInteraction.js | 26 +- .../src/structures/CategoryChannel.js | 2 +- packages/discord.js/src/structures/Channel.js | 19 +- .../src/structures/ClientPresence.js | 5 +- .../discord.js/src/structures/ClientUser.js | 2 +- .../src/structures/CommandInteraction.js | 3 +- .../CommandInteractionOptionResolver.js | 28 +- .../ContextMenuCommandInteraction.js | 8 +- .../discord.js/src/structures/DMChannel.js | 3 +- packages/discord.js/src/structures/Guild.js | 42 +-- .../src/structures/GuildAuditLogs.js | 6 +- .../discord.js/src/structures/GuildChannel.js | 4 +- .../src/structures/GuildScheduledEvent.js | 4 +- .../discord.js/src/structures/Interaction.js | 28 +- packages/discord.js/src/structures/Invite.js | 3 +- packages/discord.js/src/structures/Message.js | 18 +- .../structures/MessageComponentInteraction.js | 15 +- .../src/structures/MessageMentions.js | 5 +- .../discord.js/src/structures/NewsChannel.js | 2 +- .../src/structures/PermissionOverwrites.js | 8 +- .../discord.js/src/structures/Presence.js | 3 +- .../src/structures/StageInstance.js | 3 +- packages/discord.js/src/structures/Sticker.js | 5 +- .../discord.js/src/structures/TeamMember.js | 3 +- .../src/structures/ThreadChannel.js | 18 +- .../discord.js/src/structures/VoiceState.js | 5 +- packages/discord.js/src/structures/Webhook.js | 6 +- packages/discord.js/src/util/Constants.js | 128 +++----- packages/discord.js/src/util/EnumResolvers.js | 265 +++++++++++++++++ packages/discord.js/src/util/Util.js | 5 +- packages/discord.js/test/createGuild.js | 3 +- packages/discord.js/test/random.js | 3 +- packages/discord.js/typings/index.d.ts | 273 ++++++++---------- packages/discord.js/typings/index.test-d.ts | 175 ++++++----- 46 files changed, 696 insertions(+), 547 deletions(-) create mode 100644 packages/discord.js/src/util/EnumResolvers.js diff --git a/packages/discord.js/src/client/actions/ChannelUpdate.js b/packages/discord.js/src/client/actions/ChannelUpdate.js index dab52d153..88ee7f1bf 100644 --- a/packages/discord.js/src/client/actions/ChannelUpdate.js +++ b/packages/discord.js/src/client/actions/ChannelUpdate.js @@ -1,6 +1,5 @@ 'use strict'; -const { ChannelType } = require('discord-api-types/v9'); const Action = require('./Action'); const { Channel } = require('../../structures/Channel'); @@ -12,7 +11,7 @@ class ChannelUpdateAction extends Action { if (channel) { const old = channel._update(data); - if (ChannelType[channel.type] !== data.type) { + if (channel.type !== data.type) { const newChannel = Channel.create(this.client, data, channel.guild); for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message); channel = newChannel; diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index b06c7fa18..b23532ac5 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -17,6 +17,7 @@ exports.Collection = require('@discordjs/collection').Collection; exports.Constants = require('./util/Constants'); exports.DataResolver = require('./util/DataResolver'); exports.DiscordAPIError = require('./rest/DiscordAPIError'); +exports.EnumResolvers = require('./util/EnumResolvers'); exports.Formatters = require('./util/Formatters'); exports.HTTPError = require('./rest/HTTPError'); exports.Intents = require('./util/Intents'); diff --git a/packages/discord.js/src/managers/ApplicationCommandManager.js b/packages/discord.js/src/managers/ApplicationCommandManager.js index 4dbec0929..406c274ea 100644 --- a/packages/discord.js/src/managers/ApplicationCommandManager.js +++ b/packages/discord.js/src/managers/ApplicationCommandManager.js @@ -1,7 +1,6 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); -const { ApplicationCommandType } = require('discord-api-types/v9'); const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager'); const CachedManager = require('./CachedManager'); const { TypeError } = require('../errors'); @@ -207,7 +206,7 @@ class ApplicationCommandManager extends CachedManager { return { name: command.name, description: command.description, - type: typeof command.type === 'number' ? command.type : ApplicationCommandType[command.type], + type: command.type, options: command.options?.map(o => ApplicationCommand.transformOption(o)), default_permission: command.defaultPermission ?? command.default_permission, }; diff --git a/packages/discord.js/src/managers/ApplicationCommandPermissionsManager.js b/packages/discord.js/src/managers/ApplicationCommandPermissionsManager.js index bb46a558c..e0d36354b 100644 --- a/packages/discord.js/src/managers/ApplicationCommandPermissionsManager.js +++ b/packages/discord.js/src/managers/ApplicationCommandPermissionsManager.js @@ -1,7 +1,7 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); -const { ApplicationCommandPermissionType, RESTJSONErrorCodes } = require('discord-api-types/v9'); +const { RESTJSONErrorCodes } = require('discord-api-types/v9'); const BaseManager = require('./BaseManager'); const { Error, TypeError } = require('../errors'); @@ -96,7 +96,7 @@ class ApplicationCommandPermissionsManager extends BaseManager { const { guildId, commandId } = this._validateOptions(guild, command); if (commandId) { const data = await this.permissionsPath(guildId, commandId).get(); - return data.permissions.map(perm => this.constructor.transformPermissions(perm, true)); + return data.permissions.map(perm => this.constructor.transformPermissions(perm)); } const data = await this.permissionsPath(guildId).get(); @@ -104,7 +104,7 @@ class ApplicationCommandPermissionsManager extends BaseManager { (coll, perm) => coll.set( perm.id, - perm.permissions.map(p => this.constructor.transformPermissions(p, true)), + perm.permissions.map(p => this.constructor.transformPermissions(p)), ), new Collection(), ); @@ -137,7 +137,7 @@ class ApplicationCommandPermissionsManager extends BaseManager { * permissions: [ * { * id: '876543210987654321', - * type: 'USER', + * type: ApplicationCommandOptionType.User, * permission: false, * }, * ]}) @@ -150,7 +150,7 @@ class ApplicationCommandPermissionsManager extends BaseManager { * id: '123456789012345678', * permissions: [{ * id: '876543210987654321', - * type: 'USER', + * type: ApplicationCommandOptionType.User, * permission: false, * }], * }, @@ -168,7 +168,7 @@ class ApplicationCommandPermissionsManager extends BaseManager { const data = await this.permissionsPath(guildId, commandId).put({ data: { permissions: permissions.map(perm => this.constructor.transformPermissions(perm)) }, }); - return data.permissions.map(perm => this.constructor.transformPermissions(perm, true)); + return data.permissions.map(perm => this.constructor.transformPermissions(perm)); } if (!Array.isArray(fullPermissions)) { @@ -190,7 +190,7 @@ class ApplicationCommandPermissionsManager extends BaseManager { (coll, perm) => coll.set( perm.id, - perm.permissions.map(p => this.constructor.transformPermissions(p, true)), + perm.permissions.map(p => this.constructor.transformPermissions(p)), ), new Collection(), ); @@ -212,7 +212,7 @@ class ApplicationCommandPermissionsManager extends BaseManager { * guild.commands.permissions.add({ command: '123456789012345678', permissions: [ * { * id: '876543211234567890', - * type: 'ROLE', + * type: ApplicationCommandPermissionType.Role, * permission: false * }, * ]}) @@ -396,14 +396,11 @@ class ApplicationCommandPermissionsManager extends BaseManager { * @returns {APIApplicationCommandPermissions} * @private */ - static transformPermissions(permissions, received) { + static transformPermissions(permissions) { return { id: permissions.id, permission: permissions.permission, - type: - typeof permissions.type === 'number' && !received - ? permissions.type - : ApplicationCommandPermissionType[permissions.type], + type: permissions.type, }; } } diff --git a/packages/discord.js/src/managers/GuildChannelManager.js b/packages/discord.js/src/managers/GuildChannelManager.js index e5183947d..65c90d8ae 100644 --- a/packages/discord.js/src/managers/GuildChannelManager.js +++ b/packages/discord.js/src/managers/GuildChannelManager.js @@ -113,7 +113,7 @@ class GuildChannelManager extends CachedManager { * @example * // Create a new channel with permission overwrites * guild.channels.create('new-voice', { - * type: 'GUILD_VOICE', + * type: ChannelType.GuildVoice, * permissionOverwrites: [ * { * id: message.author.id, diff --git a/packages/discord.js/src/managers/GuildManager.js b/packages/discord.js/src/managers/GuildManager.js index e957d5ca5..51131404d 100644 --- a/packages/discord.js/src/managers/GuildManager.js +++ b/packages/discord.js/src/managers/GuildManager.js @@ -3,13 +3,6 @@ const process = require('node:process'); const { setTimeout, clearTimeout } = require('node:timers'); const { Collection } = require('@discordjs/collection'); -const { - GuildVerificationLevel, - GuildDefaultMessageNotifications, - GuildExplicitContentFilter, - ChannelType, - OverwriteType, -} = require('discord-api-types/v9'); const CachedManager = require('./CachedManager'); const { Guild } = require('../structures/Guild'); const GuildChannel = require('../structures/GuildChannel'); @@ -181,17 +174,8 @@ class GuildManager extends CachedManager { } = {}, ) { icon = await DataResolver.resolveImage(icon); - if (typeof verificationLevel === 'string') { - verificationLevel = GuildVerificationLevel[verificationLevel]; - } - if (typeof defaultMessageNotifications === 'string') { - defaultMessageNotifications = GuildDefaultMessageNotifications[defaultMessageNotifications]; - } - if (typeof explicitContentFilter === 'string') { - explicitContentFilter = GuildExplicitContentFilter[explicitContentFilter]; - } + for (const channel of channels) { - channel.type &&= typeof channel.type === 'number' ? channel.type : ChannelType[channel.type]; channel.parent_id = channel.parentId; delete channel.parentId; channel.user_limit = channel.userLimit; @@ -203,9 +187,6 @@ class GuildManager extends CachedManager { if (!channel.permissionOverwrites) continue; for (const overwrite of channel.permissionOverwrites) { - if (typeof overwrite.type === 'string') { - overwrite.type = OverwriteType[overwrite.type]; - } overwrite.allow &&= Permissions.resolve(overwrite.allow).toString(); overwrite.deny &&= Permissions.resolve(overwrite.deny).toString(); } diff --git a/packages/discord.js/src/managers/GuildScheduledEventManager.js b/packages/discord.js/src/managers/GuildScheduledEventManager.js index 086767ec4..ea2266714 100644 --- a/packages/discord.js/src/managers/GuildScheduledEventManager.js +++ b/packages/discord.js/src/managers/GuildScheduledEventManager.js @@ -44,15 +44,16 @@ class GuildScheduledEventManager extends CachedManager { * @property {string} name The name of the guild scheduled event * @property {DateResolvable} scheduledStartTime The time to schedule the event at * @property {DateResolvable} [scheduledEndTime] The time to end the event at - * This is required if `entityType` is 'EXTERNAL' + * This is required if `entityType` is `GuildScheduledEventEntityType.External` * @property {PrivacyLevel|number} privacyLevel The privacy level of the guild scheduled event * @property {GuildScheduledEventEntityType|number} entityType The scheduled entity type of the event * @property {string} [description] The description of the guild scheduled event * @property {GuildVoiceChannelResolvable} [channel] The channel of the guild scheduled event - * This is required if `entityType` is 'STAGE_INSTANCE' or `VOICE` + * This is required if `entityType` is `GuildScheduledEventEntityType.StageInstance` or + * `GuildScheduledEventEntityType.Voice` * @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the * guild scheduled event - * This is required if `entityType` is 'EXTERNAL' + * This is required if `entityType` is `GuildScheduledEventEntityType.External` * @property {string} [reason] The reason for creating the guild scheduled event */ @@ -60,7 +61,7 @@ class GuildScheduledEventManager extends CachedManager { * Options used to set entity metadata of a guild scheduled event. * @typedef {Object} GuildScheduledEventEntityMetadataOptions * @property {string} [location] The location of the guild scheduled event - * This is required if `entityType` is 'EXTERNAL' + * This is required if `entityType` is `GuildScheduledEventEntityType.External` */ /** @@ -175,7 +176,8 @@ class GuildScheduledEventManager extends CachedManager { * @property {GuildScheduledEventStatus|number} [status] The status of the guild scheduled event * @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the * guild scheduled event - * This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is 'EXTERNAL' + * This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is + * `GuildScheduledEventEntityType.External` * @property {string} [reason] The reason for editing the guild scheduled event */ diff --git a/packages/discord.js/src/managers/StageInstanceManager.js b/packages/discord.js/src/managers/StageInstanceManager.js index e5b02e014..a905be275 100644 --- a/packages/discord.js/src/managers/StageInstanceManager.js +++ b/packages/discord.js/src/managers/StageInstanceManager.js @@ -49,7 +49,7 @@ class StageInstanceManager extends CachedManager { * // Create a stage instance * guild.stageInstances.create('1234567890123456789', { * topic: 'A very creative topic', - * privacyLevel: 'GUILD_ONLY' + * privacyLevel: GuildPrivacyLevel.GuildOnly * }) * .then(stageInstance => console.log(stageInstance)) * .catch(console.error); diff --git a/packages/discord.js/src/managers/ThreadManager.js b/packages/discord.js/src/managers/ThreadManager.js index bcc3d99cb..b9841a699 100644 --- a/packages/discord.js/src/managers/ThreadManager.js +++ b/packages/discord.js/src/managers/ThreadManager.js @@ -92,7 +92,7 @@ class ThreadManager extends CachedManager { * .create({ * name: 'mod-talk', * autoArchiveDuration: 60, - * type: 'GUILD_PRIVATE_THREAD', + * type: ChannelType.GuildPrivateThread, * reason: 'Needed a separate thread for moderation', * }) * .then(threadChannel => console.log(threadChannel)) @@ -111,13 +111,14 @@ class ThreadManager extends CachedManager { if (type && typeof type !== 'string' && typeof type !== 'number') { throw new TypeError('INVALID_TYPE', 'type', 'ThreadChannelType or Number'); } - let resolvedType = this.channel.type === 'GUILD_NEWS' ? ChannelType.GuildNewsThread : ChannelType.GuildPublicThread; + let resolvedType = + this.channel.type === ChannelType.GuildNews ? ChannelType.GuildNewsThread : ChannelType.GuildPublicThread; if (startMessage) { const startMessageId = this.channel.messages.resolveId(startMessage); if (!startMessageId) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable'); path = path.messages(startMessageId); - } else if (this.channel.type !== 'GUILD_NEWS') { - resolvedType = typeof type === 'string' ? ChannelType[type] : type ?? resolvedType; + } else if (this.channel.type !== ChannelType.GuildNews) { + resolvedType = type ?? resolvedType; } if (autoArchiveDuration === 'MAX') { autoArchiveDuration = 1440; diff --git a/packages/discord.js/src/managers/UserManager.js b/packages/discord.js/src/managers/UserManager.js index f5045795b..a5d9ba2fe 100644 --- a/packages/discord.js/src/managers/UserManager.js +++ b/packages/discord.js/src/managers/UserManager.js @@ -1,5 +1,6 @@ 'use strict'; +const { ChannelType } = require('discord-api-types/v9'); const CachedManager = require('./CachedManager'); const { GuildMember } = require('../structures/GuildMember'); const { Message } = require('../structures/Message'); @@ -38,7 +39,7 @@ class UserManager extends CachedManager { * @private */ dmChannel(userId) { - return this.client.channels.cache.find(c => c.type === 'DM' && c.recipient.id === userId) ?? null; + return this.client.channels.cache.find(c => c.type === ChannelType.DM && c.recipient.id === userId) ?? null; } /** diff --git a/packages/discord.js/src/structures/AnonymousGuild.js b/packages/discord.js/src/structures/AnonymousGuild.js index 8650211eb..8490d95f4 100644 --- a/packages/discord.js/src/structures/AnonymousGuild.js +++ b/packages/discord.js/src/structures/AnonymousGuild.js @@ -1,6 +1,5 @@ 'use strict'; -const { GuildVerificationLevel, GuildNSFWLevel } = require('discord-api-types/v9'); const BaseGuild = require('./BaseGuild'); /** @@ -44,9 +43,9 @@ class AnonymousGuild extends BaseGuild { if ('verification_level' in data) { /** * The verification level of the guild - * @type {VerificationLevel} + * @type {GuildVerificationLevel} */ - this.verificationLevel = GuildVerificationLevel[data.verification_level]; + this.verificationLevel = data.verification_level; } if ('vanity_url_code' in data) { @@ -60,9 +59,9 @@ class AnonymousGuild extends BaseGuild { if ('nsfw_level' in data) { /** * The NSFW level of this guild - * @type {NSFWLevel} + * @type {GuildNSFWLevel} */ - this.nsfwLevel = GuildNSFWLevel[data.nsfw_level]; + this.nsfwLevel = data.nsfw_level; } } diff --git a/packages/discord.js/src/structures/ApplicationCommand.js b/packages/discord.js/src/structures/ApplicationCommand.js index 7dc630cdf..e84772bfb 100644 --- a/packages/discord.js/src/structures/ApplicationCommand.js +++ b/packages/discord.js/src/structures/ApplicationCommand.js @@ -1,7 +1,7 @@ 'use strict'; const { DiscordSnowflake } = require('@sapphire/snowflake'); -const { ApplicationCommandType, ApplicationCommandOptionType, ChannelType } = require('discord-api-types/v9'); +const { ApplicationCommandOptionType, ChannelType } = require('discord-api-types/v9'); const Base = require('./Base'); const ApplicationCommandPermissionsManager = require('../managers/ApplicationCommandPermissionsManager'); @@ -48,7 +48,7 @@ class ApplicationCommand extends Base { * The type of this application command * @type {ApplicationCommandType} */ - this.type = ApplicationCommandType[data.type]; + this.type = data.type; this._patch(data); } @@ -233,13 +233,12 @@ class ApplicationCommand extends Base { if (command.id && this.id !== command.id) return false; // Check top level parameters - const commandType = typeof command.type === 'string' ? command.type : ApplicationCommandType[command.type]; if ( command.name !== this.name || ('description' in command && command.description !== this.description) || ('version' in command && command.version !== this.version) || ('autocomplete' in command && command.autocomplete !== this.autocomplete) || - (commandType && commandType !== this.type) || + (command.type && command.type !== this.type) || // Future proof for options being nullable // TODO: remove ?? 0 on each when nullable (command.options?.length ?? 0) !== (this.options?.length ?? 0) || @@ -289,14 +288,15 @@ class ApplicationCommand extends Base { * @private */ static _optionEquals(existing, option, enforceOptionOrder = false) { - const optionType = typeof option.type === 'string' ? option.type : ApplicationCommandOptionType[option.type]; if ( option.name !== existing.name || - optionType !== existing.type || + option.type !== existing.type || option.description !== existing.description || option.autocomplete !== existing.autocomplete || - (option.required ?? (['SUB_COMMAND', 'SUB_COMMAND_GROUP'].includes(optionType) ? undefined : false)) !== - existing.required || + (option.required ?? + ([ApplicationCommandOptionType.Subcommand, ApplicationCommandOptionType.SubcommandGroup].includes(option.type) + ? undefined + : false)) !== existing.required || option.choices?.length !== existing.choices?.length || option.options?.length !== existing.options?.length || (option.channelTypes ?? option.channel_types)?.length !== existing.channelTypes?.length || @@ -325,9 +325,7 @@ class ApplicationCommand extends Base { } if (existing.channelTypes) { - const newTypes = (option.channelTypes ?? option.channel_types).map(type => - typeof type === 'number' ? ChannelType[type] : type, - ); + const newTypes = option.channelTypes ?? option.channel_types; for (const type of existing.channelTypes) { if (!newTypes.includes(type)) return false; } @@ -370,16 +368,19 @@ class ApplicationCommand extends Base { * @private */ static transformOption(option, received) { - const stringType = typeof option.type === 'string' ? option.type : ApplicationCommandOptionType[option.type]; const channelTypesKey = received ? 'channelTypes' : 'channel_types'; const minValueKey = received ? 'minValue' : 'min_value'; const maxValueKey = received ? 'maxValue' : 'max_value'; return { - type: typeof option.type === 'number' && !received ? option.type : ApplicationCommandOptionType[option.type], + type: option.type, name: option.name, description: option.description, required: - option.required ?? (stringType === 'SUB_COMMAND' || stringType === 'SUB_COMMAND_GROUP' ? undefined : false), + option.required ?? + (option.type === ApplicationCommandOptionType.Subcommand || + option.type === ApplicationCommandOptionType.SubcommandGroup + ? undefined + : false), autocomplete: option.autocomplete, choices: option.choices, options: option.options?.map(o => this.transformOption(o, received)), diff --git a/packages/discord.js/src/structures/AutocompleteInteraction.js b/packages/discord.js/src/structures/AutocompleteInteraction.js index fed027caa..63abf07ca 100644 --- a/packages/discord.js/src/structures/AutocompleteInteraction.js +++ b/packages/discord.js/src/structures/AutocompleteInteraction.js @@ -1,6 +1,6 @@ 'use strict'; -const { ApplicationCommandOptionType, InteractionResponseType } = require('discord-api-types/v9'); +const { InteractionResponseType } = require('discord-api-types/v9'); const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver'); const Interaction = require('./Interaction'); @@ -40,10 +40,7 @@ class AutocompleteInteraction extends Interaction { * The options passed to the command * @type {CommandInteractionOptionResolver} */ - this.options = new CommandInteractionOptionResolver( - this.client, - data.data.options?.map(option => this.transformOption(option, data.data.resolved)) ?? [], - ); + this.options = new CommandInteractionOptionResolver(this.client, data.data.options ?? []); } /** @@ -55,25 +52,6 @@ class AutocompleteInteraction extends Interaction { return this.guild?.commands.cache.get(id) ?? this.client.application.commands.cache.get(id) ?? null; } - /** - * Transforms an option received from the API. - * @param {APIApplicationCommandOption} option The received option - * @returns {CommandInteractionOption} - * @private - */ - transformOption(option) { - const result = { - name: option.name, - type: ApplicationCommandOptionType[option.type], - }; - - if ('value' in option) result.value = option.value; - if ('options' in option) result.options = option.options.map(opt => this.transformOption(opt)); - if ('focused' in option) result.focused = option.focused; - - return result; - } - /** * Sends results for the autocomplete of this interaction. * @param {ApplicationCommandOptionChoice[]} options The options for the autocomplete diff --git a/packages/discord.js/src/structures/CategoryChannel.js b/packages/discord.js/src/structures/CategoryChannel.js index ce5b5f61c..0095532bd 100644 --- a/packages/discord.js/src/structures/CategoryChannel.js +++ b/packages/discord.js/src/structures/CategoryChannel.js @@ -30,7 +30,7 @@ class CategoryChannel extends GuildChannel { /** * Options for creating a channel using {@link CategoryChannel#createChannel}. * @typedef {Object} CategoryCreateChannelOptions - * @property {ChannelType|number} [type='GUILD_TEXT'] The type of the new channel. + * @property {ChannelType} [type=ChannelType.GuildText] The type of the new channel. * @property {string} [topic] The topic for the new channel * @property {boolean} [nsfw] Whether the new channel is NSFW * @property {number} [bitrate] Bitrate of the new channel in bits (only voice) diff --git a/packages/discord.js/src/structures/Channel.js b/packages/discord.js/src/structures/Channel.js index 29b7351ae..6f2a1bb7f 100644 --- a/packages/discord.js/src/structures/Channel.js +++ b/packages/discord.js/src/structures/Channel.js @@ -22,12 +22,11 @@ class Channel extends Base { constructor(client, data, immediatePatch = true) { super(client); - const type = ChannelType[data?.type]; /** * The type of the channel * @type {ChannelType} */ - this.type = type ?? 'UNKNOWN'; + this.type = data.type; if (data && immediatePatch) this._patch(data); } @@ -107,7 +106,7 @@ class Channel extends Base { * @returns {boolean} */ isText() { - return this.type === ChannelType[ChannelType.GuildText]; + return this.type === ChannelType.GuildText; } /** @@ -115,7 +114,7 @@ class Channel extends Base { * @returns {boolean} */ isDM() { - return this.type === ChannelType[ChannelType.DM]; + return this.type === ChannelType.DM; } /** @@ -123,7 +122,7 @@ class Channel extends Base { * @returns {boolean} */ isVoice() { - return this.type === ChannelType[ChannelType.GuildVoice]; + return this.type === ChannelType.GuildVoice; } /** @@ -131,7 +130,7 @@ class Channel extends Base { * @returns {boolean} */ isGroupDM() { - return this.type === ChannelType[ChannelType.GroupDM]; + return this.type === ChannelType.GroupDM; } /** @@ -139,7 +138,7 @@ class Channel extends Base { * @returns {boolean} */ isCategory() { - return this.type === ChannelType[ChannelType.GuildCategory]; + return this.type === ChannelType.GuildCategory; } /** @@ -147,7 +146,7 @@ class Channel extends Base { * @returns {boolean} */ isNews() { - return this.type === ChannelType[ChannelType.GuildNews]; + return this.type === ChannelType.GuildNews; } /** @@ -155,7 +154,7 @@ class Channel extends Base { * @returns {boolean} */ isStore() { - return this.type === ChannelType[ChannelType.GuildStore]; + return this.type === ChannelType.GuildStore; } /** @@ -171,7 +170,7 @@ class Channel extends Base { * @returns {boolean} */ isStage() { - return this.type === ChannelType[ChannelType.GuildStageVoice]; + return this.type === ChannelType.GuildStageVoice; } /** diff --git a/packages/discord.js/src/structures/ClientPresence.js b/packages/discord.js/src/structures/ClientPresence.js index 8f16200b9..145395ceb 100644 --- a/packages/discord.js/src/structures/ClientPresence.js +++ b/packages/discord.js/src/structures/ClientPresence.js @@ -1,6 +1,5 @@ 'use strict'; -const { ActivityType } = require('discord-api-types/v9'); const { Presence } = require('./Presence'); const { TypeError } = require('../errors'); const { Opcodes } = require('../util/Constants'); @@ -53,7 +52,7 @@ class ClientPresence extends Presence { activity.type ??= 0; data.activities.push({ - type: typeof activity.type === 'number' ? activity.type : ActivityType[activity.type], + type: activity.type, name: activity.name, url: activity.url, }); @@ -62,7 +61,7 @@ class ClientPresence extends Presence { data.activities.push( ...this.activities.map(a => ({ name: a.name, - type: ActivityType[a.type], + type: a.type, url: a.url ?? undefined, })), ); diff --git a/packages/discord.js/src/structures/ClientUser.js b/packages/discord.js/src/structures/ClientUser.js index 9136752f0..8399b0951 100644 --- a/packages/discord.js/src/structures/ClientUser.js +++ b/packages/discord.js/src/structures/ClientUser.js @@ -158,7 +158,7 @@ class ClientUser extends User { * @returns {ClientPresence} * @example * // Set the client user's activity - * client.user.setActivity('discord.js', { type: 'WATCHING' }); + * client.user.setActivity('discord.js', { type: ActivityType.Watching }); */ setActivity(name, options = {}) { if (!name) return this.setPresence({ activities: [], shardId: options.shardId }); diff --git a/packages/discord.js/src/structures/CommandInteraction.js b/packages/discord.js/src/structures/CommandInteraction.js index 09baaf3b9..b7665cea0 100644 --- a/packages/discord.js/src/structures/CommandInteraction.js +++ b/packages/discord.js/src/structures/CommandInteraction.js @@ -1,7 +1,6 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); -const { ApplicationCommandOptionType } = require('discord-api-types/v9'); const Interaction = require('./Interaction'); const InteractionWebhook = require('./InteractionWebhook'); const InteractionResponses = require('./interfaces/InteractionResponses'); @@ -151,7 +150,7 @@ class CommandInteraction extends Interaction { transformOption(option, resolved) { const result = { name: option.name, - type: ApplicationCommandOptionType[option.type], + type: option.type, }; if ('value' in option) result.value = option.value; diff --git a/packages/discord.js/src/structures/CommandInteractionOptionResolver.js b/packages/discord.js/src/structures/CommandInteractionOptionResolver.js index bcd28f063..b70c8e95a 100644 --- a/packages/discord.js/src/structures/CommandInteractionOptionResolver.js +++ b/packages/discord.js/src/structures/CommandInteractionOptionResolver.js @@ -1,5 +1,6 @@ 'use strict'; +const { ApplicationCommandOptionType } = require('discord-api-types/v9'); const { TypeError } = require('../errors'); /** @@ -38,12 +39,12 @@ class CommandInteractionOptionResolver { this._hoistedOptions = options; // Hoist subcommand group if present - if (this._hoistedOptions[0]?.type === 'SUB_COMMAND_GROUP') { + if (this._hoistedOptions[0]?.type === ApplicationCommandOptionType.SubcommandGroup) { this._group = this._hoistedOptions[0].name; this._hoistedOptions = this._hoistedOptions[0].options ?? []; } // Hoist subcommand if present - if (this._hoistedOptions[0]?.type === 'SUB_COMMAND') { + if (this._hoistedOptions[0]?.type === ApplicationCommandOptionType.Subcommand) { this._subcommand = this._hoistedOptions[0].name; this._hoistedOptions = this._hoistedOptions[0].options ?? []; } @@ -133,7 +134,7 @@ class CommandInteractionOptionResolver { * @returns {?boolean} The value of the option, or null if not set and not required. */ getBoolean(name, required = false) { - const option = this._getTypedOption(name, 'BOOLEAN', ['value'], required); + const option = this._getTypedOption(name, ApplicationCommandOptionType.Boolean, ['value'], required); return option?.value ?? null; } @@ -145,7 +146,7 @@ class CommandInteractionOptionResolver { * The value of the option, or null if not set and not required. */ getChannel(name, required = false) { - const option = this._getTypedOption(name, 'CHANNEL', ['channel'], required); + const option = this._getTypedOption(name, ApplicationCommandOptionType.Channel, ['channel'], required); return option?.channel ?? null; } @@ -156,7 +157,7 @@ class CommandInteractionOptionResolver { * @returns {?string} The value of the option, or null if not set and not required. */ getString(name, required = false) { - const option = this._getTypedOption(name, 'STRING', ['value'], required); + const option = this._getTypedOption(name, ApplicationCommandOptionType.String, ['value'], required); return option?.value ?? null; } @@ -167,7 +168,7 @@ class CommandInteractionOptionResolver { * @returns {?number} The value of the option, or null if not set and not required. */ getInteger(name, required = false) { - const option = this._getTypedOption(name, 'INTEGER', ['value'], required); + const option = this._getTypedOption(name, ApplicationCommandOptionType.Integer, ['value'], required); return option?.value ?? null; } @@ -178,7 +179,7 @@ class CommandInteractionOptionResolver { * @returns {?number} The value of the option, or null if not set and not required. */ getNumber(name, required = false) { - const option = this._getTypedOption(name, 'NUMBER', ['value'], required); + const option = this._getTypedOption(name, ApplicationCommandOptionType.Number, ['value'], required); return option?.value ?? null; } @@ -189,7 +190,7 @@ class CommandInteractionOptionResolver { * @returns {?User} The value of the option, or null if not set and not required. */ getUser(name, required = false) { - const option = this._getTypedOption(name, 'USER', ['user'], required); + const option = this._getTypedOption(name, ApplicationCommandOptionType.User, ['user'], required); return option?.user ?? null; } @@ -200,7 +201,7 @@ class CommandInteractionOptionResolver { * The value of the option, or null if the user is not present in the guild or the option is not set. */ getMember(name) { - const option = this._getTypedOption(name, 'USER', ['member'], false); + const option = this._getTypedOption(name, ApplicationCommandOptionType.User, ['member'], false); return option?.member ?? null; } @@ -211,7 +212,7 @@ class CommandInteractionOptionResolver { * @returns {?(Role|APIRole)} The value of the option, or null if not set and not required. */ getRole(name, required = false) { - const option = this._getTypedOption(name, 'ROLE', ['role'], required); + const option = this._getTypedOption(name, ApplicationCommandOptionType.Role, ['role'], required); return option?.role ?? null; } @@ -223,7 +224,12 @@ class CommandInteractionOptionResolver { * The value of the option, or null if not set and not required. */ getMentionable(name, required = false) { - const option = this._getTypedOption(name, 'MENTIONABLE', ['user', 'member', 'role'], required); + const option = this._getTypedOption( + name, + ApplicationCommandOptionType.Mentionable, + ['user', 'member', 'role'], + required, + ); return option?.member ?? option?.user ?? option?.role ?? null; } diff --git a/packages/discord.js/src/structures/ContextMenuCommandInteraction.js b/packages/discord.js/src/structures/ContextMenuCommandInteraction.js index 318233efa..1d8536b3e 100644 --- a/packages/discord.js/src/structures/ContextMenuCommandInteraction.js +++ b/packages/discord.js/src/structures/ContextMenuCommandInteraction.js @@ -1,6 +1,6 @@ 'use strict'; -const { ApplicationCommandType, ApplicationCommandOptionType } = require('discord-api-types/v9'); +const { ApplicationCommandOptionType } = require('discord-api-types/v9'); const CommandInteraction = require('./CommandInteraction'); const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver'); @@ -28,10 +28,10 @@ class ContextMenuCommandInteraction extends CommandInteraction { this.targetId = data.data.target_id; /** - * The type of the target of the interaction; either USER or MESSAGE - * @type {ApplicationCommandType} + * The type of the target of the interaction; either `.User` or `.Message` + * @type {ApplicationCommandType.User|ApplicationCommandType.Message} */ - this.targetType = ApplicationCommandType[data.data.type]; + this.targetType = data.data.type; } /** diff --git a/packages/discord.js/src/structures/DMChannel.js b/packages/discord.js/src/structures/DMChannel.js index cc1a018df..5117a0eae 100644 --- a/packages/discord.js/src/structures/DMChannel.js +++ b/packages/discord.js/src/structures/DMChannel.js @@ -1,5 +1,6 @@ 'use strict'; +const { ChannelType } = require('discord-api-types/v9'); const { Channel } = require('./Channel'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); const MessageManager = require('../managers/MessageManager'); @@ -14,7 +15,7 @@ class DMChannel extends Channel { super(client, data); // Override the channel type so partials have a known type - this.type = 'DM'; + this.type = ChannelType.DM; /** * A manager of the messages belonging to this channel diff --git a/packages/discord.js/src/structures/Guild.js b/packages/discord.js/src/structures/Guild.js index c562fe326..69f87d4f4 100644 --- a/packages/discord.js/src/structures/Guild.js +++ b/packages/discord.js/src/structures/Guild.js @@ -1,14 +1,7 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); -const { - GuildPremiumTier, - GuildMFALevel, - GuildExplicitContentFilter, - GuildDefaultMessageNotifications, - GuildVerificationLevel, - ChannelType, -} = require('discord-api-types/v9'); +const { GuildPremiumTier, ChannelType } = require('discord-api-types/v9'); const AnonymousGuild = require('./AnonymousGuild'); const GuildAuditLogs = require('./GuildAuditLogs'); const GuildPreview = require('./GuildPreview'); @@ -240,7 +233,7 @@ class Guild extends AnonymousGuild { * The premium tier of this guild * @type {GuildPremiumTier} */ - this.premiumTier = GuildPremiumTier[data.premium_tier]; + this.premiumTier = data.premium_tier; } if ('premium_subscription_count' in data) { @@ -270,9 +263,9 @@ class Guild extends AnonymousGuild { if ('explicit_content_filter' in data) { /** * The explicit content filter level of the guild - * @type {ExplicitContentFilterLevel} + * @type {GuildExplicitContentFilter} */ - this.explicitContentFilter = GuildExplicitContentFilter[data.explicit_content_filter]; + this.explicitContentFilter = data.explicit_content_filter; } if ('mfa_level' in data) { @@ -280,7 +273,7 @@ class Guild extends AnonymousGuild { * The required MFA level for this guild * @type {MFALevel} */ - this.mfaLevel = GuildMFALevel[data.mfa_level]; + this.mfaLevel = data.mfa_level; } if ('joined_at' in data) { @@ -296,7 +289,7 @@ class Guild extends AnonymousGuild { * The default message notification level of the guild * @type {GuildDefaultMessageNotifications} */ - this.defaultMessageNotifications = GuildDefaultMessageNotifications[data.default_message_notifications]; + this.defaultMessageNotifications = data.default_message_notifications; } if ('system_channel_flags' in data) { @@ -566,7 +559,7 @@ class Guild extends AnonymousGuild { return 384_000; } - switch (GuildPremiumTier[this.premiumTier]) { + switch (this.premiumTier) { case GuildPremiumTier.Tier1: return 128_000; case GuildPremiumTier.Tier2: @@ -748,7 +741,6 @@ class Guild extends AnonymousGuild { */ async fetchAuditLogs(options = {}) { if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id; - if (typeof options.type === 'string') options.type = GuildAuditLogs.Actions[options.type]; const data = await this.client.api.guilds(this.id)['audit-logs'].get({ query: { @@ -817,10 +809,7 @@ class Guild extends AnonymousGuild { const _data = {}; if (data.name) _data.name = data.name; if (typeof data.verificationLevel !== 'undefined') { - _data.verification_level = - typeof data.verificationLevel === 'number' - ? data.verificationLevel - : GuildVerificationLevel[data.verificationLevel]; + _data.verification_level = data.verificationLevel; } if (typeof data.afkChannel !== 'undefined') { _data.afk_channel_id = this.client.channels.resolveId(data.afkChannel); @@ -837,16 +826,10 @@ class Guild extends AnonymousGuild { } if (typeof data.banner !== 'undefined') _data.banner = await DataResolver.resolveImage(data.banner); if (typeof data.explicitContentFilter !== 'undefined') { - _data.explicit_content_filter = - typeof data.explicitContentFilter === 'number' - ? data.explicitContentFilter - : GuildExplicitContentFilter[data.explicitContentFilter]; + _data.explicit_content_filter = data.explicitContentFilter; } if (typeof data.defaultMessageNotifications !== 'undefined') { - _data.default_message_notifications = - typeof data.defaultMessageNotifications === 'number' - ? data.defaultMessageNotifications - : GuildDefaultMessageNotifications[data.defaultMessageNotifications]; + _data.default_message_notifications = data.defaultMessageNotifications; } if (typeof data.systemChannelFlags !== 'undefined') { _data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags); @@ -1303,12 +1286,11 @@ class Guild extends AnonymousGuild { */ _sortedChannels(channel) { const category = channel.type === ChannelType.GuildCategory; + const channelTypes = [ChannelType.GuildText, ChannelType.GuildNews, ChannelType.GuildStore]; return Util.discordSort( this.channels.cache.filter( c => - (['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_STORE'].includes(channel.type) - ? ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_STORE'].includes(c.type) - : c.type === channel.type) && + (channelTypes.includes(channel.type) ? channelTypes.includes(c.type) : c.type === channel.type) && (category || c.parent === channel.parent), ), ); diff --git a/packages/discord.js/src/structures/GuildAuditLogs.js b/packages/discord.js/src/structures/GuildAuditLogs.js index 39228d379..5880ac7f6 100644 --- a/packages/discord.js/src/structures/GuildAuditLogs.js +++ b/packages/discord.js/src/structures/GuildAuditLogs.js @@ -338,19 +338,19 @@ class GuildAuditLogsEntry { case AuditLogEvent.ChannelOverwriteCreate: case AuditLogEvent.ChannelOverwriteUpdate: case AuditLogEvent.ChannelOverwriteDelete: - switch (Number(data.options.type)) { + switch (data.options.type) { case OverwriteType.Role: this.extra = guild.roles.cache.get(data.options.id) ?? { id: data.options.id, name: data.options.role_name, - type: OverwriteType[OverwriteType.Role], + type: OverwriteType.Role, }; break; case OverwriteType.Member: this.extra = guild.members.cache.get(data.options.id) ?? { id: data.options.id, - type: OverwriteType[OverwriteType.Member], + type: OverwriteType.Member, }; break; diff --git a/packages/discord.js/src/structures/GuildChannel.js b/packages/discord.js/src/structures/GuildChannel.js index 976c6d1ee..50a251b1f 100644 --- a/packages/discord.js/src/structures/GuildChannel.js +++ b/packages/discord.js/src/structures/GuildChannel.js @@ -311,7 +311,7 @@ class GuildChannel extends Channel { if (data.lockPermissions) { if (data.parent) { const newParent = this.guild.channels.resolve(data.parent); - if (newParent?.type === 'GuildCategory') { + if (newParent?.type === ChannelType.GuildCategory) { permission_overwrites = newParent.permissionOverwrites.cache.map(o => PermissionOverwrites.resolve(o, this.guild), ); @@ -326,7 +326,7 @@ class GuildChannel extends Channel { const newData = await this.client.api.channels(this.id).patch({ data: { name: (data.name ?? this.name).trim(), - type: ChannelType[data.type], + type: data.type, topic: data.topic, nsfw: data.nsfw, bitrate: data.bitrate ?? this.bitrate, diff --git a/packages/discord.js/src/structures/GuildScheduledEvent.js b/packages/discord.js/src/structures/GuildScheduledEvent.js index bb5999814..128e5481d 100644 --- a/packages/discord.js/src/structures/GuildScheduledEvent.js +++ b/packages/discord.js/src/structures/GuildScheduledEvent.js @@ -236,7 +236,7 @@ class GuildScheduledEvent extends Base { */ async createInviteURL(options) { let channelId = this.channelId; - if (this.entityType === 'EXTERNAL') { + if (this.entityType === GuildScheduledEventEntityType.External) { if (!options?.channel) throw new Error('INVITE_OPTIONS_MISSING_CHANNEL'); channelId = this.guild.channels.resolveId(options.channel); if (!channelId) throw new Error('GUILD_CHANNEL_RESOLVE'); @@ -343,7 +343,7 @@ class GuildScheduledEvent extends Base { * @returns {Promise} * @example * // Set status of a guild scheduled event - * guildScheduledEvent.setStatus('ACTIVE') + * guildScheduledEvent.setStatus(GuildScheduledEventStatus.Active) * .then(guildScheduledEvent => console.log(`Set the status to: ${guildScheduledEvent.status}`)) * .catch(console.error); */ diff --git a/packages/discord.js/src/structures/Interaction.js b/packages/discord.js/src/structures/Interaction.js index b8bc14939..01d877ca9 100644 --- a/packages/discord.js/src/structures/Interaction.js +++ b/packages/discord.js/src/structures/Interaction.js @@ -17,7 +17,7 @@ class Interaction extends Base { * The interaction's type * @type {InteractionType} */ - this.type = InteractionType[data.type]; + this.type = data.type; /** * The interaction's id @@ -154,7 +154,7 @@ class Interaction extends Base { * @returns {boolean} */ isCommand() { - return InteractionType[this.type] === InteractionType.ApplicationCommand; + return this.type === InteractionType.ApplicationCommand; } /** @@ -162,7 +162,7 @@ class Interaction extends Base { * @returns {boolean} */ isChatInputCommand() { - return InteractionType[this.type] === InteractionType.ApplicationCommand && typeof this.targetId === 'undefined'; + return this.isCommand() && typeof this.targetId === 'undefined'; } /** @@ -170,7 +170,7 @@ class Interaction extends Base { * @returns {boolean} */ isContextMenuCommand() { - return InteractionType[this.type] === InteractionType.ApplicationCommand && typeof this.targetId !== 'undefined'; + return this.isCommand() && typeof this.targetId !== 'undefined'; } /** @@ -178,7 +178,7 @@ class Interaction extends Base { * @returns {boolean} */ isUserContextMenuCommand() { - return this.isContextMenuCommand() && ApplicationCommandType[this.targetType] === ApplicationCommandType.User; + return this.isContextMenuCommand() && this.targetType === ApplicationCommandType.User; } /** @@ -186,7 +186,7 @@ class Interaction extends Base { * @returns {boolean} */ isMessageContextMenuCommand() { - return this.isContextMenuCommand() && ApplicationCommandType[this.targetType] === ApplicationCommandType.Message; + return this.isContextMenuCommand() && this.targetType === ApplicationCommandType.Message; } /** @@ -194,7 +194,7 @@ class Interaction extends Base { * @returns {boolean} */ isAutocomplete() { - return InteractionType[this.type] === InteractionType.ApplicationCommandAutocomplete; + return this.type === InteractionType.ApplicationCommandAutocomplete; } /** @@ -202,7 +202,7 @@ class Interaction extends Base { * @returns {boolean} */ isMessageComponent() { - return InteractionType[this.type] === InteractionType.MessageComponent; + return this.type === InteractionType.MessageComponent; } /** @@ -210,10 +210,7 @@ class Interaction extends Base { * @returns {boolean} */ isButton() { - return ( - InteractionType[this.type] === InteractionType.MessageComponent && - ComponentType[this.componentType] === ComponentType.Button - ); + return this.isMessageComponent() && this.componentType === ComponentType.Button; } /** @@ -221,10 +218,7 @@ class Interaction extends Base { * @returns {boolean} */ isSelectMenu() { - return ( - InteractionType[this.type] === InteractionType.MessageComponent && - ComponentType[this.componentType] === ComponentType.SelectMenu - ); + return this.isMessageComponent() && this.componentType === ComponentType.SelectMenu; } /** @@ -232,7 +226,7 @@ class Interaction extends Base { * @returns {boolean} */ isRepliable() { - return ![InteractionType.Ping, InteractionType.ApplicationCommandAutocomplete].includes(InteractionType[this.type]); + return ![InteractionType.Ping, InteractionType.ApplicationCommandAutocomplete].includes(this.type); } } diff --git a/packages/discord.js/src/structures/Invite.js b/packages/discord.js/src/structures/Invite.js index 77c96c726..7f4726304 100644 --- a/packages/discord.js/src/structures/Invite.js +++ b/packages/discord.js/src/structures/Invite.js @@ -1,6 +1,5 @@ 'use strict'; -const { InviteTargetType } = require('discord-api-types/v9'); const Base = require('./Base'); const { GuildScheduledEvent } = require('./GuildScheduledEvent'); const IntegrationApplication = require('./IntegrationApplication'); @@ -148,7 +147,7 @@ class Invite extends Base { * The target type * @type {?InviteTargetType} */ - this.targetType = InviteTargetType[data.target_type]; + this.targetType = data.target_type; } else { this.targetType ??= null; } diff --git a/packages/discord.js/src/structures/Message.js b/packages/discord.js/src/structures/Message.js index 720085f40..a9c52bc78 100644 --- a/packages/discord.js/src/structures/Message.js +++ b/packages/discord.js/src/structures/Message.js @@ -3,7 +3,7 @@ const { createComponent } = require('@discordjs/builders'); const { Collection } = require('@discordjs/collection'); const { DiscordSnowflake } = require('@sapphire/snowflake'); -const { MessageType, InteractionType } = require('discord-api-types/v9'); +const { InteractionType, ChannelType, MessageType } = require('discord-api-types/v9'); const Base = require('./Base'); const ClientApplication = require('./ClientApplication'); const InteractionCollector = require('./InteractionCollector'); @@ -15,7 +15,7 @@ const ReactionCollector = require('./ReactionCollector'); const { Sticker } = require('./Sticker'); const { Error } = require('../errors'); const ReactionManager = require('../managers/ReactionManager'); -const { SystemMessageTypes } = require('../util/Constants'); +const { NonSystemMessageTypes } = require('../util/Constants'); const MessageFlags = require('../util/MessageFlags'); const Permissions = require('../util/Permissions'); const Util = require('../util/Util'); @@ -61,13 +61,13 @@ class Message extends Base { * The type of the message * @type {?MessageType} */ - this.type = MessageType[data.type]; + this.type = data.type; /** * Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications) * @type {?boolean} */ - this.system = SystemMessageTypes.includes(this.type); + this.system = !NonSystemMessageTypes.includes(this.type); } else { this.system ??= null; this.type ??= null; @@ -334,7 +334,7 @@ class Message extends Base { */ this.interaction = { id: data.interaction.id, - type: InteractionType[data.interaction.type], + type: data.interaction.type, commandName: data.interaction.name, user: this.client.users._add(data.interaction.user), }; @@ -620,9 +620,9 @@ class Message extends Base { (this.author.id === this.client.user.id ? Permissions.defaultBit : Permissions.FLAGS.MANAGE_MESSAGES); const { channel } = this; return Boolean( - channel?.type === 'GUILD_NEWS' && + channel?.type === ChannelType.GuildNews && !this.flags.has(MessageFlags.FLAGS.CROSSPOSTED) && - this.type === 'DEFAULT' && + this.type === MessageType.Default && channel.viewable && channel.permissionsFor(this.client.user)?.has(bitfield, false), ); @@ -662,7 +662,7 @@ class Message extends Base { * @returns {Promise} * @example * // Crosspost a message - * if (message.channel.type === 'GUILD_NEWS') { + * if (message.channel.type === ChannelType.GuildNews) { * message.crosspost() * .then(() => console.log('Crossposted message')) * .catch(console.error); @@ -812,7 +812,7 @@ class Message extends Base { */ startThread(options = {}) { if (!this.channel) return Promise.reject(new Error('CHANNEL_NOT_CACHED')); - if (!['GUILD_TEXT', 'GUILD_NEWS'].includes(this.channel.type)) { + if (![ChannelType.GuildText, ChannelType.GuildNews].includes(this.channel.type)) { return Promise.reject(new Error('MESSAGE_THREAD_PARENT')); } if (this.hasThread) return Promise.reject(new Error('MESSAGE_EXISTING_THREAD')); diff --git a/packages/discord.js/src/structures/MessageComponentInteraction.js b/packages/discord.js/src/structures/MessageComponentInteraction.js index f421fc38d..1073c02bb 100644 --- a/packages/discord.js/src/structures/MessageComponentInteraction.js +++ b/packages/discord.js/src/structures/MessageComponentInteraction.js @@ -1,6 +1,5 @@ 'use strict'; -const { ComponentType } = require('discord-api-types/v9'); const Interaction = require('./Interaction'); const InteractionWebhook = require('./InteractionWebhook'); const InteractionResponses = require('./interfaces/InteractionResponses'); @@ -34,9 +33,9 @@ class MessageComponentInteraction extends Interaction { /** * The type of component which was interacted with - * @type {string} + * @type {ComponentType} */ - this.componentType = MessageComponentInteraction.resolveType(data.data.component_type); + this.componentType = data.data.component_type; /** * Whether the reply to this interaction has been deferred @@ -81,16 +80,6 @@ class MessageComponentInteraction extends Interaction { .find(component => (component.customId ?? component.custom_id) === this.customId); } - /** - * Resolves the type of a MessageComponent - * @param {MessageComponentTypeResolvable} type The type to resolve - * @returns {ComponentType} - * @private - */ - static resolveType(type) { - return typeof type === 'string' ? type : ComponentType[type]; - } - // These are here only for documentation purposes - they are implemented by InteractionResponses /* eslint-disable no-empty-function */ deferReply() {} diff --git a/packages/discord.js/src/structures/MessageMentions.js b/packages/discord.js/src/structures/MessageMentions.js index 04188320a..f967cf0f6 100644 --- a/packages/discord.js/src/structures/MessageMentions.js +++ b/packages/discord.js/src/structures/MessageMentions.js @@ -1,7 +1,6 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); -const { ChannelType } = require('discord-api-types/v9'); const Util = require('../util/Util'); /** @@ -112,13 +111,11 @@ class MessageMentions { this.crosspostedChannels = new Collection(crosspostedChannels); } else { this.crosspostedChannels = new Collection(); - const channelTypes = Object.keys(ChannelType); for (const d of crosspostedChannels) { - const type = channelTypes[d.type]; this.crosspostedChannels.set(d.id, { channelId: d.id, guildId: d.guild_id, - type: type ?? 'UNKNOWN', + type: d.type, name: d.name, }); } diff --git a/packages/discord.js/src/structures/NewsChannel.js b/packages/discord.js/src/structures/NewsChannel.js index e2ef0a87c..a39fc2a73 100644 --- a/packages/discord.js/src/structures/NewsChannel.js +++ b/packages/discord.js/src/structures/NewsChannel.js @@ -14,7 +14,7 @@ class NewsChannel extends BaseGuildTextChannel { * @param {string} [reason] Reason for creating the webhook * @returns {Promise} * @example - * if (channel.type === 'GUILD_NEWS') { + * if (channel.type === ChannelType.GuildNews) { * channel.addFollower('222197033908436994', 'Important announcements') * .then(() => console.log('Added follower')) * .catch(console.error); diff --git a/packages/discord.js/src/structures/PermissionOverwrites.js b/packages/discord.js/src/structures/PermissionOverwrites.js index e3005ed87..9a29bfa3f 100644 --- a/packages/discord.js/src/structures/PermissionOverwrites.js +++ b/packages/discord.js/src/structures/PermissionOverwrites.js @@ -37,7 +37,7 @@ class PermissionOverwrites extends Base { * The type of this overwrite * @type {OverwriteType} */ - this.type = typeof data.type === 'number' ? OverwriteType[data.type] : data.type; + this.type = data.type; } if ('deny' in data) { @@ -71,7 +71,7 @@ class PermissionOverwrites extends Base { * .catch(console.error); */ async edit(options, reason) { - await this.channel.permissionOverwrites.upsert(this.id, options, { type: OverwriteType[this.type], reason }, this); + await this.channel.permissionOverwrites.upsert(this.id, options, { type: this.type, reason }, this); return this; } @@ -88,7 +88,7 @@ class PermissionOverwrites extends Base { toJSON() { return { id: this.id, - type: OverwriteType[this.type], + type: this.type, allow: this.allow, deny: this.deny, }; @@ -174,7 +174,7 @@ class PermissionOverwrites extends Base { if (typeof overwrite.id === 'string' && overwrite.type in OverwriteType) { return { id: overwrite.id, - type: OverwriteType[overwrite.type], + type: overwrite.type, allow: Permissions.resolve(overwrite.allow ?? Permissions.defaultBit).toString(), deny: Permissions.resolve(overwrite.deny ?? Permissions.defaultBit).toString(), }; diff --git a/packages/discord.js/src/structures/Presence.js b/packages/discord.js/src/structures/Presence.js index a3cc4191a..2d4e17737 100644 --- a/packages/discord.js/src/structures/Presence.js +++ b/packages/discord.js/src/structures/Presence.js @@ -1,6 +1,5 @@ 'use strict'; -const { ActivityType } = require('discord-api-types/v9'); const Base = require('./Base'); const { Emoji } = require('./Emoji'); const ActivityFlags = require('../util/ActivityFlags'); @@ -168,7 +167,7 @@ class Activity { * The activity status's type * @type {ActivityType} */ - this.type = typeof data.type === 'number' ? ActivityType[data.type] : data.type; + this.type = data.type; /** * If the activity is being streamed, a link to the stream diff --git a/packages/discord.js/src/structures/StageInstance.js b/packages/discord.js/src/structures/StageInstance.js index f01582ae3..47c43277d 100644 --- a/packages/discord.js/src/structures/StageInstance.js +++ b/packages/discord.js/src/structures/StageInstance.js @@ -1,7 +1,6 @@ 'use strict'; const { DiscordSnowflake } = require('@sapphire/snowflake'); -const { StageInstancePrivacyLevel } = require('discord-api-types/v9'); const Base = require('./Base'); /** @@ -51,7 +50,7 @@ class StageInstance extends Base { * The privacy level of the stage instance * @type {StageInstancePrivacyLevel} */ - this.privacyLevel = StageInstancePrivacyLevel[data.privacy_level]; + this.privacyLevel = data.privacy_level; } if ('discoverable_disabled' in data) { diff --git a/packages/discord.js/src/structures/Sticker.js b/packages/discord.js/src/structures/Sticker.js index 754ff6556..834f48e76 100644 --- a/packages/discord.js/src/structures/Sticker.js +++ b/packages/discord.js/src/structures/Sticker.js @@ -1,7 +1,6 @@ 'use strict'; const { DiscordSnowflake } = require('@sapphire/snowflake'); -const { StickerType, StickerFormatType } = require('discord-api-types/v9'); const Base = require('./Base'); /** @@ -37,7 +36,7 @@ class Sticker extends Base { * The type of the sticker * @type {?StickerType} */ - this.type = StickerType[sticker.type]; + this.type = sticker.type; } else { this.type ??= null; } @@ -47,7 +46,7 @@ class Sticker extends Base { * The format of the sticker * @type {StickerFormatType} */ - this.format = StickerFormatType[sticker.format_type]; + this.format = sticker.format_type; } if ('name' in sticker) { diff --git a/packages/discord.js/src/structures/TeamMember.js b/packages/discord.js/src/structures/TeamMember.js index 92011ab6f..92704187a 100644 --- a/packages/discord.js/src/structures/TeamMember.js +++ b/packages/discord.js/src/structures/TeamMember.js @@ -1,6 +1,5 @@ 'use strict'; -const { TeamMemberMembershipState } = require('discord-api-types/v9'); const Base = require('./Base'); /** @@ -34,7 +33,7 @@ class TeamMember extends Base { * The permissions this Team Member has with regard to the team * @type {TeamMemberMembershipState} */ - this.membershipState = TeamMemberMembershipState[data.membership_state]; + this.membershipState = data.membership_state; } if ('user' in data) { diff --git a/packages/discord.js/src/structures/ThreadChannel.js b/packages/discord.js/src/structures/ThreadChannel.js index 3d26f491d..cd3b5cfd4 100644 --- a/packages/discord.js/src/structures/ThreadChannel.js +++ b/packages/discord.js/src/structures/ThreadChannel.js @@ -1,5 +1,6 @@ 'use strict'; +const { ChannelType } = require('discord-api-types/v9'); const { Channel } = require('./Channel'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); const { RangeError } = require('../errors'); @@ -79,7 +80,7 @@ class ThreadChannel extends Channel { * Always `null` in public threads * @type {?boolean} */ - this.invitable = this.type === 'GUILD_PRIVATE_THREAD' ? data.thread_metadata.invitable ?? false : null; + this.invitable = this.type === ChannelType.GuildPrivateThread ? data.thread_metadata.invitable ?? false : null; /** * Whether the thread is archived @@ -302,7 +303,7 @@ class ThreadChannel extends Channel { auto_archive_duration: autoArchiveDuration, rate_limit_per_user: data.rateLimitPerUser, locked: data.locked, - invitable: this.type === 'GUILD_PRIVATE_THREAD' ? data.invitable : undefined, + invitable: this.type === ChannelType.GuildPrivateThread ? data.invitable : undefined, }, reason, }); @@ -351,7 +352,9 @@ class ThreadChannel extends Channel { * @returns {Promise} */ setInvitable(invitable = true, reason) { - if (this.type !== 'GUILD_PRIVATE_THREAD') return Promise.reject(new RangeError('THREAD_INVITABLE_TYPE', this.type)); + if (this.type !== ChannelType.GuildPrivateThread) { + return Promise.reject(new RangeError('THREAD_INVITABLE_TYPE', this.type)); + } return this.edit({ invitable }, reason); } @@ -412,7 +415,8 @@ class ThreadChannel extends Channel { */ get editable() { return ( - (this.ownerId === this.client.user.id && (this.type !== 'GUILD_PRIVATE_THREAD' || this.joined)) || this.manageable + (this.ownerId === this.client.user.id && (this.type !== ChannelType.GuildPrivateThread || this.joined)) || + this.manageable ); } @@ -426,7 +430,9 @@ class ThreadChannel extends Channel { !this.archived && !this.joined && this.permissionsFor(this.client.user)?.has( - this.type === 'GUILD_PRIVATE_THREAD' ? Permissions.FLAGS.MANAGE_THREADS : Permissions.FLAGS.VIEW_CHANNEL, + this.type === ChannelType.GuildPrivateThread + ? Permissions.FLAGS.MANAGE_THREADS + : Permissions.FLAGS.VIEW_CHANNEL, false, ) ); @@ -474,7 +480,7 @@ class ThreadChannel extends Channel { return ( !(this.archived && this.locked && !this.manageable) && - (this.type !== 'GUILD_PRIVATE_THREAD' || this.joined || this.manageable) && + (this.type !== ChannelType.GuildPrivateThread || this.joined || this.manageable) && permissions.has(Permissions.FLAGS.SEND_MESSAGES_IN_THREADS, false) && this.guild.me.communicationDisabledUntilTimestamp < Date.now() ); diff --git a/packages/discord.js/src/structures/VoiceState.js b/packages/discord.js/src/structures/VoiceState.js index 06cc8cdad..bf8577338 100644 --- a/packages/discord.js/src/structures/VoiceState.js +++ b/packages/discord.js/src/structures/VoiceState.js @@ -1,5 +1,6 @@ 'use strict'; +const { ChannelType } = require('discord-api-types/v9'); const Base = require('./Base'); const { Error, TypeError } = require('../errors'); @@ -217,7 +218,7 @@ class VoiceState extends Base { * @returns {Promise} */ async setRequestToSpeak(request = true) { - if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL'); + if (this.channel?.type !== ChannelType.GuildStageVoice) throw new Error('VOICE_NOT_STAGE_CHANNEL'); if (this.client.user.id !== this.id) throw new Error('VOICE_STATE_NOT_OWN'); @@ -249,7 +250,7 @@ class VoiceState extends Base { async setSuppressed(suppressed = true) { if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed'); - if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL'); + if (this.channel?.type !== ChannelType.GuildStageVoice) throw new Error('VOICE_NOT_STAGE_CHANNEL'); const target = this.client.user.id === this.id ? '@me' : this.id; diff --git a/packages/discord.js/src/structures/Webhook.js b/packages/discord.js/src/structures/Webhook.js index cea5484fb..116faf51e 100644 --- a/packages/discord.js/src/structures/Webhook.js +++ b/packages/discord.js/src/structures/Webhook.js @@ -56,7 +56,7 @@ class Webhook { * The type of the webhook * @type {WebhookType} */ - this.type = WebhookType[data.type]; + this.type = data.type; } if ('guild_id' in data) { @@ -398,7 +398,7 @@ class Webhook { * @returns {boolean} */ isChannelFollower() { - return this.type === 'ChannelFollower'; + return this.type === WebhookType.ChannelFollower; } /** @@ -406,7 +406,7 @@ class Webhook { * @returns {boolean} */ isIncoming() { - return this.type === 'Incoming'; + return this.type === WebhookType.Incoming; } static applyToClass(structure, ignore = []) { diff --git a/packages/discord.js/src/util/Constants.js b/packages/discord.js/src/util/Constants.js index 153b069a8..476db7fbc 100644 --- a/packages/discord.js/src/util/Constants.js +++ b/packages/discord.js/src/util/Constants.js @@ -1,6 +1,7 @@ 'use strict'; const process = require('node:process'); +const { ChannelType, MessageType, StickerFormatType } = require('discord-api-types/v9'); const Package = (exports.Package = require('../../package.json')); const { Error, RangeError, TypeError } = require('../errors'); @@ -83,7 +84,8 @@ exports.Endpoints = { DiscoverySplash: (guildId, hash, options) => makeImageUrl(`${root}/discovery-splashes/${guildId}`, { hash, ...options }), TeamIcon: (teamId, hash, options) => makeImageUrl(`${root}/team-icons/${teamId}`, { hash, ...options }), - Sticker: (stickerId, format) => `${root}/stickers/${stickerId}.${format === 'LOTTIE' ? 'json' : 'png'}`, + Sticker: (stickerId, format) => + `${root}/stickers/${stickerId}.${format === StickerFormatType.Lottie ? 'json' : 'png'}`, RoleIcon: (roleId, hash, options) => makeImageUrl(`${root}/role-icons/${roleId}`, { hash, ...options }), }; }, @@ -384,61 +386,6 @@ exports.InviteScopes = [ */ exports.IntegrationExpireBehaviors = createEnum(['REMOVE_ROLE', 'KICK']); -/** - * The type of a message, e.g. `DEFAULT`. Here are the available types: - * * DEFAULT - * * RECIPIENT_ADD - * * RECIPIENT_REMOVE - * * CALL - * * CHANNEL_NAME_CHANGE - * * CHANNEL_ICON_CHANGE - * * CHANNEL_PINNED_MESSAGE - * * GUILD_MEMBER_JOIN - * * USER_PREMIUM_GUILD_SUBSCRIPTION - * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 - * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 - * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 - * * CHANNEL_FOLLOW_ADD - * * GUILD_DISCOVERY_DISQUALIFIED - * * GUILD_DISCOVERY_REQUALIFIED - * * GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING - * * GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING - * * THREAD_CREATED - * * REPLY - * * CHAT_INPUT_COMMAND - * * THREAD_STARTER_MESSAGE - * * GUILD_INVITE_REMINDER - * * CONTEXT_MENU_COMMAND - * @typedef {string} MessageType - * @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-types} - */ -exports.MessageTypes = [ - 'DEFAULT', - 'RECIPIENT_ADD', - 'RECIPIENT_REMOVE', - 'CALL', - 'CHANNEL_NAME_CHANGE', - 'CHANNEL_ICON_CHANGE', - 'CHANNEL_PINNED_MESSAGE', - 'GUILD_MEMBER_JOIN', - 'USER_PREMIUM_GUILD_SUBSCRIPTION', - 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1', - 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2', - 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3', - 'CHANNEL_FOLLOW_ADD', - null, - 'GUILD_DISCOVERY_DISQUALIFIED', - 'GUILD_DISCOVERY_REQUALIFIED', - 'GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING', - 'GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING', - 'THREAD_CREATED', - 'REPLY', - 'CHAT_INPUT_COMMAND', - 'THREAD_STARTER_MESSAGE', - 'GUILD_INVITE_REMINDER', - 'CONTEXT_MENU_COMMAND', -]; - /** * The name of an item to be swept in Sweepers * * `applicationCommands` - both global and guild commands @@ -475,16 +422,19 @@ exports.SweeperKeys = [ ]; /** - * The types of messages that are `System`. The available types are `MessageTypes` excluding: - * * DEFAULT - * * REPLY - * * CHAT_INPUT_COMMAND - * * CONTEXT_MENU_COMMAND - * @typedef {string} SystemMessageType + * The types of messages that are not `System`. The available types are: + * * `MessageType.Default` + * * `MessageType.Reply` + * * `MessageType.ChatInputCommand` + * * `MessageType.ContextMenuCommand` + * @typedef {MessageType[]} NonSystemMessageTypes */ -exports.SystemMessageTypes = exports.MessageTypes.filter( - type => type && !['DEFAULT', 'REPLY', 'CHAT_INPUT_COMMAND', 'CONTEXT_MENU_COMMAND'].includes(type), -); +exports.NonSystemMessageTypes = [ + MessageType.Default, + MessageType.Reply, + MessageType.ChatInputCommand, + MessageType.ContextMenuCommand, +]; /** * The channels that are text-based. @@ -497,39 +447,43 @@ exports.SystemMessageTypes = exports.MessageTypes.filter( /** * The types of channels that are text-based. The available types are: - * * DM - * * GUILD_TEXT - * * GUILD_NEWS - * * GUILD_NEWS_THREAD - * * GUILD_PUBLIC_THREAD - * * GUILD_PRIVATE_THREAD - * @typedef {string} TextBasedChannelTypes + * * `ChannelType.DM` + * * `ChannelType.GuildText` + * * `ChannelType.GuildNews` + * * `ChannelType.GuildNewsThread` + * * `ChannelType.GuildPublicThread` + * * `ChannelType.GuildPrivateThread` + * @typedef {ChannelType} TextBasedChannelTypes */ exports.TextBasedChannelTypes = [ - 'DM', - 'GUILD_TEXT', - 'GUILD_NEWS', - 'GUILD_NEWS_THREAD', - 'GUILD_PUBLIC_THREAD', - 'GUILD_PRIVATE_THREAD', + ChannelType.DM, + ChannelType.GuildText, + ChannelType.GuildNews, + ChannelType.GuildNewsThread, + ChannelType.GuildPublicThread, + ChannelType.GuildPrivateThread, ]; /** * The types of channels that are threads. The available types are: - * * GUILD_NEWS_THREAD - * * GUILD_PUBLIC_THREAD - * * GUILD_PRIVATE_THREAD - * @typedef {string} ThreadChannelTypes + * * `ChannelType.GuildNewsThread` + * * `ChannelType.GuildPublicThread` + * * `ChannelType.GuildPrivateThread` + * @typedef {ChannelType[]} ThreadChannelTypes */ -exports.ThreadChannelTypes = ['GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD']; +exports.ThreadChannelTypes = [ + ChannelType.GuildNewsThread, + ChannelType.GuildPublicThread, + ChannelType.GuildPrivateThread, +]; /** * The types of channels that are voice-based. The available types are: - * * GUILD_VOICE - * * GUILD_STAGE_VOICE - * @typedef {string} VoiceBasedChannelTypes + * * `ChannelType.GuildVoice` + * * `ChannelType.GuildStageVoice` + * @typedef {ChannelType[]} VoiceBasedChannelTypes */ -exports.VoiceBasedChannelTypes = ['GUILD_VOICE', 'GUILD_STAGE_VOICE']; +exports.VoiceBasedChannelTypes = [ChannelType.GuildVoice, ChannelType.GuildStageVoice]; exports.Colors = { DEFAULT: 0x000000, diff --git a/packages/discord.js/src/util/EnumResolvers.js b/packages/discord.js/src/util/EnumResolvers.js new file mode 100644 index 000000000..947ec4a80 --- /dev/null +++ b/packages/discord.js/src/util/EnumResolvers.js @@ -0,0 +1,265 @@ +'use strict'; + +const { + ApplicationCommandType, + InteractionType, + ComponentType, + ButtonStyle, + ApplicationCommandOptionType, + ChannelType, + ApplicationCommandPermissionType, + MessageType, +} = require('discord-api-types/v9'); + +function unknownKeyStrategy(val) { + throw new Error(`Could not resolve enum value for ${val}`); +} + +class EnumResolvers extends null { + /** + * Resolves enum key to `ChannelType` enum value + * @param {string|ChannelType} key The key to resolve + * @returns {ChannelType} + */ + static resolveChannelType(key) { + switch (key) { + case 'GUILD_TEXT': + return ChannelType.GuildText; + case 'DM': + return ChannelType.DM; + case 'GUILD_VOICE': + return ChannelType.GuildVoice; + case 'GROUP_DM': + return ChannelType.GroupDM; + case 'GUILD_CATEGORY': + return ChannelType.GuildCategory; + case 'GUILD_NEWS': + return ChannelType.GuildNews; + case 'GUILD_NEWS_THREAD': + return ChannelType.GuildNewsThread; + case 'GUILD_PUBLIC_THREAD': + return ChannelType.GuildPublicThread; + case 'GUILD_PRIVATE_THREAD': + return ChannelType.GuildPrivateThread; + case 'GUILD_STAGE_VOICE': + return ChannelType.GuildStageVoice; + default: + return unknownKeyStrategy(key); + } + } + + /** + * Resolves enum key to `InteractionType` enum value + * @param {string|InteractionType} key The key to resolve + * @returns {InteractionType} + */ + static resolveInteractionType(key) { + switch (key) { + case 'PING': + return InteractionType.Ping; + case 'APPLICATION_COMMAND': + return InteractionType.ApplicationCommand; + case 'MESSAGE_COMPONENT': + return InteractionType.MessageComponent; + case 'APPLICATION_COMMAND_AUTOCOMPLETE': + return InteractionType.ApplicationCommandAutocomplete; + default: + return unknownKeyStrategy(key); + } + } + + /** + * Resolves enum key to `ApplicationCommandType` enum value + * @param {string|ApplicationCommandType} key The key to resolve + * @returns {ApplicationCommandType} + */ + static resolveApplicationCommandType(key) { + switch (key) { + case 'CHAT_INPUT': + return ApplicationCommandType.ChatInput; + case 'USER': + return ApplicationCommandType.User; + case 'MESSAGE': + return ApplicationCommandType.Message; + default: + return unknownKeyStrategy(key); + } + } + + /** + * Resolves enum key to `ApplicationCommandOptionType` enum value + * @param {string|ApplicationCommandOptionType} key The key to resolve + * @returns {ApplicationCommandOptionType} + */ + static resolveApplicationCommandOptionType(key) { + switch (key) { + case 'SUB_COMMAND': + return ApplicationCommandOptionType.Subcommand; + case 'SUB_COMMAND_GROUP': + return ApplicationCommandOptionType.SubcommandGroup; + case 'STRING': + return ApplicationCommandOptionType.String; + case 'INTEGER': + return ApplicationCommandOptionType.Integer; + case 'BOOLEAN': + return ApplicationCommandOptionType.Boolean; + case 'USER': + return ApplicationCommandOptionType.User; + case 'CHANNEL': + return ApplicationCommandOptionType.Channel; + case 'ROLE': + return ApplicationCommandOptionType.Role; + case 'NUMBER': + return ApplicationCommandOptionType.Number; + case 'MENTIONABLE': + return ApplicationCommandOptionType.Mentionable; + default: + return unknownKeyStrategy(key); + } + } + + /** + * Resolves enum key to `ApplicationCommandPermissionType` enum value + * @param {string|ApplicationCommandPermissionType} key The key to resolve + * @returns {ApplicationCommandPermissionType} + */ + static resolveApplicationCommandPermissionType(key) { + switch (key) { + case 'ROLE': + return ApplicationCommandPermissionType.Role; + case 'USER': + return ApplicationCommandPermissionType.User; + default: + return unknownKeyStrategy(key); + } + } + + /** + * Resolves enum key to `ComponentType` enum value + * @param {string|ComponentType} key The key to resolve + * @returns {ComponentType} + */ + static resolveComponentType(key) { + switch (key) { + case 'ACTION_ROW': + return ComponentType.ActionRow; + case 'BUTTON': + return ComponentType.Button; + case 'SELECT_MENU': + return ComponentType.SelectMenu; + default: + return unknownKeyStrategy(key); + } + } + + /** + * Resolves enum key to `ButtonStyle` enum value + * @param {string|ButtonStyle} key The key to resolve + * @returns {ButtonStyle} + */ + static resolveButtonStyle(key) { + switch (key) { + case 'PRIMARY': + return ButtonStyle.Primary; + case 'SECONDARY': + return ButtonStyle.Secondary; + case 'SUCCESS': + return ButtonStyle.Success; + case 'DANGER': + return ButtonStyle.Danger; + case 'LINK': + return ButtonStyle.Link; + default: + return unknownKeyStrategy(key); + } + } + + /** + * Resolves enum key to `MessageType` enum value + * @param {string|MessageType} key The key to lookup + * @returns {MessageType} + */ + static resolveMessageType(key) { + switch (key) { + case 'DEFAULT': + return MessageType.Default; + case 'RECIPIENT_ADD': + return MessageType.RecipientAdd; + case 'RECIPIENT_REMOVE': + return MessageType.RecipientRemove; + case 'CALL': + return MessageType.Call; + case 'CHANNEL_NAME_CHANGE': + return MessageType.ChannelNameChange; + case 'CHANNEL_ICON_CHANGE': + return MessageType.ChannelIconChange; + case 'CHANNEL_PINNED_MESSAGE': + return MessageType.ChannelPinnedMessage; + case 'GUILD_MEMBER_JOIN': + return MessageType.GuildMemberJoin; + case 'USER_PREMIUM_GUILD_SUBSCRIPTION': + return MessageType.UserPremiumGuildSubscription; + case 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1': + return MessageType.UserPremiumGuildSubscriptionTier1; + case 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2': + return MessageType.UserPremiumGuildSubscriptionTier2; + case 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3': + return MessageType.UserPremiumGuildSubscriptionTier3; + case 'CHANNEL_FOLLOW_ADD': + return MessageType.ChannelFollowAdd; + case 'GUILD_DISCOVERY_DISQUALIFIED': + return MessageType.GuildDiscoveryDisqualified; + case 'GUILD_DISCOVERY_REQUALIFIED': + return MessageType.GuildDiscoveryRequalified; + case 'GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING': + return MessageType.GuildDiscoveryGracePeriodInitialWarning; + case 'GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING': + return MessageType.GuildDiscoveryGracePeriodFinalWarning; + case 'THREAD_CREATED': + return MessageType.ThreadCreated; + case 'REPLY': + return MessageType.Reply; + case 'CHAT_INPUT_COMMAND': + return MessageType.ChatInputCommand; + case 'THREAD_STARTER_MESSAGE': + return MessageType.ThreadStarterMessage; + case 'GUILD_INVITE_REMINDER': + return MessageType.GuildInviteReminder; + case 'CONTEXT_MENU_COMMAND': + return MessageType.ContextMenuCommand; + default: + return unknownKeyStrategy(key); + } + } +} + +// Precondition logic wrapper +function preconditioner(func) { + return key => { + if (typeof key !== 'string' && typeof key !== 'number') { + throw new Error('Enum value must be string or number'); + } + + if (typeof key === 'number') { + return key; + } + + return func(key); + }; +} + +// Injects wrapper into class static methods. +function applyPreconditioner(obj) { + for (const name in Object.getOwnPropertyNames(obj)) { + if (typeof obj[name] !== 'function') { + return; + } + + obj[name] = preconditioner(obj[name]); + } +} + +// Apply precondition logic +applyPreconditioner(EnumResolvers); + +module.exports = EnumResolvers; diff --git a/packages/discord.js/src/util/Util.js b/packages/discord.js/src/util/Util.js index b8f2e576b..48999e6c6 100644 --- a/packages/discord.js/src/util/Util.js +++ b/packages/discord.js/src/util/Util.js @@ -2,6 +2,7 @@ const { parse } = require('node:path'); const { Collection } = require('@discordjs/collection'); +const { ChannelType } = require('discord-api-types/v9'); const fetch = require('node-fetch'); const { Colors, Endpoints } = require('./Constants'); const Options = require('./Options'); @@ -528,7 +529,7 @@ class Util extends null { str = str .replace(/<@!?[0-9]+>/g, input => { const id = input.replace(/<|!|>|@/g, ''); - if (channel.type === 'DM') { + if (channel.type === ChannelType.DM) { const user = channel.client.users.cache.get(id); return user ? `@${user.username}` : input; } @@ -546,7 +547,7 @@ class Util extends null { return mentionedChannel ? `#${mentionedChannel.name}` : input; }) .replace(/<@&[0-9]+>/g, input => { - if (channel.type === 'DM') return input; + if (channel.type === ChannelType.DM) return input; const role = channel.guild.roles.cache.get(input.replace(/<|@|>|&/g, '')); return role ? `@${role.name}` : input; }); diff --git a/packages/discord.js/test/createGuild.js b/packages/discord.js/test/createGuild.js index 24826c419..27de1d841 100644 --- a/packages/discord.js/test/createGuild.js +++ b/packages/discord.js/test/createGuild.js @@ -1,6 +1,7 @@ 'use strict'; const assert = require('node:assert'); +const { ChannelType } = require('discord-api-types/v9'); const { token } = require('./auth'); const { Client, Intents } = require('../src'); @@ -10,7 +11,7 @@ client.on('ready', async () => { try { const guild = await client.guilds.create('testing', { channels: [ - { name: 'afk channel', type: 'GUILD_VOICE', id: 0 }, + { name: 'afk channel', type: ChannelType.GuildVoice, id: 0 }, { name: 'system-channel', id: 1 }, ], afkChannelId: 0, diff --git a/packages/discord.js/test/random.js b/packages/discord.js/test/random.js index c24f70043..2e4fd35cc 100644 --- a/packages/discord.js/test/random.js +++ b/packages/discord.js/test/random.js @@ -6,6 +6,7 @@ const request = require('superagent'); const ytdl = require('ytdl-core'); const { token, song } = require('./auth.js'); const { Client, Intents } = require('../src'); +const { ChannelType } = require('discord-api-types/v9'); console.time('magic'); @@ -57,7 +58,7 @@ client.on('messageCreate', message => { if (true) { if (message.content === 'makechann') { if (message.channel.guild) { - message.channel.guild.channels.create('hi', { type: 'GUILD_TEXT' }).then(console.log); + message.channel.guild.channels.create('hi', { type: ChannelType.GuildText }).then(console.log); } } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 6421fdc71..c43368010 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -174,7 +174,7 @@ export class Activity { start: Date | null; end: Date | null; } | null; - public type: ActivityTypeKey; + public type: ActivityType; public url: string | null; public equals(activity: Activity): boolean; } @@ -230,7 +230,7 @@ export class ApplicationCommand extends Base { Guild | null, Snowflake >; - public type: ApplicationCommandTypeKey; + public type: ApplicationCommandType; public version: Snowflake; public delete(): Promise>; public edit(data: ApplicationCommandData): Promise>; @@ -473,35 +473,29 @@ export class ButtonInteraction extends Mes public inRawGuild(): this is ButtonInteraction<'raw'>; } -export type KeyedEnum = { - [Key in keyof K]: T | string; -}; +export interface MappedChannelCategoryTypes { + [ChannelType.GuildNews]: NewsChannel; + [ChannelType.GuildVoice]: VoiceChannel; + [ChannelType.GuildText]: TextChannel; + [ChannelType.GuildStore]: StoreChannel; + [ChannelType.GuildStageVoice]: StageChannel; +} -export type EnumValueMapped, T extends Partial>> = T & { - [Key in keyof T as E[Key]]: T[Key]; -}; - -export type MappedChannelCategoryTypes = EnumValueMapped< - typeof ChannelType, - { - GuildNews: NewsChannel; - GuildVoice: VoiceChannel; - GuildText: TextChannel; - GuildStore: StoreChannel; - GuildStageVoice: StageChannel; - } ->; - -export type CategoryChannelTypes = ExcludeEnum< - typeof ChannelType, - 'DM' | 'GroupDM' | 'GuildPublicThread' | 'GuildNewsThread' | 'GuildPrivateThread' | 'GuildCategory' +export type CategoryChannelType = Exclude< + ChannelType, + | ChannelType.DM + | ChannelType.GroupDM + | ChannelType.GuildPublicThread + | ChannelType.GuildNewsThread + | ChannelType.GuildPrivateThread + | ChannelType.GuildCategory >; export class CategoryChannel extends GuildChannel { public readonly children: Collection>; - public type: 'GuildCategory'; + public type: ChannelType.GuildCategory; - public createChannel>( + public createChannel>( name: string, options: CategoryCreateChannelOptions & { type: T }, ): Promise; @@ -509,7 +503,7 @@ export class CategoryChannel extends GuildChannel { /** @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */ public createChannel( name: string, - options: CategoryCreateChannelOptions & { type: 'GuildStore' | ChannelType.GuildStore }, + options: CategoryCreateChannelOptions & { type: ChannelType.GuildStore }, ): Promise; public createChannel(name: string, options?: CategoryCreateChannelOptions): Promise; } @@ -522,7 +516,7 @@ export abstract class Channel extends Base { public readonly createdTimestamp: number; public id: Snowflake; public readonly partial: false; - public type: keyof typeof ChannelType; + public type: ChannelType; public delete(): Promise; public fetch(force?: boolean): Promise; public isText(): this is TextChannel; @@ -743,7 +737,6 @@ export class AutocompleteInteraction exten public inGuild(): this is AutocompleteInteraction<'raw' | 'cached'>; public inCachedGuild(): this is AutocompleteInteraction<'cached'>; public inRawGuild(): this is AutocompleteInteraction<'raw'>; - private transformOption(option: APIApplicationCommandOption): CommandInteractionOption; public respond(options: ApplicationCommandOptionChoice[]): Promise; } @@ -757,13 +750,13 @@ export class CommandInteractionOptionResolver; private _getTypedOption( name: string, - type: ApplicationCommandOptionTypeKey, + type: ApplicationCommandOptionType, properties: (keyof ApplicationCommandOption)[], required: boolean, ): CommandInteractionOption | null; @@ -819,7 +812,7 @@ export class ContextMenuCommandInteraction | 'getSubcommand' >; public targetId: Snowflake; - public targetType: Exclude; + public targetType: Exclude; public inGuild(): this is ContextMenuCommandInteraction<'raw' | 'cached'>; public inCachedGuild(): this is ContextMenuCommandInteraction<'cached'>; public inRawGuild(): this is ContextMenuCommandInteraction<'raw'>; @@ -837,6 +830,22 @@ export class DataResolver extends null { public static resolveGuildTemplateCode(data: GuildTemplateResolvable): string; } +export class EnumResolvers extends null { + private constructor(); + public static resolveChannelType(key: string | ChannelType): ChannelType; + public static resolveInteractionType(key: string | InteractionType): InteractionType; + public static resolveApplicationCommandType(key: string | ApplicationCommandType): ApplicationCommandType; + public static resolveApplicationCommandOptionType( + key: string | ApplicationCommandOptionType, + ): ApplicationCommandOptionType; + public static resolveApplicationCommandPermissionType( + key: string | ApplicationCommandPermissionType, + ): ApplicationCommandPermissionType; + public static resolveComponentType(key: string | ComponentType): ComponentType; + public static resolveButtonStyle(key: string | ButtonStyle): ButtonStyle; + public static resolveMessageType(key: string | MessageType): MessageType; +} + export class DiscordAPIError extends Error { private constructor(error: unknown, status: number, request: unknown); private static flattenErrors(obj: unknown, key: string): string[]; @@ -852,7 +861,7 @@ export class DMChannel extends TextBasedChannelMixin(Channel, ['bulkDelete']) { private constructor(client: Client, data?: RawDMChannelData); public messages: MessageManager; public recipient: User; - public type: 'DM'; + public type: ChannelType.DM; public fetch(force?: boolean): Promise; } @@ -897,7 +906,7 @@ export class Guild extends AnonymousGuild { public readonly me: GuildMember | null; public memberCount: number; public members: GuildMemberManager; - public mfaLevel: GuildMFALevelKey; + public mfaLevel: GuildMFALevel; public ownerId: Snowflake; public preferredLocale: string; public premiumSubscriptionCount: number | null; @@ -1047,7 +1056,7 @@ export abstract class GuildChannel extends Channel { public readonly permissionsLocked: boolean | null; public readonly position: number; public rawPosition: number; - public type: Exclude; + public type: Exclude; public readonly viewable: boolean; public clone(options?: GuildChannelCloneOptions): Promise; public delete(reason?: string): Promise; @@ -1348,7 +1357,7 @@ export class InteractionCollector extends Collector extends Collection { public keepOverLimit: ((value: V, key: K, collection: this) => boolean) | null; } -export type MessageCollectorOptionsParams = +export type MessageCollectorOptionsParams = | { componentType?: T; } & MessageComponentCollectorOptions[T]>; -export type MessageChannelCollectorOptionsParams< - T extends MessageComponentTypeResolvable, - Cached extends boolean = boolean, -> = +export type MessageChannelCollectorOptionsParams = | { componentType?: T; } & MessageChannelComponentCollectorOptions[T]>; -export type AwaitMessageCollectorOptionsParams< - T extends MessageComponentTypeResolvable, - Cached extends boolean = boolean, -> = +export type AwaitMessageCollectorOptionsParams = | { componentType?: T } & Pick< InteractionCollectorOptions[T]>, keyof AwaitMessageComponentOptions @@ -1459,14 +1462,11 @@ export interface StringMappedInteractionTypes = If; -export type MappedInteractionTypes = EnumValueMapped< - typeof ComponentType, - { - Button: ButtonInteraction>; - SelectMenu: SelectMenuInteraction>; - ActionRow: MessageComponentInteraction>; - } ->; +export interface MappedInteractionTypes { + [ComponentType.Button]: ButtonInteraction>; + [ComponentType.SelectMenu]: SelectMenuInteraction>; + [ComponentType.ActionRow]: MessageComponentInteraction>; +} export class Message extends Base { private readonly _cacheType: Cached; @@ -1507,17 +1507,17 @@ export class Message extends Base { public system: boolean; public readonly thread: ThreadChannel | null; public tts: boolean; - public type: MessageTypeKey; + public type: MessageType; public readonly url: string; public webhookId: Snowflake | null; public flags: Readonly; public reference: MessageReference | null; - public awaitMessageComponent( + public awaitMessageComponent( options?: AwaitMessageCollectorOptionsParams, ): Promise[T]>; public awaitReactions(options?: AwaitReactionsOptions): Promise>; public createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector; - public createMessageComponentCollector( + public createMessageComponentCollector( options?: MessageCollectorOptionsParams, ): InteractionCollector[T]>; public delete(): Promise; @@ -1608,8 +1608,6 @@ export class MessageComponentInteraction e public reply(options: string | MessagePayload | InteractionReplyOptions): Promise; public update(options: InteractionUpdateOptions & { fetchReply: true }): Promise>; public update(options: string | MessagePayload | InteractionUpdateOptions): Promise; - - public static resolveType(type: MessageComponentTypeResolvable): ComponentTypeKey; } export class MessageContextMenuCommandInteraction< @@ -1745,7 +1743,7 @@ export class MessageReaction { export class NewsChannel extends BaseGuildTextChannel { public threads: ThreadManager; - public type: 'GuildNews'; + public type: ChannelType.GuildNews; public addFollower(channel: TextChannelResolvable, reason?: string): Promise; } @@ -2032,7 +2030,7 @@ export { export class StageChannel extends BaseGuildVoiceChannel { public topic: string | null; - public type: 'GuildStageVoice'; + public type: ChannelType.GuildStageVoice; public readonly stageInstance: StageInstance | null; public createStageInstance(options: StageInstanceCreateOptions): Promise; public setTopic(topic: string): Promise; @@ -2104,7 +2102,7 @@ export class StoreChannel extends GuildChannel { /** @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */ public clone(options?: GuildChannelCloneOptions): Promise; public nsfw: boolean; - public type: 'GuildStore'; + public type: ChannelType.GuildStore; } export class Sweepers { @@ -2205,7 +2203,7 @@ export class TeamMember extends Base { export class TextChannel extends BaseGuildTextChannel { public rateLimitPerUser: number; public threads: ThreadManager; - public type: 'GuildText'; + public type: ChannelType.GuildText; public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise; } @@ -2235,7 +2233,7 @@ export class ThreadChannel extends TextBasedChannelMixin(Channel) { public readonly parent: TextChannel | NewsChannel | null; public parentId: Snowflake | null; public rateLimitPerUser: number | null; - public type: ThreadChannelTypeKey; + public type: ThreadChannelType; public readonly unarchivable: boolean; public delete(reason?: string): Promise; public edit(data: ThreadEditData, reason?: string): Promise; @@ -2399,7 +2397,7 @@ export class Formatters extends null { export class VoiceChannel extends BaseGuildVoiceChannel { public readonly speakable: boolean; - public type: 'GuildVoice'; + public type: ChannelType.GuildVoice; public setBitrate(bitrate: number, reason?: string): Promise; public setUserLimit(userLimit: number, reason?: string): Promise; } @@ -2613,10 +2611,6 @@ export class WelcomeScreen extends Base { //#region Constants -export type EnumHolder = { [P in keyof T]: T[P] }; - -export type ExcludeEnum = Exclude; - export const Constants: { Package: { name: string; @@ -2676,7 +2670,7 @@ export const Constants: { Colors: ConstantsColors; Status: ConstantsStatus; Opcodes: ConstantsOpcodes; - ThreadChannelTypes: ThreadChannelTypeKey[]; + ThreadChannelTypes: ThreadChannelType[]; TextBasedChannelTypes: TextBasedChannelTypes[]; VoiceBasedChannelTypes: VoiceBasedChannelTypes[]; IntegrationExpireBehaviors: IntegrationExpireBehaviors[]; @@ -2831,23 +2825,23 @@ export class GuildApplicationCommandManager extends ApplicationCommandManager>; } -export type MappedGuildChannelTypes = EnumValueMapped< - typeof ChannelType, - { - GuildCategory: CategoryChannel; - } -> & - MappedChannelCategoryTypes; +export type MappedGuildChannelTypes = { + [ChannelType.GuildCategory]: CategoryChannel; +} & MappedChannelCategoryTypes; -export type GuildChannelTypes = CategoryChannelTypes | ChannelType.GuildCategory | 'GuildCategory'; +export type GuildChannelTypes = CategoryChannelType | ChannelType.GuildCategory; export class GuildChannelManager extends CachedManager { private constructor(guild: Guild, iterable?: Iterable); public readonly channelCountWithoutThreads: number; public guild: Guild; /** @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */ - public create(name: string, options: GuildChannelCreateOptions & { type: 'GuildStore' }): Promise; - public create( + public create( + name: string, + options: GuildChannelCreateOptions & { type: ChannelType.GuildStore }, + ): Promise; + /** @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */ + public create( name: string, options: GuildChannelCreateOptions & { type: T }, ): Promise; @@ -3139,7 +3133,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields { readonly lastMessage: Message | null; lastPinTimestamp: number | null; readonly lastPinAt: Date | null; - awaitMessageComponent( + awaitMessageComponent( options?: AwaitMessageCollectorOptionsParams, ): Promise; awaitMessages(options?: AwaitMessagesOptions): Promise>; @@ -3147,7 +3141,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields { messages: Collection | readonly MessageResolvable[] | number, filterOld?: boolean, ): Promise>; - createMessageComponentCollector( + createMessageComponentCollector( options?: MessageChannelCollectorOptionsParams, ): InteractionCollector; createMessageCollector(options?: MessageCollectorOptions): MessageCollector; @@ -3197,14 +3191,12 @@ export type ActivitiesOptions = Omit; export interface ActivityOptions { name?: string; url?: string; - type?: ExcludeEnum; + type?: Exclude; shardId?: number | readonly number[]; } export type ActivityPlatform = 'desktop' | 'samsung' | 'xbox'; -export type ActivityTypeKey = keyof typeof ActivityType; - export interface AddGuildMemberOptions { accessToken: string; nick?: string; @@ -3221,13 +3213,9 @@ export type AllowedImageSize = 16 | 32 | 56 | 64 | 96 | 128 | 256 | 300 | 512 | export type AllowedPartial = User | Channel | GuildMember | Message | MessageReaction; -export type AllowedThreadTypeForNewsChannel = 'GUILD_NEWS_THREAD' | ChannelType.GuildNewsThread; +export type AllowedThreadTypeForNewsChannel = ChannelType.GuildNewsThread; -export type AllowedThreadTypeForTextChannel = - | 'GUILD_PUBLIC_THREAD' - | 'GUILD_PRIVATE_THREAD' - | ChannelType.GuildPublicThread - | ChannelType.GuildPrivateThread; +export type AllowedThreadTypeForTextChannel = ChannelType.GuildPublicThread | ChannelType.GuildPrivateThread; export interface APIRequest { method: 'get' | 'post' | 'delete' | 'patch' | 'put'; @@ -3242,26 +3230,21 @@ export interface BaseApplicationCommandData { defaultPermission?: boolean; } -export type CommandOptionDataTypeResolvable = ApplicationCommandOptionTypeKey | ApplicationCommandOptionType; +export type CommandOptionDataTypeResolvable = ApplicationCommandOptionType; -export type CommandOptionChannelResolvableType = ApplicationCommandOptionType.Channel | 'Channel'; +export type CommandOptionChannelResolvableType = ApplicationCommandOptionType.Channel; export type CommandOptionChoiceResolvableType = | ApplicationCommandOptionType.String - | 'String' | CommandOptionNumericResolvableType; export type CommandOptionNumericResolvableType = | ApplicationCommandOptionType.Number - | 'Number' - | ApplicationCommandOptionType.Integer - | 'Integer'; + | ApplicationCommandOptionType.Integer; export type CommandOptionSubOptionResolvableType = | ApplicationCommandOptionType.Subcommand - | 'Subcommand' - | ApplicationCommandOptionType.SubcommandGroup - | 'SubcommandGroup'; + | ApplicationCommandOptionType.SubcommandGroup; export type CommandOptionNonChoiceResolvableType = Exclude< CommandOptionDataTypeResolvable, @@ -3301,7 +3284,7 @@ export interface ApplicationCommandChannelOptionData extends BaseApplicationComm } export interface ApplicationCommandChannelOption extends BaseApplicationCommandOptionsData { - type: 'CHANNEL'; + type: ApplicationCommandOptionType.Channel; channelTypes?: (keyof typeof ChannelType)[]; } @@ -3398,13 +3381,9 @@ export interface ApplicationCommandOptionChoice { value: string | number; } -export type ApplicationCommandTypeKey = keyof typeof ApplicationCommandType; - -export type ApplicationCommandOptionTypeKey = keyof typeof ApplicationCommandOptionType; - export interface ApplicationCommandPermissionData { id: Snowflake; - type: ApplicationCommandPermissionTypeKey | ApplicationCommandPermissionType; + type: ApplicationCommandPermissionType; permission: boolean; } @@ -3412,8 +3391,6 @@ export interface ApplicationCommandPermissions extends ApplicationCommandPermiss type: ApplicationCommandPermissionType; } -export type ApplicationCommandPermissionTypeKey = keyof typeof ApplicationCommandPermissionType; - export type ApplicationCommandResolvable = ApplicationCommand | Snowflake; export type ApplicationFlagsString = @@ -3466,7 +3443,7 @@ export interface ThreadMemberFetchOptions extends BaseFetchOptions { } export interface BaseMessageComponentOptions { - type?: ComponentTypeKey | ComponentType; + type?: ComponentType; } export type BitFieldResolvable = @@ -3523,10 +3500,7 @@ export type CacheWithLimitsOptions = { export interface CategoryCreateChannelOptions { permissionOverwrites?: OverwriteResolvable[] | Collection; topic?: string; - type?: ExcludeEnum< - typeof ChannelType, - 'DM' | 'GroupDM' | 'GuildPublicThread' | 'GuildNewsThread' | 'GuildPrivateThread' | 'GuildCategory' - >; + type?: CategoryChannelType; nsfw?: boolean; bitrate?: number; userLimit?: number; @@ -3770,7 +3744,7 @@ export type ColorResolvable = export interface CommandInteractionOption { name: string; - type: ApplicationCommandOptionTypeKey; + type: ApplicationCommandOptionType; value?: string | number | boolean; focused?: boolean; autocomplete?: boolean; @@ -4281,9 +4255,13 @@ export type GuildChannelResolvable = Snowflake | GuildBasedChannel; export interface GuildChannelCreateOptions extends Omit { parent?: CategoryChannelResolvable; - type?: ExcludeEnum< - typeof ChannelType, - 'DM' | 'GroupDM' | 'GuildPublicThread' | 'GuildNewsThread' | 'GuildPrivateThread' + type?: Exclude< + ChannelType, + | ChannelType.DM + | ChannelType.GroupDM + | ChannelType.GuildPublicThread + | ChannelType.GuildNewsThread + | ChannelType.GuildPrivateThread >; } @@ -4419,15 +4397,13 @@ export interface GuildListMembersOptions { cache?: boolean; } -export type GuildScheduledEventPrivacyLevelKey = keyof typeof GuildScheduledEventPrivacyLevel; - // TODO: use conditional types for better TS support export interface GuildScheduledEventCreateOptions { name: string; scheduledStartTime: DateResolvable; scheduledEndTime?: DateResolvable; - privacyLevel: GuildScheduledEventPrivacyLevel | GuildScheduledEventPrivacyLevelKey; - entityType: GuildScheduledEventEntityType | GuildScheduledEventEntityTypeKey; + privacyLevel: GuildScheduledEventPrivacyLevel; + entityType: GuildScheduledEventEntityType; description?: string; channel?: GuildVoiceChannelResolvable; entityMetadata?: GuildScheduledEventEntityMetadataOptions; @@ -4450,8 +4426,6 @@ export interface GuildScheduledEventEntityMetadataOptions { location?: string; } -export type GuildScheduledEventEntityTypeKey = keyof typeof GuildScheduledEventEntityType; - export type GuildScheduledEventManagerFetchResult< T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, > = T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions @@ -4524,9 +4498,9 @@ export type IntegrationType = 'twitch' | 'youtube' | 'discord'; export interface InteractionCollectorOptions extends CollectorOptions<[T]> { channel?: TextBasedChannel; - componentType?: ComponentType | ComponentTypeKey; + componentType?: ComponentType; guild?: Guild; - interactionType?: InteractionTypeKey | InteractionType; + interactionType?: InteractionType; max?: number; maxComponents?: number; maxUsers?: number; @@ -4545,10 +4519,6 @@ export interface InteractionReplyOptions extends Omit; + style: Exclude; customId: string; } export type MessageButtonOptions = InteractionButtonOptions | LinkButtonOptions; -export type ButtonStyleKey = keyof typeof ButtonStyle; - -export type MessageButtonStyleResolvable = ButtonStyleKey | ButtonStyle; - export interface MessageCollectorOptions extends CollectorOptions<[Message]> { max?: number; maxProcessed?: number; @@ -4691,10 +4657,6 @@ export type MessageComponentOptions = | MessageButtonOptions | MessageSelectMenuOptions; -export type ComponentTypeKey = keyof typeof ComponentType; - -export type MessageComponentTypeResolvable = ComponentTypeKey | ComponentType; - export interface MessageEditOptions { attachments?: MessageAttachment[]; content?: string | null; @@ -4861,10 +4823,6 @@ export type MessageTarget = | Message | MessageManager; -export type MessageTypeKey = keyof typeof MessageType; - -export type GuildMFALevelKey = keyof typeof GuildMFALevel; - export interface MultipleShardRespawnOptions { shardDelay?: number; respawnDelay?: number; @@ -4883,13 +4841,11 @@ export interface OverwriteData { allow?: PermissionResolvable; deny?: PermissionResolvable; id: GuildMemberResolvable | RoleResolvable; - type?: OverwriteTypeKey; + type?: OverwriteType; } export type OverwriteResolvable = PermissionOverwrites | OverwriteData; -export type OverwriteTypeKey = keyof typeof OverwriteType; - export type PermissionFlags = Record; export type PermissionOverwriteOptions = Partial>; @@ -4963,16 +4919,16 @@ export type PresenceResolvable = Presence | UserResolvable | Snowflake; export interface PartialChannelData { id?: Snowflake | number; parentId?: Snowflake | number; - type?: ExcludeEnum< - typeof ChannelType, - | 'DM' - | 'GroupDM' - | 'GuildNews' - | 'GuildStore' - | 'GuildNewsThread' - | 'GuildPublicThread' - | 'GuildPrivateThread' - | 'GuildStageVoice' + type?: Exclude< + ChannelType, + | ChannelType.DM + | ChannelType.GroupDM + | ChannelType.GuildNews + | ChannelType.GuildStore + | ChannelType.GuildNewsThread + | ChannelType.GuildPublicThread + | ChannelType.GuildPrivateThread + | ChannelType.GuildStageVoice >; name: string; topic?: string; @@ -5152,7 +5108,7 @@ export type SystemChannelFlagsResolvable = BitFieldResolvable; export type StageChannelResolvable = StageChannel | Snowflake; @@ -5234,12 +5190,15 @@ export type ThreadAutoArchiveDuration = 60 | 1440 | 4320 | 10080 | 'MAX'; export type ThreadChannelResolvable = ThreadChannel | Snowflake; -export type ThreadChannelTypeKey = 'GuildNewsThread' | 'GuildPublicThread' | 'GuildPrivateThread'; +export type ThreadChannelType = + | ChannelType.GuildNewsThread + | ChannelType.GuildPublicThread + | ChannelType.GuildPrivateThread; export interface ThreadCreateOptions extends StartThreadOptions { startMessage?: MessageResolvable; type?: AllowedThreadType; - invitable?: AllowedThreadType extends 'GUILD_PRIVATE_THREAD' | ChannelType.GuildPrivateThread ? boolean : never; + invitable?: AllowedThreadType extends ChannelType.GuildPrivateThread ? boolean : never; rateLimitPerUser?: number; } @@ -5325,8 +5284,6 @@ export interface WebhookMessageOptions extends Omit { await globalPermissionsManager?.add({ command: globalCommandId, guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await globalPermissionsManager?.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId }); await globalPermissionsManager?.fetch({ guild: testGuildId }); @@ -162,17 +166,22 @@ client.on('ready', async () => { await globalPermissionsManager?.set({ command: globalCommandId, guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await globalPermissionsManager?.set({ guild: testGuildId, - fullPermissions: [{ id: globalCommandId, permissions: [{ type: 'Role', id: testGuildId, permission: true }] }], + fullPermissions: [ + { + id: globalCommandId, + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }, + ], }); // @ts-expect-error await globalPermissionsManager?.add({ command: globalCommandId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await globalPermissionsManager?.has({ command: globalCommandId, permissionId: testGuildId }); @@ -205,7 +214,7 @@ client.on('ready', async () => { // @ts-expect-error await globalPermissionsManager?.add({ guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await globalPermissionsManager?.has({ guild: testGuildId, permissionId: testGuildId }); @@ -218,13 +227,13 @@ client.on('ready', async () => { // @ts-expect-error await globalPermissionsManager?.set({ guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // Permissions from guild manager await guildPermissionsManager?.add({ command: globalCommandId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await guildPermissionsManager?.has({ command: globalCommandId, permissionId: testGuildId }); await guildPermissionsManager?.fetch({}); @@ -234,17 +243,22 @@ client.on('ready', async () => { await guildPermissionsManager?.remove({ command: globalCommandId, roles: [testGuildId], users: [testUserId] }); await guildPermissionsManager?.set({ command: globalCommandId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await guildPermissionsManager?.set({ - fullPermissions: [{ id: globalCommandId, permissions: [{ type: 'Role', id: testGuildId, permission: true }] }], + fullPermissions: [ + { + id: globalCommandId, + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }, + ], }); await guildPermissionsManager?.add({ command: globalCommandId, // @ts-expect-error guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await guildPermissionsManager?.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId }); @@ -272,11 +286,18 @@ client.on('ready', async () => { await guildPermissionsManager?.set({ // @ts-expect-error guild: testGuildId, - fullPermissions: [{ id: globalCommandId, permissions: [{ type: 'Role', id: testGuildId, permission: true }] }], + fullPermissions: [ + { + id: globalCommandId, + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }, + ], }); // @ts-expect-error - await guildPermissionsManager?.add({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await guildPermissionsManager?.add({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); // @ts-expect-error await guildPermissionsManager?.has({ permissionId: testGuildId }); // @ts-expect-error @@ -286,17 +307,24 @@ client.on('ready', async () => { // @ts-expect-error await guildPermissionsManager?.remove({ roles: [testGuildId], users: [testUserId] }); // @ts-expect-error - await guildPermissionsManager?.set({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await guildPermissionsManager?.set({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); // @ts-expect-error await guildPermissionsManager?.set({ command: globalCommandId, - fullPermissions: [{ id: globalCommandId, permissions: [{ type: 'Role', id: testGuildId, permission: true }] }], + fullPermissions: [ + { + id: globalCommandId, + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }, + ], }); // Permissions from cached global ApplicationCommand await globalCommand?.permissions.add({ guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await globalCommand?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); await globalCommand?.permissions.fetch({ guild: testGuildId }); @@ -305,14 +333,14 @@ client.on('ready', async () => { await globalCommand?.permissions.remove({ guild: testGuildId, roles: [testGuildId], users: [testUserId] }); await globalCommand?.permissions.set({ guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await globalCommand?.permissions.add({ // @ts-expect-error command: globalCommandId, guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await globalCommand?.permissions.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId }); @@ -333,11 +361,13 @@ client.on('ready', async () => { // @ts-expect-error command: globalCommandId, guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error - await globalCommand?.permissions.add({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await globalCommand?.permissions.add({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); // @ts-expect-error await globalCommand?.permissions.has({ permissionId: testGuildId }); // @ts-expect-error @@ -349,21 +379,27 @@ client.on('ready', async () => { // @ts-expect-error await globalCommand?.permissions.remove({ roles: [testGuildId], users: [testUserId] }); // @ts-expect-error - await globalCommand?.permissions.set({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await globalCommand?.permissions.set({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); // Permissions from cached guild ApplicationCommand - await guildCommandFromGlobal?.permissions.add({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await guildCommandFromGlobal?.permissions.add({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); await guildCommandFromGlobal?.permissions.has({ permissionId: testGuildId }); await guildCommandFromGlobal?.permissions.fetch({}); await guildCommandFromGlobal?.permissions.remove({ roles: [testGuildId] }); await guildCommandFromGlobal?.permissions.remove({ users: [testUserId] }); await guildCommandFromGlobal?.permissions.remove({ roles: [testGuildId], users: [testUserId] }); - await guildCommandFromGlobal?.permissions.set({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await guildCommandFromGlobal?.permissions.set({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); await guildCommandFromGlobal?.permissions.add({ // @ts-expect-error command: globalCommandId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await guildCommandFromGlobal?.permissions.has({ command: guildCommandId, permissionId: testGuildId }); @@ -380,13 +416,13 @@ client.on('ready', async () => { await guildCommandFromGlobal?.permissions.set({ // @ts-expect-error command: guildCommandId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await guildCommandFromGlobal?.permissions.add({ // @ts-expect-error guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await guildCommandFromGlobal?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); @@ -399,21 +435,25 @@ client.on('ready', async () => { await guildCommandFromGlobal?.permissions.set({ // @ts-expect-error guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); - await guildCommandFromGuild?.permissions.add({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await guildCommandFromGuild?.permissions.add({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); await guildCommandFromGuild?.permissions.has({ permissionId: testGuildId }); await guildCommandFromGuild?.permissions.fetch({}); await guildCommandFromGuild?.permissions.remove({ roles: [testGuildId] }); await guildCommandFromGuild?.permissions.remove({ users: [testUserId] }); await guildCommandFromGuild?.permissions.remove({ roles: [testGuildId], users: [testUserId] }); - await guildCommandFromGuild?.permissions.set({ permissions: [{ type: 'Role', id: testGuildId, permission: true }] }); + await guildCommandFromGuild?.permissions.set({ + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], + }); await guildCommandFromGuild?.permissions.add({ // @ts-expect-error command: globalCommandId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await guildCommandFromGuild?.permissions.has({ command: guildCommandId, permissionId: testGuildId }); @@ -430,13 +470,13 @@ client.on('ready', async () => { await guildCommandFromGuild?.permissions.set({ // @ts-expect-error command: guildCommandId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); await guildCommandFromGuild?.permissions.add({ // @ts-expect-error guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); // @ts-expect-error await guildCommandFromGuild?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); @@ -449,7 +489,7 @@ client.on('ready', async () => { await guildCommandFromGuild?.permissions.set({ // @ts-expect-error guild: testGuildId, - permissions: [{ type: 'Role', id: testGuildId, permission: true }], + permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], }); client.application?.commands.permissions.set({ @@ -528,11 +568,11 @@ client.on('messageCreate', async message => { if (message.inGuild()) { expectAssignable>(message); - const component = await message.awaitMessageComponent({ componentType: 'Button' }); + const component = await message.awaitMessageComponent({ componentType: ComponentType.Button }); expectType>(component); expectType>(await component.reply({ fetchReply: true })); - const buttonCollector = message.createMessageComponentCollector({ componentType: 'Button' }); + const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button }); expectType>>(buttonCollector); expectAssignable<(test: ButtonInteraction<'cached'>) => boolean | Promise>(buttonCollector.filter); expectType(message.channel); @@ -551,15 +591,19 @@ client.on('messageCreate', async message => { // Check collector creations. // Verify that buttons interactions are inferred. - const buttonCollector = message.createMessageComponentCollector({ componentType: 'Button' }); - expectAssignable>(message.awaitMessageComponent({ componentType: 'Button' })); - expectAssignable>(channel.awaitMessageComponent({ componentType: 'Button' })); + const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button }); + expectAssignable>(message.awaitMessageComponent({ componentType: ComponentType.Button })); + expectAssignable>(channel.awaitMessageComponent({ componentType: ComponentType.Button })); expectAssignable>(buttonCollector); // Verify that select menus interaction are inferred. - const selectMenuCollector = message.createMessageComponentCollector({ componentType: 'SelectMenu' }); - expectAssignable>(message.awaitMessageComponent({ componentType: 'SelectMenu' })); - expectAssignable>(channel.awaitMessageComponent({ componentType: 'SelectMenu' })); + const selectMenuCollector = message.createMessageComponentCollector({ componentType: ComponentType.SelectMenu }); + expectAssignable>( + message.awaitMessageComponent({ componentType: ComponentType.SelectMenu }), + ); + expectAssignable>( + channel.awaitMessageComponent({ componentType: ComponentType.SelectMenu }), + ); expectAssignable>(selectMenuCollector); // Verify that message component interactions are default collected types. @@ -575,9 +619,10 @@ client.on('messageCreate', async message => { expectType>(semiDefaultCollectorChannel); // Verify that interaction collector options can't be used. - - // @ts-expect-error - const interactionOptions = message.createMessageComponentCollector({ interactionType: 'APPLICATION_COMMAND' }); + message.createMessageComponentCollector({ + // @ts-expect-error + interactionType: InteractionType.ApplicationCommand, + }); // Make sure filter parameters are properly inferred. message.createMessageComponentCollector({ @@ -588,7 +633,7 @@ client.on('messageCreate', async message => { }); message.createMessageComponentCollector({ - componentType: 'Button', + componentType: ComponentType.Button, filter: i => { expectType(i); return true; @@ -596,7 +641,7 @@ client.on('messageCreate', async message => { }); message.createMessageComponentCollector({ - componentType: 'SelectMenu', + componentType: ComponentType.SelectMenu, filter: i => { expectType(i); return true; @@ -611,7 +656,7 @@ client.on('messageCreate', async message => { }); message.awaitMessageComponent({ - componentType: 'Button', + componentType: ComponentType.Button, filter: i => { expectType(i); return true; @@ -619,7 +664,7 @@ client.on('messageCreate', async message => { }); message.awaitMessageComponent({ - componentType: 'SelectMenu', + componentType: ComponentType.SelectMenu, filter: i => { expectType(i); return true; @@ -647,7 +692,7 @@ client.on('messageCreate', async message => { }); channel.awaitMessageComponent({ - componentType: 'Button', + componentType: ComponentType.Button, filter: i => { expectType>(i); return true; @@ -655,7 +700,7 @@ client.on('messageCreate', async message => { }); channel.awaitMessageComponent({ - componentType: 'SelectMenu', + componentType: ComponentType.SelectMenu, filter: i => { expectType>(i); return true; @@ -774,8 +819,8 @@ expectType(newsChannel.lastMessage); expectType(textChannel.lastMessage); expectDeprecated(storeChannel.clone()); -expectDeprecated(categoryChannel.createChannel('Store', { type: 'GuildStore' })); -expectDeprecated(guild.channels.create('Store', { type: 'GuildStore' })); +expectDeprecated(categoryChannel.createChannel('Store', { type: ChannelType.GuildStore })); +expectDeprecated(guild.channels.create('Store', { type: ChannelType.GuildStore })); notPropertyOf(user, 'lastMessage'); notPropertyOf(user, 'lastMessageId'); @@ -857,11 +902,11 @@ expectType>(guildApplicationCommandManager.fetch('0' declare const categoryChannel: CategoryChannel; { - expectType>(categoryChannel.createChannel('name', { type: 'GuildVoice' })); - expectType>(categoryChannel.createChannel('name', { type: 'GuildText' })); - expectType>(categoryChannel.createChannel('name', { type: 'GuildNews' })); - expectDeprecated(categoryChannel.createChannel('name', { type: 'GuildStore' })); - expectType>(categoryChannel.createChannel('name', { type: 'GuildStageVoice' })); + expectType>(categoryChannel.createChannel('name', { type: ChannelType.GuildVoice })); + expectType>(categoryChannel.createChannel('name', { type: ChannelType.GuildText })); + expectType>(categoryChannel.createChannel('name', { type: ChannelType.GuildNews })); + expectDeprecated(categoryChannel.createChannel('name', { type: ChannelType.GuildStore })); + expectType>(categoryChannel.createChannel('name', { type: ChannelType.GuildStageVoice })); expectType>(categoryChannel.createChannel('name', {})); expectType>(categoryChannel.createChannel('name')); } @@ -870,12 +915,12 @@ declare const guildChannelManager: GuildChannelManager; { type AnyChannel = TextChannel | VoiceChannel | CategoryChannel | NewsChannel | StoreChannel | StageChannel; - expectType>(guildChannelManager.create('name', { type: 'GuildVoice' })); - expectType>(guildChannelManager.create('name', { type: 'GuildCategory' })); - expectType>(guildChannelManager.create('name', { type: 'GuildText' })); - expectType>(guildChannelManager.create('name', { type: 'GuildNews' })); - expectType>(guildChannelManager.create('name', { type: 'GuildStore' })); - expectType>(guildChannelManager.create('name', { type: 'GuildStageVoice' })); + expectType>(guildChannelManager.create('name', { type: ChannelType.GuildVoice })); + expectType>(guildChannelManager.create('name', { type: ChannelType.GuildCategory })); + expectType>(guildChannelManager.create('name', { type: ChannelType.GuildText })); + expectType>(guildChannelManager.create('name', { type: ChannelType.GuildNews })); + expectType>(guildChannelManager.create('name', { type: ChannelType.GuildStore })); + expectType>(guildChannelManager.create('name', { type: ChannelType.GuildStageVoice })); expectType>>(guildChannelManager.fetch()); expectType>>(guildChannelManager.fetch(undefined, {})); @@ -1079,7 +1124,7 @@ client.on('interactionCreate', async interaction => { expectType(interaction.options.getRole('test', true)); } else if (interaction.inCachedGuild()) { const msg = await interaction.reply({ fetchReply: true }); - const btn = await msg.awaitMessageComponent({ componentType: 'Button' }); + const btn = await msg.awaitMessageComponent({ componentType: ComponentType.Button }); expectType>(msg); expectType>(btn); @@ -1263,9 +1308,7 @@ declare const NonThreadGuildBasedChannel: NonThreadGuildBasedChannel; declare const GuildTextBasedChannel: GuildTextBasedChannel; expectType(TextBasedChannel); -expectType<'DM' | 'GuildNews' | 'GuildText' | 'GuildPublicThread' | 'GuildPrivateThread' | 'GuildNewsThread'>( - TextBasedChannelTypes, -); +expectType(TextBasedChannelTypes); expectType(VoiceBasedChannel); expectType( GuildBasedChannel,