¿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.

{ 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.




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:


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.
Esto debemos agregarlo a nuestro archivo .env, con el nombre que queramos asignarle.
Tu archivo .env debe tener una estructura similar a esta:
Ahora en nuestro archivo index.js rescataremos la variables de ambiente:
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. ¡Saludos!