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 ActionRowBuilderopen in new window.

- new ActionRowBuilder()
+ new ActionRowBuilder<ButtonBuilder>()
1
2

Para crear tus botones, haz uso de las clases ActionRowBuilderopen in new window y ButtonBuilderopen in new window. A continuación, pasa el ActionRow a ChatInputCommandInteraction#replyopen in new window en el array components de InteractionReplyOptionsopen 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] });
	}
});
 





 
 
 
 
 
 
 

 


1
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:

Usuario used /button
Bot de pruebas Bot 07/16/2023
Creo que deberías...

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] });
	}
});
 










 
 
 
 
 

 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Usuario used /button
Bot de pruebas Bot 07/16/2023
Creo que deberías...
Una descripción
Only you can see this

Deshabilitar botones

Si deseas evitar que se utilice un botón, pero sin eliminarlo del mensaje, puedes desactivarlo con el método ButtonBuilder#setDisabledopen in new window:

const button = new ButtonBuilder()
	.setCustomId('primary')
	.setLabel('¡Presionarme!')
	.setStyle(ButtonStyle.Primary)
	.setDisabled(true);




 
1
2
3
4
5
Usuario used /button
Bot de pruebas Bot 07/16/2023
Creo que deberías...

Botones con emojis

Si deseas usar un emoji con un ButtonBuilderopen in new window, puedes utilizar el método ButtonBuilder#setEmojiopen in new window:

const button = new ButtonBuilder()
	.setCustomId('primary')
	.setLabel('Botón con emoji')
	.setStyle(ButtonStyle.Primary)
	.setEmoji('123456789012345678');




 
1
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 InteractionCollectoropen in new window, o con su variante awaitMessageComponent a base de promesa. Ambas proporcionan instancias de la clase MessageComponentInteractionopen 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 ButtonInteractionopen in new window, adjunta un oyente de evento Client#event:interactionCreateopen in new window a tu cliente y usa la protección de tipado BaseInteraction#isButtonopen in new window para asegurarte que solo estás recibiendo botones:

client.on(Events.InteractionCreate, interaction => {
	if (!interaction.isButton()) return;
	console.log(interaction);
});

 


1
2
3
4

Respondiendo a botones

La clase MessageComponentInteractionopen in new window proporciona los mismos métodos que la clase ChatInputCommandInteractionopen in new window. Estos métodos se comportan igual:

  • reply()
  • editReply()
  • deferReply()
  • fetchReply()
  • deleteReply()
  • followUp()

Actualizar el mensaje del botón

La clase MessageComponentInteractionopen in new window también proporciona el método MessageComponentInteraction#updateopen 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`));





 



1
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`));
 





 
 
 




1
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.
Bot de pruebas Bot 07/16/2023
Link

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.