feat: Enum resolvers & internal enum string removal (#7290)

Co-authored-by: Almeida <almeidx@pm.me>
This commit is contained in:
Suneet Tipirneni
2022-01-19 08:11:10 -05:00
committed by GitHub
parent 164589c551
commit 213acd7997
46 changed files with 696 additions and 547 deletions

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { ChannelType } = require('discord-api-types/v9');
const Action = require('./Action'); const Action = require('./Action');
const { Channel } = require('../../structures/Channel'); const { Channel } = require('../../structures/Channel');
@@ -12,7 +11,7 @@ class ChannelUpdateAction extends Action {
if (channel) { if (channel) {
const old = channel._update(data); 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); const newChannel = Channel.create(this.client, data, channel.guild);
for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message); for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message);
channel = newChannel; channel = newChannel;

View File

@@ -17,6 +17,7 @@ exports.Collection = require('@discordjs/collection').Collection;
exports.Constants = require('./util/Constants'); exports.Constants = require('./util/Constants');
exports.DataResolver = require('./util/DataResolver'); exports.DataResolver = require('./util/DataResolver');
exports.DiscordAPIError = require('./rest/DiscordAPIError'); exports.DiscordAPIError = require('./rest/DiscordAPIError');
exports.EnumResolvers = require('./util/EnumResolvers');
exports.Formatters = require('./util/Formatters'); exports.Formatters = require('./util/Formatters');
exports.HTTPError = require('./rest/HTTPError'); exports.HTTPError = require('./rest/HTTPError');
exports.Intents = require('./util/Intents'); exports.Intents = require('./util/Intents');

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { ApplicationCommandType } = require('discord-api-types/v9');
const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager'); const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager');
const CachedManager = require('./CachedManager'); const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors'); const { TypeError } = require('../errors');
@@ -207,7 +206,7 @@ class ApplicationCommandManager extends CachedManager {
return { return {
name: command.name, name: command.name,
description: command.description, description: command.description,
type: typeof command.type === 'number' ? command.type : ApplicationCommandType[command.type], type: command.type,
options: command.options?.map(o => ApplicationCommand.transformOption(o)), options: command.options?.map(o => ApplicationCommand.transformOption(o)),
default_permission: command.defaultPermission ?? command.default_permission, default_permission: command.defaultPermission ?? command.default_permission,
}; };

View File

@@ -1,7 +1,7 @@
'use strict'; 'use strict';
const { Collection } = require('@discordjs/collection'); 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 BaseManager = require('./BaseManager');
const { Error, TypeError } = require('../errors'); const { Error, TypeError } = require('../errors');
@@ -96,7 +96,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
const { guildId, commandId } = this._validateOptions(guild, command); const { guildId, commandId } = this._validateOptions(guild, command);
if (commandId) { if (commandId) {
const data = await this.permissionsPath(guildId, commandId).get(); 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(); const data = await this.permissionsPath(guildId).get();
@@ -104,7 +104,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
(coll, perm) => (coll, perm) =>
coll.set( coll.set(
perm.id, perm.id,
perm.permissions.map(p => this.constructor.transformPermissions(p, true)), perm.permissions.map(p => this.constructor.transformPermissions(p)),
), ),
new Collection(), new Collection(),
); );
@@ -137,7 +137,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* permissions: [ * permissions: [
* { * {
* id: '876543210987654321', * id: '876543210987654321',
* type: 'USER', * type: ApplicationCommandOptionType.User,
* permission: false, * permission: false,
* }, * },
* ]}) * ]})
@@ -150,7 +150,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* id: '123456789012345678', * id: '123456789012345678',
* permissions: [{ * permissions: [{
* id: '876543210987654321', * id: '876543210987654321',
* type: 'USER', * type: ApplicationCommandOptionType.User,
* permission: false, * permission: false,
* }], * }],
* }, * },
@@ -168,7 +168,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
const data = await this.permissionsPath(guildId, commandId).put({ const data = await this.permissionsPath(guildId, commandId).put({
data: { permissions: permissions.map(perm => this.constructor.transformPermissions(perm)) }, 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)) { if (!Array.isArray(fullPermissions)) {
@@ -190,7 +190,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
(coll, perm) => (coll, perm) =>
coll.set( coll.set(
perm.id, perm.id,
perm.permissions.map(p => this.constructor.transformPermissions(p, true)), perm.permissions.map(p => this.constructor.transformPermissions(p)),
), ),
new Collection(), new Collection(),
); );
@@ -212,7 +212,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* guild.commands.permissions.add({ command: '123456789012345678', permissions: [ * guild.commands.permissions.add({ command: '123456789012345678', permissions: [
* { * {
* id: '876543211234567890', * id: '876543211234567890',
* type: 'ROLE', * type: ApplicationCommandPermissionType.Role,
* permission: false * permission: false
* }, * },
* ]}) * ]})
@@ -396,14 +396,11 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* @returns {APIApplicationCommandPermissions} * @returns {APIApplicationCommandPermissions}
* @private * @private
*/ */
static transformPermissions(permissions, received) { static transformPermissions(permissions) {
return { return {
id: permissions.id, id: permissions.id,
permission: permissions.permission, permission: permissions.permission,
type: type: permissions.type,
typeof permissions.type === 'number' && !received
? permissions.type
: ApplicationCommandPermissionType[permissions.type],
}; };
} }
} }

View File

@@ -113,7 +113,7 @@ class GuildChannelManager extends CachedManager {
* @example * @example
* // Create a new channel with permission overwrites * // Create a new channel with permission overwrites
* guild.channels.create('new-voice', { * guild.channels.create('new-voice', {
* type: 'GUILD_VOICE', * type: ChannelType.GuildVoice,
* permissionOverwrites: [ * permissionOverwrites: [
* { * {
* id: message.author.id, * id: message.author.id,

View File

@@ -3,13 +3,6 @@
const process = require('node:process'); const process = require('node:process');
const { setTimeout, clearTimeout } = require('node:timers'); const { setTimeout, clearTimeout } = require('node:timers');
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const {
GuildVerificationLevel,
GuildDefaultMessageNotifications,
GuildExplicitContentFilter,
ChannelType,
OverwriteType,
} = require('discord-api-types/v9');
const CachedManager = require('./CachedManager'); const CachedManager = require('./CachedManager');
const { Guild } = require('../structures/Guild'); const { Guild } = require('../structures/Guild');
const GuildChannel = require('../structures/GuildChannel'); const GuildChannel = require('../structures/GuildChannel');
@@ -181,17 +174,8 @@ class GuildManager extends CachedManager {
} = {}, } = {},
) { ) {
icon = await DataResolver.resolveImage(icon); 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) { for (const channel of channels) {
channel.type &&= typeof channel.type === 'number' ? channel.type : ChannelType[channel.type];
channel.parent_id = channel.parentId; channel.parent_id = channel.parentId;
delete channel.parentId; delete channel.parentId;
channel.user_limit = channel.userLimit; channel.user_limit = channel.userLimit;
@@ -203,9 +187,6 @@ class GuildManager extends CachedManager {
if (!channel.permissionOverwrites) continue; if (!channel.permissionOverwrites) continue;
for (const overwrite of channel.permissionOverwrites) { for (const overwrite of channel.permissionOverwrites) {
if (typeof overwrite.type === 'string') {
overwrite.type = OverwriteType[overwrite.type];
}
overwrite.allow &&= Permissions.resolve(overwrite.allow).toString(); overwrite.allow &&= Permissions.resolve(overwrite.allow).toString();
overwrite.deny &&= Permissions.resolve(overwrite.deny).toString(); overwrite.deny &&= Permissions.resolve(overwrite.deny).toString();
} }

View File

@@ -44,15 +44,16 @@ class GuildScheduledEventManager extends CachedManager {
* @property {string} name The name of the guild scheduled event * @property {string} name The name of the guild scheduled event
* @property {DateResolvable} scheduledStartTime The time to schedule the event at * @property {DateResolvable} scheduledStartTime The time to schedule the event at
* @property {DateResolvable} [scheduledEndTime] The time to end the event at * @property {DateResolvable} [scheduledEndTime] The time to end the event at
* <warn>This is required if `entityType` is 'EXTERNAL'</warn> * <warn>This is required if `entityType` is `GuildScheduledEventEntityType.External`</warn>
* @property {PrivacyLevel|number} privacyLevel The privacy level of the guild scheduled event * @property {PrivacyLevel|number} privacyLevel The privacy level of the guild scheduled event
* @property {GuildScheduledEventEntityType|number} entityType The scheduled entity type of the event * @property {GuildScheduledEventEntityType|number} entityType The scheduled entity type of the event
* @property {string} [description] The description of the guild scheduled event * @property {string} [description] The description of the guild scheduled event
* @property {GuildVoiceChannelResolvable} [channel] The channel of the guild scheduled event * @property {GuildVoiceChannelResolvable} [channel] The channel of the guild scheduled event
* <warn>This is required if `entityType` is 'STAGE_INSTANCE' or `VOICE`</warn> * <warn>This is required if `entityType` is `GuildScheduledEventEntityType.StageInstance` or
* `GuildScheduledEventEntityType.Voice`</warn>
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the * @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
* guild scheduled event * guild scheduled event
* <warn>This is required if `entityType` is 'EXTERNAL'</warn> * <warn>This is required if `entityType` is `GuildScheduledEventEntityType.External`</warn>
* @property {string} [reason] The reason for creating the guild scheduled event * @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. * Options used to set entity metadata of a guild scheduled event.
* @typedef {Object} GuildScheduledEventEntityMetadataOptions * @typedef {Object} GuildScheduledEventEntityMetadataOptions
* @property {string} [location] The location of the guild scheduled event * @property {string} [location] The location of the guild scheduled event
* <warn>This is required if `entityType` is 'EXTERNAL'</warn> * <warn>This is required if `entityType` is `GuildScheduledEventEntityType.External`</warn>
*/ */
/** /**
@@ -175,7 +176,8 @@ class GuildScheduledEventManager extends CachedManager {
* @property {GuildScheduledEventStatus|number} [status] The status of the guild scheduled event * @property {GuildScheduledEventStatus|number} [status] The status of the guild scheduled event
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the * @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
* guild scheduled event * guild scheduled event
* <warn>This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is 'EXTERNAL'</warn> * <warn>This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is
* `GuildScheduledEventEntityType.External`</warn>
* @property {string} [reason] The reason for editing the guild scheduled event * @property {string} [reason] The reason for editing the guild scheduled event
*/ */

View File

@@ -49,7 +49,7 @@ class StageInstanceManager extends CachedManager {
* // Create a stage instance * // Create a stage instance
* guild.stageInstances.create('1234567890123456789', { * guild.stageInstances.create('1234567890123456789', {
* topic: 'A very creative topic', * topic: 'A very creative topic',
* privacyLevel: 'GUILD_ONLY' * privacyLevel: GuildPrivacyLevel.GuildOnly
* }) * })
* .then(stageInstance => console.log(stageInstance)) * .then(stageInstance => console.log(stageInstance))
* .catch(console.error); * .catch(console.error);

View File

@@ -92,7 +92,7 @@ class ThreadManager extends CachedManager {
* .create({ * .create({
* name: 'mod-talk', * name: 'mod-talk',
* autoArchiveDuration: 60, * autoArchiveDuration: 60,
* type: 'GUILD_PRIVATE_THREAD', * type: ChannelType.GuildPrivateThread,
* reason: 'Needed a separate thread for moderation', * reason: 'Needed a separate thread for moderation',
* }) * })
* .then(threadChannel => console.log(threadChannel)) * .then(threadChannel => console.log(threadChannel))
@@ -111,13 +111,14 @@ class ThreadManager extends CachedManager {
if (type && typeof type !== 'string' && typeof type !== 'number') { if (type && typeof type !== 'string' && typeof type !== 'number') {
throw new TypeError('INVALID_TYPE', 'type', 'ThreadChannelType or 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) { if (startMessage) {
const startMessageId = this.channel.messages.resolveId(startMessage); const startMessageId = this.channel.messages.resolveId(startMessage);
if (!startMessageId) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable'); if (!startMessageId) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable');
path = path.messages(startMessageId); path = path.messages(startMessageId);
} else if (this.channel.type !== 'GUILD_NEWS') { } else if (this.channel.type !== ChannelType.GuildNews) {
resolvedType = typeof type === 'string' ? ChannelType[type] : type ?? resolvedType; resolvedType = type ?? resolvedType;
} }
if (autoArchiveDuration === 'MAX') { if (autoArchiveDuration === 'MAX') {
autoArchiveDuration = 1440; autoArchiveDuration = 1440;

View File

@@ -1,5 +1,6 @@
'use strict'; 'use strict';
const { ChannelType } = require('discord-api-types/v9');
const CachedManager = require('./CachedManager'); const CachedManager = require('./CachedManager');
const { GuildMember } = require('../structures/GuildMember'); const { GuildMember } = require('../structures/GuildMember');
const { Message } = require('../structures/Message'); const { Message } = require('../structures/Message');
@@ -38,7 +39,7 @@ class UserManager extends CachedManager {
* @private * @private
*/ */
dmChannel(userId) { 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;
} }
/** /**

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { GuildVerificationLevel, GuildNSFWLevel } = require('discord-api-types/v9');
const BaseGuild = require('./BaseGuild'); const BaseGuild = require('./BaseGuild');
/** /**
@@ -44,9 +43,9 @@ class AnonymousGuild extends BaseGuild {
if ('verification_level' in data) { if ('verification_level' in data) {
/** /**
* The verification level of the guild * 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) { if ('vanity_url_code' in data) {
@@ -60,9 +59,9 @@ class AnonymousGuild extends BaseGuild {
if ('nsfw_level' in data) { if ('nsfw_level' in data) {
/** /**
* The NSFW level of this guild * The NSFW level of this guild
* @type {NSFWLevel} * @type {GuildNSFWLevel}
*/ */
this.nsfwLevel = GuildNSFWLevel[data.nsfw_level]; this.nsfwLevel = data.nsfw_level;
} }
} }

View File

@@ -1,7 +1,7 @@
'use strict'; 'use strict';
const { DiscordSnowflake } = require('@sapphire/snowflake'); 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 Base = require('./Base');
const ApplicationCommandPermissionsManager = require('../managers/ApplicationCommandPermissionsManager'); const ApplicationCommandPermissionsManager = require('../managers/ApplicationCommandPermissionsManager');
@@ -48,7 +48,7 @@ class ApplicationCommand extends Base {
* The type of this application command * The type of this application command
* @type {ApplicationCommandType} * @type {ApplicationCommandType}
*/ */
this.type = ApplicationCommandType[data.type]; this.type = data.type;
this._patch(data); this._patch(data);
} }
@@ -233,13 +233,12 @@ class ApplicationCommand extends Base {
if (command.id && this.id !== command.id) return false; if (command.id && this.id !== command.id) return false;
// Check top level parameters // Check top level parameters
const commandType = typeof command.type === 'string' ? command.type : ApplicationCommandType[command.type];
if ( if (
command.name !== this.name || command.name !== this.name ||
('description' in command && command.description !== this.description) || ('description' in command && command.description !== this.description) ||
('version' in command && command.version !== this.version) || ('version' in command && command.version !== this.version) ||
('autocomplete' in command && command.autocomplete !== this.autocomplete) || ('autocomplete' in command && command.autocomplete !== this.autocomplete) ||
(commandType && commandType !== this.type) || (command.type && command.type !== this.type) ||
// Future proof for options being nullable // Future proof for options being nullable
// TODO: remove ?? 0 on each when nullable // TODO: remove ?? 0 on each when nullable
(command.options?.length ?? 0) !== (this.options?.length ?? 0) || (command.options?.length ?? 0) !== (this.options?.length ?? 0) ||
@@ -289,14 +288,15 @@ class ApplicationCommand extends Base {
* @private * @private
*/ */
static _optionEquals(existing, option, enforceOptionOrder = false) { static _optionEquals(existing, option, enforceOptionOrder = false) {
const optionType = typeof option.type === 'string' ? option.type : ApplicationCommandOptionType[option.type];
if ( if (
option.name !== existing.name || option.name !== existing.name ||
optionType !== existing.type || option.type !== existing.type ||
option.description !== existing.description || option.description !== existing.description ||
option.autocomplete !== existing.autocomplete || option.autocomplete !== existing.autocomplete ||
(option.required ?? (['SUB_COMMAND', 'SUB_COMMAND_GROUP'].includes(optionType) ? undefined : false)) !== (option.required ??
existing.required || ([ApplicationCommandOptionType.Subcommand, ApplicationCommandOptionType.SubcommandGroup].includes(option.type)
? undefined
: false)) !== existing.required ||
option.choices?.length !== existing.choices?.length || option.choices?.length !== existing.choices?.length ||
option.options?.length !== existing.options?.length || option.options?.length !== existing.options?.length ||
(option.channelTypes ?? option.channel_types)?.length !== existing.channelTypes?.length || (option.channelTypes ?? option.channel_types)?.length !== existing.channelTypes?.length ||
@@ -325,9 +325,7 @@ class ApplicationCommand extends Base {
} }
if (existing.channelTypes) { if (existing.channelTypes) {
const newTypes = (option.channelTypes ?? option.channel_types).map(type => const newTypes = option.channelTypes ?? option.channel_types;
typeof type === 'number' ? ChannelType[type] : type,
);
for (const type of existing.channelTypes) { for (const type of existing.channelTypes) {
if (!newTypes.includes(type)) return false; if (!newTypes.includes(type)) return false;
} }
@@ -370,16 +368,19 @@ class ApplicationCommand extends Base {
* @private * @private
*/ */
static transformOption(option, received) { static transformOption(option, received) {
const stringType = typeof option.type === 'string' ? option.type : ApplicationCommandOptionType[option.type];
const channelTypesKey = received ? 'channelTypes' : 'channel_types'; const channelTypesKey = received ? 'channelTypes' : 'channel_types';
const minValueKey = received ? 'minValue' : 'min_value'; const minValueKey = received ? 'minValue' : 'min_value';
const maxValueKey = received ? 'maxValue' : 'max_value'; const maxValueKey = received ? 'maxValue' : 'max_value';
return { return {
type: typeof option.type === 'number' && !received ? option.type : ApplicationCommandOptionType[option.type], type: option.type,
name: option.name, name: option.name,
description: option.description, description: option.description,
required: 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, autocomplete: option.autocomplete,
choices: option.choices, choices: option.choices,
options: option.options?.map(o => this.transformOption(o, received)), options: option.options?.map(o => this.transformOption(o, received)),

View File

@@ -1,6 +1,6 @@
'use strict'; 'use strict';
const { ApplicationCommandOptionType, InteractionResponseType } = require('discord-api-types/v9'); const { InteractionResponseType } = require('discord-api-types/v9');
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver'); const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
const Interaction = require('./Interaction'); const Interaction = require('./Interaction');
@@ -40,10 +40,7 @@ class AutocompleteInteraction extends Interaction {
* The options passed to the command * The options passed to the command
* @type {CommandInteractionOptionResolver} * @type {CommandInteractionOptionResolver}
*/ */
this.options = new CommandInteractionOptionResolver( this.options = new CommandInteractionOptionResolver(this.client, data.data.options ?? []);
this.client,
data.data.options?.map(option => this.transformOption(option, data.data.resolved)) ?? [],
);
} }
/** /**
@@ -55,25 +52,6 @@ class AutocompleteInteraction extends Interaction {
return this.guild?.commands.cache.get(id) ?? this.client.application.commands.cache.get(id) ?? null; 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. * Sends results for the autocomplete of this interaction.
* @param {ApplicationCommandOptionChoice[]} options The options for the autocomplete * @param {ApplicationCommandOptionChoice[]} options The options for the autocomplete

View File

@@ -30,7 +30,7 @@ class CategoryChannel extends GuildChannel {
/** /**
* Options for creating a channel using {@link CategoryChannel#createChannel}. * Options for creating a channel using {@link CategoryChannel#createChannel}.
* @typedef {Object} CategoryCreateChannelOptions * @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 {string} [topic] The topic for the new channel
* @property {boolean} [nsfw] Whether the new channel is NSFW * @property {boolean} [nsfw] Whether the new channel is NSFW
* @property {number} [bitrate] Bitrate of the new channel in bits (only voice) * @property {number} [bitrate] Bitrate of the new channel in bits (only voice)

View File

@@ -22,12 +22,11 @@ class Channel extends Base {
constructor(client, data, immediatePatch = true) { constructor(client, data, immediatePatch = true) {
super(client); super(client);
const type = ChannelType[data?.type];
/** /**
* The type of the channel * The type of the channel
* @type {ChannelType} * @type {ChannelType}
*/ */
this.type = type ?? 'UNKNOWN'; this.type = data.type;
if (data && immediatePatch) this._patch(data); if (data && immediatePatch) this._patch(data);
} }
@@ -107,7 +106,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isText() { isText() {
return this.type === ChannelType[ChannelType.GuildText]; return this.type === ChannelType.GuildText;
} }
/** /**
@@ -115,7 +114,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isDM() { isDM() {
return this.type === ChannelType[ChannelType.DM]; return this.type === ChannelType.DM;
} }
/** /**
@@ -123,7 +122,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isVoice() { isVoice() {
return this.type === ChannelType[ChannelType.GuildVoice]; return this.type === ChannelType.GuildVoice;
} }
/** /**
@@ -131,7 +130,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isGroupDM() { isGroupDM() {
return this.type === ChannelType[ChannelType.GroupDM]; return this.type === ChannelType.GroupDM;
} }
/** /**
@@ -139,7 +138,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isCategory() { isCategory() {
return this.type === ChannelType[ChannelType.GuildCategory]; return this.type === ChannelType.GuildCategory;
} }
/** /**
@@ -147,7 +146,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isNews() { isNews() {
return this.type === ChannelType[ChannelType.GuildNews]; return this.type === ChannelType.GuildNews;
} }
/** /**
@@ -155,7 +154,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isStore() { isStore() {
return this.type === ChannelType[ChannelType.GuildStore]; return this.type === ChannelType.GuildStore;
} }
/** /**
@@ -171,7 +170,7 @@ class Channel extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isStage() { isStage() {
return this.type === ChannelType[ChannelType.GuildStageVoice]; return this.type === ChannelType.GuildStageVoice;
} }
/** /**

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { ActivityType } = require('discord-api-types/v9');
const { Presence } = require('./Presence'); const { Presence } = require('./Presence');
const { TypeError } = require('../errors'); const { TypeError } = require('../errors');
const { Opcodes } = require('../util/Constants'); const { Opcodes } = require('../util/Constants');
@@ -53,7 +52,7 @@ class ClientPresence extends Presence {
activity.type ??= 0; activity.type ??= 0;
data.activities.push({ data.activities.push({
type: typeof activity.type === 'number' ? activity.type : ActivityType[activity.type], type: activity.type,
name: activity.name, name: activity.name,
url: activity.url, url: activity.url,
}); });
@@ -62,7 +61,7 @@ class ClientPresence extends Presence {
data.activities.push( data.activities.push(
...this.activities.map(a => ({ ...this.activities.map(a => ({
name: a.name, name: a.name,
type: ActivityType[a.type], type: a.type,
url: a.url ?? undefined, url: a.url ?? undefined,
})), })),
); );

View File

@@ -158,7 +158,7 @@ class ClientUser extends User {
* @returns {ClientPresence} * @returns {ClientPresence}
* @example * @example
* // Set the client user's activity * // Set the client user's activity
* client.user.setActivity('discord.js', { type: 'WATCHING' }); * client.user.setActivity('discord.js', { type: ActivityType.Watching });
*/ */
setActivity(name, options = {}) { setActivity(name, options = {}) {
if (!name) return this.setPresence({ activities: [], shardId: options.shardId }); if (!name) return this.setPresence({ activities: [], shardId: options.shardId });

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { ApplicationCommandOptionType } = require('discord-api-types/v9');
const Interaction = require('./Interaction'); const Interaction = require('./Interaction');
const InteractionWebhook = require('./InteractionWebhook'); const InteractionWebhook = require('./InteractionWebhook');
const InteractionResponses = require('./interfaces/InteractionResponses'); const InteractionResponses = require('./interfaces/InteractionResponses');
@@ -151,7 +150,7 @@ class CommandInteraction extends Interaction {
transformOption(option, resolved) { transformOption(option, resolved) {
const result = { const result = {
name: option.name, name: option.name,
type: ApplicationCommandOptionType[option.type], type: option.type,
}; };
if ('value' in option) result.value = option.value; if ('value' in option) result.value = option.value;

View File

@@ -1,5 +1,6 @@
'use strict'; 'use strict';
const { ApplicationCommandOptionType } = require('discord-api-types/v9');
const { TypeError } = require('../errors'); const { TypeError } = require('../errors');
/** /**
@@ -38,12 +39,12 @@ class CommandInteractionOptionResolver {
this._hoistedOptions = options; this._hoistedOptions = options;
// Hoist subcommand group if present // 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._group = this._hoistedOptions[0].name;
this._hoistedOptions = this._hoistedOptions[0].options ?? []; this._hoistedOptions = this._hoistedOptions[0].options ?? [];
} }
// Hoist subcommand if present // 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._subcommand = this._hoistedOptions[0].name;
this._hoistedOptions = this._hoistedOptions[0].options ?? []; 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. * @returns {?boolean} The value of the option, or null if not set and not required.
*/ */
getBoolean(name, required = false) { 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; return option?.value ?? null;
} }
@@ -145,7 +146,7 @@ class CommandInteractionOptionResolver {
* The value of the option, or null if not set and not required. * The value of the option, or null if not set and not required.
*/ */
getChannel(name, required = false) { 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; 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. * @returns {?string} The value of the option, or null if not set and not required.
*/ */
getString(name, required = false) { 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; 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. * @returns {?number} The value of the option, or null if not set and not required.
*/ */
getInteger(name, required = false) { 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; 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. * @returns {?number} The value of the option, or null if not set and not required.
*/ */
getNumber(name, required = false) { 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; 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. * @returns {?User} The value of the option, or null if not set and not required.
*/ */
getUser(name, required = false) { 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; 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. * The value of the option, or null if the user is not present in the guild or the option is not set.
*/ */
getMember(name) { getMember(name) {
const option = this._getTypedOption(name, 'USER', ['member'], false); const option = this._getTypedOption(name, ApplicationCommandOptionType.User, ['member'], false);
return option?.member ?? null; 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. * @returns {?(Role|APIRole)} The value of the option, or null if not set and not required.
*/ */
getRole(name, required = false) { 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; return option?.role ?? null;
} }
@@ -223,7 +224,12 @@ class CommandInteractionOptionResolver {
* The value of the option, or null if not set and not required. * The value of the option, or null if not set and not required.
*/ */
getMentionable(name, required = false) { 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; return option?.member ?? option?.user ?? option?.role ?? null;
} }

View File

@@ -1,6 +1,6 @@
'use strict'; 'use strict';
const { ApplicationCommandType, ApplicationCommandOptionType } = require('discord-api-types/v9'); const { ApplicationCommandOptionType } = require('discord-api-types/v9');
const CommandInteraction = require('./CommandInteraction'); const CommandInteraction = require('./CommandInteraction');
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver'); const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
@@ -28,10 +28,10 @@ class ContextMenuCommandInteraction extends CommandInteraction {
this.targetId = data.data.target_id; this.targetId = data.data.target_id;
/** /**
* The type of the target of the interaction; either USER or MESSAGE * The type of the target of the interaction; either `.User` or `.Message`
* @type {ApplicationCommandType} * @type {ApplicationCommandType.User|ApplicationCommandType.Message}
*/ */
this.targetType = ApplicationCommandType[data.data.type]; this.targetType = data.data.type;
} }
/** /**

View File

@@ -1,5 +1,6 @@
'use strict'; 'use strict';
const { ChannelType } = require('discord-api-types/v9');
const { Channel } = require('./Channel'); const { Channel } = require('./Channel');
const TextBasedChannel = require('./interfaces/TextBasedChannel'); const TextBasedChannel = require('./interfaces/TextBasedChannel');
const MessageManager = require('../managers/MessageManager'); const MessageManager = require('../managers/MessageManager');
@@ -14,7 +15,7 @@ class DMChannel extends Channel {
super(client, data); super(client, data);
// Override the channel type so partials have a known type // 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 * A manager of the messages belonging to this channel

View File

@@ -1,14 +1,7 @@
'use strict'; 'use strict';
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { const { GuildPremiumTier, ChannelType } = require('discord-api-types/v9');
GuildPremiumTier,
GuildMFALevel,
GuildExplicitContentFilter,
GuildDefaultMessageNotifications,
GuildVerificationLevel,
ChannelType,
} = require('discord-api-types/v9');
const AnonymousGuild = require('./AnonymousGuild'); const AnonymousGuild = require('./AnonymousGuild');
const GuildAuditLogs = require('./GuildAuditLogs'); const GuildAuditLogs = require('./GuildAuditLogs');
const GuildPreview = require('./GuildPreview'); const GuildPreview = require('./GuildPreview');
@@ -240,7 +233,7 @@ class Guild extends AnonymousGuild {
* The premium tier of this guild * The premium tier of this guild
* @type {GuildPremiumTier} * @type {GuildPremiumTier}
*/ */
this.premiumTier = GuildPremiumTier[data.premium_tier]; this.premiumTier = data.premium_tier;
} }
if ('premium_subscription_count' in data) { if ('premium_subscription_count' in data) {
@@ -270,9 +263,9 @@ class Guild extends AnonymousGuild {
if ('explicit_content_filter' in data) { if ('explicit_content_filter' in data) {
/** /**
* The explicit content filter level of the guild * 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) { if ('mfa_level' in data) {
@@ -280,7 +273,7 @@ class Guild extends AnonymousGuild {
* The required MFA level for this guild * The required MFA level for this guild
* @type {MFALevel} * @type {MFALevel}
*/ */
this.mfaLevel = GuildMFALevel[data.mfa_level]; this.mfaLevel = data.mfa_level;
} }
if ('joined_at' in data) { if ('joined_at' in data) {
@@ -296,7 +289,7 @@ class Guild extends AnonymousGuild {
* The default message notification level of the guild * The default message notification level of the guild
* @type {GuildDefaultMessageNotifications} * @type {GuildDefaultMessageNotifications}
*/ */
this.defaultMessageNotifications = GuildDefaultMessageNotifications[data.default_message_notifications]; this.defaultMessageNotifications = data.default_message_notifications;
} }
if ('system_channel_flags' in data) { if ('system_channel_flags' in data) {
@@ -566,7 +559,7 @@ class Guild extends AnonymousGuild {
return 384_000; return 384_000;
} }
switch (GuildPremiumTier[this.premiumTier]) { switch (this.premiumTier) {
case GuildPremiumTier.Tier1: case GuildPremiumTier.Tier1:
return 128_000; return 128_000;
case GuildPremiumTier.Tier2: case GuildPremiumTier.Tier2:
@@ -748,7 +741,6 @@ class Guild extends AnonymousGuild {
*/ */
async fetchAuditLogs(options = {}) { async fetchAuditLogs(options = {}) {
if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id; 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({ const data = await this.client.api.guilds(this.id)['audit-logs'].get({
query: { query: {
@@ -817,10 +809,7 @@ class Guild extends AnonymousGuild {
const _data = {}; const _data = {};
if (data.name) _data.name = data.name; if (data.name) _data.name = data.name;
if (typeof data.verificationLevel !== 'undefined') { if (typeof data.verificationLevel !== 'undefined') {
_data.verification_level = _data.verification_level = data.verificationLevel;
typeof data.verificationLevel === 'number'
? data.verificationLevel
: GuildVerificationLevel[data.verificationLevel];
} }
if (typeof data.afkChannel !== 'undefined') { if (typeof data.afkChannel !== 'undefined') {
_data.afk_channel_id = this.client.channels.resolveId(data.afkChannel); _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.banner !== 'undefined') _data.banner = await DataResolver.resolveImage(data.banner);
if (typeof data.explicitContentFilter !== 'undefined') { if (typeof data.explicitContentFilter !== 'undefined') {
_data.explicit_content_filter = _data.explicit_content_filter = data.explicitContentFilter;
typeof data.explicitContentFilter === 'number'
? data.explicitContentFilter
: GuildExplicitContentFilter[data.explicitContentFilter];
} }
if (typeof data.defaultMessageNotifications !== 'undefined') { if (typeof data.defaultMessageNotifications !== 'undefined') {
_data.default_message_notifications = _data.default_message_notifications = data.defaultMessageNotifications;
typeof data.defaultMessageNotifications === 'number'
? data.defaultMessageNotifications
: GuildDefaultMessageNotifications[data.defaultMessageNotifications];
} }
if (typeof data.systemChannelFlags !== 'undefined') { if (typeof data.systemChannelFlags !== 'undefined') {
_data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags); _data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags);
@@ -1303,12 +1286,11 @@ class Guild extends AnonymousGuild {
*/ */
_sortedChannels(channel) { _sortedChannels(channel) {
const category = channel.type === ChannelType.GuildCategory; const category = channel.type === ChannelType.GuildCategory;
const channelTypes = [ChannelType.GuildText, ChannelType.GuildNews, ChannelType.GuildStore];
return Util.discordSort( return Util.discordSort(
this.channels.cache.filter( this.channels.cache.filter(
c => c =>
(['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_STORE'].includes(channel.type) (channelTypes.includes(channel.type) ? channelTypes.includes(c.type) : c.type === channel.type) &&
? ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_STORE'].includes(c.type)
: c.type === channel.type) &&
(category || c.parent === channel.parent), (category || c.parent === channel.parent),
), ),
); );

View File

@@ -338,19 +338,19 @@ class GuildAuditLogsEntry {
case AuditLogEvent.ChannelOverwriteCreate: case AuditLogEvent.ChannelOverwriteCreate:
case AuditLogEvent.ChannelOverwriteUpdate: case AuditLogEvent.ChannelOverwriteUpdate:
case AuditLogEvent.ChannelOverwriteDelete: case AuditLogEvent.ChannelOverwriteDelete:
switch (Number(data.options.type)) { switch (data.options.type) {
case OverwriteType.Role: case OverwriteType.Role:
this.extra = guild.roles.cache.get(data.options.id) ?? { this.extra = guild.roles.cache.get(data.options.id) ?? {
id: data.options.id, id: data.options.id,
name: data.options.role_name, name: data.options.role_name,
type: OverwriteType[OverwriteType.Role], type: OverwriteType.Role,
}; };
break; break;
case OverwriteType.Member: case OverwriteType.Member:
this.extra = guild.members.cache.get(data.options.id) ?? { this.extra = guild.members.cache.get(data.options.id) ?? {
id: data.options.id, id: data.options.id,
type: OverwriteType[OverwriteType.Member], type: OverwriteType.Member,
}; };
break; break;

View File

@@ -311,7 +311,7 @@ class GuildChannel extends Channel {
if (data.lockPermissions) { if (data.lockPermissions) {
if (data.parent) { if (data.parent) {
const newParent = this.guild.channels.resolve(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 => permission_overwrites = newParent.permissionOverwrites.cache.map(o =>
PermissionOverwrites.resolve(o, this.guild), PermissionOverwrites.resolve(o, this.guild),
); );
@@ -326,7 +326,7 @@ class GuildChannel extends Channel {
const newData = await this.client.api.channels(this.id).patch({ const newData = await this.client.api.channels(this.id).patch({
data: { data: {
name: (data.name ?? this.name).trim(), name: (data.name ?? this.name).trim(),
type: ChannelType[data.type], type: data.type,
topic: data.topic, topic: data.topic,
nsfw: data.nsfw, nsfw: data.nsfw,
bitrate: data.bitrate ?? this.bitrate, bitrate: data.bitrate ?? this.bitrate,

View File

@@ -236,7 +236,7 @@ class GuildScheduledEvent extends Base {
*/ */
async createInviteURL(options) { async createInviteURL(options) {
let channelId = this.channelId; let channelId = this.channelId;
if (this.entityType === 'EXTERNAL') { if (this.entityType === GuildScheduledEventEntityType.External) {
if (!options?.channel) throw new Error('INVITE_OPTIONS_MISSING_CHANNEL'); if (!options?.channel) throw new Error('INVITE_OPTIONS_MISSING_CHANNEL');
channelId = this.guild.channels.resolveId(options.channel); channelId = this.guild.channels.resolveId(options.channel);
if (!channelId) throw new Error('GUILD_CHANNEL_RESOLVE'); if (!channelId) throw new Error('GUILD_CHANNEL_RESOLVE');
@@ -343,7 +343,7 @@ class GuildScheduledEvent extends Base {
* @returns {Promise<GuildScheduledEvent>} * @returns {Promise<GuildScheduledEvent>}
* @example * @example
* // Set status of a guild scheduled event * // Set status of a guild scheduled event
* guildScheduledEvent.setStatus('ACTIVE') * guildScheduledEvent.setStatus(GuildScheduledEventStatus.Active)
* .then(guildScheduledEvent => console.log(`Set the status to: ${guildScheduledEvent.status}`)) * .then(guildScheduledEvent => console.log(`Set the status to: ${guildScheduledEvent.status}`))
* .catch(console.error); * .catch(console.error);
*/ */

View File

@@ -17,7 +17,7 @@ class Interaction extends Base {
* The interaction's type * The interaction's type
* @type {InteractionType} * @type {InteractionType}
*/ */
this.type = InteractionType[data.type]; this.type = data.type;
/** /**
* The interaction's id * The interaction's id
@@ -154,7 +154,7 @@ class Interaction extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isCommand() { isCommand() {
return InteractionType[this.type] === InteractionType.ApplicationCommand; return this.type === InteractionType.ApplicationCommand;
} }
/** /**
@@ -162,7 +162,7 @@ class Interaction extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isChatInputCommand() { 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} * @returns {boolean}
*/ */
isContextMenuCommand() { 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} * @returns {boolean}
*/ */
isUserContextMenuCommand() { 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} * @returns {boolean}
*/ */
isMessageContextMenuCommand() { 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} * @returns {boolean}
*/ */
isAutocomplete() { isAutocomplete() {
return InteractionType[this.type] === InteractionType.ApplicationCommandAutocomplete; return this.type === InteractionType.ApplicationCommandAutocomplete;
} }
/** /**
@@ -202,7 +202,7 @@ class Interaction extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isMessageComponent() { isMessageComponent() {
return InteractionType[this.type] === InteractionType.MessageComponent; return this.type === InteractionType.MessageComponent;
} }
/** /**
@@ -210,10 +210,7 @@ class Interaction extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isButton() { isButton() {
return ( return this.isMessageComponent() && this.componentType === ComponentType.Button;
InteractionType[this.type] === InteractionType.MessageComponent &&
ComponentType[this.componentType] === ComponentType.Button
);
} }
/** /**
@@ -221,10 +218,7 @@ class Interaction extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isSelectMenu() { isSelectMenu() {
return ( return this.isMessageComponent() && this.componentType === ComponentType.SelectMenu;
InteractionType[this.type] === InteractionType.MessageComponent &&
ComponentType[this.componentType] === ComponentType.SelectMenu
);
} }
/** /**
@@ -232,7 +226,7 @@ class Interaction extends Base {
* @returns {boolean} * @returns {boolean}
*/ */
isRepliable() { isRepliable() {
return ![InteractionType.Ping, InteractionType.ApplicationCommandAutocomplete].includes(InteractionType[this.type]); return ![InteractionType.Ping, InteractionType.ApplicationCommandAutocomplete].includes(this.type);
} }
} }

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { InviteTargetType } = require('discord-api-types/v9');
const Base = require('./Base'); const Base = require('./Base');
const { GuildScheduledEvent } = require('./GuildScheduledEvent'); const { GuildScheduledEvent } = require('./GuildScheduledEvent');
const IntegrationApplication = require('./IntegrationApplication'); const IntegrationApplication = require('./IntegrationApplication');
@@ -148,7 +147,7 @@ class Invite extends Base {
* The target type * The target type
* @type {?InviteTargetType} * @type {?InviteTargetType}
*/ */
this.targetType = InviteTargetType[data.target_type]; this.targetType = data.target_type;
} else { } else {
this.targetType ??= null; this.targetType ??= null;
} }

View File

@@ -3,7 +3,7 @@
const { createComponent } = require('@discordjs/builders'); const { createComponent } = require('@discordjs/builders');
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { DiscordSnowflake } = require('@sapphire/snowflake'); 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 Base = require('./Base');
const ClientApplication = require('./ClientApplication'); const ClientApplication = require('./ClientApplication');
const InteractionCollector = require('./InteractionCollector'); const InteractionCollector = require('./InteractionCollector');
@@ -15,7 +15,7 @@ const ReactionCollector = require('./ReactionCollector');
const { Sticker } = require('./Sticker'); const { Sticker } = require('./Sticker');
const { Error } = require('../errors'); const { Error } = require('../errors');
const ReactionManager = require('../managers/ReactionManager'); const ReactionManager = require('../managers/ReactionManager');
const { SystemMessageTypes } = require('../util/Constants'); const { NonSystemMessageTypes } = require('../util/Constants');
const MessageFlags = require('../util/MessageFlags'); const MessageFlags = require('../util/MessageFlags');
const Permissions = require('../util/Permissions'); const Permissions = require('../util/Permissions');
const Util = require('../util/Util'); const Util = require('../util/Util');
@@ -61,13 +61,13 @@ class Message extends Base {
* The type of the message * The type of the message
* @type {?MessageType} * @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) * Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications)
* @type {?boolean} * @type {?boolean}
*/ */
this.system = SystemMessageTypes.includes(this.type); this.system = !NonSystemMessageTypes.includes(this.type);
} else { } else {
this.system ??= null; this.system ??= null;
this.type ??= null; this.type ??= null;
@@ -334,7 +334,7 @@ class Message extends Base {
*/ */
this.interaction = { this.interaction = {
id: data.interaction.id, id: data.interaction.id,
type: InteractionType[data.interaction.type], type: data.interaction.type,
commandName: data.interaction.name, commandName: data.interaction.name,
user: this.client.users._add(data.interaction.user), 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); (this.author.id === this.client.user.id ? Permissions.defaultBit : Permissions.FLAGS.MANAGE_MESSAGES);
const { channel } = this; const { channel } = this;
return Boolean( return Boolean(
channel?.type === 'GUILD_NEWS' && channel?.type === ChannelType.GuildNews &&
!this.flags.has(MessageFlags.FLAGS.CROSSPOSTED) && !this.flags.has(MessageFlags.FLAGS.CROSSPOSTED) &&
this.type === 'DEFAULT' && this.type === MessageType.Default &&
channel.viewable && channel.viewable &&
channel.permissionsFor(this.client.user)?.has(bitfield, false), channel.permissionsFor(this.client.user)?.has(bitfield, false),
); );
@@ -662,7 +662,7 @@ class Message extends Base {
* @returns {Promise<Message>} * @returns {Promise<Message>}
* @example * @example
* // Crosspost a message * // Crosspost a message
* if (message.channel.type === 'GUILD_NEWS') { * if (message.channel.type === ChannelType.GuildNews) {
* message.crosspost() * message.crosspost()
* .then(() => console.log('Crossposted message')) * .then(() => console.log('Crossposted message'))
* .catch(console.error); * .catch(console.error);
@@ -812,7 +812,7 @@ class Message extends Base {
*/ */
startThread(options = {}) { startThread(options = {}) {
if (!this.channel) return Promise.reject(new Error('CHANNEL_NOT_CACHED')); 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')); return Promise.reject(new Error('MESSAGE_THREAD_PARENT'));
} }
if (this.hasThread) return Promise.reject(new Error('MESSAGE_EXISTING_THREAD')); if (this.hasThread) return Promise.reject(new Error('MESSAGE_EXISTING_THREAD'));

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { ComponentType } = require('discord-api-types/v9');
const Interaction = require('./Interaction'); const Interaction = require('./Interaction');
const InteractionWebhook = require('./InteractionWebhook'); const InteractionWebhook = require('./InteractionWebhook');
const InteractionResponses = require('./interfaces/InteractionResponses'); const InteractionResponses = require('./interfaces/InteractionResponses');
@@ -34,9 +33,9 @@ class MessageComponentInteraction extends Interaction {
/** /**
* The type of component which was interacted with * 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 * 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); .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 // These are here only for documentation purposes - they are implemented by InteractionResponses
/* eslint-disable no-empty-function */ /* eslint-disable no-empty-function */
deferReply() {} deferReply() {}

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { ChannelType } = require('discord-api-types/v9');
const Util = require('../util/Util'); const Util = require('../util/Util');
/** /**
@@ -112,13 +111,11 @@ class MessageMentions {
this.crosspostedChannels = new Collection(crosspostedChannels); this.crosspostedChannels = new Collection(crosspostedChannels);
} else { } else {
this.crosspostedChannels = new Collection(); this.crosspostedChannels = new Collection();
const channelTypes = Object.keys(ChannelType);
for (const d of crosspostedChannels) { for (const d of crosspostedChannels) {
const type = channelTypes[d.type];
this.crosspostedChannels.set(d.id, { this.crosspostedChannels.set(d.id, {
channelId: d.id, channelId: d.id,
guildId: d.guild_id, guildId: d.guild_id,
type: type ?? 'UNKNOWN', type: d.type,
name: d.name, name: d.name,
}); });
} }

View File

@@ -14,7 +14,7 @@ class NewsChannel extends BaseGuildTextChannel {
* @param {string} [reason] Reason for creating the webhook * @param {string} [reason] Reason for creating the webhook
* @returns {Promise<NewsChannel>} * @returns {Promise<NewsChannel>}
* @example * @example
* if (channel.type === 'GUILD_NEWS') { * if (channel.type === ChannelType.GuildNews) {
* channel.addFollower('222197033908436994', 'Important announcements') * channel.addFollower('222197033908436994', 'Important announcements')
* .then(() => console.log('Added follower')) * .then(() => console.log('Added follower'))
* .catch(console.error); * .catch(console.error);

View File

@@ -37,7 +37,7 @@ class PermissionOverwrites extends Base {
* The type of this overwrite * The type of this overwrite
* @type {OverwriteType} * @type {OverwriteType}
*/ */
this.type = typeof data.type === 'number' ? OverwriteType[data.type] : data.type; this.type = data.type;
} }
if ('deny' in data) { if ('deny' in data) {
@@ -71,7 +71,7 @@ class PermissionOverwrites extends Base {
* .catch(console.error); * .catch(console.error);
*/ */
async edit(options, reason) { 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; return this;
} }
@@ -88,7 +88,7 @@ class PermissionOverwrites extends Base {
toJSON() { toJSON() {
return { return {
id: this.id, id: this.id,
type: OverwriteType[this.type], type: this.type,
allow: this.allow, allow: this.allow,
deny: this.deny, deny: this.deny,
}; };
@@ -174,7 +174,7 @@ class PermissionOverwrites extends Base {
if (typeof overwrite.id === 'string' && overwrite.type in OverwriteType) { if (typeof overwrite.id === 'string' && overwrite.type in OverwriteType) {
return { return {
id: overwrite.id, id: overwrite.id,
type: OverwriteType[overwrite.type], type: overwrite.type,
allow: Permissions.resolve(overwrite.allow ?? Permissions.defaultBit).toString(), allow: Permissions.resolve(overwrite.allow ?? Permissions.defaultBit).toString(),
deny: Permissions.resolve(overwrite.deny ?? Permissions.defaultBit).toString(), deny: Permissions.resolve(overwrite.deny ?? Permissions.defaultBit).toString(),
}; };

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { ActivityType } = require('discord-api-types/v9');
const Base = require('./Base'); const Base = require('./Base');
const { Emoji } = require('./Emoji'); const { Emoji } = require('./Emoji');
const ActivityFlags = require('../util/ActivityFlags'); const ActivityFlags = require('../util/ActivityFlags');
@@ -168,7 +167,7 @@ class Activity {
* The activity status's type * The activity status's type
* @type {ActivityType} * @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 * If the activity is being streamed, a link to the stream

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
const { DiscordSnowflake } = require('@sapphire/snowflake'); const { DiscordSnowflake } = require('@sapphire/snowflake');
const { StageInstancePrivacyLevel } = require('discord-api-types/v9');
const Base = require('./Base'); const Base = require('./Base');
/** /**
@@ -51,7 +50,7 @@ class StageInstance extends Base {
* The privacy level of the stage instance * The privacy level of the stage instance
* @type {StageInstancePrivacyLevel} * @type {StageInstancePrivacyLevel}
*/ */
this.privacyLevel = StageInstancePrivacyLevel[data.privacy_level]; this.privacyLevel = data.privacy_level;
} }
if ('discoverable_disabled' in data) { if ('discoverable_disabled' in data) {

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
const { DiscordSnowflake } = require('@sapphire/snowflake'); const { DiscordSnowflake } = require('@sapphire/snowflake');
const { StickerType, StickerFormatType } = require('discord-api-types/v9');
const Base = require('./Base'); const Base = require('./Base');
/** /**
@@ -37,7 +36,7 @@ class Sticker extends Base {
* The type of the sticker * The type of the sticker
* @type {?StickerType} * @type {?StickerType}
*/ */
this.type = StickerType[sticker.type]; this.type = sticker.type;
} else { } else {
this.type ??= null; this.type ??= null;
} }
@@ -47,7 +46,7 @@ class Sticker extends Base {
* The format of the sticker * The format of the sticker
* @type {StickerFormatType} * @type {StickerFormatType}
*/ */
this.format = StickerFormatType[sticker.format_type]; this.format = sticker.format_type;
} }
if ('name' in sticker) { if ('name' in sticker) {

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { TeamMemberMembershipState } = require('discord-api-types/v9');
const Base = require('./Base'); const Base = require('./Base');
/** /**
@@ -34,7 +33,7 @@ class TeamMember extends Base {
* The permissions this Team Member has with regard to the team * The permissions this Team Member has with regard to the team
* @type {TeamMemberMembershipState} * @type {TeamMemberMembershipState}
*/ */
this.membershipState = TeamMemberMembershipState[data.membership_state]; this.membershipState = data.membership_state;
} }
if ('user' in data) { if ('user' in data) {

View File

@@ -1,5 +1,6 @@
'use strict'; 'use strict';
const { ChannelType } = require('discord-api-types/v9');
const { Channel } = require('./Channel'); const { Channel } = require('./Channel');
const TextBasedChannel = require('./interfaces/TextBasedChannel'); const TextBasedChannel = require('./interfaces/TextBasedChannel');
const { RangeError } = require('../errors'); const { RangeError } = require('../errors');
@@ -79,7 +80,7 @@ class ThreadChannel extends Channel {
* <info>Always `null` in public threads</info> * <info>Always `null` in public threads</info>
* @type {?boolean} * @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 * Whether the thread is archived
@@ -302,7 +303,7 @@ class ThreadChannel extends Channel {
auto_archive_duration: autoArchiveDuration, auto_archive_duration: autoArchiveDuration,
rate_limit_per_user: data.rateLimitPerUser, rate_limit_per_user: data.rateLimitPerUser,
locked: data.locked, locked: data.locked,
invitable: this.type === 'GUILD_PRIVATE_THREAD' ? data.invitable : undefined, invitable: this.type === ChannelType.GuildPrivateThread ? data.invitable : undefined,
}, },
reason, reason,
}); });
@@ -351,7 +352,9 @@ class ThreadChannel extends Channel {
* @returns {Promise<ThreadChannel>} * @returns {Promise<ThreadChannel>}
*/ */
setInvitable(invitable = true, reason) { 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); return this.edit({ invitable }, reason);
} }
@@ -412,7 +415,8 @@ class ThreadChannel extends Channel {
*/ */
get editable() { get editable() {
return ( 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.archived &&
!this.joined && !this.joined &&
this.permissionsFor(this.client.user)?.has( 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, false,
) )
); );
@@ -474,7 +480,7 @@ class ThreadChannel extends Channel {
return ( return (
!(this.archived && this.locked && !this.manageable) && !(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) && permissions.has(Permissions.FLAGS.SEND_MESSAGES_IN_THREADS, false) &&
this.guild.me.communicationDisabledUntilTimestamp < Date.now() this.guild.me.communicationDisabledUntilTimestamp < Date.now()
); );

View File

@@ -1,5 +1,6 @@
'use strict'; 'use strict';
const { ChannelType } = require('discord-api-types/v9');
const Base = require('./Base'); const Base = require('./Base');
const { Error, TypeError } = require('../errors'); const { Error, TypeError } = require('../errors');
@@ -217,7 +218,7 @@ class VoiceState extends Base {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async setRequestToSpeak(request = true) { 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'); 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) { async setSuppressed(suppressed = true) {
if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed'); 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; const target = this.client.user.id === this.id ? '@me' : this.id;

View File

@@ -56,7 +56,7 @@ class Webhook {
* The type of the webhook * The type of the webhook
* @type {WebhookType} * @type {WebhookType}
*/ */
this.type = WebhookType[data.type]; this.type = data.type;
} }
if ('guild_id' in data) { if ('guild_id' in data) {
@@ -398,7 +398,7 @@ class Webhook {
* @returns {boolean} * @returns {boolean}
*/ */
isChannelFollower() { isChannelFollower() {
return this.type === 'ChannelFollower'; return this.type === WebhookType.ChannelFollower;
} }
/** /**
@@ -406,7 +406,7 @@ class Webhook {
* @returns {boolean} * @returns {boolean}
*/ */
isIncoming() { isIncoming() {
return this.type === 'Incoming'; return this.type === WebhookType.Incoming;
} }
static applyToClass(structure, ignore = []) { static applyToClass(structure, ignore = []) {

View File

@@ -1,6 +1,7 @@
'use strict'; 'use strict';
const process = require('node:process'); const process = require('node:process');
const { ChannelType, MessageType, StickerFormatType } = require('discord-api-types/v9');
const Package = (exports.Package = require('../../package.json')); const Package = (exports.Package = require('../../package.json'));
const { Error, RangeError, TypeError } = require('../errors'); const { Error, RangeError, TypeError } = require('../errors');
@@ -83,7 +84,8 @@ exports.Endpoints = {
DiscoverySplash: (guildId, hash, options) => DiscoverySplash: (guildId, hash, options) =>
makeImageUrl(`${root}/discovery-splashes/${guildId}`, { hash, ...options }), makeImageUrl(`${root}/discovery-splashes/${guildId}`, { hash, ...options }),
TeamIcon: (teamId, hash, options) => makeImageUrl(`${root}/team-icons/${teamId}`, { 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 }), RoleIcon: (roleId, hash, options) => makeImageUrl(`${root}/role-icons/${roleId}`, { hash, ...options }),
}; };
}, },
@@ -384,61 +386,6 @@ exports.InviteScopes = [
*/ */
exports.IntegrationExpireBehaviors = createEnum(['REMOVE_ROLE', 'KICK']); 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 * The name of an item to be swept in Sweepers
* * `applicationCommands` - both global and guild commands * * `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: * The types of messages that are not `System`. The available types are:
* * DEFAULT * * `MessageType.Default`
* * REPLY * * `MessageType.Reply`
* * CHAT_INPUT_COMMAND * * `MessageType.ChatInputCommand`
* * CONTEXT_MENU_COMMAND * * `MessageType.ContextMenuCommand`
* @typedef {string} SystemMessageType * @typedef {MessageType[]} NonSystemMessageTypes
*/ */
exports.SystemMessageTypes = exports.MessageTypes.filter( exports.NonSystemMessageTypes = [
type => type && !['DEFAULT', 'REPLY', 'CHAT_INPUT_COMMAND', 'CONTEXT_MENU_COMMAND'].includes(type), MessageType.Default,
); MessageType.Reply,
MessageType.ChatInputCommand,
MessageType.ContextMenuCommand,
];
/** /**
* The channels that are text-based. * 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: * The types of channels that are text-based. The available types are:
* * DM * * `ChannelType.DM`
* * GUILD_TEXT * * `ChannelType.GuildText`
* * GUILD_NEWS * * `ChannelType.GuildNews`
* * GUILD_NEWS_THREAD * * `ChannelType.GuildNewsThread`
* * GUILD_PUBLIC_THREAD * * `ChannelType.GuildPublicThread`
* * GUILD_PRIVATE_THREAD * * `ChannelType.GuildPrivateThread`
* @typedef {string} TextBasedChannelTypes * @typedef {ChannelType} TextBasedChannelTypes
*/ */
exports.TextBasedChannelTypes = [ exports.TextBasedChannelTypes = [
'DM', ChannelType.DM,
'GUILD_TEXT', ChannelType.GuildText,
'GUILD_NEWS', ChannelType.GuildNews,
'GUILD_NEWS_THREAD', ChannelType.GuildNewsThread,
'GUILD_PUBLIC_THREAD', ChannelType.GuildPublicThread,
'GUILD_PRIVATE_THREAD', ChannelType.GuildPrivateThread,
]; ];
/** /**
* The types of channels that are threads. The available types are: * The types of channels that are threads. The available types are:
* * GUILD_NEWS_THREAD * * `ChannelType.GuildNewsThread`
* * GUILD_PUBLIC_THREAD * * `ChannelType.GuildPublicThread`
* * GUILD_PRIVATE_THREAD * * `ChannelType.GuildPrivateThread`
* @typedef {string} ThreadChannelTypes * @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: * The types of channels that are voice-based. The available types are:
* * GUILD_VOICE * * `ChannelType.GuildVoice`
* * GUILD_STAGE_VOICE * * `ChannelType.GuildStageVoice`
* @typedef {string} VoiceBasedChannelTypes * @typedef {ChannelType[]} VoiceBasedChannelTypes
*/ */
exports.VoiceBasedChannelTypes = ['GUILD_VOICE', 'GUILD_STAGE_VOICE']; exports.VoiceBasedChannelTypes = [ChannelType.GuildVoice, ChannelType.GuildStageVoice];
exports.Colors = { exports.Colors = {
DEFAULT: 0x000000, DEFAULT: 0x000000,

View File

@@ -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;

View File

@@ -2,6 +2,7 @@
const { parse } = require('node:path'); const { parse } = require('node:path');
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { ChannelType } = require('discord-api-types/v9');
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const { Colors, Endpoints } = require('./Constants'); const { Colors, Endpoints } = require('./Constants');
const Options = require('./Options'); const Options = require('./Options');
@@ -528,7 +529,7 @@ class Util extends null {
str = str str = str
.replace(/<@!?[0-9]+>/g, input => { .replace(/<@!?[0-9]+>/g, input => {
const id = input.replace(/<|!|>|@/g, ''); const id = input.replace(/<|!|>|@/g, '');
if (channel.type === 'DM') { if (channel.type === ChannelType.DM) {
const user = channel.client.users.cache.get(id); const user = channel.client.users.cache.get(id);
return user ? `@${user.username}` : input; return user ? `@${user.username}` : input;
} }
@@ -546,7 +547,7 @@ class Util extends null {
return mentionedChannel ? `#${mentionedChannel.name}` : input; return mentionedChannel ? `#${mentionedChannel.name}` : input;
}) })
.replace(/<@&[0-9]+>/g, 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, '')); const role = channel.guild.roles.cache.get(input.replace(/<|@|>|&/g, ''));
return role ? `@${role.name}` : input; return role ? `@${role.name}` : input;
}); });

View File

@@ -1,6 +1,7 @@
'use strict'; 'use strict';
const assert = require('node:assert'); const assert = require('node:assert');
const { ChannelType } = require('discord-api-types/v9');
const { token } = require('./auth'); const { token } = require('./auth');
const { Client, Intents } = require('../src'); const { Client, Intents } = require('../src');
@@ -10,7 +11,7 @@ client.on('ready', async () => {
try { try {
const guild = await client.guilds.create('testing', { const guild = await client.guilds.create('testing', {
channels: [ channels: [
{ name: 'afk channel', type: 'GUILD_VOICE', id: 0 }, { name: 'afk channel', type: ChannelType.GuildVoice, id: 0 },
{ name: 'system-channel', id: 1 }, { name: 'system-channel', id: 1 },
], ],
afkChannelId: 0, afkChannelId: 0,

View File

@@ -6,6 +6,7 @@ const request = require('superagent');
const ytdl = require('ytdl-core'); const ytdl = require('ytdl-core');
const { token, song } = require('./auth.js'); const { token, song } = require('./auth.js');
const { Client, Intents } = require('../src'); const { Client, Intents } = require('../src');
const { ChannelType } = require('discord-api-types/v9');
console.time('magic'); console.time('magic');
@@ -57,7 +58,7 @@ client.on('messageCreate', message => {
if (true) { if (true) {
if (message.content === 'makechann') { if (message.content === 'makechann') {
if (message.channel.guild) { 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);
} }
} }

View File

@@ -174,7 +174,7 @@ export class Activity {
start: Date | null; start: Date | null;
end: Date | null; end: Date | null;
} | null; } | null;
public type: ActivityTypeKey; public type: ActivityType;
public url: string | null; public url: string | null;
public equals(activity: Activity): boolean; public equals(activity: Activity): boolean;
} }
@@ -230,7 +230,7 @@ export class ApplicationCommand<PermissionsFetchType = {}> extends Base {
Guild | null, Guild | null,
Snowflake Snowflake
>; >;
public type: ApplicationCommandTypeKey; public type: ApplicationCommandType;
public version: Snowflake; public version: Snowflake;
public delete(): Promise<ApplicationCommand<PermissionsFetchType>>; public delete(): Promise<ApplicationCommand<PermissionsFetchType>>;
public edit(data: ApplicationCommandData): Promise<ApplicationCommand<PermissionsFetchType>>; public edit(data: ApplicationCommandData): Promise<ApplicationCommand<PermissionsFetchType>>;
@@ -473,35 +473,29 @@ export class ButtonInteraction<Cached extends CacheType = CacheType> extends Mes
public inRawGuild(): this is ButtonInteraction<'raw'>; public inRawGuild(): this is ButtonInteraction<'raw'>;
} }
export type KeyedEnum<K, T> = { export interface MappedChannelCategoryTypes {
[Key in keyof K]: T | string; [ChannelType.GuildNews]: NewsChannel;
}; [ChannelType.GuildVoice]: VoiceChannel;
[ChannelType.GuildText]: TextChannel;
[ChannelType.GuildStore]: StoreChannel;
[ChannelType.GuildStageVoice]: StageChannel;
}
export type EnumValueMapped<E extends KeyedEnum<T, number>, T extends Partial<Record<keyof E, unknown>>> = T & { export type CategoryChannelType = Exclude<
[Key in keyof T as E[Key]]: T[Key]; ChannelType,
}; | ChannelType.DM
| ChannelType.GroupDM
export type MappedChannelCategoryTypes = EnumValueMapped< | ChannelType.GuildPublicThread
typeof ChannelType, | ChannelType.GuildNewsThread
{ | ChannelType.GuildPrivateThread
GuildNews: NewsChannel; | ChannelType.GuildCategory
GuildVoice: VoiceChannel;
GuildText: TextChannel;
GuildStore: StoreChannel;
GuildStageVoice: StageChannel;
}
>;
export type CategoryChannelTypes = ExcludeEnum<
typeof ChannelType,
'DM' | 'GroupDM' | 'GuildPublicThread' | 'GuildNewsThread' | 'GuildPrivateThread' | 'GuildCategory'
>; >;
export class CategoryChannel extends GuildChannel { export class CategoryChannel extends GuildChannel {
public readonly children: Collection<Snowflake, Exclude<NonThreadGuildBasedChannel, CategoryChannel>>; public readonly children: Collection<Snowflake, Exclude<NonThreadGuildBasedChannel, CategoryChannel>>;
public type: 'GuildCategory'; public type: ChannelType.GuildCategory;
public createChannel<T extends Exclude<CategoryChannelTypes, 'GuildStore'>>( public createChannel<T extends Exclude<CategoryChannelType, ChannelType.GuildStore>>(
name: string, name: string,
options: CategoryCreateChannelOptions & { type: T }, options: CategoryCreateChannelOptions & { type: T },
): Promise<MappedChannelCategoryTypes[T]>; ): Promise<MappedChannelCategoryTypes[T]>;
@@ -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 */ /** @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */
public createChannel( public createChannel(
name: string, name: string,
options: CategoryCreateChannelOptions & { type: 'GuildStore' | ChannelType.GuildStore }, options: CategoryCreateChannelOptions & { type: ChannelType.GuildStore },
): Promise<StoreChannel>; ): Promise<StoreChannel>;
public createChannel(name: string, options?: CategoryCreateChannelOptions): Promise<TextChannel>; public createChannel(name: string, options?: CategoryCreateChannelOptions): Promise<TextChannel>;
} }
@@ -522,7 +516,7 @@ export abstract class Channel extends Base {
public readonly createdTimestamp: number; public readonly createdTimestamp: number;
public id: Snowflake; public id: Snowflake;
public readonly partial: false; public readonly partial: false;
public type: keyof typeof ChannelType; public type: ChannelType;
public delete(): Promise<this>; public delete(): Promise<this>;
public fetch(force?: boolean): Promise<this>; public fetch(force?: boolean): Promise<this>;
public isText(): this is TextChannel; public isText(): this is TextChannel;
@@ -743,7 +737,6 @@ export class AutocompleteInteraction<Cached extends CacheType = CacheType> exten
public inGuild(): this is AutocompleteInteraction<'raw' | 'cached'>; public inGuild(): this is AutocompleteInteraction<'raw' | 'cached'>;
public inCachedGuild(): this is AutocompleteInteraction<'cached'>; public inCachedGuild(): this is AutocompleteInteraction<'cached'>;
public inRawGuild(): this is AutocompleteInteraction<'raw'>; public inRawGuild(): this is AutocompleteInteraction<'raw'>;
private transformOption(option: APIApplicationCommandOption): CommandInteractionOption;
public respond(options: ApplicationCommandOptionChoice[]): Promise<void>; public respond(options: ApplicationCommandOptionChoice[]): Promise<void>;
} }
@@ -757,13 +750,13 @@ export class CommandInteractionOptionResolver<Cached extends CacheType = CacheTy
private _subcommand: string | null; private _subcommand: string | null;
private _getTypedOption( private _getTypedOption(
name: string, name: string,
type: ApplicationCommandOptionTypeKey, type: ApplicationCommandOptionType,
properties: (keyof ApplicationCommandOption)[], properties: (keyof ApplicationCommandOption)[],
required: true, required: true,
): CommandInteractionOption<Cached>; ): CommandInteractionOption<Cached>;
private _getTypedOption( private _getTypedOption(
name: string, name: string,
type: ApplicationCommandOptionTypeKey, type: ApplicationCommandOptionType,
properties: (keyof ApplicationCommandOption)[], properties: (keyof ApplicationCommandOption)[],
required: boolean, required: boolean,
): CommandInteractionOption<Cached> | null; ): CommandInteractionOption<Cached> | null;
@@ -819,7 +812,7 @@ export class ContextMenuCommandInteraction<Cached extends CacheType = CacheType>
| 'getSubcommand' | 'getSubcommand'
>; >;
public targetId: Snowflake; public targetId: Snowflake;
public targetType: Exclude<ApplicationCommandTypeKey, 'ChatInput'>; public targetType: Exclude<ApplicationCommandType, ApplicationCommandType.ChatInput>;
public inGuild(): this is ContextMenuCommandInteraction<'raw' | 'cached'>; public inGuild(): this is ContextMenuCommandInteraction<'raw' | 'cached'>;
public inCachedGuild(): this is ContextMenuCommandInteraction<'cached'>; public inCachedGuild(): this is ContextMenuCommandInteraction<'cached'>;
public inRawGuild(): this is ContextMenuCommandInteraction<'raw'>; public inRawGuild(): this is ContextMenuCommandInteraction<'raw'>;
@@ -837,6 +830,22 @@ export class DataResolver extends null {
public static resolveGuildTemplateCode(data: GuildTemplateResolvable): string; 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 { export class DiscordAPIError extends Error {
private constructor(error: unknown, status: number, request: unknown); private constructor(error: unknown, status: number, request: unknown);
private static flattenErrors(obj: unknown, key: string): string[]; 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); private constructor(client: Client, data?: RawDMChannelData);
public messages: MessageManager; public messages: MessageManager;
public recipient: User; public recipient: User;
public type: 'DM'; public type: ChannelType.DM;
public fetch(force?: boolean): Promise<this>; public fetch(force?: boolean): Promise<this>;
} }
@@ -897,7 +906,7 @@ export class Guild extends AnonymousGuild {
public readonly me: GuildMember | null; public readonly me: GuildMember | null;
public memberCount: number; public memberCount: number;
public members: GuildMemberManager; public members: GuildMemberManager;
public mfaLevel: GuildMFALevelKey; public mfaLevel: GuildMFALevel;
public ownerId: Snowflake; public ownerId: Snowflake;
public preferredLocale: string; public preferredLocale: string;
public premiumSubscriptionCount: number | null; public premiumSubscriptionCount: number | null;
@@ -1047,7 +1056,7 @@ export abstract class GuildChannel extends Channel {
public readonly permissionsLocked: boolean | null; public readonly permissionsLocked: boolean | null;
public readonly position: number; public readonly position: number;
public rawPosition: number; public rawPosition: number;
public type: Exclude<keyof typeof ChannelType, 'DM' | 'GroupDM'>; public type: Exclude<ChannelType, ChannelType.DM | ChannelType.GroupDM>;
public readonly viewable: boolean; public readonly viewable: boolean;
public clone(options?: GuildChannelCloneOptions): Promise<this>; public clone(options?: GuildChannelCloneOptions): Promise<this>;
public delete(reason?: string): Promise<this>; public delete(reason?: string): Promise<this>;
@@ -1348,7 +1357,7 @@ export class InteractionCollector<T extends Interaction> extends Collector<Snowf
private _handleGuildDeletion(guild: Guild): void; private _handleGuildDeletion(guild: Guild): void;
public channelId: Snowflake | null; public channelId: Snowflake | null;
public componentType: ComponentTypeKey | null; public componentType: ComponentType | null;
public readonly endReason: string | null; public readonly endReason: string | null;
public guildId: Snowflake | null; public guildId: Snowflake | null;
public interactionType: InteractionType | null; public interactionType: InteractionType | null;
@@ -1429,23 +1438,17 @@ export class LimitedCollection<K, V> extends Collection<K, V> {
public keepOverLimit: ((value: V, key: K, collection: this) => boolean) | null; public keepOverLimit: ((value: V, key: K, collection: this) => boolean) | null;
} }
export type MessageCollectorOptionsParams<T extends MessageComponentTypeResolvable, Cached extends boolean = boolean> = export type MessageCollectorOptionsParams<T extends ComponentType, Cached extends boolean = boolean> =
| { | {
componentType?: T; componentType?: T;
} & MessageComponentCollectorOptions<MappedInteractionTypes<Cached>[T]>; } & MessageComponentCollectorOptions<MappedInteractionTypes<Cached>[T]>;
export type MessageChannelCollectorOptionsParams< export type MessageChannelCollectorOptionsParams<T extends ComponentType, Cached extends boolean = boolean> =
T extends MessageComponentTypeResolvable,
Cached extends boolean = boolean,
> =
| { | {
componentType?: T; componentType?: T;
} & MessageChannelComponentCollectorOptions<MappedInteractionTypes<Cached>[T]>; } & MessageChannelComponentCollectorOptions<MappedInteractionTypes<Cached>[T]>;
export type AwaitMessageCollectorOptionsParams< export type AwaitMessageCollectorOptionsParams<T extends ComponentType, Cached extends boolean = boolean> =
T extends MessageComponentTypeResolvable,
Cached extends boolean = boolean,
> =
| { componentType?: T } & Pick< | { componentType?: T } & Pick<
InteractionCollectorOptions<MappedInteractionTypes<Cached>[T]>, InteractionCollectorOptions<MappedInteractionTypes<Cached>[T]>,
keyof AwaitMessageComponentOptions<any> keyof AwaitMessageComponentOptions<any>
@@ -1459,14 +1462,11 @@ export interface StringMappedInteractionTypes<Cached extends CacheType = CacheTy
export type WrapBooleanCache<T extends boolean> = If<T, 'cached', CacheType>; export type WrapBooleanCache<T extends boolean> = If<T, 'cached', CacheType>;
export type MappedInteractionTypes<Cached extends boolean = boolean> = EnumValueMapped< export interface MappedInteractionTypes<Cached extends boolean = boolean> {
typeof ComponentType, [ComponentType.Button]: ButtonInteraction<WrapBooleanCache<Cached>>;
{ [ComponentType.SelectMenu]: SelectMenuInteraction<WrapBooleanCache<Cached>>;
Button: ButtonInteraction<WrapBooleanCache<Cached>>; [ComponentType.ActionRow]: MessageComponentInteraction<WrapBooleanCache<Cached>>;
SelectMenu: SelectMenuInteraction<WrapBooleanCache<Cached>>; }
ActionRow: MessageComponentInteraction<WrapBooleanCache<Cached>>;
}
>;
export class Message<Cached extends boolean = boolean> extends Base { export class Message<Cached extends boolean = boolean> extends Base {
private readonly _cacheType: Cached; private readonly _cacheType: Cached;
@@ -1507,17 +1507,17 @@ export class Message<Cached extends boolean = boolean> extends Base {
public system: boolean; public system: boolean;
public readonly thread: ThreadChannel | null; public readonly thread: ThreadChannel | null;
public tts: boolean; public tts: boolean;
public type: MessageTypeKey; public type: MessageType;
public readonly url: string; public readonly url: string;
public webhookId: Snowflake | null; public webhookId: Snowflake | null;
public flags: Readonly<MessageFlags>; public flags: Readonly<MessageFlags>;
public reference: MessageReference | null; public reference: MessageReference | null;
public awaitMessageComponent<T extends MessageComponentTypeResolvable = 'ActionRow'>( public awaitMessageComponent<T extends ComponentType = ComponentType.ActionRow>(
options?: AwaitMessageCollectorOptionsParams<T, Cached>, options?: AwaitMessageCollectorOptionsParams<T, Cached>,
): Promise<MappedInteractionTypes<Cached>[T]>; ): Promise<MappedInteractionTypes<Cached>[T]>;
public awaitReactions(options?: AwaitReactionsOptions): Promise<Collection<Snowflake | string, MessageReaction>>; public awaitReactions(options?: AwaitReactionsOptions): Promise<Collection<Snowflake | string, MessageReaction>>;
public createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector; public createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector;
public createMessageComponentCollector<T extends MessageComponentTypeResolvable = 'ActionRow'>( public createMessageComponentCollector<T extends ComponentType = ComponentType.ActionRow>(
options?: MessageCollectorOptionsParams<T, Cached>, options?: MessageCollectorOptionsParams<T, Cached>,
): InteractionCollector<MappedInteractionTypes<Cached>[T]>; ): InteractionCollector<MappedInteractionTypes<Cached>[T]>;
public delete(): Promise<Message>; public delete(): Promise<Message>;
@@ -1608,8 +1608,6 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
public reply(options: string | MessagePayload | InteractionReplyOptions): Promise<void>; public reply(options: string | MessagePayload | InteractionReplyOptions): Promise<void>;
public update(options: InteractionUpdateOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>; public update(options: InteractionUpdateOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
public update(options: string | MessagePayload | InteractionUpdateOptions): Promise<void>; public update(options: string | MessagePayload | InteractionUpdateOptions): Promise<void>;
public static resolveType(type: MessageComponentTypeResolvable): ComponentTypeKey;
} }
export class MessageContextMenuCommandInteraction< export class MessageContextMenuCommandInteraction<
@@ -1745,7 +1743,7 @@ export class MessageReaction {
export class NewsChannel extends BaseGuildTextChannel { export class NewsChannel extends BaseGuildTextChannel {
public threads: ThreadManager<AllowedThreadTypeForNewsChannel>; public threads: ThreadManager<AllowedThreadTypeForNewsChannel>;
public type: 'GuildNews'; public type: ChannelType.GuildNews;
public addFollower(channel: TextChannelResolvable, reason?: string): Promise<NewsChannel>; public addFollower(channel: TextChannelResolvable, reason?: string): Promise<NewsChannel>;
} }
@@ -2032,7 +2030,7 @@ export {
export class StageChannel extends BaseGuildVoiceChannel { export class StageChannel extends BaseGuildVoiceChannel {
public topic: string | null; public topic: string | null;
public type: 'GuildStageVoice'; public type: ChannelType.GuildStageVoice;
public readonly stageInstance: StageInstance | null; public readonly stageInstance: StageInstance | null;
public createStageInstance(options: StageInstanceCreateOptions): Promise<StageInstance>; public createStageInstance(options: StageInstanceCreateOptions): Promise<StageInstance>;
public setTopic(topic: string): Promise<StageChannel>; public setTopic(topic: string): Promise<StageChannel>;
@@ -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 */ /** @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<this>; public clone(options?: GuildChannelCloneOptions): Promise<this>;
public nsfw: boolean; public nsfw: boolean;
public type: 'GuildStore'; public type: ChannelType.GuildStore;
} }
export class Sweepers { export class Sweepers {
@@ -2205,7 +2203,7 @@ export class TeamMember extends Base {
export class TextChannel extends BaseGuildTextChannel { export class TextChannel extends BaseGuildTextChannel {
public rateLimitPerUser: number; public rateLimitPerUser: number;
public threads: ThreadManager<AllowedThreadTypeForTextChannel>; public threads: ThreadManager<AllowedThreadTypeForTextChannel>;
public type: 'GuildText'; public type: ChannelType.GuildText;
public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise<TextChannel>; public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise<TextChannel>;
} }
@@ -2235,7 +2233,7 @@ export class ThreadChannel extends TextBasedChannelMixin(Channel) {
public readonly parent: TextChannel | NewsChannel | null; public readonly parent: TextChannel | NewsChannel | null;
public parentId: Snowflake | null; public parentId: Snowflake | null;
public rateLimitPerUser: number | null; public rateLimitPerUser: number | null;
public type: ThreadChannelTypeKey; public type: ThreadChannelType;
public readonly unarchivable: boolean; public readonly unarchivable: boolean;
public delete(reason?: string): Promise<this>; public delete(reason?: string): Promise<this>;
public edit(data: ThreadEditData, reason?: string): Promise<ThreadChannel>; public edit(data: ThreadEditData, reason?: string): Promise<ThreadChannel>;
@@ -2399,7 +2397,7 @@ export class Formatters extends null {
export class VoiceChannel extends BaseGuildVoiceChannel { export class VoiceChannel extends BaseGuildVoiceChannel {
public readonly speakable: boolean; public readonly speakable: boolean;
public type: 'GuildVoice'; public type: ChannelType.GuildVoice;
public setBitrate(bitrate: number, reason?: string): Promise<VoiceChannel>; public setBitrate(bitrate: number, reason?: string): Promise<VoiceChannel>;
public setUserLimit(userLimit: number, reason?: string): Promise<VoiceChannel>; public setUserLimit(userLimit: number, reason?: string): Promise<VoiceChannel>;
} }
@@ -2613,10 +2611,6 @@ export class WelcomeScreen extends Base {
//#region Constants //#region Constants
export type EnumHolder<T> = { [P in keyof T]: T[P] };
export type ExcludeEnum<T, K extends keyof T> = Exclude<keyof T | T[keyof T], K | T[K]>;
export const Constants: { export const Constants: {
Package: { Package: {
name: string; name: string;
@@ -2676,7 +2670,7 @@ export const Constants: {
Colors: ConstantsColors; Colors: ConstantsColors;
Status: ConstantsStatus; Status: ConstantsStatus;
Opcodes: ConstantsOpcodes; Opcodes: ConstantsOpcodes;
ThreadChannelTypes: ThreadChannelTypeKey[]; ThreadChannelTypes: ThreadChannelType[];
TextBasedChannelTypes: TextBasedChannelTypes[]; TextBasedChannelTypes: TextBasedChannelTypes[];
VoiceBasedChannelTypes: VoiceBasedChannelTypes[]; VoiceBasedChannelTypes: VoiceBasedChannelTypes[];
IntegrationExpireBehaviors: IntegrationExpireBehaviors[]; IntegrationExpireBehaviors: IntegrationExpireBehaviors[];
@@ -2831,23 +2825,23 @@ export class GuildApplicationCommandManager extends ApplicationCommandManager<Ap
public set(commands: ApplicationCommandDataResolvable[]): Promise<Collection<Snowflake, ApplicationCommand>>; public set(commands: ApplicationCommandDataResolvable[]): Promise<Collection<Snowflake, ApplicationCommand>>;
} }
export type MappedGuildChannelTypes = EnumValueMapped< export type MappedGuildChannelTypes = {
typeof ChannelType, [ChannelType.GuildCategory]: CategoryChannel;
{ } & MappedChannelCategoryTypes;
GuildCategory: CategoryChannel;
}
> &
MappedChannelCategoryTypes;
export type GuildChannelTypes = CategoryChannelTypes | ChannelType.GuildCategory | 'GuildCategory'; export type GuildChannelTypes = CategoryChannelType | ChannelType.GuildCategory;
export class GuildChannelManager extends CachedManager<Snowflake, GuildBasedChannel, GuildChannelResolvable> { export class GuildChannelManager extends CachedManager<Snowflake, GuildBasedChannel, GuildChannelResolvable> {
private constructor(guild: Guild, iterable?: Iterable<RawGuildChannelData>); private constructor(guild: Guild, iterable?: Iterable<RawGuildChannelData>);
public readonly channelCountWithoutThreads: number; public readonly channelCountWithoutThreads: number;
public guild: Guild; public guild: Guild;
/** @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */ /** @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<StoreChannel>; public create(
public create<T extends GuildChannelTypes>( name: string,
options: GuildChannelCreateOptions & { type: ChannelType.GuildStore },
): Promise<StoreChannel>;
/** @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */
public create<T extends CategoryChannelType | ChannelType.GuildCategory>(
name: string, name: string,
options: GuildChannelCreateOptions & { type: T }, options: GuildChannelCreateOptions & { type: T },
): Promise<MappedGuildChannelTypes[T]>; ): Promise<MappedGuildChannelTypes[T]>;
@@ -3139,7 +3133,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
readonly lastMessage: Message | null; readonly lastMessage: Message | null;
lastPinTimestamp: number | null; lastPinTimestamp: number | null;
readonly lastPinAt: Date | null; readonly lastPinAt: Date | null;
awaitMessageComponent<T extends MessageComponentTypeResolvable = 'ActionRow'>( awaitMessageComponent<T extends ComponentType = ComponentType.ActionRow>(
options?: AwaitMessageCollectorOptionsParams<T, true>, options?: AwaitMessageCollectorOptionsParams<T, true>,
): Promise<MappedInteractionTypes[T]>; ): Promise<MappedInteractionTypes[T]>;
awaitMessages(options?: AwaitMessagesOptions): Promise<Collection<Snowflake, Message>>; awaitMessages(options?: AwaitMessagesOptions): Promise<Collection<Snowflake, Message>>;
@@ -3147,7 +3141,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
messages: Collection<Snowflake, Message> | readonly MessageResolvable[] | number, messages: Collection<Snowflake, Message> | readonly MessageResolvable[] | number,
filterOld?: boolean, filterOld?: boolean,
): Promise<Collection<Snowflake, Message>>; ): Promise<Collection<Snowflake, Message>>;
createMessageComponentCollector<T extends MessageComponentTypeResolvable = 'ActionRow'>( createMessageComponentCollector<T extends ComponentType = ComponentType.ActionRow>(
options?: MessageChannelCollectorOptionsParams<T, true>, options?: MessageChannelCollectorOptionsParams<T, true>,
): InteractionCollector<MappedInteractionTypes[T]>; ): InteractionCollector<MappedInteractionTypes[T]>;
createMessageCollector(options?: MessageCollectorOptions): MessageCollector; createMessageCollector(options?: MessageCollectorOptions): MessageCollector;
@@ -3197,14 +3191,12 @@ export type ActivitiesOptions = Omit<ActivityOptions, 'shardId'>;
export interface ActivityOptions { export interface ActivityOptions {
name?: string; name?: string;
url?: string; url?: string;
type?: ExcludeEnum<typeof ActivityType, 'Custom'>; type?: Exclude<ActivityType, ActivityType.Custom>;
shardId?: number | readonly number[]; shardId?: number | readonly number[];
} }
export type ActivityPlatform = 'desktop' | 'samsung' | 'xbox'; export type ActivityPlatform = 'desktop' | 'samsung' | 'xbox';
export type ActivityTypeKey = keyof typeof ActivityType;
export interface AddGuildMemberOptions { export interface AddGuildMemberOptions {
accessToken: string; accessToken: string;
nick?: 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 AllowedPartial = User | Channel | GuildMember | Message | MessageReaction;
export type AllowedThreadTypeForNewsChannel = 'GUILD_NEWS_THREAD' | ChannelType.GuildNewsThread; export type AllowedThreadTypeForNewsChannel = ChannelType.GuildNewsThread;
export type AllowedThreadTypeForTextChannel = export type AllowedThreadTypeForTextChannel = ChannelType.GuildPublicThread | ChannelType.GuildPrivateThread;
| 'GUILD_PUBLIC_THREAD'
| 'GUILD_PRIVATE_THREAD'
| ChannelType.GuildPublicThread
| ChannelType.GuildPrivateThread;
export interface APIRequest { export interface APIRequest {
method: 'get' | 'post' | 'delete' | 'patch' | 'put'; method: 'get' | 'post' | 'delete' | 'patch' | 'put';
@@ -3242,26 +3230,21 @@ export interface BaseApplicationCommandData {
defaultPermission?: boolean; 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 = export type CommandOptionChoiceResolvableType =
| ApplicationCommandOptionType.String | ApplicationCommandOptionType.String
| 'String'
| CommandOptionNumericResolvableType; | CommandOptionNumericResolvableType;
export type CommandOptionNumericResolvableType = export type CommandOptionNumericResolvableType =
| ApplicationCommandOptionType.Number | ApplicationCommandOptionType.Number
| 'Number' | ApplicationCommandOptionType.Integer;
| ApplicationCommandOptionType.Integer
| 'Integer';
export type CommandOptionSubOptionResolvableType = export type CommandOptionSubOptionResolvableType =
| ApplicationCommandOptionType.Subcommand | ApplicationCommandOptionType.Subcommand
| 'Subcommand' | ApplicationCommandOptionType.SubcommandGroup;
| ApplicationCommandOptionType.SubcommandGroup
| 'SubcommandGroup';
export type CommandOptionNonChoiceResolvableType = Exclude< export type CommandOptionNonChoiceResolvableType = Exclude<
CommandOptionDataTypeResolvable, CommandOptionDataTypeResolvable,
@@ -3301,7 +3284,7 @@ export interface ApplicationCommandChannelOptionData extends BaseApplicationComm
} }
export interface ApplicationCommandChannelOption extends BaseApplicationCommandOptionsData { export interface ApplicationCommandChannelOption extends BaseApplicationCommandOptionsData {
type: 'CHANNEL'; type: ApplicationCommandOptionType.Channel;
channelTypes?: (keyof typeof ChannelType)[]; channelTypes?: (keyof typeof ChannelType)[];
} }
@@ -3398,13 +3381,9 @@ export interface ApplicationCommandOptionChoice {
value: string | number; value: string | number;
} }
export type ApplicationCommandTypeKey = keyof typeof ApplicationCommandType;
export type ApplicationCommandOptionTypeKey = keyof typeof ApplicationCommandOptionType;
export interface ApplicationCommandPermissionData { export interface ApplicationCommandPermissionData {
id: Snowflake; id: Snowflake;
type: ApplicationCommandPermissionTypeKey | ApplicationCommandPermissionType; type: ApplicationCommandPermissionType;
permission: boolean; permission: boolean;
} }
@@ -3412,8 +3391,6 @@ export interface ApplicationCommandPermissions extends ApplicationCommandPermiss
type: ApplicationCommandPermissionType; type: ApplicationCommandPermissionType;
} }
export type ApplicationCommandPermissionTypeKey = keyof typeof ApplicationCommandPermissionType;
export type ApplicationCommandResolvable = ApplicationCommand | Snowflake; export type ApplicationCommandResolvable = ApplicationCommand | Snowflake;
export type ApplicationFlagsString = export type ApplicationFlagsString =
@@ -3466,7 +3443,7 @@ export interface ThreadMemberFetchOptions extends BaseFetchOptions {
} }
export interface BaseMessageComponentOptions { export interface BaseMessageComponentOptions {
type?: ComponentTypeKey | ComponentType; type?: ComponentType;
} }
export type BitFieldResolvable<T extends string, N extends number | bigint> = export type BitFieldResolvable<T extends string, N extends number | bigint> =
@@ -3523,10 +3500,7 @@ export type CacheWithLimitsOptions = {
export interface CategoryCreateChannelOptions { export interface CategoryCreateChannelOptions {
permissionOverwrites?: OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>; permissionOverwrites?: OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>;
topic?: string; topic?: string;
type?: ExcludeEnum< type?: CategoryChannelType;
typeof ChannelType,
'DM' | 'GroupDM' | 'GuildPublicThread' | 'GuildNewsThread' | 'GuildPrivateThread' | 'GuildCategory'
>;
nsfw?: boolean; nsfw?: boolean;
bitrate?: number; bitrate?: number;
userLimit?: number; userLimit?: number;
@@ -3770,7 +3744,7 @@ export type ColorResolvable =
export interface CommandInteractionOption<Cached extends CacheType = CacheType> { export interface CommandInteractionOption<Cached extends CacheType = CacheType> {
name: string; name: string;
type: ApplicationCommandOptionTypeKey; type: ApplicationCommandOptionType;
value?: string | number | boolean; value?: string | number | boolean;
focused?: boolean; focused?: boolean;
autocomplete?: boolean; autocomplete?: boolean;
@@ -4281,9 +4255,13 @@ export type GuildChannelResolvable = Snowflake | GuildBasedChannel;
export interface GuildChannelCreateOptions extends Omit<CategoryCreateChannelOptions, 'type'> { export interface GuildChannelCreateOptions extends Omit<CategoryCreateChannelOptions, 'type'> {
parent?: CategoryChannelResolvable; parent?: CategoryChannelResolvable;
type?: ExcludeEnum< type?: Exclude<
typeof ChannelType, ChannelType,
'DM' | 'GroupDM' | 'GuildPublicThread' | 'GuildNewsThread' | 'GuildPrivateThread' | ChannelType.DM
| ChannelType.GroupDM
| ChannelType.GuildPublicThread
| ChannelType.GuildNewsThread
| ChannelType.GuildPrivateThread
>; >;
} }
@@ -4419,15 +4397,13 @@ export interface GuildListMembersOptions {
cache?: boolean; cache?: boolean;
} }
export type GuildScheduledEventPrivacyLevelKey = keyof typeof GuildScheduledEventPrivacyLevel;
// TODO: use conditional types for better TS support // TODO: use conditional types for better TS support
export interface GuildScheduledEventCreateOptions { export interface GuildScheduledEventCreateOptions {
name: string; name: string;
scheduledStartTime: DateResolvable; scheduledStartTime: DateResolvable;
scheduledEndTime?: DateResolvable; scheduledEndTime?: DateResolvable;
privacyLevel: GuildScheduledEventPrivacyLevel | GuildScheduledEventPrivacyLevelKey; privacyLevel: GuildScheduledEventPrivacyLevel;
entityType: GuildScheduledEventEntityType | GuildScheduledEventEntityTypeKey; entityType: GuildScheduledEventEntityType;
description?: string; description?: string;
channel?: GuildVoiceChannelResolvable; channel?: GuildVoiceChannelResolvable;
entityMetadata?: GuildScheduledEventEntityMetadataOptions; entityMetadata?: GuildScheduledEventEntityMetadataOptions;
@@ -4450,8 +4426,6 @@ export interface GuildScheduledEventEntityMetadataOptions {
location?: string; location?: string;
} }
export type GuildScheduledEventEntityTypeKey = keyof typeof GuildScheduledEventEntityType;
export type GuildScheduledEventManagerFetchResult< export type GuildScheduledEventManagerFetchResult<
T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions,
> = T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions > = T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions
@@ -4524,9 +4498,9 @@ export type IntegrationType = 'twitch' | 'youtube' | 'discord';
export interface InteractionCollectorOptions<T extends Interaction, Cached extends CacheType = CacheType> export interface InteractionCollectorOptions<T extends Interaction, Cached extends CacheType = CacheType>
extends CollectorOptions<[T]> { extends CollectorOptions<[T]> {
channel?: TextBasedChannel; channel?: TextBasedChannel;
componentType?: ComponentType | ComponentTypeKey; componentType?: ComponentType;
guild?: Guild; guild?: Guild;
interactionType?: InteractionTypeKey | InteractionType; interactionType?: InteractionType;
max?: number; max?: number;
maxComponents?: number; maxComponents?: number;
maxUsers?: number; maxUsers?: number;
@@ -4545,10 +4519,6 @@ export interface InteractionReplyOptions extends Omit<WebhookMessageOptions, 'us
fetchReply?: boolean; fetchReply?: boolean;
} }
export type InteractionResponseTypeKey = keyof typeof InteractionResponseType;
export type InteractionTypeKey = keyof typeof InteractionType;
export interface InteractionUpdateOptions extends MessageEditOptions { export interface InteractionUpdateOptions extends MessageEditOptions {
fetchReply?: boolean; fetchReply?: boolean;
} }
@@ -4658,16 +4628,12 @@ export interface LinkButtonOptions extends BaseButtonOptions {
} }
export interface InteractionButtonOptions extends BaseButtonOptions { export interface InteractionButtonOptions extends BaseButtonOptions {
style: ExcludeEnum<typeof ButtonStyle, 'Link'>; style: Exclude<ButtonStyle, ButtonStyle.Link>;
customId: string; customId: string;
} }
export type MessageButtonOptions = InteractionButtonOptions | LinkButtonOptions; export type MessageButtonOptions = InteractionButtonOptions | LinkButtonOptions;
export type ButtonStyleKey = keyof typeof ButtonStyle;
export type MessageButtonStyleResolvable = ButtonStyleKey | ButtonStyle;
export interface MessageCollectorOptions extends CollectorOptions<[Message]> { export interface MessageCollectorOptions extends CollectorOptions<[Message]> {
max?: number; max?: number;
maxProcessed?: number; maxProcessed?: number;
@@ -4691,10 +4657,6 @@ export type MessageComponentOptions =
| MessageButtonOptions | MessageButtonOptions
| MessageSelectMenuOptions; | MessageSelectMenuOptions;
export type ComponentTypeKey = keyof typeof ComponentType;
export type MessageComponentTypeResolvable = ComponentTypeKey | ComponentType;
export interface MessageEditOptions { export interface MessageEditOptions {
attachments?: MessageAttachment[]; attachments?: MessageAttachment[];
content?: string | null; content?: string | null;
@@ -4861,10 +4823,6 @@ export type MessageTarget =
| Message | Message
| MessageManager; | MessageManager;
export type MessageTypeKey = keyof typeof MessageType;
export type GuildMFALevelKey = keyof typeof GuildMFALevel;
export interface MultipleShardRespawnOptions { export interface MultipleShardRespawnOptions {
shardDelay?: number; shardDelay?: number;
respawnDelay?: number; respawnDelay?: number;
@@ -4883,13 +4841,11 @@ export interface OverwriteData {
allow?: PermissionResolvable; allow?: PermissionResolvable;
deny?: PermissionResolvable; deny?: PermissionResolvable;
id: GuildMemberResolvable | RoleResolvable; id: GuildMemberResolvable | RoleResolvable;
type?: OverwriteTypeKey; type?: OverwriteType;
} }
export type OverwriteResolvable = PermissionOverwrites | OverwriteData; export type OverwriteResolvable = PermissionOverwrites | OverwriteData;
export type OverwriteTypeKey = keyof typeof OverwriteType;
export type PermissionFlags = Record<PermissionString, bigint>; export type PermissionFlags = Record<PermissionString, bigint>;
export type PermissionOverwriteOptions = Partial<Record<PermissionString, boolean | null>>; export type PermissionOverwriteOptions = Partial<Record<PermissionString, boolean | null>>;
@@ -4963,16 +4919,16 @@ export type PresenceResolvable = Presence | UserResolvable | Snowflake;
export interface PartialChannelData { export interface PartialChannelData {
id?: Snowflake | number; id?: Snowflake | number;
parentId?: Snowflake | number; parentId?: Snowflake | number;
type?: ExcludeEnum< type?: Exclude<
typeof ChannelType, ChannelType,
| 'DM' | ChannelType.DM
| 'GroupDM' | ChannelType.GroupDM
| 'GuildNews' | ChannelType.GuildNews
| 'GuildStore' | ChannelType.GuildStore
| 'GuildNewsThread' | ChannelType.GuildNewsThread
| 'GuildPublicThread' | ChannelType.GuildPublicThread
| 'GuildPrivateThread' | ChannelType.GuildPrivateThread
| 'GuildStageVoice' | ChannelType.GuildStageVoice
>; >;
name: string; name: string;
topic?: string; topic?: string;
@@ -5152,7 +5108,7 @@ export type SystemChannelFlagsResolvable = BitFieldResolvable<SystemChannelFlags
export type SystemMessageType = Exclude< export type SystemMessageType = Exclude<
MessageType, MessageType,
'DEFAULT' | 'REPLY' | 'CHAT_INPUT_COMMAND' | 'CONTEXT_MENU_COMMAND' MessageType.Default | MessageType.Reply | MessageType.ChatInputCommand | MessageType.ContextMenuCommand
>; >;
export type StageChannelResolvable = StageChannel | Snowflake; export type StageChannelResolvable = StageChannel | Snowflake;
@@ -5234,12 +5190,15 @@ export type ThreadAutoArchiveDuration = 60 | 1440 | 4320 | 10080 | 'MAX';
export type ThreadChannelResolvable = ThreadChannel | Snowflake; export type ThreadChannelResolvable = ThreadChannel | Snowflake;
export type ThreadChannelTypeKey = 'GuildNewsThread' | 'GuildPublicThread' | 'GuildPrivateThread'; export type ThreadChannelType =
| ChannelType.GuildNewsThread
| ChannelType.GuildPublicThread
| ChannelType.GuildPrivateThread;
export interface ThreadCreateOptions<AllowedThreadType> extends StartThreadOptions { export interface ThreadCreateOptions<AllowedThreadType> extends StartThreadOptions {
startMessage?: MessageResolvable; startMessage?: MessageResolvable;
type?: AllowedThreadType; type?: AllowedThreadType;
invitable?: AllowedThreadType extends 'GUILD_PRIVATE_THREAD' | ChannelType.GuildPrivateThread ? boolean : never; invitable?: AllowedThreadType extends ChannelType.GuildPrivateThread ? boolean : never;
rateLimitPerUser?: number; rateLimitPerUser?: number;
} }
@@ -5325,8 +5284,6 @@ export interface WebhookMessageOptions extends Omit<MessageOptions, 'reply' | 's
threadId?: Snowflake; threadId?: Snowflake;
} }
export type WebhookTypeKey = keyof typeof WebhookType;
export interface WebSocketOptions { export interface WebSocketOptions {
large_threshold?: number; large_threshold?: number;
compress?: boolean; compress?: boolean;

View File

@@ -11,6 +11,9 @@ import {
APISelectMenuComponent, APISelectMenuComponent,
ApplicationCommandOptionType, ApplicationCommandOptionType,
ComponentType, ComponentType,
ApplicationCommandPermissionType,
ChannelType,
InteractionType,
} from 'discord-api-types/v9'; } from 'discord-api-types/v9';
import { AuditLogEvent } from 'discord-api-types/v9'; import { AuditLogEvent } from 'discord-api-types/v9';
import { import {
@@ -93,6 +96,7 @@ import {
SelectMenuComponent, SelectMenuComponent,
ActionRowComponent, ActionRowComponent,
InteractionResponseFields, InteractionResponseFields,
ThreadChannelType,
} from '.'; } from '.';
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd'; import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
@@ -146,7 +150,7 @@ client.on('ready', async () => {
await globalPermissionsManager?.add({ await globalPermissionsManager?.add({
command: globalCommandId, command: globalCommandId,
guild: testGuildId, 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?.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId });
await globalPermissionsManager?.fetch({ guild: testGuildId }); await globalPermissionsManager?.fetch({ guild: testGuildId });
@@ -162,17 +166,22 @@ client.on('ready', async () => {
await globalPermissionsManager?.set({ await globalPermissionsManager?.set({
command: globalCommandId, command: globalCommandId,
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
await globalPermissionsManager?.set({ await globalPermissionsManager?.set({
guild: testGuildId, 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 // @ts-expect-error
await globalPermissionsManager?.add({ await globalPermissionsManager?.add({
command: globalCommandId, command: globalCommandId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await globalPermissionsManager?.has({ command: globalCommandId, permissionId: testGuildId }); await globalPermissionsManager?.has({ command: globalCommandId, permissionId: testGuildId });
@@ -205,7 +214,7 @@ client.on('ready', async () => {
// @ts-expect-error // @ts-expect-error
await globalPermissionsManager?.add({ await globalPermissionsManager?.add({
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await globalPermissionsManager?.has({ guild: testGuildId, permissionId: testGuildId }); await globalPermissionsManager?.has({ guild: testGuildId, permissionId: testGuildId });
@@ -218,13 +227,13 @@ client.on('ready', async () => {
// @ts-expect-error // @ts-expect-error
await globalPermissionsManager?.set({ await globalPermissionsManager?.set({
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// Permissions from guild manager // Permissions from guild manager
await guildPermissionsManager?.add({ await guildPermissionsManager?.add({
command: globalCommandId, 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?.has({ command: globalCommandId, permissionId: testGuildId });
await guildPermissionsManager?.fetch({}); await guildPermissionsManager?.fetch({});
@@ -234,17 +243,22 @@ client.on('ready', async () => {
await guildPermissionsManager?.remove({ command: globalCommandId, roles: [testGuildId], users: [testUserId] }); await guildPermissionsManager?.remove({ command: globalCommandId, roles: [testGuildId], users: [testUserId] });
await guildPermissionsManager?.set({ await guildPermissionsManager?.set({
command: globalCommandId, command: globalCommandId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
await guildPermissionsManager?.set({ 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({ await guildPermissionsManager?.add({
command: globalCommandId, command: globalCommandId,
// @ts-expect-error // @ts-expect-error
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await guildPermissionsManager?.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId }); await guildPermissionsManager?.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId });
@@ -272,11 +286,18 @@ client.on('ready', async () => {
await guildPermissionsManager?.set({ await guildPermissionsManager?.set({
// @ts-expect-error // @ts-expect-error
guild: testGuildId, 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 // @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 // @ts-expect-error
await guildPermissionsManager?.has({ permissionId: testGuildId }); await guildPermissionsManager?.has({ permissionId: testGuildId });
// @ts-expect-error // @ts-expect-error
@@ -286,17 +307,24 @@ client.on('ready', async () => {
// @ts-expect-error // @ts-expect-error
await guildPermissionsManager?.remove({ roles: [testGuildId], users: [testUserId] }); await guildPermissionsManager?.remove({ roles: [testGuildId], users: [testUserId] });
// @ts-expect-error // @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 // @ts-expect-error
await guildPermissionsManager?.set({ await guildPermissionsManager?.set({
command: globalCommandId, 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 // Permissions from cached global ApplicationCommand
await globalCommand?.permissions.add({ await globalCommand?.permissions.add({
guild: testGuildId, 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.has({ guild: testGuildId, permissionId: testGuildId });
await globalCommand?.permissions.fetch({ guild: 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.remove({ guild: testGuildId, roles: [testGuildId], users: [testUserId] });
await globalCommand?.permissions.set({ await globalCommand?.permissions.set({
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
await globalCommand?.permissions.add({ await globalCommand?.permissions.add({
// @ts-expect-error // @ts-expect-error
command: globalCommandId, command: globalCommandId,
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await globalCommand?.permissions.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId }); await globalCommand?.permissions.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId });
@@ -333,11 +361,13 @@ client.on('ready', async () => {
// @ts-expect-error // @ts-expect-error
command: globalCommandId, command: globalCommandId,
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @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 // @ts-expect-error
await globalCommand?.permissions.has({ permissionId: testGuildId }); await globalCommand?.permissions.has({ permissionId: testGuildId });
// @ts-expect-error // @ts-expect-error
@@ -349,21 +379,27 @@ client.on('ready', async () => {
// @ts-expect-error // @ts-expect-error
await globalCommand?.permissions.remove({ roles: [testGuildId], users: [testUserId] }); await globalCommand?.permissions.remove({ roles: [testGuildId], users: [testUserId] });
// @ts-expect-error // @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 // 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.has({ permissionId: testGuildId });
await guildCommandFromGlobal?.permissions.fetch({}); await guildCommandFromGlobal?.permissions.fetch({});
await guildCommandFromGlobal?.permissions.remove({ roles: [testGuildId] }); await guildCommandFromGlobal?.permissions.remove({ roles: [testGuildId] });
await guildCommandFromGlobal?.permissions.remove({ users: [testUserId] }); await guildCommandFromGlobal?.permissions.remove({ users: [testUserId] });
await guildCommandFromGlobal?.permissions.remove({ roles: [testGuildId], 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({ await guildCommandFromGlobal?.permissions.add({
// @ts-expect-error // @ts-expect-error
command: globalCommandId, command: globalCommandId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await guildCommandFromGlobal?.permissions.has({ command: guildCommandId, permissionId: testGuildId }); await guildCommandFromGlobal?.permissions.has({ command: guildCommandId, permissionId: testGuildId });
@@ -380,13 +416,13 @@ client.on('ready', async () => {
await guildCommandFromGlobal?.permissions.set({ await guildCommandFromGlobal?.permissions.set({
// @ts-expect-error // @ts-expect-error
command: guildCommandId, command: guildCommandId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
await guildCommandFromGlobal?.permissions.add({ await guildCommandFromGlobal?.permissions.add({
// @ts-expect-error // @ts-expect-error
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await guildCommandFromGlobal?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); await guildCommandFromGlobal?.permissions.has({ guild: testGuildId, permissionId: testGuildId });
@@ -399,21 +435,25 @@ client.on('ready', async () => {
await guildCommandFromGlobal?.permissions.set({ await guildCommandFromGlobal?.permissions.set({
// @ts-expect-error // @ts-expect-error
guild: testGuildId, 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.has({ permissionId: testGuildId });
await guildCommandFromGuild?.permissions.fetch({}); await guildCommandFromGuild?.permissions.fetch({});
await guildCommandFromGuild?.permissions.remove({ roles: [testGuildId] }); await guildCommandFromGuild?.permissions.remove({ roles: [testGuildId] });
await guildCommandFromGuild?.permissions.remove({ users: [testUserId] }); await guildCommandFromGuild?.permissions.remove({ users: [testUserId] });
await guildCommandFromGuild?.permissions.remove({ roles: [testGuildId], 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({ await guildCommandFromGuild?.permissions.add({
// @ts-expect-error // @ts-expect-error
command: globalCommandId, command: globalCommandId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await guildCommandFromGuild?.permissions.has({ command: guildCommandId, permissionId: testGuildId }); await guildCommandFromGuild?.permissions.has({ command: guildCommandId, permissionId: testGuildId });
@@ -430,13 +470,13 @@ client.on('ready', async () => {
await guildCommandFromGuild?.permissions.set({ await guildCommandFromGuild?.permissions.set({
// @ts-expect-error // @ts-expect-error
command: guildCommandId, command: guildCommandId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
await guildCommandFromGuild?.permissions.add({ await guildCommandFromGuild?.permissions.add({
// @ts-expect-error // @ts-expect-error
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
// @ts-expect-error // @ts-expect-error
await guildCommandFromGuild?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); await guildCommandFromGuild?.permissions.has({ guild: testGuildId, permissionId: testGuildId });
@@ -449,7 +489,7 @@ client.on('ready', async () => {
await guildCommandFromGuild?.permissions.set({ await guildCommandFromGuild?.permissions.set({
// @ts-expect-error // @ts-expect-error
guild: testGuildId, guild: testGuildId,
permissions: [{ type: 'Role', id: testGuildId, permission: true }], permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }],
}); });
client.application?.commands.permissions.set({ client.application?.commands.permissions.set({
@@ -528,11 +568,11 @@ client.on('messageCreate', async message => {
if (message.inGuild()) { if (message.inGuild()) {
expectAssignable<Message<true>>(message); expectAssignable<Message<true>>(message);
const component = await message.awaitMessageComponent({ componentType: 'Button' }); const component = await message.awaitMessageComponent({ componentType: ComponentType.Button });
expectType<ButtonInteraction<'cached'>>(component); expectType<ButtonInteraction<'cached'>>(component);
expectType<Message<true>>(await component.reply({ fetchReply: true })); expectType<Message<true>>(await component.reply({ fetchReply: true }));
const buttonCollector = message.createMessageComponentCollector({ componentType: 'Button' }); const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
expectType<InteractionCollector<ButtonInteraction<'cached'>>>(buttonCollector); expectType<InteractionCollector<ButtonInteraction<'cached'>>>(buttonCollector);
expectAssignable<(test: ButtonInteraction<'cached'>) => boolean | Promise<boolean>>(buttonCollector.filter); expectAssignable<(test: ButtonInteraction<'cached'>) => boolean | Promise<boolean>>(buttonCollector.filter);
expectType<GuildTextBasedChannel>(message.channel); expectType<GuildTextBasedChannel>(message.channel);
@@ -551,15 +591,19 @@ client.on('messageCreate', async message => {
// Check collector creations. // Check collector creations.
// Verify that buttons interactions are inferred. // Verify that buttons interactions are inferred.
const buttonCollector = message.createMessageComponentCollector({ componentType: 'Button' }); const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
expectAssignable<Promise<ButtonInteraction>>(message.awaitMessageComponent({ componentType: 'Button' })); expectAssignable<Promise<ButtonInteraction>>(message.awaitMessageComponent({ componentType: ComponentType.Button }));
expectAssignable<Promise<ButtonInteraction>>(channel.awaitMessageComponent({ componentType: 'Button' })); expectAssignable<Promise<ButtonInteraction>>(channel.awaitMessageComponent({ componentType: ComponentType.Button }));
expectAssignable<InteractionCollector<ButtonInteraction>>(buttonCollector); expectAssignable<InteractionCollector<ButtonInteraction>>(buttonCollector);
// Verify that select menus interaction are inferred. // Verify that select menus interaction are inferred.
const selectMenuCollector = message.createMessageComponentCollector({ componentType: 'SelectMenu' }); const selectMenuCollector = message.createMessageComponentCollector({ componentType: ComponentType.SelectMenu });
expectAssignable<Promise<SelectMenuInteraction>>(message.awaitMessageComponent({ componentType: 'SelectMenu' })); expectAssignable<Promise<SelectMenuInteraction>>(
expectAssignable<Promise<SelectMenuInteraction>>(channel.awaitMessageComponent({ componentType: 'SelectMenu' })); message.awaitMessageComponent({ componentType: ComponentType.SelectMenu }),
);
expectAssignable<Promise<SelectMenuInteraction>>(
channel.awaitMessageComponent({ componentType: ComponentType.SelectMenu }),
);
expectAssignable<InteractionCollector<SelectMenuInteraction>>(selectMenuCollector); expectAssignable<InteractionCollector<SelectMenuInteraction>>(selectMenuCollector);
// Verify that message component interactions are default collected types. // Verify that message component interactions are default collected types.
@@ -575,9 +619,10 @@ client.on('messageCreate', async message => {
expectType<InteractionCollector<MessageComponentInteraction>>(semiDefaultCollectorChannel); expectType<InteractionCollector<MessageComponentInteraction>>(semiDefaultCollectorChannel);
// Verify that interaction collector options can't be used. // Verify that interaction collector options can't be used.
message.createMessageComponentCollector({
// @ts-expect-error // @ts-expect-error
const interactionOptions = message.createMessageComponentCollector({ interactionType: 'APPLICATION_COMMAND' }); interactionType: InteractionType.ApplicationCommand,
});
// Make sure filter parameters are properly inferred. // Make sure filter parameters are properly inferred.
message.createMessageComponentCollector({ message.createMessageComponentCollector({
@@ -588,7 +633,7 @@ client.on('messageCreate', async message => {
}); });
message.createMessageComponentCollector({ message.createMessageComponentCollector({
componentType: 'Button', componentType: ComponentType.Button,
filter: i => { filter: i => {
expectType<ButtonInteraction>(i); expectType<ButtonInteraction>(i);
return true; return true;
@@ -596,7 +641,7 @@ client.on('messageCreate', async message => {
}); });
message.createMessageComponentCollector({ message.createMessageComponentCollector({
componentType: 'SelectMenu', componentType: ComponentType.SelectMenu,
filter: i => { filter: i => {
expectType<SelectMenuInteraction>(i); expectType<SelectMenuInteraction>(i);
return true; return true;
@@ -611,7 +656,7 @@ client.on('messageCreate', async message => {
}); });
message.awaitMessageComponent({ message.awaitMessageComponent({
componentType: 'Button', componentType: ComponentType.Button,
filter: i => { filter: i => {
expectType<ButtonInteraction>(i); expectType<ButtonInteraction>(i);
return true; return true;
@@ -619,7 +664,7 @@ client.on('messageCreate', async message => {
}); });
message.awaitMessageComponent({ message.awaitMessageComponent({
componentType: 'SelectMenu', componentType: ComponentType.SelectMenu,
filter: i => { filter: i => {
expectType<SelectMenuInteraction>(i); expectType<SelectMenuInteraction>(i);
return true; return true;
@@ -647,7 +692,7 @@ client.on('messageCreate', async message => {
}); });
channel.awaitMessageComponent({ channel.awaitMessageComponent({
componentType: 'Button', componentType: ComponentType.Button,
filter: i => { filter: i => {
expectType<ButtonInteraction<'cached'>>(i); expectType<ButtonInteraction<'cached'>>(i);
return true; return true;
@@ -655,7 +700,7 @@ client.on('messageCreate', async message => {
}); });
channel.awaitMessageComponent({ channel.awaitMessageComponent({
componentType: 'SelectMenu', componentType: ComponentType.SelectMenu,
filter: i => { filter: i => {
expectType<SelectMenuInteraction<'cached'>>(i); expectType<SelectMenuInteraction<'cached'>>(i);
return true; return true;
@@ -774,8 +819,8 @@ expectType<Message | null>(newsChannel.lastMessage);
expectType<Message | null>(textChannel.lastMessage); expectType<Message | null>(textChannel.lastMessage);
expectDeprecated(storeChannel.clone()); expectDeprecated(storeChannel.clone());
expectDeprecated(categoryChannel.createChannel('Store', { type: 'GuildStore' })); expectDeprecated(categoryChannel.createChannel('Store', { type: ChannelType.GuildStore }));
expectDeprecated(guild.channels.create('Store', { type: 'GuildStore' })); expectDeprecated(guild.channels.create('Store', { type: ChannelType.GuildStore }));
notPropertyOf(user, 'lastMessage'); notPropertyOf(user, 'lastMessage');
notPropertyOf(user, 'lastMessageId'); notPropertyOf(user, 'lastMessageId');
@@ -857,11 +902,11 @@ expectType<Promise<ApplicationCommand>>(guildApplicationCommandManager.fetch('0'
declare const categoryChannel: CategoryChannel; declare const categoryChannel: CategoryChannel;
{ {
expectType<Promise<VoiceChannel>>(categoryChannel.createChannel('name', { type: 'GuildVoice' })); expectType<Promise<VoiceChannel>>(categoryChannel.createChannel('name', { type: ChannelType.GuildVoice }));
expectType<Promise<TextChannel>>(categoryChannel.createChannel('name', { type: 'GuildText' })); expectType<Promise<TextChannel>>(categoryChannel.createChannel('name', { type: ChannelType.GuildText }));
expectType<Promise<NewsChannel>>(categoryChannel.createChannel('name', { type: 'GuildNews' })); expectType<Promise<NewsChannel>>(categoryChannel.createChannel('name', { type: ChannelType.GuildNews }));
expectDeprecated(categoryChannel.createChannel('name', { type: 'GuildStore' })); expectDeprecated(categoryChannel.createChannel('name', { type: ChannelType.GuildStore }));
expectType<Promise<StageChannel>>(categoryChannel.createChannel('name', { type: 'GuildStageVoice' })); expectType<Promise<StageChannel>>(categoryChannel.createChannel('name', { type: ChannelType.GuildStageVoice }));
expectType<Promise<TextChannel>>(categoryChannel.createChannel('name', {})); expectType<Promise<TextChannel>>(categoryChannel.createChannel('name', {}));
expectType<Promise<TextChannel>>(categoryChannel.createChannel('name')); expectType<Promise<TextChannel>>(categoryChannel.createChannel('name'));
} }
@@ -870,12 +915,12 @@ declare const guildChannelManager: GuildChannelManager;
{ {
type AnyChannel = TextChannel | VoiceChannel | CategoryChannel | NewsChannel | StoreChannel | StageChannel; type AnyChannel = TextChannel | VoiceChannel | CategoryChannel | NewsChannel | StoreChannel | StageChannel;
expectType<Promise<VoiceChannel>>(guildChannelManager.create('name', { type: 'GuildVoice' })); expectType<Promise<VoiceChannel>>(guildChannelManager.create('name', { type: ChannelType.GuildVoice }));
expectType<Promise<CategoryChannel>>(guildChannelManager.create('name', { type: 'GuildCategory' })); expectType<Promise<CategoryChannel>>(guildChannelManager.create('name', { type: ChannelType.GuildCategory }));
expectType<Promise<TextChannel>>(guildChannelManager.create('name', { type: 'GuildText' })); expectType<Promise<TextChannel>>(guildChannelManager.create('name', { type: ChannelType.GuildText }));
expectType<Promise<NewsChannel>>(guildChannelManager.create('name', { type: 'GuildNews' })); expectType<Promise<NewsChannel>>(guildChannelManager.create('name', { type: ChannelType.GuildNews }));
expectType<Promise<StoreChannel>>(guildChannelManager.create('name', { type: 'GuildStore' })); expectType<Promise<StoreChannel>>(guildChannelManager.create('name', { type: ChannelType.GuildStore }));
expectType<Promise<StageChannel>>(guildChannelManager.create('name', { type: 'GuildStageVoice' })); expectType<Promise<StageChannel>>(guildChannelManager.create('name', { type: ChannelType.GuildStageVoice }));
expectType<Promise<Collection<Snowflake, AnyChannel>>>(guildChannelManager.fetch()); expectType<Promise<Collection<Snowflake, AnyChannel>>>(guildChannelManager.fetch());
expectType<Promise<Collection<Snowflake, AnyChannel>>>(guildChannelManager.fetch(undefined, {})); expectType<Promise<Collection<Snowflake, AnyChannel>>>(guildChannelManager.fetch(undefined, {}));
@@ -1079,7 +1124,7 @@ client.on('interactionCreate', async interaction => {
expectType<APIRole>(interaction.options.getRole('test', true)); expectType<APIRole>(interaction.options.getRole('test', true));
} else if (interaction.inCachedGuild()) { } else if (interaction.inCachedGuild()) {
const msg = await interaction.reply({ fetchReply: true }); const msg = await interaction.reply({ fetchReply: true });
const btn = await msg.awaitMessageComponent({ componentType: 'Button' }); const btn = await msg.awaitMessageComponent({ componentType: ComponentType.Button });
expectType<Message<true>>(msg); expectType<Message<true>>(msg);
expectType<ButtonInteraction<'cached'>>(btn); expectType<ButtonInteraction<'cached'>>(btn);
@@ -1263,9 +1308,7 @@ declare const NonThreadGuildBasedChannel: NonThreadGuildBasedChannel;
declare const GuildTextBasedChannel: GuildTextBasedChannel; declare const GuildTextBasedChannel: GuildTextBasedChannel;
expectType<DMChannel | PartialDMChannel | NewsChannel | TextChannel | ThreadChannel>(TextBasedChannel); expectType<DMChannel | PartialDMChannel | NewsChannel | TextChannel | ThreadChannel>(TextBasedChannel);
expectType<'DM' | 'GuildNews' | 'GuildText' | 'GuildPublicThread' | 'GuildPrivateThread' | 'GuildNewsThread'>( expectType<ChannelType.GuildText | ChannelType.DM | ChannelType.GuildNews | ThreadChannelType>(TextBasedChannelTypes);
TextBasedChannelTypes,
);
expectType<StageChannel | VoiceChannel>(VoiceBasedChannel); expectType<StageChannel | VoiceChannel>(VoiceBasedChannel);
expectType<CategoryChannel | NewsChannel | StageChannel | StoreChannel | TextChannel | ThreadChannel | VoiceChannel>( expectType<CategoryChannel | NewsChannel | StageChannel | StoreChannel | TextChannel | ThreadChannel | VoiceChannel>(
GuildBasedChannel, GuildBasedChannel,