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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,15 +44,16 @@ class GuildScheduledEventManager extends CachedManager {
* @property {string} name The name of the guild scheduled event
* @property {DateResolvable} scheduledStartTime The time to schedule the event at
* @property {DateResolvable} [scheduledEndTime] The time to end the event at
* <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 {GuildScheduledEventEntityType|number} entityType The scheduled entity type of the event
* @property {string} [description] The description of the guild scheduled event
* @property {GuildVoiceChannelResolvable} [channel] The channel of the guild scheduled event
* <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
* 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
*/
@@ -60,7 +61,7 @@ class GuildScheduledEventManager extends CachedManager {
* Options used to set entity metadata of a guild scheduled event.
* @typedef {Object} GuildScheduledEventEntityMetadataOptions
* @property {string} [location] The location of the guild scheduled event
* <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 {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
* 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
*/

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
'use strict';
const { ChannelType } = require('discord-api-types/v9');
const CachedManager = require('./CachedManager');
const { GuildMember } = require('../structures/GuildMember');
const { Message } = require('../structures/Message');
@@ -38,7 +39,7 @@ class UserManager extends CachedManager {
* @private
*/
dmChannel(userId) {
return this.client.channels.cache.find(c => c.type === 'DM' && c.recipient.id === userId) ?? null;
return this.client.channels.cache.find(c => c.type === ChannelType.DM && c.recipient.id === userId) ?? null;
}
/**

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
'use strict';
const { ApplicationCommandOptionType, InteractionResponseType } = require('discord-api-types/v9');
const { InteractionResponseType } = require('discord-api-types/v9');
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
const Interaction = require('./Interaction');
@@ -40,10 +40,7 @@ class AutocompleteInteraction extends Interaction {
* The options passed to the command
* @type {CommandInteractionOptionResolver}
*/
this.options = new CommandInteractionOptionResolver(
this.client,
data.data.options?.map(option => this.transformOption(option, data.data.resolved)) ?? [],
);
this.options = new CommandInteractionOptionResolver(this.client, data.data.options ?? []);
}
/**
@@ -55,25 +52,6 @@ class AutocompleteInteraction extends Interaction {
return this.guild?.commands.cache.get(id) ?? this.client.application.commands.cache.get(id) ?? null;
}
/**
* Transforms an option received from the API.
* @param {APIApplicationCommandOption} option The received option
* @returns {CommandInteractionOption}
* @private
*/
transformOption(option) {
const result = {
name: option.name,
type: ApplicationCommandOptionType[option.type],
};
if ('value' in option) result.value = option.value;
if ('options' in option) result.options = option.options.map(opt => this.transformOption(opt));
if ('focused' in option) result.focused = option.focused;
return result;
}
/**
* Sends results for the autocomplete of this interaction.
* @param {ApplicationCommandOptionChoice[]} options The options for the autocomplete

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
'use strict';
const { ApplicationCommandOptionType } = require('discord-api-types/v9');
const { TypeError } = require('../errors');
/**
@@ -38,12 +39,12 @@ class CommandInteractionOptionResolver {
this._hoistedOptions = options;
// Hoist subcommand group if present
if (this._hoistedOptions[0]?.type === 'SUB_COMMAND_GROUP') {
if (this._hoistedOptions[0]?.type === ApplicationCommandOptionType.SubcommandGroup) {
this._group = this._hoistedOptions[0].name;
this._hoistedOptions = this._hoistedOptions[0].options ?? [];
}
// Hoist subcommand if present
if (this._hoistedOptions[0]?.type === 'SUB_COMMAND') {
if (this._hoistedOptions[0]?.type === ApplicationCommandOptionType.Subcommand) {
this._subcommand = this._hoistedOptions[0].name;
this._hoistedOptions = this._hoistedOptions[0].options ?? [];
}
@@ -133,7 +134,7 @@ class CommandInteractionOptionResolver {
* @returns {?boolean} The value of the option, or null if not set and not required.
*/
getBoolean(name, required = false) {
const option = this._getTypedOption(name, 'BOOLEAN', ['value'], required);
const option = this._getTypedOption(name, ApplicationCommandOptionType.Boolean, ['value'], required);
return option?.value ?? null;
}
@@ -145,7 +146,7 @@ class CommandInteractionOptionResolver {
* The value of the option, or null if not set and not required.
*/
getChannel(name, required = false) {
const option = this._getTypedOption(name, 'CHANNEL', ['channel'], required);
const option = this._getTypedOption(name, ApplicationCommandOptionType.Channel, ['channel'], required);
return option?.channel ?? null;
}
@@ -156,7 +157,7 @@ class CommandInteractionOptionResolver {
* @returns {?string} The value of the option, or null if not set and not required.
*/
getString(name, required = false) {
const option = this._getTypedOption(name, 'STRING', ['value'], required);
const option = this._getTypedOption(name, ApplicationCommandOptionType.String, ['value'], required);
return option?.value ?? null;
}
@@ -167,7 +168,7 @@ class CommandInteractionOptionResolver {
* @returns {?number} The value of the option, or null if not set and not required.
*/
getInteger(name, required = false) {
const option = this._getTypedOption(name, 'INTEGER', ['value'], required);
const option = this._getTypedOption(name, ApplicationCommandOptionType.Integer, ['value'], required);
return option?.value ?? null;
}
@@ -178,7 +179,7 @@ class CommandInteractionOptionResolver {
* @returns {?number} The value of the option, or null if not set and not required.
*/
getNumber(name, required = false) {
const option = this._getTypedOption(name, 'NUMBER', ['value'], required);
const option = this._getTypedOption(name, ApplicationCommandOptionType.Number, ['value'], required);
return option?.value ?? null;
}
@@ -189,7 +190,7 @@ class CommandInteractionOptionResolver {
* @returns {?User} The value of the option, or null if not set and not required.
*/
getUser(name, required = false) {
const option = this._getTypedOption(name, 'USER', ['user'], required);
const option = this._getTypedOption(name, ApplicationCommandOptionType.User, ['user'], required);
return option?.user ?? null;
}
@@ -200,7 +201,7 @@ class CommandInteractionOptionResolver {
* The value of the option, or null if the user is not present in the guild or the option is not set.
*/
getMember(name) {
const option = this._getTypedOption(name, 'USER', ['member'], false);
const option = this._getTypedOption(name, ApplicationCommandOptionType.User, ['member'], false);
return option?.member ?? null;
}
@@ -211,7 +212,7 @@ class CommandInteractionOptionResolver {
* @returns {?(Role|APIRole)} The value of the option, or null if not set and not required.
*/
getRole(name, required = false) {
const option = this._getTypedOption(name, 'ROLE', ['role'], required);
const option = this._getTypedOption(name, ApplicationCommandOptionType.Role, ['role'], required);
return option?.role ?? null;
}
@@ -223,7 +224,12 @@ class CommandInteractionOptionResolver {
* The value of the option, or null if not set and not required.
*/
getMentionable(name, required = false) {
const option = this._getTypedOption(name, 'MENTIONABLE', ['user', 'member', 'role'], required);
const option = this._getTypedOption(
name,
ApplicationCommandOptionType.Mentionable,
['user', 'member', 'role'],
required,
);
return option?.member ?? option?.user ?? option?.role ?? null;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -17,7 +17,7 @@ class Interaction extends Base {
* The interaction's type
* @type {InteractionType}
*/
this.type = InteractionType[data.type];
this.type = data.type;
/**
* The interaction's id
@@ -154,7 +154,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isCommand() {
return InteractionType[this.type] === InteractionType.ApplicationCommand;
return this.type === InteractionType.ApplicationCommand;
}
/**
@@ -162,7 +162,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isChatInputCommand() {
return InteractionType[this.type] === InteractionType.ApplicationCommand && typeof this.targetId === 'undefined';
return this.isCommand() && typeof this.targetId === 'undefined';
}
/**
@@ -170,7 +170,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isContextMenuCommand() {
return InteractionType[this.type] === InteractionType.ApplicationCommand && typeof this.targetId !== 'undefined';
return this.isCommand() && typeof this.targetId !== 'undefined';
}
/**
@@ -178,7 +178,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isUserContextMenuCommand() {
return this.isContextMenuCommand() && ApplicationCommandType[this.targetType] === ApplicationCommandType.User;
return this.isContextMenuCommand() && this.targetType === ApplicationCommandType.User;
}
/**
@@ -186,7 +186,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isMessageContextMenuCommand() {
return this.isContextMenuCommand() && ApplicationCommandType[this.targetType] === ApplicationCommandType.Message;
return this.isContextMenuCommand() && this.targetType === ApplicationCommandType.Message;
}
/**
@@ -194,7 +194,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isAutocomplete() {
return InteractionType[this.type] === InteractionType.ApplicationCommandAutocomplete;
return this.type === InteractionType.ApplicationCommandAutocomplete;
}
/**
@@ -202,7 +202,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isMessageComponent() {
return InteractionType[this.type] === InteractionType.MessageComponent;
return this.type === InteractionType.MessageComponent;
}
/**
@@ -210,10 +210,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isButton() {
return (
InteractionType[this.type] === InteractionType.MessageComponent &&
ComponentType[this.componentType] === ComponentType.Button
);
return this.isMessageComponent() && this.componentType === ComponentType.Button;
}
/**
@@ -221,10 +218,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isSelectMenu() {
return (
InteractionType[this.type] === InteractionType.MessageComponent &&
ComponentType[this.componentType] === ComponentType.SelectMenu
);
return this.isMessageComponent() && this.componentType === ComponentType.SelectMenu;
}
/**
@@ -232,7 +226,7 @@ class Interaction extends Base {
* @returns {boolean}
*/
isRepliable() {
return ![InteractionType.Ping, InteractionType.ApplicationCommandAutocomplete].includes(InteractionType[this.type]);
return ![InteractionType.Ping, InteractionType.ApplicationCommandAutocomplete].includes(this.type);
}
}

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
'use strict';
const { ComponentType } = require('discord-api-types/v9');
const Interaction = require('./Interaction');
const InteractionWebhook = require('./InteractionWebhook');
const InteractionResponses = require('./interfaces/InteractionResponses');
@@ -34,9 +33,9 @@ class MessageComponentInteraction extends Interaction {
/**
* The type of component which was interacted with
* @type {string}
* @type {ComponentType}
*/
this.componentType = MessageComponentInteraction.resolveType(data.data.component_type);
this.componentType = data.data.component_type;
/**
* Whether the reply to this interaction has been deferred
@@ -81,16 +80,6 @@ class MessageComponentInteraction extends Interaction {
.find(component => (component.customId ?? component.custom_id) === this.customId);
}
/**
* Resolves the type of a MessageComponent
* @param {MessageComponentTypeResolvable} type The type to resolve
* @returns {ComponentType}
* @private
*/
static resolveType(type) {
return typeof type === 'string' ? type : ComponentType[type];
}
// These are here only for documentation purposes - they are implemented by InteractionResponses
/* eslint-disable no-empty-function */
deferReply() {}

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
'use strict';
const { ActivityType } = require('discord-api-types/v9');
const Base = require('./Base');
const { Emoji } = require('./Emoji');
const ActivityFlags = require('../util/ActivityFlags');
@@ -168,7 +167,7 @@ class Activity {
* The activity status's type
* @type {ActivityType}
*/
this.type = typeof data.type === 'number' ? ActivityType[data.type] : data.type;
this.type = data.type;
/**
* If the activity is being streamed, a link to the stream

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
'use strict';
const process = require('node:process');
const { ChannelType, MessageType, StickerFormatType } = require('discord-api-types/v9');
const Package = (exports.Package = require('../../package.json'));
const { Error, RangeError, TypeError } = require('../errors');
@@ -83,7 +84,8 @@ exports.Endpoints = {
DiscoverySplash: (guildId, hash, options) =>
makeImageUrl(`${root}/discovery-splashes/${guildId}`, { hash, ...options }),
TeamIcon: (teamId, hash, options) => makeImageUrl(`${root}/team-icons/${teamId}`, { hash, ...options }),
Sticker: (stickerId, format) => `${root}/stickers/${stickerId}.${format === 'LOTTIE' ? 'json' : 'png'}`,
Sticker: (stickerId, format) =>
`${root}/stickers/${stickerId}.${format === StickerFormatType.Lottie ? 'json' : 'png'}`,
RoleIcon: (roleId, hash, options) => makeImageUrl(`${root}/role-icons/${roleId}`, { hash, ...options }),
};
},
@@ -384,61 +386,6 @@ exports.InviteScopes = [
*/
exports.IntegrationExpireBehaviors = createEnum(['REMOVE_ROLE', 'KICK']);
/**
* The type of a message, e.g. `DEFAULT`. Here are the available types:
* * DEFAULT
* * RECIPIENT_ADD
* * RECIPIENT_REMOVE
* * CALL
* * CHANNEL_NAME_CHANGE
* * CHANNEL_ICON_CHANGE
* * CHANNEL_PINNED_MESSAGE
* * GUILD_MEMBER_JOIN
* * USER_PREMIUM_GUILD_SUBSCRIPTION
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3
* * CHANNEL_FOLLOW_ADD
* * GUILD_DISCOVERY_DISQUALIFIED
* * GUILD_DISCOVERY_REQUALIFIED
* * GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING
* * GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING
* * THREAD_CREATED
* * REPLY
* * CHAT_INPUT_COMMAND
* * THREAD_STARTER_MESSAGE
* * GUILD_INVITE_REMINDER
* * CONTEXT_MENU_COMMAND
* @typedef {string} MessageType
* @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-types}
*/
exports.MessageTypes = [
'DEFAULT',
'RECIPIENT_ADD',
'RECIPIENT_REMOVE',
'CALL',
'CHANNEL_NAME_CHANGE',
'CHANNEL_ICON_CHANGE',
'CHANNEL_PINNED_MESSAGE',
'GUILD_MEMBER_JOIN',
'USER_PREMIUM_GUILD_SUBSCRIPTION',
'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1',
'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2',
'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3',
'CHANNEL_FOLLOW_ADD',
null,
'GUILD_DISCOVERY_DISQUALIFIED',
'GUILD_DISCOVERY_REQUALIFIED',
'GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING',
'GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING',
'THREAD_CREATED',
'REPLY',
'CHAT_INPUT_COMMAND',
'THREAD_STARTER_MESSAGE',
'GUILD_INVITE_REMINDER',
'CONTEXT_MENU_COMMAND',
];
/**
* The name of an item to be swept in Sweepers
* * `applicationCommands` - both global and guild commands
@@ -475,16 +422,19 @@ exports.SweeperKeys = [
];
/**
* The types of messages that are `System`. The available types are `MessageTypes` excluding:
* * DEFAULT
* * REPLY
* * CHAT_INPUT_COMMAND
* * CONTEXT_MENU_COMMAND
* @typedef {string} SystemMessageType
* The types of messages that are not `System`. The available types are:
* * `MessageType.Default`
* * `MessageType.Reply`
* * `MessageType.ChatInputCommand`
* * `MessageType.ContextMenuCommand`
* @typedef {MessageType[]} NonSystemMessageTypes
*/
exports.SystemMessageTypes = exports.MessageTypes.filter(
type => type && !['DEFAULT', 'REPLY', 'CHAT_INPUT_COMMAND', 'CONTEXT_MENU_COMMAND'].includes(type),
);
exports.NonSystemMessageTypes = [
MessageType.Default,
MessageType.Reply,
MessageType.ChatInputCommand,
MessageType.ContextMenuCommand,
];
/**
* The channels that are text-based.
@@ -497,39 +447,43 @@ exports.SystemMessageTypes = exports.MessageTypes.filter(
/**
* The types of channels that are text-based. The available types are:
* * DM
* * GUILD_TEXT
* * GUILD_NEWS
* * GUILD_NEWS_THREAD
* * GUILD_PUBLIC_THREAD
* * GUILD_PRIVATE_THREAD
* @typedef {string} TextBasedChannelTypes
* * `ChannelType.DM`
* * `ChannelType.GuildText`
* * `ChannelType.GuildNews`
* * `ChannelType.GuildNewsThread`
* * `ChannelType.GuildPublicThread`
* * `ChannelType.GuildPrivateThread`
* @typedef {ChannelType} TextBasedChannelTypes
*/
exports.TextBasedChannelTypes = [
'DM',
'GUILD_TEXT',
'GUILD_NEWS',
'GUILD_NEWS_THREAD',
'GUILD_PUBLIC_THREAD',
'GUILD_PRIVATE_THREAD',
ChannelType.DM,
ChannelType.GuildText,
ChannelType.GuildNews,
ChannelType.GuildNewsThread,
ChannelType.GuildPublicThread,
ChannelType.GuildPrivateThread,
];
/**
* The types of channels that are threads. The available types are:
* * GUILD_NEWS_THREAD
* * GUILD_PUBLIC_THREAD
* * GUILD_PRIVATE_THREAD
* @typedef {string} ThreadChannelTypes
* * `ChannelType.GuildNewsThread`
* * `ChannelType.GuildPublicThread`
* * `ChannelType.GuildPrivateThread`
* @typedef {ChannelType[]} ThreadChannelTypes
*/
exports.ThreadChannelTypes = ['GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD'];
exports.ThreadChannelTypes = [
ChannelType.GuildNewsThread,
ChannelType.GuildPublicThread,
ChannelType.GuildPrivateThread,
];
/**
* The types of channels that are voice-based. The available types are:
* * GUILD_VOICE
* * GUILD_STAGE_VOICE
* @typedef {string} VoiceBasedChannelTypes
* * `ChannelType.GuildVoice`
* * `ChannelType.GuildStageVoice`
* @typedef {ChannelType[]} VoiceBasedChannelTypes
*/
exports.VoiceBasedChannelTypes = ['GUILD_VOICE', 'GUILD_STAGE_VOICE'];
exports.VoiceBasedChannelTypes = [ChannelType.GuildVoice, ChannelType.GuildStageVoice];
exports.Colors = {
DEFAULT: 0x000000,

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

View File

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

View File

@@ -6,6 +6,7 @@ const request = require('superagent');
const ytdl = require('ytdl-core');
const { token, song } = require('./auth.js');
const { Client, Intents } = require('../src');
const { ChannelType } = require('discord-api-types/v9');
console.time('magic');
@@ -57,7 +58,7 @@ client.on('messageCreate', message => {
if (true) {
if (message.content === 'makechann') {
if (message.channel.guild) {
message.channel.guild.channels.create('hi', { type: 'GUILD_TEXT' }).then(console.log);
message.channel.guild.channels.create('hi', { type: ChannelType.GuildText }).then(console.log);
}
}

View File

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

View File

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