Menús de selección
Con la API de componentes, puedes crear componentes de mensajes interactivos. En esta página, veremos cómo enviar, recibir y responder a menús de selección con discord.js.
CONSEJO
Esta página es un seguimiento de la sección de interacciones (comandos de barra). Por favor, lee atentamente esa sección primero para que puedas comprender los métodos utilizados en esta sección.
Creación y envío de menús de selección
Los menús de selección son una de las clases MessageComponent
, que pueden enviarse a través de mensajes o respuestas de interacción. Un menú de selección, como cualquier otro componente de mensaje, debe estar en una ActionRow
.
ADVERTENCIA
Puede tener un máximo de cinco ActionRow
por mensaje, y un menú de selección dentro de un ActionRow
.
Para crear un menú de selección, utilice las clases ActionRowBuilder
open in new window y StringSelectMenuBuilder
open in new window. A continuación, pase el contenedor de componentes resultante a ChatInputCommandInteraction#reply
open in new window en el array components
de InteractionReplyOptions
open in new window:
const { ActionRowBuilder, Events, StringSelectMenuBuilder } = require('discord.js');
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
const row = new ActionRowBuilder()
.addComponents(
new StringSelectMenuBuilder()
.setCustomId('selección')
.setPlaceholder('Nada seleccionado')
.addOptions(
{
label: 'Seleccioname',
description: 'Esto es una descripción',
value: 'primera_opción',
},
{
label: 'También puedes seleccionarme',
description: 'Esto también es otra descripción',
value: 'segunda_opción',
},
),
);
await interaction.reply({ content: '¡Pong!', components: [row] });
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 menús de selección.
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, EmbedBuilder, Events, StringSelectMenuBuilder } = require('discord.js');
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
const row = new ActionRowBuilder()
.addComponents(
// ...
);
const embed = new EmbedBuilder()
.setColor(0x0099FF)
.setTitle('Titulo ingenioso')
.setURL('https://discord.js.org/')
.setDescription('Alguna descripción');
await interaction.reply({ content: '¡Pong!', 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
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:
ADVERTENCIA
Si estás usando TypeScript necesitarás especificar el tipo de componentes que contiene tu contenedor de componentes. Esto se puede hacer especificando el constructor de componentes que le añadirás utilizando un parámetro genérico en ActionRowBuilder
open in new window.
- new ActionRowBuilder()
+ new ActionRowBuilder<StringSelectMenuBuilder>()
2
¡Ahora ya sabes todo lo que hay que saber para construir y enviar un SelectMenu
! Pasemos ahora a cómo recibir menús.
Recibiendo interacciones de menús de selección
Colectores de componentes
Las interacciones de componentes de mensajes se pueden recopilar dentro del ámbito del comando de barra que las envió utilizando un InteractionCollector
open in new window, o su variante awaitMessageComponent
a base de promesa. Ambos proporcionan instancias de la clase MessageComponentInteraction
open in new window como elementos recogidos.
CONSEJO
Puede crear los colectores en un message
o en un channel
.
Para obtener una guía detallada sobre la recepción de componentes de mensajes a través de recopiladores, consulta la guía de recopiladores.
El evento interactionCreate
Para recibir un StringSelectMenuInteraction
open in new window, adjunta un oyente de evento Client#event:interactionCreate
open in new window a su cliente y utilice la protección de tipado BaseInteraction#isStringSelectMenu
open in new window para asegurarte de que sólo recibe menús de selección:
client.on(Events.InteractionCreate, interaction => {
if (!interaction.isStringSelectMenu()) return;
console.log(interaction);
});
2
3
4
Respondiendo a menús de selección
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()
Actualización del mensaje del menú de selección
La clase MessageComponentInteraction
open in new window proporciona un método MessageComponentInteraction#update
open in new window para actualizar el mensaje al que se adjuntó el menú de selección. Si se pasa un array vacío a la opción components
se eliminarán todos los menús una vez seleccionada una opción.
This method should be used in favour of editReply()
on the original interaction, to ensure you respond to the select menu interaction.
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isStringSelectMenu()) return;
if (interaction.customId === 'select') {
await interaction.update({ content: 'Something was selected!', components: [] });
}
});
2
3
4
5
6
7
Deferring and updating the select menu's message
Este método debe usarse en lugar de editReply()
en la interacción original, para asegurar que respondes a la interacción del menú de selección.
const wait = require('node:timers/promises').setTimeout;
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isStringSelectMenu()) return;
if (interaction.customId === 'select') {
await interaction.deferUpdate();
await wait(4000);
await interaction.editReply({ content: '¡Se seleccionó algo!', components: [] });
}
});
2
3
4
5
6
7
8
9
10
11
Menús multiselección
Un menú de selección no está vinculado a una única selección; puede especificar una cantidad mínima y máxima de opciones que deben seleccionarse. Puede utilizar los métodos SelectMenuBuilder#setMinValues
open in new window y StringSelectMenuBuilder#setMaxValues
open in new window para determinar estos valores.
const { ActionRowBuilder, Events, StringSelectMenuBuilder } = require('discord.js');
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
const row = new ActionRowBuilder()
.addComponents(
new StringSelectMenuBuilder()
.setCustomId('selección')
.setPlaceholder('Nada seleccionado')
.setMinValues(2)
.setMaxValues(3)
.addOptions([
{
label: 'Seleccioname',
description: 'Esto es una descripción',
value: 'primera_opción',
},
{
label: 'También puedes seleccionarme',
description: 'Esto también es una descripción',
value: 'segunda_opción',
},
{
label: 'También soy una opción',
description: 'Esta es una descripción también',
value: 'tercera_opción',
},
]),
);
await interaction.reply({ content: '¡Pong!', components: [row] });
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Accediendo a los valores de interacción del menú de selección
Después de recibir su StringSelectMenuInteraction
open in new window, podrás acceder a los valores seleccionados desde StringSelectMenuInteraction#values
open in new window. Esto devolverá un array de string asociados a las opciones seleccionadas en su menú de selección.
Por defecto, los menús de selección sólo aceptan una única selección. Puede recuperar el valor seleccionado accediendo al primer índice del array devuelta, como se muestra en el siguiente fragmento:
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isStringSelectMenu()) return;
const selected = interaction.values[0];
if (selected === 'ping') {
await interaction.update('¡Se ha seleccionado la opción ping!');
} else if (selected === 'pong') {
await interaction.update('¡Se ha seleccionado la opción Pong!');
}
});
2
3
4
5
6
7
8
9
10
11
En el caso de un menú de selección múltiple, el StringSelectMenuInteraction#values
open in new window recibido puede contener más de un valor, y debe tratarse en consecuencia:
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isStringSelectMenu()) return;
const selected = interaction.values.join(', ');
await interaction.update(`¡El usuario ha seleccionado ${selected}!`);
});
2
3
4
5
6
7