Comandos con entrada de usuario en Discord

Comandos con entrada de usuario en Discord

A veces querrá determinar el resultado de un comando en función de la entrada del usuario. Es un caso muy común con una solución muy simple

Esta sección le enseñará cómo extraer la entrada del usuario de un mensaje y usarla en su código. Generalmente, escuchará a otras personas referirse a esto como "argumentos", y usted debe referirse a ellos también como eso.

#Argumentos básicos

De hecho, abordaremos 2 cosas a la vez aquí. Las cosas se explicarán a lo largo del camino, así que no se preocupe si no comprende de inmediato.

Vaya a su archivo bot principal y busque el client.on('message', ...)bit. Agregue el siguiente bloque de código en la parte superior de esta función de devolución de llamada de los oyentes de eventos (la parte que reemplazamos ...aquí).

// client.on('message', message => {

if (!message.content.startsWith(prefix) || message.author.bot) return;

const args = message.content.slice(prefix.length).trim().split(' ');

const command = args.shift().toLowerCase();

// the rest of your code

  • Si el mensaje no comienza con el prefijo o lo envió un bot, salga temprano.
  • Cree una argsvariable que corte el prefijo por completo, elimine los espacios en blanco sobrantes y luego lo divida en una matriz por espacios.
  • Cree una commandvariable llamando args.shift(), que tomará el primer elemento de la matriz y lo devolverá al mismo tiempo que lo eliminará de la matriz original (para que no tenga la cadena de nombre del comando dentro de la argsmatriz).

Con suerte, eso es un poco más claro, si hubo alguna confusión. Creemos un comando rápido para ver el resultado de nuestra nueva adición:

// using the new `command` variable, this makes it easier to manage!

// you can switch your other commands to this format as well

else if (command === 'args-info') {

if (!args.length) {

return message.channel.send(`You didn't provide any arguments, ${message.author}!`);

}

message.channel.send(`Command name: ${command}\nArguments: ${args}`);

}

Ahora que tiene una serie de argumentos, ¡puede interactuar con ellos en consecuencia! Pruebe esta pequeña adición al comando:

else if (command === 'args-info') {

if (!args.length) {

return message.channel.send(`You didn't provide any arguments, ${message.author}!`);

}

else if (args[0] === 'foo') {

return message.channel.send('bar');

}

message.channel.send(`First argument: ${args[0]}`);

}

Entonces, si el primer argumento proporcionado es igual a "foo", devuelva "bar". De lo contrario, devuelva el argumento proporcionado por el usuario.

Advertencias

Actualmente, está utilizando .split(' ')para dividir los argumentos del comando. Sin embargo, en realidad hay un pequeño problema con esto. Tal como está, dividirá la cadena por todos y cada uno de los espacios. Bueno, ¿qué sucede si alguien accidentalmente (o incluso intencionalmente) agrega espacios adicionales?

Si nunca antes has hecho algo como esto, probablemente no sea lo que esperabas, ¿verdad? Afortunadamente, existe una solución simple para este problema. La línea roja es lo que se debe quitar y la línea verde es lo que se debe reemplazar.

- const args = message.content.slice(prefix.length).trim().split(' ');

+ const args = message.content.slice(prefix.length).trim().split(/ +/);

Increíble! No hay nada de qué preocuparse en ese sentido por ahora. Ahora está usando algo llamado "expresión regular" (comúnmente conocida como "regex") para manejar ese pequeño (pero importante) error.

Situaciones comunes con argumentos

Aquí es donde repasaremos algunas situaciones comunes en las que querrá asegurarse de que un argumento se ajuste a ciertos criterios.

Menciones

Usando el ejemplo de un comando de patada, lo más probable es que desee que le permita al usuario usar el comando y mencionar a la persona a patear, ¿verdad? En realidad, no construiremos el comando kick completo en este ejemplo, pero así es como puede hacerlo:

else if (command === 'kick') {

// grab the "first" mentioned user from the message

// this will return a `User` object, just like `message.author`

const taggedUser = message.mentions.users.first();

message.channel.send(`You wanted to kick: ${taggedUser.username}`);

}

Pero, ¿qué pasa si intentas usar el comando sin mencionar a nadie? Si lo prueba usted mismo, notará que el bot no responde (debido a que se bloquea) y debería ver algo como esto en su consola:

message.channel.send(`You wanted to kick: ${taggedUser.username}`);

TypeError: Cannot read property 'username' of undefined

¡Eso es porque estás intentando acceder a la usernamepropiedad de un usuario que no mencionaste! Como message.mentions.userses una colección y estás intentando llamar .first()a una colección vacía, volverá undefined. Puede agregar una verificación de coherencia rápida por encima de la const taggedUser = ...línea para evitar que esto suceda.

if (!message.mentions.users.size) {

return message.reply('you need to tag a user in order to kick them!');

}

Dado que message.mentions.userses una Colección, tiene una .sizepropiedad. Si no se menciona ningún usuario, devolverá 0 (que es un falsyvalor), lo que significa que puede hacer if (!value)para verificar si es falso.

Si vuelve a intentarlo, debería funcionar como se esperaba.

Trabajando con múltiples menciones

Digamos que tiene algún tipo de !avatarcomando, donde mostrará el avatar de todos los usuarios mencionados, o su propio avatar si no se mencionó ningún usuario. Concéntrese en esa segunda parte por ahora: ¿cómo haría para mostrar su propio avatar si no se mencionara a ningún usuario? Tomando el fragmento del código que acaba de usar, puede hacerlo así:

else if (command === 'avatar') {

if (!message.mentions.users.size) {

return message.channel.send(`Your avatar: <${message.author.displayAvatarURL({ format: "png", dynamic: true })}>`);

}

// ...

}

Si dynamicse proporciona la opción, recibirá una .gifURL si la imagen está animada; de lo contrario, volverá a la especificada formato la predeterminada .webpsi no se proporciona ninguna.

Esa parte es simple; simplemente recicla la declaración if que usaste en la sección anterior y muestra el enlace a tu avatar.

La siguiente parte es donde da un giro: mostrar los avatares de todos los usuarios mencionados. ¡Pero es más simple de lo que piensas! message.mentions.usersdevuelve una colección (como se mencionó anteriormente), que puede recorrer de varias maneras diferentes. Utilizará el .map()bucle aquí, ya que le permite recopilar y almacenar datos fácilmente en una variable para enviar 1 mensaje final al final, en lugar de varios.

else if (command === 'avatar') {

if (!message.mentions.users.size) {

return message.channel.send(`Your avatar: <${message.author.displayAvatarURL({ format: "png", dynamic: true })}>`);

}

const avatarList = message.mentions.users.map(user => {

return `${user.username}'s avatar: <${user.displayAvatarURL({ format: "png", dynamic: true })}>`;

});

// send the entire array of strings as a message

// by default, discord.js will `.join()` the array with `\n`

message.channel.send(avatarList);

}

Si dynamicse proporciona la opción, recibirá una .gifURL si la imagen está animada; de lo contrario, volverá a la especificada formato la predeterminada .webpsi no se proporciona ninguna.

¡Y ta-da! Ahora tiene una lista de enlaces de avatar de todos los usuarios que etiquetó.

Rangos de números

A veces querrá que los usuarios le den datos que van de X a Y, pero nada fuera de eso. Además, debes asegurarte de que te den un número real y no caracteres aleatorios. Un buen ejemplo de esto sería un !prunecomando, donde borra X mensajes en el canal, dependiendo de lo que ingrese el usuario.

El primer paso sería verificar si la entrada que dieron es un número real.

else if (command === 'prune') {

const amount = parseInt(args[0]);

if (isNaN(amount)) {

return message.reply('that doesn\'t seem to be a valid number.');

}

// ...

}

Y si lo prueba, debería funcionar como se esperaba.

Entonces, lo que debe hacer a continuación es verificar si el primer argumento está entre X e Y. Siguiendo la idea de un comando de poda, lo más probable es que desee usar el .bulkDelete()método, que le permite eliminar varios mensajes de una sola vez.

Dicho esto, ese método tiene sus límites: solo puede eliminar un mínimo de 2 y un máximo de 100 mensajes (a la vez). Afortunadamente, hay algunas formas de lidiar con eso. Una de esas formas sería simplemente verificar el valor de la amountvariable, así:

if (isNaN(amount)) {

return message.reply('that doesn\'t seem to be a valid number.');

} else if (amount < 2 || amount > 100) {

return message.reply('you need to input a number between 2 and 100.');

}

// ...

¡Ahora todo lo que queda es borrar los mensajes! Es una simple línea de código:

message.channel.bulkDelete(amount);

¡Y tienes un comando de poda que funciona! Cree un canal de prueba, envíe algunos mensajes aleatorios y pruébelo.

#Advertencias

Debe tener en cuenta que en realidad hay algunas advertencias con el .bulkDelete()método. El primero sería intentar eliminar mensajes de más de 2 semanas, lo que normalmente sería un error. Aquí hay una solución fácil para eso:

message.channel.bulkDelete(amount, true);

El segundo parámetro del .bulkDelete()método filtrará los mensajes de más de 2 semanas si le da un valor verdadero. Entonces, si hay 50 mensajes y 25 de ellos tienen más de 2 semanas, solo eliminará los primeros 25 sin arrojar un error. Sin embargo, si todos los mensajes que está intentando eliminar tienen más de 2 semanas, todavía generará un error. Sabiendo esto, debería detectar ese error encadenando un archivo .catch().

message.channel.bulkDelete(amount, true).catch(err => {

console.error(err);

message.channel.send('there was an error trying to prune messages in this channel!');

});

La otra advertencia con esto es que el !prune {number}mensaje que envió también contará para la cantidad eliminada. Lo que esto significa es que si lo envía !prune 2, eliminará ese mensaje y solo otro. Hay un par de formas de evitar esto, pero tomaremos la ruta más fácil por el bien del tutorial. Aquí están las ediciones para realizar en su código actual:

- const amount = parseInt(args[0]);

+ const amount = parseInt(args[0]) + 1;

- else if (amount < 2 || amount > 100) {

- return message.reply('you need to input a number between 2 and 100.');

- }

+ else if (amount <= 1 || amount > 100) {

+ return message.reply('you need to input a number between 1 and 99.');

+ }

Autor: Oscar olg Fecha actualización el 2021-10-19. Fecha publicación el 2020-10-19. Categoría: Discord. Mapa del sitio Fuente: discordjs