It's my first time seeing this feature from a Discord bot. I tried looking everywhere but it seems that I have failed. There's this feature from Captcha.bot Discord bot where you can accept input from a pop-up window inside Discord.
There's a button in an embedded message made by Captcha.bot where you will have to answer a Captcha test. After pressing the button, it creates a pop-up window like this.
After placing the right answer on the captcha bot, here's the aftermath of the experience.
All I want to learn is how to summon that pop-up window using Discord.js if it's even possible or at least learn how they did it.
Those are called modals, and they will be available in the next major discord.js version, v14. There is already a pull request for this.
There are some changes in v14. If you try to update your code from v13.7, there are a few differences:
Modal
is now ModalBuilder
MessageActionRow
is now ActionRowBuilder
TextInputComponent
is now TextInputBuilder
TextInputStyle.Short
, ButtonStyle.Primary
, etc. instead of strings (i.e. "SHORT"
, or "PRIMARY"
)interaction
no longer has a isModalSubmit
type guard. You'll need to check its type
against the InteractionType.ModalSubmit
enumYou can find the full code below that you can use with discord.js v14:
// discord.js version v14.0.0+
const {
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
Client,
Events,
GatewayIntentBits,
InteractionType,
ModalBuilder,
TextInputBuilder,
TextInputStyle,
} = require('discord.js');
const TOKEN = 'YOUR TOKEN HERE';
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
],
});
client.on(Events.MessageCreate, (message) => {
if (message.author.bot) return;
let button = new ActionRowBuilder();
button.addComponents(
new ButtonBuilder()
.setCustomId('verification-button')
.setStyle(ButtonStyle.Primary)
.setLabel('Open modal dialog'),
);
message.reply({
components: [button],
});
});
client.on(Events.InteractionCreate, async (interaction) => {
if (interaction.isButton()) {
if (interaction.customId === 'verification-button') {
const modal = new ModalBuilder()
.setCustomId('verification-modal')
.setTitle('Verify yourself')
.addComponents([
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId('verification-input')
.setLabel('Answer')
.setStyle(TextInputStyle.Short)
.setMinLength(4)
.setMaxLength(12)
.setPlaceholder('ABCDEF')
.setRequired(true),
),
]);
await interaction.showModal(modal);
}
}
if (interaction.type === InteractionType.ModalSubmit) {
if (interaction.customId === 'verification-modal') {
const response =
interaction.fields.getTextInputValue('verification-input');
interaction.reply(`Yay, your answer is submitted: "${response}"`);
}
}
});
client.once('ready', () => {
console.log('Bot v14 is connected...');
});
client.login(TOKEN);
Modals are available since v13.7.0. If you try to update your code from discord-modals
, there are a few differences:
Modal
and TextInputComponent
from discord.jsTextInputComponent
s must be inside a MessageActionRow
sinteraction
has a showModal()
method that opens the modalinteraction
has an isModalSubmit()
method that checks if it's a ModalSubmitInteraction
modalSubmit
eventinteraction.fields.getTextInputValue()
You can find the full code below that you can use in v13.7:
// discord.js version v13.7.0+
const {
Client,
Intents,
MessageActionRow,
MessageButton,
Modal,
TextInputComponent,
} = require('discord.js');
const TOKEN = 'YOUR TOKEN HERE';
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES],
});
client.on('messageCreate', (message) => {
if (message.author.bot) return;
let button = new MessageActionRow();
button.addComponents(
new MessageButton()
.setCustomId('verification-button')
.setStyle('PRIMARY')
.setLabel('Open modal dialog'),
);
message.reply({
components: [button],
});
});
client.on('interactionCreate', async (interaction) => {
if (interaction.isButton()) {
if (interaction.customId === 'verification-button') {
const modal = new Modal()
.setCustomId('verification-modal')
.setTitle('Verify yourself')
.addComponents([
new MessageActionRow().addComponents(
new TextInputComponent()
.setCustomId('verification-input')
.setLabel('Answer')
.setStyle('SHORT')
.setMinLength(4)
.setMaxLength(12)
.setPlaceholder('ABCDEF')
.setRequired(true),
),
]);
await interaction.showModal(modal);
}
}
if (interaction.isModalSubmit()) {
if (interaction.customId === 'verification-modal') {
const response =
interaction.fields.getTextInputValue('verification-input');
interaction.reply(`Yay, your answer is submitted: "${response}"`);
}
}
});
client.once('ready', () => {
console.log('Bot v13 is connected...');
});
client.login(TOKEN);
discord-modals
packageIn the meantime, you can use an npm package like discord-modals or discordjs-modal.
You can find a working example with the discord-modals
package below. Don't forget to install it first using npm i discord-modals
.
// discord-modals
const {
Client,
Intents,
MessageActionRow,
MessageButton,
} = require('discord.js');
const discordModals = require('discord-modals');
const { Modal, TextInputComponent, showModal } = discordModals;
const TOKEN = 'YOUR TOKEN HERE';
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES],
});
discordModals(client);
client.on('messageCreate', (message) => {
if (message.author.bot) return;
let button = new MessageActionRow();
button.addComponents(
new MessageButton()
.setCustomId('verification-button')
.setStyle('PRIMARY')
.setLabel('Open modal dialog'),
);
message.reply({
components: [button],
});
});
client.on('interactionCreate', async (interaction) => {
if (interaction.isButton()) {
if (interaction.customId === 'verification-button') {
const modal = new Modal() // We create a Modal
.setCustomId('verification-modal')
.setTitle('Verify yourself')
.addComponents([
new TextInputComponent()
.setCustomId('verification-input')
.setLabel('Answer')
.setStyle('SHORT')
.setMinLength(4)
.setMaxLength(12)
.setPlaceholder('ABCDEF')
.setRequired(true),
]);
showModal(modal, {
client,
interaction,
});
}
}
});
client.on('modalSubmit', async (modal) => {
if (modal.customId === 'verification-modal') {
const response = modal.getTextInputValue('verification-input');
modal.reply(`Yay, your answer is submitted: "${response}"`);
}
});
client.once('ready', () => {
console.log('Bot v13 is connected...');
});
client.login(TOKEN);