refactor: Use Base prefix for channel and interaction base classes (#8099)

This commit is contained in:
Suneet Tipirneni
2022-06-24 04:42:50 -04:00
committed by GitHub
parent 65dc8d677e
commit e24970e3c3
25 changed files with 128 additions and 112 deletions

View File

@@ -118,7 +118,7 @@ class Client extends BaseClient {
this.guilds = new GuildManager(this);
/**
* All of the {@link Channel}s that the client is currently handling, mapped by their ids -
* All of the {@link BaseChannel}s that the client is currently handling, mapped by their ids -
* as long as sharding isn't being used, this will be *every* channel in *every* guild the bot
* is a member of. Note that DM channels will not be initially cached, and thus not be present
* in the Manager without their explicit fetching or use.

View File

@@ -76,7 +76,7 @@ class InteractionCreateAction extends Action {
/**
* Emitted when an interaction is created.
* @event Client#interactionCreate
* @param {Interaction} interaction The interaction which was created
* @param {BaseInteraction} interaction The interaction which was created
*/
client.emit(Events.InteractionCreate, interaction);
}

View File

@@ -94,7 +94,7 @@ exports.ButtonBuilder = require('./structures/ButtonBuilder');
exports.ButtonComponent = require('./structures/ButtonComponent');
exports.ButtonInteraction = require('./structures/ButtonInteraction');
exports.CategoryChannel = require('./structures/CategoryChannel');
exports.Channel = require('./structures/Channel').Channel;
exports.BaseChannel = require('./structures/BaseChannel').BaseChannel;
exports.ChatInputCommandInteraction = require('./structures/ChatInputCommandInteraction');
exports.ClientApplication = require('./structures/ClientApplication');
exports.ClientPresence = require('./structures/ClientPresence');
@@ -121,7 +121,7 @@ exports.GuildScheduledEvent = require('./structures/GuildScheduledEvent').GuildS
exports.GuildTemplate = require('./structures/GuildTemplate');
exports.Integration = require('./structures/Integration');
exports.IntegrationApplication = require('./structures/IntegrationApplication');
exports.Interaction = require('./structures/Interaction');
exports.BaseInteraction = require('./structures/BaseInteraction');
exports.InteractionCollector = require('./structures/InteractionCollector');
exports.InteractionResponse = require('./structures/InteractionResponse');
exports.InteractionWebhook = require('./structures/InteractionWebhook');

View File

@@ -3,7 +3,7 @@
const process = require('node:process');
const { Routes } = require('discord-api-types/v10');
const CachedManager = require('./CachedManager');
const { Channel } = require('../structures/Channel');
const { BaseChannel } = require('../structures/BaseChannel');
const { createChannel } = require('../util/Channels');
const { ThreadChannelTypes } = require('../util/Constants');
const Events = require('../util/Events');
@@ -16,7 +16,7 @@ let cacheWarningEmitted = false;
*/
class ChannelManager extends CachedManager {
constructor(client, iterable) {
super(client, Channel, iterable);
super(client, BaseChannel, iterable);
const defaultCaching =
this._cache.constructor.name === 'Collection' ||
this._cache.maxSize === undefined ||
@@ -32,7 +32,7 @@ class ChannelManager extends CachedManager {
/**
* The cache of Channels
* @type {Collection<Snowflake, Channel>}
* @type {Collection<Snowflake, BaseChannel>}
* @name ChannelManager#cache
*/
@@ -75,7 +75,7 @@ class ChannelManager extends CachedManager {
* Data that can be resolved to give a Channel object. This can be:
* * A Channel object
* * A Snowflake
* @typedef {Channel|Snowflake} ChannelResolvable
* @typedef {BaseChannel|Snowflake} ChannelResolvable
*/
/**
@@ -84,7 +84,7 @@ class ChannelManager extends CachedManager {
* @memberof ChannelManager
* @instance
* @param {ChannelResolvable} channel The channel resolvable to resolve
* @returns {?Channel}
* @returns {?BaseChannel}
*/
/**
@@ -107,7 +107,7 @@ class ChannelManager extends CachedManager {
* Obtains a channel from Discord, or the channel cache if it's already available.
* @param {Snowflake} id The channel's id
* @param {FetchChannelOptions} [options] Additional options for this fetch
* @returns {Promise<?Channel>}
* @returns {Promise<?BaseChannel>}
* @example
* // Fetch a channel by its id
* client.channels.fetch('222109930545610754')

View File

@@ -1,15 +1,15 @@
'use strict';
const { InteractionResponseType, Routes } = require('discord-api-types/v10');
const BaseInteraction = require('./BaseInteraction');
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
const Interaction = require('./Interaction');
const { ErrorCodes } = require('../errors');
/**
* Represents an autocomplete interaction.
* @extends {Interaction}
* @extends {BaseInteraction}
*/
class AutocompleteInteraction extends Interaction {
class AutocompleteInteraction extends BaseInteraction {
constructor(client, data) {
super(client, data);

View File

@@ -10,7 +10,7 @@ const { ThreadChannelTypes } = require('../util/Constants');
* @extends {Base}
* @abstract
*/
class Channel extends Base {
class BaseChannel extends Base {
constructor(client, data, immediatePatch = true) {
super(client);
@@ -81,7 +81,7 @@ class Channel extends Base {
/**
* Deletes this channel.
* @returns {Promise<Channel>}
* @returns {Promise<BaseChannel>}
* @example
* // Delete the channel
* channel.delete()
@@ -96,7 +96,7 @@ class Channel extends Base {
/**
* Fetches this channel.
* @param {boolean} [force=true] Whether to skip the cache check and request the API
* @returns {Promise<Channel>}
* @returns {Promise<BaseChannel>}
*/
fetch(force = true) {
return this.client.channels.fetch(this.id, { force });
@@ -139,7 +139,7 @@ class Channel extends Base {
}
}
exports.Channel = Channel;
exports.BaseChannel = BaseChannel;
/**
* @external APIChannel

View File

@@ -8,8 +8,9 @@ const PermissionsBitField = require('../util/PermissionsBitField');
/**
* Represents an interaction.
* @extends {Base}
* @abstract
*/
class Interaction extends Base {
class BaseInteraction extends Base {
constructor(client, data) {
super(client);
@@ -28,7 +29,7 @@ class Interaction extends Base {
/**
* The interaction's token
* @type {string}
* @name Interaction#token
* @name BaseInteraction#token
* @readonly
*/
Object.defineProperty(this, 'token', { value: data.token });
@@ -246,4 +247,4 @@ class Interaction extends Base {
}
}
module.exports = Interaction;
module.exports = BaseInteraction;

View File

@@ -2,17 +2,17 @@
const { Collection } = require('@discordjs/collection');
const Attachment = require('./Attachment');
const Interaction = require('./Interaction');
const BaseInteraction = require('./BaseInteraction');
const InteractionWebhook = require('./InteractionWebhook');
const InteractionResponses = require('./interfaces/InteractionResponses');
/**
* Represents a command interaction.
* @extends {Interaction}
* @extends {BaseInteraction}
* @implements {InteractionResponses}
* @abstract
*/
class CommandInteraction extends Interaction {
class CommandInteraction extends BaseInteraction {
constructor(client, data) {
super(client, data);
@@ -86,7 +86,7 @@ class CommandInteraction extends Interaction {
* @property {Collection<Snowflake, User>} [users] The resolved users
* @property {Collection<Snowflake, GuildMember|APIGuildMember>} [members] The resolved guild members
* @property {Collection<Snowflake, Role|APIRole>} [roles] The resolved roles
* @property {Collection<Snowflake, Channel|APIChannel>} [channels] The resolved channels
* @property {Collection<Snowflake, BaseChannel|APIChannel>} [channels] The resolved channels
* @property {Collection<Snowflake, Message|APIMessage>} [messages] The resolved messages
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
*/

View File

@@ -2,17 +2,17 @@
const { userMention } = require('@discordjs/builders');
const { ChannelType } = require('discord-api-types/v10');
const { Channel } = require('./Channel');
const { BaseChannel } = require('./BaseChannel');
const TextBasedChannel = require('./interfaces/TextBasedChannel');
const MessageManager = require('../managers/MessageManager');
const Partials = require('../util/Partials');
/**
* Represents a direct message channel between two users.
* @extends {Channel}
* @extends {BaseChannel}
* @implements {TextBasedChannel}
*/
class DMChannel extends Channel {
class DMChannel extends BaseChannel {
constructor(client, data) {
super(client, data);

View File

@@ -1,12 +1,12 @@
'use strict';
const { Channel } = require('./Channel');
const { BaseChannel } = require('./BaseChannel');
/**
* Represents a channel that displays a directory of guilds.
* @extends {Channel}
* @extends {BaseChannel}
*/
class DirectoryChannel extends Channel {
class DirectoryChannel extends BaseChannel {
constructor(guild, data, client) {
super(client, data);

View File

@@ -48,7 +48,7 @@ const Targets = {
* * An application command
* * An object with an id key if target was deleted or fake entity
* * An object where the keys represent either the new value or the old value
* @typedef {?(Object|Guild|Channel|User|Role|Invite|Webhook|GuildEmoji|Message|Integration|StageInstance|Sticker|
* @typedef {?(Object|Guild|BaseChannel|User|Role|Invite|Webhook|GuildEmoji|Message|Integration|StageInstance|Sticker|
* GuildScheduledEvent|ApplicationCommand)} AuditLogEntryTarget
*/

View File

@@ -1,7 +1,7 @@
'use strict';
const { PermissionFlagsBits } = require('discord-api-types/v10');
const { Channel } = require('./Channel');
const { BaseChannel } = require('./BaseChannel');
const { Error, ErrorCodes } = require('../errors');
const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager');
const { VoiceBasedChannelTypes } = require('../util/Constants');
@@ -14,10 +14,10 @@ const PermissionsBitField = require('../util/PermissionsBitField');
* - {@link CategoryChannel}
* - {@link NewsChannel}
* - {@link StageChannel}
* @extends {Channel}
* @extends {BaseChannel}
* @abstract
*/
class GuildChannel extends Channel {
class GuildChannel extends BaseChannel {
constructor(guild, data, client, immediatePatch = true) {
super(guild?.client ?? client, data, false);

View File

@@ -137,7 +137,7 @@ class InteractionCollector extends Collector {
/**
* Handles an incoming interaction for possible collection.
* @param {Interaction} interaction The interaction to possibly collect
* @param {BaseInteraction} interaction The interaction to possibly collect
* @returns {?Snowflake}
* @private
*/
@@ -145,7 +145,7 @@ class InteractionCollector extends Collector {
/**
* Emitted whenever an interaction is collected.
* @event InteractionCollector#collect
* @param {Interaction} interaction The interaction that was collected
* @param {BaseInteraction} interaction The interaction that was collected
*/
if (this.interactionType && interaction.type !== this.interactionType) return null;
if (this.componentType && interaction.componentType !== this.componentType) return null;
@@ -159,14 +159,14 @@ class InteractionCollector extends Collector {
/**
* Handles an interaction for possible disposal.
* @param {Interaction} interaction The interaction that could be disposed of
* @param {BaseInteraction} interaction The interaction that could be disposed of
* @returns {?Snowflake}
*/
dispose(interaction) {
/**
* Emitted whenever an interaction is disposed of.
* @event InteractionCollector#dispose
* @param {Interaction} interaction The interaction that was disposed of
* @param {BaseInteraction} interaction The interaction that was disposed of
*/
if (this.type && interaction.type !== this.type) return null;
if (this.componentType && interaction.componentType !== this.componentType) return null;

View File

@@ -8,14 +8,14 @@ const { ErrorCodes } = require('../errors');
*/
class InteractionResponse {
/**
* @param {Interaction} interaction The interaction associated with this response
* @param {BaseInteraction} interaction The interaction associated with this response
* @param {Snowflake?} id The interaction id associated with the original response
* @private
*/
constructor(interaction, id) {
/**
* The interaction associated with the interaction response
* @type {Interaction}
* @type {BaseInteraction}
*/
this.interaction = interaction;
/**

View File

@@ -169,7 +169,7 @@ class Invite extends Base {
if ('channel' in data) {
/**
* The channel this invite is for
* @type {?Channel}
* @type {?BaseChannel}
*/
this.channel =
this.client.channels._add(data.channel, this.guild, { cache: false }) ??

View File

@@ -1,6 +1,6 @@
'use strict';
const Interaction = require('./Interaction');
const BaseInteraction = require('./BaseInteraction');
const InteractionWebhook = require('./InteractionWebhook');
const InteractionResponses = require('./interfaces/InteractionResponses');
const { lazy } = require('../util/Util');
@@ -9,10 +9,10 @@ const getMessage = lazy(() => require('./Message').Message);
/**
* Represents a message component interaction.
* @extends {Interaction}
* @extends {BaseInteraction}
* @implements {InteractionResponses}
*/
class MessageComponentInteraction extends Interaction {
class MessageComponentInteraction extends BaseInteraction {
constructor(client, data) {
super(client, data);

View File

@@ -115,7 +115,7 @@ class MessageMentions {
/**
* Cached channels for {@link MessageMentions#channels}
* @type {?Collection<Snowflake, Channel>}
* @type {?Collection<Snowflake, BaseChannel>}
* @private
*/
this._channels = null;
@@ -179,7 +179,7 @@ class MessageMentions {
/**
* Any channels that were mentioned
* <info>Order as they appear first in the message content</info>
* @type {Collection<Snowflake, Channel>}
* @type {Collection<Snowflake, BaseChannel>}
* @readonly
*/
get channels() {

View File

@@ -7,7 +7,9 @@ const ActionRowBuilder = require('./ActionRowBuilder');
const { RangeError, ErrorCodes } = require('../errors');
const DataResolver = require('../util/DataResolver');
const MessageFlagsBitField = require('../util/MessageFlagsBitField');
const { basename, cloneObject, verifyString } = require('../util/Util');
const { basename, cloneObject, verifyString, lazy } = require('../util/Util');
const getBaseInteraction = lazy(() => require('./BaseInteraction'));
/**
* Represents a message to be sent to the API.
@@ -86,14 +88,14 @@ class MessagePayload {
}
/**
* Whether or not the target is an {@link Interaction} or an {@link InteractionWebhook}
* Whether or not the target is an {@link BaseInteraction} or an {@link InteractionWebhook}
* @type {boolean}
* @readonly
*/
get isInteraction() {
const Interaction = require('./Interaction');
const BaseInteraction = getBaseInteraction();
const InteractionWebhook = require('./InteractionWebhook');
return this.target instanceof Interaction || this.target instanceof InteractionWebhook;
return this.target instanceof BaseInteraction || this.target instanceof InteractionWebhook;
}
/**
@@ -277,7 +279,7 @@ module.exports = MessagePayload;
/**
* A target for a message.
* @typedef {TextBasedChannels|User|GuildMember|Webhook|WebhookClient|Interaction|InteractionWebhook|
* @typedef {TextBasedChannels|User|GuildMember|Webhook|WebhookClient|BaseInteraction|InteractionWebhook|
* Message|MessageManager} MessageTarget
*/

View File

@@ -1,6 +1,6 @@
'use strict';
const Interaction = require('./Interaction');
const BaseInteraction = require('./BaseInteraction');
const InteractionWebhook = require('./InteractionWebhook');
const ModalSubmitFields = require('./ModalSubmitFields');
const InteractionResponses = require('./interfaces/InteractionResponses');
@@ -25,7 +25,7 @@ const getMessage = lazy(() => require('./Message').Message);
* Represents a modal interaction
* @implements {InteractionResponses}
*/
class ModalSubmitInteraction extends Interaction {
class ModalSubmitInteraction extends BaseInteraction {
constructor(client, data) {
super(client, data);
/**

View File

@@ -1,13 +1,13 @@
'use strict';
const { Channel } = require('./Channel');
const { BaseChannel } = require('./BaseChannel');
const { Error, ErrorCodes } = require('../errors');
/**
* Represents a Partial Group DM Channel on Discord.
* @extends {Channel}
* @extends {BaseChannel}
*/
class PartialGroupDMChannel extends Channel {
class PartialGroupDMChannel extends BaseChannel {
constructor(client, data) {
super(client, data);

View File

@@ -1,7 +1,7 @@
'use strict';
const { ChannelType, PermissionFlagsBits, Routes } = require('discord-api-types/v10');
const { Channel } = require('./Channel');
const { BaseChannel } = require('./BaseChannel');
const TextBasedChannel = require('./interfaces/TextBasedChannel');
const { RangeError, ErrorCodes } = require('../errors');
const MessageManager = require('../managers/MessageManager');
@@ -9,10 +9,10 @@ const ThreadMemberManager = require('../managers/ThreadMemberManager');
/**
* Represents a thread channel on Discord.
* @extends {Channel}
* @extends {BaseChannel}
* @implements {TextBasedChannel}
*/
class ThreadChannel extends Channel {
class ThreadChannel extends BaseChannel {
constructor(guild, data, client, fromInteraction = false) {
super(guild?.client ?? client, data, false);

View File

@@ -20,7 +20,7 @@ const MessagePayload = require('../MessagePayload');
*/
class InteractionResponses {
/**
* Options for deferring the reply to an {@link Interaction}.
* Options for deferring the reply to an {@link BaseInteraction}.
* @typedef {Object} InteractionDeferReplyOptions
* @property {boolean} [ephemeral] Whether the reply should be ephemeral
* @property {boolean} [fetchReply] Whether to fetch the reply
@@ -33,7 +33,7 @@ class InteractionResponses {
*/
/**
* Options for a reply to an {@link Interaction}.
* Options for a reply to an {@link BaseInteraction}.
* @typedef {BaseMessageOptions} InteractionReplyOptions
* @property {boolean} [ephemeral] Whether the reply should be ephemeral
* @property {boolean} [fetchReply] Whether to fetch the reply

View File

@@ -445,14 +445,14 @@ function discordSort(collection) {
/**
* Sets the position of a Channel or Role.
* @param {Channel|Role} item Object to set the position of
* @param {BaseChannel|Role} item Object to set the position of
* @param {number} position New position for the object
* @param {boolean} relative Whether `position` is relative to its current position
* @param {Collection<string, Channel|Role>} sorted A collection of the objects sorted properly
* @param {Collection<string, BaseChannel|Role>} sorted A collection of the objects sorted properly
* @param {Client} client The client to use to patch the data
* @param {string} route Route to call PATCH on
* @param {string} [reason] Reason for the change
* @returns {Promise<Channel[]|Role[]>} Updated item list, with `id` and `position` properties
* @returns {Promise<BaseChannel[]|Role[]>} Updated item list, with `id` and `position` properties
* @private
*/
async function setPosition(item, position, relative, sorted, client, route, reason) {

View File

@@ -416,7 +416,7 @@ export interface InteractionResponseFields<Cached extends CacheType = CacheType>
export type BooleanCache<T extends CacheType> = T extends 'cached' ? true : false;
export abstract class CommandInteraction<Cached extends CacheType = CacheType> extends Interaction<Cached> {
export abstract class CommandInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> {
public type: InteractionType.ApplicationCommand;
public get command(): ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null;
public options: Omit<
@@ -481,10 +481,10 @@ export class InteractionResponse<Cached extends boolean = boolean> {
public interaction: Interaction<WrapBooleanCache<Cached>>;
public client: Client;
public id: Snowflake;
public awaitMessageComponent<T extends MessageComponentType = ComponentType.ActionRow>(
public awaitMessageComponent<T extends MessageComponentType>(
options?: AwaitMessageCollectorOptionsParams<T, Cached>,
): Promise<MappedInteractionTypes<Cached>[T]>;
public createMessageComponentCollector<T extends MessageComponentType = ComponentType.ActionRow>(
public createMessageComponentCollector<T extends MessageComponentType>(
options?: MessageCollectorOptionsParams<T, Cached>,
): InteractionCollector<MappedInteractionTypes<Cached>[T]>;
}
@@ -746,7 +746,7 @@ export class CategoryChannel extends GuildChannel {
export type CategoryChannelResolvable = Snowflake | CategoryChannel;
export abstract class Channel extends Base {
export abstract class BaseChannel extends Base {
public constructor(client: Client, data?: RawChannelData, immediatePatch?: boolean);
public get createdAt(): Date | null;
public get createdTimestamp(): number | null;
@@ -932,7 +932,7 @@ export class ChatInputCommandInteraction<Cached extends CacheType = CacheType> e
public toString(): string;
}
export class AutocompleteInteraction<Cached extends CacheType = CacheType> extends Interaction<Cached> {
export class AutocompleteInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> {
public type: InteractionType.ApplicationCommandAutocomplete;
public get command(): ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null;
public channelId: Snowflake;
@@ -1045,7 +1045,7 @@ export class DataResolver extends null {
public static resolveGuildTemplateCode(data: GuildTemplateResolvable): string;
}
export class DMChannel extends TextBasedChannelMixin(Channel, [
export class DMChannel extends TextBasedChannelMixin(BaseChannel, [
'bulkDelete',
'fetchWebhooks',
'createWebhook',
@@ -1226,7 +1226,7 @@ export class GuildBan extends Base {
public fetch(force?: boolean): Promise<GuildBan>;
}
export abstract class GuildChannel extends Channel {
export abstract class GuildChannel extends BaseChannel {
public constructor(guild: Guild, data?: RawGuildChannelData, client?: Client, immediatePatch?: boolean);
private memberPermissions(member: GuildMember, checkAdmin: boolean): Readonly<PermissionsBitField>;
private rolePermissions(role: Role, checkAdmin: boolean): Readonly<PermissionsBitField>;
@@ -1486,7 +1486,7 @@ export type CacheTypeReducer<
? PresentType
: Fallback;
export type AnyInteraction<Cached extends CacheType = CacheType> =
export type Interaction<Cached extends CacheType = CacheType> =
| ChatInputCommandInteraction<Cached>
| MessageContextMenuCommandInteraction<Cached>
| UserContextMenuCommandInteraction<Cached>
@@ -1495,7 +1495,7 @@ export type AnyInteraction<Cached extends CacheType = CacheType> =
| AutocompleteInteraction<Cached>
| ModalSubmitInteraction<Cached>;
export class Interaction<Cached extends CacheType = CacheType> extends Base {
export class BaseInteraction<Cached extends CacheType = CacheType> extends Base {
// This a technique used to brand different cached types. Or else we'll get `never` errors on typeguard checks.
private readonly _cacheType: Cached;
protected constructor(client: Client, data: RawInteractionData);
@@ -1521,9 +1521,9 @@ export class Interaction<Cached extends CacheType = CacheType> extends Base {
public memberPermissions: CacheTypeReducer<Cached, Readonly<PermissionsBitField>>;
public locale: Locale;
public guildLocale: CacheTypeReducer<Cached, Locale>;
public inGuild(): this is Interaction<'raw' | 'cached'>;
public inCachedGuild(): this is Interaction<'cached'>;
public inRawGuild(): this is Interaction<'raw'>;
public inGuild(): this is BaseInteraction<'raw' | 'cached'>;
public inCachedGuild(): this is BaseInteraction<'cached'>;
public inRawGuild(): this is BaseInteraction<'raw'>;
public isButton(): this is ButtonInteraction<Cached>;
public isChatInputCommand(): this is ChatInputCommandInteraction<Cached>;
public isContextMenuCommand(): this is ContextMenuCommandInteraction<Cached>;
@@ -1533,7 +1533,11 @@ export class Interaction<Cached extends CacheType = CacheType> extends Base {
public isRepliable(): this is this & InteractionResponseFields<Cached>;
}
export class InteractionCollector<T extends Interaction> extends Collector<Snowflake, T, [Collection<Snowflake, T>]> {
export class InteractionCollector<T extends CollectedInteraction> extends Collector<
Snowflake,
T,
[Collection<Snowflake, T>]
> {
public constructor(client: Client, options?: InteractionCollectorOptions<T>);
private _handleMessageDeletion(message: Message): void;
private _handleChannelDeletion(channel: NonThreadGuildBasedChannel): void;
@@ -1628,7 +1632,7 @@ export class LimitedCollection<K, V> extends Collection<K, V> {
public keepOverLimit: ((value: V, key: K, collection: this) => boolean) | null;
}
export type MessageComponentType = Exclude<ComponentType, ComponentType.TextInput>;
export type MessageComponentType = Exclude<ComponentType, ComponentType.TextInput | ComponentType.ActionRow>;
export type MessageCollectorOptionsParams<T extends MessageComponentType, Cached extends boolean = boolean> =
| {
@@ -1657,8 +1661,6 @@ export type WrapBooleanCache<T extends boolean> = If<T, 'cached', CacheType>;
export interface MappedInteractionTypes<Cached extends boolean = boolean> {
[ComponentType.Button]: ButtonInteraction<WrapBooleanCache<Cached>>;
[ComponentType.SelectMenu]: SelectMenuInteraction<WrapBooleanCache<Cached>>;
[ComponentType.ActionRow]: MessageComponentInteraction<WrapBooleanCache<Cached>>;
[ComponentType.TextInput]: never;
}
export class Message<Cached extends boolean = boolean> extends Base {
@@ -1705,12 +1707,12 @@ export class Message<Cached extends boolean = boolean> extends Base {
public webhookId: Snowflake | null;
public flags: Readonly<MessageFlagsBitField>;
public reference: MessageReference | null;
public awaitMessageComponent<T extends MessageComponentType = ComponentType.ActionRow>(
public awaitMessageComponent<T extends MessageComponentType>(
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 MessageComponentType = ComponentType.ActionRow>(
public createMessageComponentCollector<T extends MessageComponentType>(
options?: MessageCollectorOptionsParams<T, Cached>,
): InteractionCollector<MappedInteractionTypes<Cached>[T]>;
public delete(): Promise<Message>;
@@ -1777,7 +1779,7 @@ export class MessageCollector extends Collector<Snowflake, Message, [Collection<
public dispose(message: Message): Snowflake | null;
}
export class MessageComponentInteraction<Cached extends CacheType = CacheType> extends Interaction<Cached> {
export class MessageComponentInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> {
protected constructor(client: Client, data: RawMessageComponentInteractionData);
public type: InteractionType.MessageComponent;
public get component(): CacheTypeReducer<
@@ -1854,11 +1856,11 @@ export class MessageMentions {
everyone: boolean,
repliedUser?: APIUser | User,
);
private _channels: Collection<Snowflake, AnyChannel> | null;
private _channels: Collection<Snowflake, Channel> | null;
private readonly _content: string;
private _members: Collection<Snowflake, GuildMember> | null;
public get channels(): Collection<Snowflake, AnyChannel>;
public get channels(): Collection<Snowflake, Channel>;
public readonly client: Client;
public everyone: boolean;
public readonly guild: Guild;
@@ -1968,7 +1970,7 @@ export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = C
inRawGuild(): this is ModalMessageModalSubmitInteraction<'raw'>;
}
export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extends Interaction<Cached> {
export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> {
private constructor(client: Client, data: APIModalSubmitInteraction);
public type: InteractionType.ModalSubmit;
public readonly customId: string;
@@ -2011,7 +2013,7 @@ export class OAuth2Guild extends BaseGuild {
public permissions: Readonly<PermissionsBitField>;
}
export class PartialGroupDMChannel extends Channel {
export class PartialGroupDMChannel extends BaseChannel {
private constructor(client: Client, data: RawPartialGroupDMChannelData);
public type: ChannelType.GroupDM;
public name: string | null;
@@ -2306,7 +2308,7 @@ export class StageChannel extends BaseGuildVoiceChannel {
public setTopic(topic: string): Promise<StageChannel>;
}
export class DirectoryChannel extends Channel {
export class DirectoryChannel extends BaseChannel {
public guild: InviteGuild;
public guildId: Snowflake;
public name: string;
@@ -2487,7 +2489,7 @@ export interface PrivateThreadChannel extends ThreadChannel {
type: ChannelType.GuildPrivateThread;
}
export class ThreadChannel extends TextBasedChannelMixin(Channel, ['fetchWebhooks', 'createWebhook', 'setNSFW']) {
export class ThreadChannel extends TextBasedChannelMixin(BaseChannel, ['fetchWebhooks', 'createWebhook', 'setNSFW']) {
private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client, fromInteraction?: boolean);
public archived: boolean | null;
public get archivedAt(): Date | null;
@@ -2648,7 +2650,7 @@ export function parseEmoji(text: string): { animated: boolean; name: string; id:
export function resolveColor(color: ColorResolvable): number;
export function resolvePartialEmoji(emoji: EmojiIdentifierResolvable): Partial<APIPartialEmoji> | null;
export function verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string;
export function setPosition<T extends AnyChannel | Role>(
export function setPosition<T extends Channel | Role>(
item: T,
position: number,
relative: boolean,
@@ -2677,7 +2679,7 @@ export interface CreateChannelOptions {
fromInteraction?: boolean;
}
export function createChannel(client: Client, data: APIChannel, options?: CreateChannelOptions): AnyChannel;
export function createChannel(client: Client, data: APIChannel, options?: CreateChannelOptions): Channel;
export function createComponent<T extends keyof MappedComponentTypes>(
data: APIMessageComponent & { type: T },
@@ -3285,9 +3287,9 @@ export class CategoryChannelChildManager extends DataManager<
public create(options: CategoryCreateChannelOptions): Promise<TextChannel>;
}
export class ChannelManager extends CachedManager<Snowflake, AnyChannel, ChannelResolvable> {
export class ChannelManager extends CachedManager<Snowflake, Channel, ChannelResolvable> {
private constructor(client: Client, iterable: Iterable<RawChannelData>);
public fetch(id: Snowflake, options?: FetchChannelOptions): Promise<AnyChannel | null>;
public fetch(id: Snowflake, options?: FetchChannelOptions): Promise<Channel | null>;
}
export type FetchGuildApplicationCommandFetchOptions = Omit<FetchApplicationCommandOptions, 'guildId'>;
@@ -3615,7 +3617,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
lastPinTimestamp: number | null;
get lastPinAt(): Date | null;
messages: MessageManager;
awaitMessageComponent<T extends MessageComponentType = ComponentType.ActionRow>(
awaitMessageComponent<T extends MessageComponentType>(
options?: AwaitMessageCollectorOptionsParams<T, true>,
): Promise<MappedInteractionTypes[T]>;
awaitMessages(options?: AwaitMessagesOptions): Promise<Collection<Snowflake, Message>>;
@@ -3623,7 +3625,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
messages: Collection<Snowflake, Message> | readonly MessageResolvable[] | number,
filterOld?: boolean,
): Promise<Collection<Snowflake, Message>>;
createMessageComponentCollector<T extends MessageComponentType = ComponentType.ActionRow>(
createMessageComponentCollector<T extends MessageComponentType>(
options?: MessageChannelCollectorOptionsParams<T, true>,
): InteractionCollector<MappedInteractionTypes[T]>;
createMessageCollector(options?: MessageCollectorOptions): MessageCollector;
@@ -3896,7 +3898,7 @@ export interface AuditLogChange {
export type Awaitable<T> = T | PromiseLike<T>;
export type AwaitMessageComponentOptions<T extends MessageComponentInteraction> = Omit<
export type AwaitMessageComponentOptions<T extends CollectedMessageInteraction> = Omit<
MessageComponentCollectorOptions<T>,
'max' | 'maxComponents' | 'maxUsers'
>;
@@ -4038,7 +4040,7 @@ export interface ChannelPosition {
}
export type GuildTextChannelResolvable = TextChannel | NewsChannel | Snowflake;
export type ChannelResolvable = AnyChannel | Snowflake;
export type ChannelResolvable = Channel | Snowflake;
export interface ChannelWebhookCreateOptions {
name: string;
@@ -4115,7 +4117,7 @@ export interface ClientEvents {
userUpdate: [oldUser: User | PartialUser, newUser: User];
voiceStateUpdate: [oldState: VoiceState, newState: VoiceState];
webhookUpdate: [channel: TextChannel | NewsChannel | VoiceChannel];
interactionCreate: [interaction: AnyInteraction];
interactionCreate: [interaction: Interaction];
shardDisconnect: [closeEvent: CloseEvent, shardId: number];
shardError: [error: Error, shardId: number];
shardReady: [shardId: number, unavailableGuilds: Set<Snowflake> | undefined];
@@ -4218,7 +4220,7 @@ export interface CommandInteractionResolvedData<Cached extends CacheType = Cache
users?: Collection<Snowflake, User>;
members?: Collection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
roles?: Collection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
channels?: Collection<Snowflake, CacheTypeReducer<Cached, AnyChannel, APIInteractionDataResolvedChannel>>;
channels?: Collection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
messages?: Collection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
attachments?: Collection<Snowflake, Attachment>;
}
@@ -4857,7 +4859,12 @@ export interface IntegrationAccount {
export type IntegrationType = 'twitch' | 'youtube' | 'discord';
export interface InteractionCollectorOptions<T extends Interaction, Cached extends CacheType = CacheType>
export type CollectedInteraction<Cached extends CacheType = CacheType> =
| SelectMenuInteraction<Cached>
| ButtonInteraction<Cached>
| ModalSubmitInteraction<Cached>;
export interface InteractionCollectorOptions<T extends CollectedInteraction, Cached extends CacheType = CacheType>
extends CollectorOptions<[T, Collection<Snowflake, T>]> {
channel?: TextBasedChannelResolvable;
componentType?: ComponentType;
@@ -4962,12 +4969,17 @@ export type MessageComponent =
| ButtonComponent
| SelectMenuComponent;
export type MessageComponentCollectorOptions<T extends MessageComponentInteraction> = Omit<
export type CollectedMessageInteraction<Cached extends CacheType = CacheType> = Exclude<
CollectedInteraction<Cached>,
ModalSubmitInteraction
>;
export type MessageComponentCollectorOptions<T extends CollectedMessageInteraction> = Omit<
InteractionCollectorOptions<T>,
'channel' | 'message' | 'guild' | 'interactionType'
>;
export type MessageChannelComponentCollectorOptions<T extends MessageComponentInteraction> = Omit<
export type MessageChannelComponentCollectorOptions<T extends CollectedMessageInteraction> = Omit<
InteractionCollectorOptions<T>,
'channel' | 'guild' | 'interactionType'
>;
@@ -5367,7 +5379,7 @@ export interface LimitedCollectionOptions<K, V> {
keepOverLimit?: (value: V, key: K, collection: LimitedCollection<K, V>) => boolean;
}
export type AnyChannel =
export type Channel =
| CategoryChannel
| DMChannel
| PartialDMChannel
@@ -5378,13 +5390,13 @@ export type AnyChannel =
| AnyThreadChannel
| VoiceChannel;
export type TextBasedChannel = Extract<AnyChannel, { messages: MessageManager }>;
export type TextBasedChannel = Extract<Channel, { messages: MessageManager }>;
export type TextBasedChannelTypes = TextBasedChannel['type'];
export type VoiceBasedChannel = Extract<AnyChannel, { bitrate: number }>;
export type VoiceBasedChannel = Extract<Channel, { bitrate: number }>;
export type GuildBasedChannel = Extract<AnyChannel, { guild: Guild }>;
export type GuildBasedChannel = Extract<Channel, { guild: Guild }>;
export type NonCategoryGuildBasedChannel = Exclude<GuildBasedChannel, CategoryChannel>;

View File

@@ -127,6 +127,7 @@ import {
UserContextMenuCommandInteraction,
AnyThreadChannel,
ThreadMemberManager,
CollectedMessageInteraction,
} from '.';
import { expectAssignable, expectNotAssignable, expectNotType, expectType } from 'tsd';
import { UnsafeButtonBuilder, UnsafeEmbedBuilder, UnsafeSelectMenuBuilder } from '@discordjs/builders';
@@ -754,13 +755,13 @@ client.on('messageCreate', async message => {
const defaultCollector = message.createMessageComponentCollector();
expectAssignable<Promise<MessageComponentInteraction>>(message.awaitMessageComponent());
expectAssignable<Promise<MessageComponentInteraction>>(channel.awaitMessageComponent());
expectAssignable<InteractionCollector<MessageComponentInteraction>>(defaultCollector);
expectAssignable<InteractionCollector<CollectedMessageInteraction>>(defaultCollector);
// Verify that additional options don't affect default collector types.
const semiDefaultCollector = message.createMessageComponentCollector({ time: 10000 });
expectType<InteractionCollector<MessageComponentInteraction>>(semiDefaultCollector);
expectType<InteractionCollector<CollectedMessageInteraction>>(semiDefaultCollector);
const semiDefaultCollectorChannel = message.createMessageComponentCollector({ time: 10000 });
expectType<InteractionCollector<MessageComponentInteraction>>(semiDefaultCollectorChannel);
expectType<InteractionCollector<CollectedMessageInteraction>>(semiDefaultCollectorChannel);
// Verify that interaction collector options can't be used.
message.createMessageComponentCollector({
@@ -771,7 +772,7 @@ client.on('messageCreate', async message => {
// Make sure filter parameters are properly inferred.
message.createMessageComponentCollector({
filter: i => {
expectType<MessageComponentInteraction>(i);
expectType<CollectedMessageInteraction>(i);
return true;
},
});
@@ -794,7 +795,7 @@ client.on('messageCreate', async message => {
message.awaitMessageComponent({
filter: i => {
expectType<MessageComponentInteraction>(i);
expectType<CollectedMessageInteraction>(i);
return true;
},
});
@@ -830,7 +831,7 @@ client.on('messageCreate', async message => {
channel.awaitMessageComponent({
filter: i => {
expectType<MessageComponentInteraction<'cached'>>(i);
expectType<CollectedMessageInteraction<'cached'>>(i);
return true;
},
});