feat(modal): add awaitModalSubmit (#7751)

* feat(modal): add awaitModalSubmit

* fix: allow command interactions to await modal submissions

* Update packages/discord.js/src/structures/CommandInteraction.js

Co-authored-by: MateoDeveloper <79017590+Mateo-tem@users.noreply.github.com>

* chore: less is more

* Update packages/discord.js/src/structures/interfaces/InteractionResponses.js

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

Co-authored-by: MateoDeveloper <79017590+Mateo-tem@users.noreply.github.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
This commit is contained in:
Suneet Tipirneni
2022-04-12 11:13:46 -04:00
committed by GitHub
parent e4f27051ca
commit 3037fca196
4 changed files with 51 additions and 1 deletions

View File

@@ -204,6 +204,7 @@ class CommandInteraction extends Interaction {
deleteReply() {}
followUp() {}
showModal() {}
awaitModalSubmit() {}
}
InteractionResponses.applyToClass(CommandInteraction, ['deferUpdate', 'update']);

View File

@@ -91,6 +91,7 @@ class MessageComponentInteraction extends Interaction {
deferUpdate() {}
update() {}
showModal() {}
awaitModalSubmit() {}
}
InteractionResponses.applyToClass(MessageComponentInteraction);

View File

@@ -1,8 +1,9 @@
'use strict';
const { isJSONEncodable } = require('@discordjs/builders');
const { InteractionResponseType, MessageFlags, Routes } = require('discord-api-types/v10');
const { InteractionResponseType, MessageFlags, Routes, InteractionType } = require('discord-api-types/v10');
const { Error } = require('../../errors');
const InteractionCollector = require('../InteractionCollector');
const MessagePayload = require('../MessagePayload');
/**
@@ -248,6 +249,38 @@ class InteractionResponses {
this.replied = true;
}
/**
* An object containing the same properties as {@link CollectorOptions}, but a few less:
* @typedef {Object} AwaitModalSubmitOptions
* @property {CollectorFilter} [filter] The filter applied to this collector
* @property {number} time Time to wait for an interaction before rejecting
*/
/**
* Collects a single modal submit interaction that passes the filter.
* The Promise will reject if the time expires.
* @param {AwaitModalSubmitOptions} options Options to pass to the internal collector
* @returns {Promise<ModalSubmitInteraction>}
* @example
* // Collect a modal submit interaction
* const filter = (interaction) => interaction.customId === 'modal';
* interaction.awaitModalSubmit({ filter, time: 15_000 })
* .then(interaction => console.log(`${interaction.customId} was submitted!`))
* .catch(console.error);
*/
awaitModalSubmit(options) {
if (typeof options.time !== 'number') throw new Error('INVALID_TYPE', 'time', 'number');
const _options = { ...options, max: 1, interactionType: InteractionType.ModalSubmit };
return new Promise((resolve, reject) => {
const collector = new InteractionCollector(this.client, _options);
collector.once('end', (interactions, reason) => {
const interaction = interactions.first();
if (interaction) resolve(interaction);
else reject(new Error('INTERACTION_COLLECTOR_ERROR', reason));
});
});
}
static applyToClass(structure, ignore = []) {
const props = [
'deferReply',
@@ -259,6 +292,7 @@ class InteractionResponses {
'deferUpdate',
'update',
'showModal',
'awaitModalSubmit',
];
for (const prop of props) {

View File

@@ -379,6 +379,7 @@ export interface InteractionResponseFields<Cached extends CacheType = CacheType>
showModal(
modal: JSONEncodable<APIModalInteractionResponseCallbackData> | ModalData | APIModalInteractionResponseCallbackData,
): Promise<void>;
awaitModalSubmit(options: AwaitModalSubmitOptions<ModalSubmitInteraction>): Promise<ModalSubmitInteraction<Cached>>;
}
export abstract class CommandInteraction<Cached extends CacheType = CacheType> extends Interaction<Cached> {
@@ -1744,6 +1745,7 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
public showModal(
modal: JSONEncodable<APIModalInteractionResponseCallbackData> | ModalData | APIModalInteractionResponseCallbackData,
): Promise<void>;
public awaitModalSubmit(options: AwaitModalSubmitOptions<ModalSubmitInteraction>): Promise<ModalSubmitInteraction>;
}
export class MessageContextMenuCommandInteraction<
@@ -3563,6 +3565,18 @@ export type AwaitMessageComponentOptions<T extends MessageComponentInteraction>
'max' | 'maxComponents' | 'maxUsers'
>;
export type ModalSubmitInteractionCollectorOptions<T extends ModalSubmitInteraction> = Omit<
InteractionCollectorOptions<T>,
'channel' | 'message' | 'guild' | 'interactionType'
>;
export type AwaitModalSubmitOptions<T extends ModalSubmitInteraction> = Omit<
ModalSubmitInteractionCollectorOptions<T>,
'max' | 'maxComponents' | 'maxUsers'
> & {
time: number;
};
export interface AwaitMessagesOptions extends MessageCollectorOptions {
errors?: string[];
}