mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 00:23:30 +01:00
feat: allow createMessageComponentCollector without using fetchReply (#7623)
* feat: allow creation of message component collectors without fetchReply * chore: attempt at requested changes * fix: collector bug * refactor: use better names * feat: add update() support * feat: add defer support * refactor: InteractionReply -> InteractionResponse * fix: remove log * chore: make requested changes * Update packages/discord.js/src/structures/InteractionResponse.js Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com> * chore: make requested changes Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
This commit is contained in:
@@ -117,6 +117,7 @@ exports.Integration = require('./structures/Integration');
|
||||
exports.IntegrationApplication = require('./structures/IntegrationApplication');
|
||||
exports.Interaction = require('./structures/Interaction');
|
||||
exports.InteractionCollector = require('./structures/InteractionCollector');
|
||||
exports.InteractionResponse = require('./structures/InteractionResponse');
|
||||
exports.InteractionWebhook = require('./structures/InteractionWebhook');
|
||||
exports.Invite = require('./structures/Invite');
|
||||
exports.InviteStageInstance = require('./structures/InviteStageInstance');
|
||||
|
||||
@@ -14,6 +14,8 @@ const Events = require('../util/Events');
|
||||
* @property {number} [maxComponents] The maximum number of components to collect
|
||||
* @property {number} [maxUsers] The maximum number of users to interact
|
||||
* @property {Message|APIMessage} [message] The message to listen to interactions from
|
||||
* @property {InteractionResponse} interactionResponse The interaction response to listen
|
||||
* to message component interactions from
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -40,18 +42,28 @@ class InteractionCollector extends Collector {
|
||||
*/
|
||||
this.messageId = options.message?.id ?? null;
|
||||
|
||||
/**
|
||||
* The message interaction id from which to collect interactions, if provided
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.messageInteractionId = options.interactionResponse?.id ?? null;
|
||||
|
||||
/**
|
||||
* The channel from which to collect interactions, if provided
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.channelId =
|
||||
options.message?.channelId ?? options.message?.channel_id ?? this.client.channels.resolveId(options.channel);
|
||||
options.interactionResponse?.interaction.channelId ??
|
||||
options.message?.channelId ??
|
||||
options.message?.channel_id ??
|
||||
this.client.channels.resolveId(options.channel);
|
||||
|
||||
/**
|
||||
* The guild from which to collect interactions, if provided
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.guildId =
|
||||
options.interactionResponse?.interaction.guildId ??
|
||||
options.message?.guildId ??
|
||||
options.message?.guild_id ??
|
||||
this.client.guilds.resolveId(options.channel?.guild) ??
|
||||
@@ -87,7 +99,7 @@ class InteractionCollector extends Collector {
|
||||
if (messages.has(this.messageId)) this.stop('messageDelete');
|
||||
};
|
||||
|
||||
if (this.messageId) {
|
||||
if (this.messageId || this.messageInteractionId) {
|
||||
this._handleMessageDeletion = this._handleMessageDeletion.bind(this);
|
||||
this.client.on(Events.MessageDelete, this._handleMessageDeletion);
|
||||
this.client.on(Events.MessageBulkDelete, bulkDeleteListener);
|
||||
@@ -138,6 +150,7 @@ class InteractionCollector extends Collector {
|
||||
if (this.interactionType && interaction.type !== this.interactionType) return null;
|
||||
if (this.componentType && interaction.componentType !== this.componentType) return null;
|
||||
if (this.messageId && interaction.message?.id !== this.messageId) return null;
|
||||
if (this.messageInteractionId && interaction.message?.interaction?.id !== this.messageInteractionId) return null;
|
||||
if (this.channelId && interaction.channelId !== this.channelId) return null;
|
||||
if (this.guildId && interaction.guildId !== this.guildId) return null;
|
||||
|
||||
@@ -158,6 +171,7 @@ class InteractionCollector extends Collector {
|
||||
if (this.type && interaction.type !== this.type) return null;
|
||||
if (this.componentType && interaction.componentType !== this.componentType) return null;
|
||||
if (this.messageId && interaction.message?.id !== this.messageId) return null;
|
||||
if (this.messageInteractionId && interaction.message?.interaction?.id !== this.messageInteractionId) return null;
|
||||
if (this.channelId && interaction.channelId !== this.channelId) return null;
|
||||
if (this.guildId && interaction.guildId !== this.guildId) return null;
|
||||
|
||||
@@ -196,6 +210,10 @@ class InteractionCollector extends Collector {
|
||||
if (message.id === this.messageId) {
|
||||
this.stop('messageDelete');
|
||||
}
|
||||
|
||||
if (message.interaction.id === this.messageInteractionId) {
|
||||
this.stop('messageDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
61
packages/discord.js/src/structures/InteractionResponse.js
Normal file
61
packages/discord.js/src/structures/InteractionResponse.js
Normal file
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
|
||||
const { InteractionType } = require('discord-api-types/v10');
|
||||
|
||||
/**
|
||||
* Represents an interaction's response
|
||||
*/
|
||||
class InteractionResponse {
|
||||
/**
|
||||
* @param {Interaction} 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}
|
||||
*/
|
||||
this.interaction = interaction;
|
||||
/**
|
||||
* The id of the original interaction response
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = id ?? interaction.id;
|
||||
this.client = interaction.client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects a single component interaction that passes the filter.
|
||||
* The Promise will reject if the time expires.
|
||||
* @param {AwaitMessageComponentOptions} [options={}] Options to pass to the internal collector
|
||||
* @returns {Promise<MessageComponentInteraction>}
|
||||
*/
|
||||
awaitMessageComponent(options = {}) {
|
||||
const _options = { ...options, max: 1 };
|
||||
return new Promise((resolve, reject) => {
|
||||
const collector = this.createMessageComponentCollector(_options);
|
||||
collector.once('end', (interactions, reason) => {
|
||||
const interaction = interactions.first();
|
||||
if (interaction) resolve(interaction);
|
||||
else reject(new Error('INTERACTION_COLLECTOR_ERROR', reason));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a message component interaction collector
|
||||
* @param {MessageComponentCollectorOptions} [options={}] Options to send to the collector
|
||||
* @returns {InteractionCollector}
|
||||
*/
|
||||
createMessageComponentCollector(options = {}) {
|
||||
return new InteractionCollector(this.client, {
|
||||
...options,
|
||||
interactionResponse: this,
|
||||
interactionType: InteractionType.MessageComponent,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const InteractionCollector = require('./InteractionCollector');
|
||||
module.exports = InteractionResponse;
|
||||
@@ -4,6 +4,7 @@ const { isJSONEncodable } = require('@discordjs/builders');
|
||||
const { InteractionResponseType, MessageFlags, Routes, InteractionType } = require('discord-api-types/v10');
|
||||
const { Error } = require('../../errors');
|
||||
const InteractionCollector = require('../InteractionCollector');
|
||||
const InteractionResponse = require('../InteractionResponse');
|
||||
const MessagePayload = require('../MessagePayload');
|
||||
|
||||
/**
|
||||
@@ -49,7 +50,7 @@ class InteractionResponses {
|
||||
/**
|
||||
* Defers the reply to this interaction.
|
||||
* @param {InteractionDeferReplyOptions} [options] Options for deferring the reply to this interaction
|
||||
* @returns {Promise<Message|APIMessage|void>}
|
||||
* @returns {Promise<Message|APIMessage|InteractionResponse>}
|
||||
* @example
|
||||
* // Defer the reply to this interaction
|
||||
* interaction.deferReply()
|
||||
@@ -75,14 +76,14 @@ class InteractionResponses {
|
||||
});
|
||||
this.deferred = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : undefined;
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a reply to this interaction.
|
||||
* <info>Use the `fetchReply` option to get the bot's reply message.</info>
|
||||
* @param {string|MessagePayload|InteractionReplyOptions} options The options for the reply
|
||||
* @returns {Promise<Message|APIMessage|void>}
|
||||
* @returns {Promise<Message|APIMessage|InteractionResponse>}
|
||||
* @example
|
||||
* // Reply to the interaction and fetch the response
|
||||
* interaction.reply({ content: 'Pong!', fetchReply: true })
|
||||
@@ -116,7 +117,7 @@ class InteractionResponses {
|
||||
});
|
||||
this.replied = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : undefined;
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,7 +180,7 @@ class InteractionResponses {
|
||||
/**
|
||||
* Defers an update to the message to which the component was attached.
|
||||
* @param {InteractionDeferUpdateOptions} [options] Options for deferring the update to this interaction
|
||||
* @returns {Promise<Message|APIMessage|void>}
|
||||
* @returns {Promise<Message|APIMessage|InteractionResponse>}
|
||||
* @example
|
||||
* // Defer updating and reset the component's loading state
|
||||
* interaction.deferUpdate()
|
||||
@@ -196,7 +197,7 @@ class InteractionResponses {
|
||||
});
|
||||
this.deferred = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : undefined;
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction.id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +232,7 @@ class InteractionResponses {
|
||||
});
|
||||
this.replied = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : undefined;
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
39
packages/discord.js/typings/index.d.ts
vendored
39
packages/discord.js/typings/index.d.ts
vendored
@@ -397,6 +397,8 @@ export interface InteractionResponseFields<Cached extends CacheType = CacheType>
|
||||
awaitModalSubmit(options: AwaitModalSubmitOptions<ModalSubmitInteraction>): Promise<ModalSubmitInteraction<Cached>>;
|
||||
}
|
||||
|
||||
export type BooleanCache<T extends CacheType> = T extends ['cached'] ? true : false;
|
||||
|
||||
export abstract class CommandInteraction<Cached extends CacheType = CacheType> extends Interaction<Cached> {
|
||||
public get command(): ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null;
|
||||
public options: Omit<
|
||||
@@ -426,13 +428,15 @@ export abstract class CommandInteraction<Cached extends CacheType = CacheType> e
|
||||
public inCachedGuild(): this is CommandInteraction<'cached'>;
|
||||
public inRawGuild(): this is CommandInteraction<'raw'>;
|
||||
public deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public deferReply(options?: InteractionDeferReplyOptions): Promise<void>;
|
||||
public deferReply(options?: InteractionDeferReplyOptions): Promise<InteractionResponse<BooleanCache<Cached>>>;
|
||||
public deleteReply(): Promise<void>;
|
||||
public editReply(options: string | MessagePayload | WebhookEditMessageOptions): Promise<GuildCacheMessage<Cached>>;
|
||||
public fetchReply(): Promise<GuildCacheMessage<Cached>>;
|
||||
public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise<GuildCacheMessage<Cached>>;
|
||||
public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public reply(options: string | MessagePayload | InteractionReplyOptions): Promise<void>;
|
||||
public reply(
|
||||
options: string | MessagePayload | InteractionReplyOptions,
|
||||
): Promise<InteractionResponse<BooleanCache<Cached>>>;
|
||||
public showModal(
|
||||
modal: JSONEncodable<APIModalInteractionResponseCallbackData> | ModalData | APIModalInteractionResponseCallbackData,
|
||||
): Promise<void>;
|
||||
@@ -445,6 +449,19 @@ export abstract class CommandInteraction<Cached extends CacheType = CacheType> e
|
||||
): CommandInteractionResolvedData<Cached>;
|
||||
}
|
||||
|
||||
export class InteractionResponse<Cached extends boolean = boolean> {
|
||||
private constructor(interaction: Interaction, id?: Snowflake);
|
||||
public interaction: Interaction<WrapBooleanCache<Cached>>;
|
||||
public client: Client;
|
||||
public id: Snowflake;
|
||||
public awaitMessageComponent<T extends MessageComponentType = ComponentType.ActionRow>(
|
||||
options?: AwaitMessageCollectorOptionsParams<T, Cached>,
|
||||
): Promise<MappedInteractionTypes<Cached>[T]>;
|
||||
public createMessageComponentCollector<T extends MessageComponentType = ComponentType.ActionRow>(
|
||||
options?: MessageCollectorOptionsParams<T, Cached>,
|
||||
): InteractionCollector<MappedInteractionTypes<Cached>[T]>;
|
||||
}
|
||||
|
||||
export abstract class BaseGuild extends Base {
|
||||
protected constructor(client: Client, data: RawBaseGuildData);
|
||||
public get createdAt(): Date;
|
||||
@@ -1522,6 +1539,7 @@ export class InteractionCollector<T extends Interaction> extends Collector<Snowf
|
||||
private _handleGuildDeletion(guild: Guild): void;
|
||||
|
||||
public channelId: Snowflake | null;
|
||||
public messageInteractionId: Snowflake | null;
|
||||
public componentType: ComponentType | null;
|
||||
public get endReason(): string | null;
|
||||
public guildId: Snowflake | null;
|
||||
@@ -1767,17 +1785,17 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
|
||||
public inCachedGuild(): this is MessageComponentInteraction<'cached'>;
|
||||
public inRawGuild(): this is MessageComponentInteraction<'raw'>;
|
||||
public deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public deferReply(options?: InteractionDeferReplyOptions): Promise<void>;
|
||||
public deferReply(options?: InteractionDeferReplyOptions): Promise<InteractionResponse<BooleanCache<Cached>>>;
|
||||
public deferUpdate(options: InteractionDeferUpdateOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public deferUpdate(options?: InteractionDeferUpdateOptions): Promise<void>;
|
||||
public deferUpdate(options?: InteractionDeferUpdateOptions): Promise<InteractionResponse>;
|
||||
public deleteReply(): Promise<void>;
|
||||
public editReply(options: string | MessagePayload | WebhookEditMessageOptions): Promise<GuildCacheMessage<Cached>>;
|
||||
public fetchReply(): Promise<GuildCacheMessage<Cached>>;
|
||||
public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise<GuildCacheMessage<Cached>>;
|
||||
public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public reply(options: string | MessagePayload | InteractionReplyOptions): Promise<void>;
|
||||
public reply(options: string | MessagePayload | InteractionReplyOptions): Promise<InteractionResponse>;
|
||||
public update(options: InteractionUpdateOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public update(options: string | MessagePayload | InteractionUpdateOptions): Promise<void>;
|
||||
public update(options: string | MessagePayload | InteractionUpdateOptions): Promise<InteractionResponse>;
|
||||
public showModal(
|
||||
modal: JSONEncodable<APIModalInteractionResponseCallbackData> | ModalData | APIModalInteractionResponseCallbackData,
|
||||
): Promise<void>;
|
||||
@@ -1882,9 +1900,9 @@ export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = C
|
||||
extends ModalSubmitInteraction<Cached> {
|
||||
message: GuildCacheMessage<Cached>;
|
||||
update(options: InteractionUpdateOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
update(options: string | MessagePayload | InteractionUpdateOptions): Promise<void>;
|
||||
update(options: string | MessagePayload | InteractionUpdateOptions): Promise<InteractionResponse>;
|
||||
deferUpdate(options: InteractionDeferUpdateOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
deferUpdate(options?: InteractionDeferUpdateOptions): Promise<void>;
|
||||
deferUpdate(options?: InteractionDeferUpdateOptions): Promise<InteractionResponse>;
|
||||
inGuild(): this is ModalMessageModalSubmitInteraction<'raw' | 'cached'>;
|
||||
inCachedGuild(): this is ModalMessageModalSubmitInteraction<'cached'>;
|
||||
inRawGuild(): this is ModalMessageModalSubmitInteraction<'raw'>;
|
||||
@@ -1901,11 +1919,11 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
|
||||
public replied: boolean;
|
||||
public readonly webhook: InteractionWebhook;
|
||||
public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public reply(options: string | MessagePayload | InteractionReplyOptions): Promise<void>;
|
||||
public reply(options: string | MessagePayload | InteractionReplyOptions): Promise<InteractionResponse>;
|
||||
public deleteReply(): Promise<void>;
|
||||
public editReply(options: string | MessagePayload | WebhookEditMessageOptions): Promise<GuildCacheMessage<Cached>>;
|
||||
public deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||
public deferReply(options?: InteractionDeferReplyOptions): Promise<void>;
|
||||
public deferReply(options?: InteractionDeferReplyOptions): Promise<InteractionResponse>;
|
||||
public fetchReply(): Promise<GuildCacheMessage<Cached>>;
|
||||
public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise<GuildCacheMessage<Cached>>;
|
||||
public inGuild(): this is ModalSubmitInteraction<'raw' | 'cached'>;
|
||||
@@ -4661,6 +4679,7 @@ export interface InteractionCollectorOptions<T extends Interaction, Cached exten
|
||||
maxComponents?: number;
|
||||
maxUsers?: number;
|
||||
message?: CacheTypeReducer<Cached, Message, APIMessage>;
|
||||
interactionResponse?: InteractionResponse;
|
||||
}
|
||||
|
||||
export interface InteractionDeferReplyOptions {
|
||||
|
||||
Reference in New Issue
Block a user