El desarrollo de este repositorio se encuenta en desarrollo al dia de la fecha: 15/03/2024
Haz click para ver.
Descargo de Responsabilidad:
Este bot de Discord, utilizando la biblioteca Necord, tiene fines recreativos y de entretenimiento. La información proporcionada por el bot puede no ser completamente precisa o actualizada. No me hago responsable de las decisiones tomadas basándose en la información proporcionada por el bot.
El uso del bot está sujeto a cambios sin previo aviso. No garantizamos la disponibilidad continua, la funcionalidad o la precisión de los comandos proporcionados.
Este bot puede contener enlaces a sitios web de terceros. No respaldamos ni asumimos responsabilidad por el contenido de esos sitios.
Los usuarios son responsables de cumplir con los términos de servicio de Discord y cualquier otra regulación aplicable al utilizar este bot.
Al utilizar este bot, aceptas este descargo de responsabilidad y los términos de uso asociados.
Este es un proyecto basado en Necord realizado sobre Nest a modo de prueba y tutorial (pero en español).
Cabe aclarar que es necesario tener instalado Node.js
Instalar Necord, y su dependencia Discord.js
$ yarn add necord discord.js
$ yarn global add @nestjs/cli
#Comandos propios de Necord
$ yarn add --dev @necord/schematics
Primero y principal necesitamos configurar nuestro bot con el token que nos provee Discord.
- New Aplication.
- Ingresamos el nombre de como lo llamaremos al bot y aceptamos términos.
- Nos vamos a la pestaña Bot y presionamos en Reset token para obtener nuestro token.
- Lo copiamos y anotamos para el siguiente paso.
- Vamos a la pestaña OAuth.
- En Default Authorization Link elegimos In-app Authorization.
- Nos aparecen los SCOPES, seleccionamos bot y applications.commands.
- Luego, en BOT PERMISSIONS elegimos los permisos que veas más adecuados al desarrollo.
- Una ves seleccionados, en la parte inferior de la página se generará un enlace, el cual es al que debes ir para agregar el bot a tu servidor.
Construyo las variables de entorno en el archivo .env
para la configuracion de token y futuras propiedades:
Renombrar
.env-template
a.env
Éstas dependencias nos permitirán hacer uso de las variables de entorno:
$ yarn add @nestjs/config dotenv
e importamos ConfigModule.forRoot()
en el modulo app.module.ts
.
Código: app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from "@nestjs/config";
@Module({
imports: [
ConfigModule.forRoot(),
],
controllers: [],
providers: [],
})
export class AppModule {}
Luego, importamos NecordModule.forRoot()
y configuramos nuestra variable de entorno con el mismo nombre que se encontraba en .env
de la siguiente manera:
NecordModule.forRoot({
token: process.env.ENV_TOKEN_NAME,
})
Código: app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from "@nestjs/config";
import { NecordModule } from "necord";
@Module({
imports: [
ConfigModule.forRoot(),
NecordModule.forRoot({
token: process.env.DISCORD_TOKEN,
//y agregamos y guild para empezar a detectar el token y levantar bot
intents: [IntentsBitField.Flags.Guilds],
}),
],
controllers: [],
providers: [],
})
export class AppModule {}
Una vez realizado todo lo anterior, ya podemos poner en marcha para probar por primera vez nuestro bot funcionando:
$ yarn start:dev
Para los casos en que el bot no responda o funcione incorrectamente mientras hacemos pruebas, pero nuestro código está corriendo sin errores:
Para poder realizar los comandos de barra diagonal ( / ) o slash command, primero generamos un nuevo recurso:
$ nest g res slash-commands
Solo nos quedaremos con el module y services. (Lo demas se puede eliminar por el momento).
Con el decorador @SlashCommand()
podemos empezar a generar el primer comando de barra diagonal o 'Slash command'.
Para generarlo, deberemos ingresar algunas propiedades, principalmente name
que hacer referencia al comando /name
, y description
para mostrar una descripción del comando:
@SlashCommand({
name: 'ping',
description: 'Ping-Pong Command',
})
Luego, usamos el decorador @Context
para enviar argumentos, en este caso [interaction]
y del tipo SlashCommandContext
@SlashCommand({
name: 'ping',
description: 'Ping-Pong Command',
})
public async onPing(@Context() [interaction]: SlashCommandContext){
....
}
Y para devolver la respuesta por mensaje, retornamos la respuesta de [interaction]
mediante .reply
añadiendo la propiedad content
y el valor a retornar.
return interaction.reply({ content: 'Pong!' });
Código: slash-commands.service.ts
import { Injectable } from '@nestjs/common';
import { Context,
SlashCommand,
SlashCommandContext
} from 'necord';
@Injectable()
export class SlashCommandsService {
@SlashCommand({
name: 'ping',
description: 'Ping-Pong Command',
})
public async onPing(@Context() [interaction]: SlashCommandContext) {
return interaction.reply({ content: 'Pong!' });
}
}
Para generar menues contextuales, tanto en usuarios ccomo mensajes, usaremos el decorador @UserCommand()
. Agregandole la propiedad name:
nombraremos nuestra opcion del menu.
@UserCommand({ name: 'Obtener avatar' })
public async getUserAvatar(
@Context() [interaction]: UserCommandContext,
...
) {
return interaction.reply({
....
});
}
Para esto podriamos hacer, por ejemplo un embed que nos muestre el nombre del usuario y la imagen de perfil.
- Primero agregaremos
@TargetUser() user: User
para obtener el usuario. - Retornaremos, en este caso, un embed, conformado solo por el el nombre del usuario y la imagen de perfil.
@UserCommand({ name: 'Obtener avatar' })
public async getUserAvatar(
@Context() [interaction]: UserCommandContext,
@TargetUser() user: User
) {
return interaction.reply({
embeds: [
new EmbedBuilder().setTitle(`Avatar de ${user.username}`).setImage(user.displayAvatarURL({size:4096}))
]
});
}
Puede ver más en EmbedBuilder
El resultado de este código sera de la siguiente manera:
Para la creacion de Botones utilizamos ButtonBuilder()
new ButtonBuilder()
.setCustomId('primary')
.setLabel('Primary')
.setStyle(ButtonStyle.Primary);
Ver mas en: ButtonBuilder()
Luego con ActionRowBuilder()
agregamos cada boton generado a una fila de botones:
const rowbuttons = new ActionRowBuilder()
.addComponents(primary, secondary, success, danger, link);
Y luego generamos la respuesta a mostrar, colocanto el contenido y la fila de botones:
await interaction.reply({
content: 'Selecciona un botón',
components: [rowbuttons],
});
Generamos un nuevo slash command /botones
y se veria de la siguiente manera: \
(Imagen ejemplo del código funcional)
Para la creacion de de la lista de opciones utilizamos StringSelectMenuBuilder()
new StringSelectMenuBuilder()
.setCustomId('pokemons')
.setPlaceholder('Pokemones!')
.addOptions(
new StringSelectMenuOptionBuilder()
.setLabel('Bulbasaur')
.setDescription('The dual-type Grass/Poison Seed Pokémon.')
.setValue('bulbasaur')
.setEmoji('💚'),
new StringSelectMenuOptionBuilder()
.setLabel('Charmander')
.setDescription('The Fire-type Lizard Pokémon.')
.setValue('charmander')
.setEmoji('🧡'),
new StringSelectMenuOptionBuilder()
.setLabel('Squirtle')
.setDescription('The Water-type Tiny Turtle Pokémon.')
.setValue('squirtle')
.setEmoji('💙'),
);
Generamos un nuevo slash command /string-select
y se veria de la siguiente manera:
(Imagenes ejemplo del código funcional)
Vale aclarar que tambien existen otros componentes similares:
User Select
new UserSelectMenuBuilder()
.setCustomId('USER_SELECT_MENU')
.setPlaceholder('Select a user')
.setMaxValues(1)
.setMinValues(1)
Role Select
new RoleSelectMenuBuilder()
.setCustomId('ROLE_SELECT_MENU')
.setPlaceholder('Select a role')
.setMaxValues(1)
.setMinValues(1)
Channel Select
new ChannelSelectMenuBuilder()
.setCustomId('CHANNEL_SELECT_MENU')
.setPlaceholder('Select a channel')
.setMaxValues(1)
.setMinValues(1)
Mentionable Select
new MentionableSelectMenuBuilder()
.setCustomId('MENTIONABLE_SELECT_MENU')
.setPlaceholder('Select a user/role')
.setMaxValues(1)
.setMinValues(1)
Pero al final, la implementación termina siendo igual a la de Buttons.