¿Qué aprenderemos en ésta entrega?
En el tutorial pasado logramos que nuestro Bot se conectara a Discord, en esta nueva entrega:- Analizaremos el código de la sesión pasada
- Introduciremos los "Intents", la forma en que nuestro Bot se comunica con Discord
- Introduciremos los Slash Commands
- Crearemos nuestro primer Slash Command
Analizando el código para conectar nuestro Bot
import dotenv from "dotenv";
import { Client, GatewayIntentBits } from "discord.js";
dotenv.config();
const token = process.env.token;
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.login(token);
Recordemos que todo esto se encuentra dentro del archivo index.js que hemos corrido mediante el comando:
node index.js
Con ello hacemos que Node interprete nuestro código. Sin embargo para que pueda ejecutarse de forma correcta, es necesario por detrás tener todos los mecanismos (código/librerías) que especifican como debe comunicarse Node con Discord. Para conseguir esto es que instalamos previamente las dependencias de discord.js y ademas instalamos dotenv. Para lograr conectar dichas librerías con el código de nuestro archivo index.js utilizamos la instrucción:
import
Por lo tanto, mediante las líneas:
import dotenv from "dotenv";
import { Client, GatewayIntentBits } from "discord.js";
conseguimos conectar las librerías de dotenv y discordjs. En particular estamos importando completamente la librería de dotenv y de discord.js solo importamos Client, y GatewayIntentBits, eso lo logramos especificando dichos elementos entre llaves. Ya que en nuestro código solo utilizamos la función "config" del paquete dotenv, también podríamos haber indicado que solo queríamos este elemento, así las líneas:
import dotenv from "dotenv";
dotenv.config();
bien podrían ser cambiadas por:
import { config } from "dotenv";
config();
y nuestro código correría sin problemas. ¿Qué hace este par de líneas?.
La función config() del paquete dotenv busca y consulta el archivo .env y eleva todas las definiciones que tengamos en ese archivo como variables de ambiente que se encontrarán disponibles mientras nuestro proceso creado al ejecutar index.js se encuentre "vivo". Recordemos que la estructura que habíamos dado a nuestro archivo .env era la siguiente:
token = [el token de nuestro Bot]
Por lo tanto ahora podremos acceder a esa variable, como una variable de ambiente mediante la línea:
const token = process.env.token;
donde asignamos a una constante la variable de ambiente token, para ello la extraemos del conjunto de variables de ambiente del proceso, "process.env".
¿Por que no escribir directamente el token en nuestro código?
Si bien es posible ahorrarnos la importación y ejecución de la función config y simplemente asignar el token a la constante "token", esto es una grave vulnerabilidad para nuestro Bot. Idealmente para un proyecto mediano a grande, el código será compartido por múltiples personas y además será subido a algún servicio de backend para que se ejecute 24/7, si dejamos el token en el código, cualquier persona con acceso a este, podría simplemente copiarlo y hacer mal uso de el. No debemos olvidar que el token es la llave de acceso para que nuestro bot se conecte a Discord. Por ello lo ideal es conservarlo en una archivo independiente, de forma que podemos compartir el código sin exponer nuestro token. Es oportuno mencionar que si usamos alguna herramienta de control de versiones como git, podemos hacer que el sistema ignore el archivo .env y lo mantenga solo de forma local.
Pasemos ahora con la línea:
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
Esta línea nos permite crear un cliente para la API de Discord. Este cliente es quien hará las peticiones a la API para escuchar lo que ocurre en nuestro servidor y hacer que nuestro bot responda según le indiquemos. En la siguiente sección ahondaremos un poco más en este elemento.
Finalmente con nuestro cliente creado, debemos indicarle que se conecte a Discord, para ello utilizamos la línea:
client.login(token);
Nota que enviamos nuestro token, para que se nos autorice el acceso. Si este token no es correcto, nuestro bot no podrá conectarse.

Tanto si anteriormente habías creado un Bot para discord o es tu primera vez notarás que la función constructora de nuestro cliente lleva un argumento peculiar, que además es obligatorio:
{ intents: [GatewayIntentBits.Guilds] }
Desde la versión 13 de Discord.js se requiere este elemento al momento de crear un cliente. Basicamente los Intents son grupos predefinido de eventos Websocket que recibirá nuestro cliente, es decir, mediante los Intents nuestro Bot podrá reconocer distintos tipos de eventos provenientes de la API de Discord. Ejemplos podrían ser:
- Un nuevo miembro en nuestro Servidor de Discord
- Un mensaje en el Servidor
- Cambio de rol de un miembro del servidor
- Reacciones a mensajes
- etc.

Aunque aún podemos hacer que nuestro Bot escuche cada una de las líneas que escriben los miembros de un servidor, esto se considera un privilegio especial y tendría el impacto en performance que mencionamos en el apartado anterior. Lo mismo ocurre con el contenido de los mensajes, no queremos que nuestro Bot analice la disertación de nuestros miembros mas prolíficos. Sin embargo aún necesitamos que nuestro Bot atienda a los comandos específicos para los que lo hayamos creado.
¿Cómo logramos entonces que nuestro Bot atienda los comandos?
Para dar solución a este nuevo modelo de gestión de eventos, Discord introdujo en Marzo del 2021, los Slash Commands. Básicamente los Slash Commands son conforman un nuevo tipo de Interacción que vuelve más transparente e integran mejor el manejo de comandos en los servidores de Discord. Basta introducir una diagnonal (Slash) y podremos ver todos los comandos que existen en un servidor.

Además de los comandos que integremos con nuestro Bot, podremos notar que Discord ha incluido varios comandos de forma estándar a todos los servidores. Notamos además que cada comando tiene una descripción de su utilidad y al elegir uno de ellos, en caso de requerir argumentos, nos especifica el nombre y a que hace referencia el argumento que debemos proporcionar.

Si anteriormente usaste comandos en Discord a la vieja usanza, notarás que es una mejora increíble, ya que antes batallabas con recordar cual era el prefijo ya que cada bot usaba las preferencias del desarrollador (comúnmente se usaba $ o #), después de finalmente recordar el prefijo, se te olvidaba el comando o cuales eran los argumentos que debían darse. Si el desarrollador no incluía mensajes de ayuda, podías pasarte un buen rato descifrando como usar un comando. Ahora siempre usaremos el slash (diagonal - / ) y tendremos la ayuda cada que escribamos el comando. Pero bueno ¡pasemos a la acción!

En primer lugar necesitaremos dos nuevos elementos de nuestro paquete de discord.js, por lo tanto los agregaremos a nuestra importación. La línea:
import { Client, GatewayIntentBits} from "discord.js";
Pasará a:
import { Client, GatewayIntentBits, Events, Routes, REST, SlashCommandBuilde } from "discord.js";
Events nos permitirá manejar los eventos que reciba nuestro Bot y que recordemos hemos suscrito a partir de los Intents que registremos al crear el cliente.
Un primer evento que podemos manejar es el echo de que nuestro Bot se encuentre listo una vez que lo echemos a andar. Para ello podemos utilizar el evento ClientReady. Entonces definiremos mediante nuestro cliente el manejador que se ejecutará una sola vez cuando esto ocurra:
client.once(Events.ClientReady, () => {
}
Como vemos utilizamos la función once de nuestro cliente para un evento del cual esperamos solo ocurra una vez. Como primer argumento debemos introducir el evento, que para nuestro caso es Events.ClienReady y como segundo argumento una función (callback) que indique que hará al ocurrir dicho evento. Podríamos simplemente mostrar en consola que nuestro Bot esta listo, así sabríamos cuando podemos comenzar a jugar con nuestros comandos. Para ello dentro de las llaves agregaríamos la línea:
console.log(`${client.user.tag} has logged in!`);
Nuestro código quedaría como sigue:

Ahora al ejecutar nuestro bot, en la terminal nos mostrará cuando se encuentre listo:

Por otro lado tanto REST como Routes nos ayudarán a hacer el registro de nuestro comandos en el servidor.
Primero debemos crear nuestra instancia del módulo REST, la cual usará nuestro token para validarse. Para ello después de crear nuestro cliente usamos:
const rest = new REST({ version: "10" }).setToken(token);
Seguido, creamos un arreglo para nuestros comandos:
const commands = []
Como primer comando de ejemplo agregaremos el siguiente comando:
commands.push(
{
name: 'saludar',
description: 'Te saluda'
}
)
Vemos que la estructura básica de un comando consta de dos elementos básicos, el nombre y la descripción. Nuestro código debería verse así:

client.on(Events.InteractionCreate, (interaction) => {}
La estructura es similar a la que tiene el método "once", recibe un evento, que para nuestro caso será la creación de una interacción y después definimos una función para manejar dicha interacción, podemos especificar mandar la interacción como argumento.
Dentro de las llaves en primera instancia debemos discriminar que la interacción que recibimos es un comando, de otro modo ignoraremos la interacción para ello dentro de las llaves indicamos:
if (!interaction.isChatInputCommand()) return;
A continuación debemos identificar el comando, esto ya que si tenemos múltiples comandos queremos discernir entre ellos. Para ello utilizaremos la propiedad interaction.commandName e indicaremos la acción que queremos realizar al recibir el comando, nótese validamos el comando "saludar".
if (interaction.commandName == "saludar") {
interaction.reply(`Hola ${interaction.member.user.username}`);
}
Nuestro código va así:

El Id de nuestro bot lo encontramos en la página de Discord Developers
Damos clic sobre nuestra aplicación, al desplegarse la información encontraremos el APPLICATION_ID.
El Id de nuestro servidor lo encontraremos en la App de Discord dando clic derecho sobre nuestro servidor, ahí nos permitirá copiar nuestro ID.


const CLIENT_ID = process.env.CLIENT_ID;
const GUILD_ID = process.env.GUILD_ID;
y terminaremos haciendo el registro de neustro comando con:
rest.put(Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID), {
body: commands, //Arreglo de comandos
});
Nuestro código final debe quedar de ésta forma:




Con esto terminamos el tutorial del día de hoy, en la próxima entrega reestructuraremos nuestros archivos para modularizar nuestros comandos en archivos independientes, además haremos nuestra primera interacción con la blockchain de Hive.
Comments (1)
Congratulations, your post has been upvoted by @dsc-r2cornell, which is the curating account for @R2cornell's Discord Community.
Thanks!