Botones
Con la API de componentes, puedes crear componentes de mensajes interactivos. En esta página, aprenderás cómo enviar, recibir y responder a interacción de botones con discord.js.
CONSEJO
Esta página es una continuación de la página de creación de comandos avanzados. Por favor, leé primero con atención para que puedas entender los métodos utilizados en esta sección.
Construyendo y enviando botones
Los botones son una de las clases MessageComponent
, que pueden enviarse a través de mensajes o respuestas de interacción. Un botón, como cualquier otro componente de mensaje, debe estar en una ActionRow
.
ADVERTENCIA
Puedes tener un máximo de cinco ActionRow
por mensaje, y cinco botones dentro de un ActionRow
.
Si estás utilizando TypeScript, necestiarás especificar el tipo de componentes que contiene tu ActionRow
. Esto se puede hacer especificando el constructor del componente que le añadirás utilizando un parámetro genérico en ActionRowBuilder
open in new window.
- new ActionRowBuilder()
+ new ActionRowBuilder<ButtonBuilder>()
2
Para crear tus botones, haz uso de las clases ActionRowBuilder
open in new window y ButtonBuilder
open in new window. A continuación, pasa el ActionRow
a ChatInputCommandInteraction#reply
open in new window en el array components
de InteractionReplyOptions
open in new window:
const { ActionRowBuilder, ButtonBuilder, ButtonStyle, Events } = require('discord.js');
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'button') {
const row = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('primary')
.setLabel('¡Presionarme!')
.setStyle(ButtonStyle.Primary),
);
await interaction.reply({ content: 'Creo que deberías...', components: [row] });
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CONSEJO
La id personalizada (custom_id
) es una string definida por ti de hasta 100 caracteres. Utiliza este campo para asegurarte de que puedas definir de forma única todas las interacciones procedentes de tus botones.
Reinicia tu bot y luego envía el comando a un canal al que tu bot tenga acceso. Si todo va bien, deberías ver algo como esto:
También puede enviar componentes de mensajes dentro de una respuesta efímera o junto a embeds.
const { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, Events } = require('discord.js');
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'button') {
const row = new ActionRowBuilder()
.addComponents(
// ...
);
const embed = new EmbedBuilder()
.setColor(0x0099FF)
.setTitle('Titulo ingenioso')
.setURL('https://discord.js.org')
.setDescription('Una descripción');
await interaction.reply({ content: 'Creo que deberías...', ephemeral: true, embeds: [embed], components: [row] });
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Deshabilitar botones
Si deseas evitar que se utilice un botón, pero sin eliminarlo del mensaje, puedes desactivarlo con el método ButtonBuilder#setDisabled
open in new window:
const button = new ButtonBuilder()
.setCustomId('primary')
.setLabel('¡Presionarme!')
.setStyle(ButtonStyle.Primary)
.setDisabled(true);
2
3
4
5
Botones con emojis
Si deseas usar un emoji con un ButtonBuilder
open in new window, puedes utilizar el método ButtonBuilder#setEmoji
open in new window:
const button = new ButtonBuilder()
.setCustomId('primary')
.setLabel('Botón con emoji')
.setStyle(ButtonStyle.Primary)
.setEmoji('123456789012345678');
2
3
4
5
Ahora ya sabes todo lo que hay que hacer para crear y enviar un botón. Pasemos ahora a recibir las interacciones de los botones.
Recibiendo interacción de botones
Colectores de componentes
Las interacciones de los componentes de mensajes pueden ser recolectados dentro del ámbito del comando de barra que las envió con un InteractionCollector
open in new window, o con su variante awaitMessageComponent
a base de promesa. Ambas proporcionan instancias de la clase MessageComponentInteraction
open in new window como elementos recogidos.
CONSEJO
Puedes crear los colectores en un message
o en un channel
.
Para obtener una guía detallada sobre la recepción de componentes de mensaje a través de colectores, puedes consultar la guía de colectores.
El evento interactionCreate
Para recibir un evento ButtonInteraction
open in new window, adjunta un oyente de evento Client#event:interactionCreate
open in new window a tu cliente y usa la protección de tipado BaseInteraction#isButton
open in new window para asegurarte que solo estás recibiendo botones:
client.on(Events.InteractionCreate, interaction => {
if (!interaction.isButton()) return;
console.log(interaction);
});
2
3
4
Respondiendo a botones
La clase MessageComponentInteraction
open in new window proporciona los mismos métodos que la clase ChatInputCommandInteraction
open in new window. Estos métodos se comportan igual:
reply()
editReply()
deferReply()
fetchReply()
deleteReply()
followUp()
Actualizar el mensaje del botón
La clase MessageComponentInteraction
open in new window también proporciona el método MessageComponentInteraction#update
open in new window para actualizar el mensaje del botón al que fue adjuntado. Pasar un array vacío a la opción components
hará que se remuevan todos los botones que se hayan presionado.
Este método debería usarse en lugar de editReply()
en la interacción original, para asegurarse de que responde a la interacción del botón.
const filter = i => i.customId === 'primary' && i.user.id === '122157285790187530';
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 15000 });
collector.on('collect', async i => {
await i.update({ content: '¡Un botón fue presionado!', components: [] });
});
collector.on('end', collected => console.log(`${collected.size} elementos recolectados`));
2
3
4
5
6
7
8
9
Aplazar y actualizar el mensaje del botón
Además de aplazar una respuesta de interacción, puede aplazar la actualización del botón, que activará un estado de carga y luego volverá a su estado original:
const wait = require('node:timers/promises').setTimeout;
// ...
collector.on('collect', async i => {
if (i.customId === 'primary') {
await i.deferUpdate();
await wait(4000);
await i.editReply({ content: '¡Un botón fue presionado!', components: [] });
}
});
collector.on('end', collected => console.log(`${collected.size} elementos recolectados`));
2
3
4
5
6
7
8
9
10
11
12
13
Estilos de botones
Actualmente hay cinco estilos de botón disponibles:
Primary
, un botón blurple;Secondary
, un botón gris;Success
, un botón verde;Danger
, un botón rojo;Link
, un botón que te dirige a una URL.
ADVERTENCIA
Solo los botones Link
pueden contener una url
. Los botones Link
no pueden tener una customId
y no envían un evento de interacción cuando son pulsados.