Slash CommandsInteraccionesdiscord.js6 min de lectura

Configurar Slash Commands

Registrar slash commands globales y por servidor, manejar interacciones, opciones y autocompletado.


¿Qué son los Slash Commands?

Los slash commands son la forma moderna de interactuar con bots en Discord. Aparecen cuando el usuario escribe / y ofrecen autocompletado, validación de tipos y mejor UX.

Paso 1: Registrar comandos

Creá un archivo deploy-commands.js:

javascript
const { REST, Routes, SlashCommandBuilder } = require('discord.js');
require('dotenv').config();

const commands = [
  new SlashCommandBuilder()
    .setName('ping')
    .setDescription('Responde con pong y la latencia'),
  new SlashCommandBuilder()
    .setName('info')
    .setDescription('Muestra info de un usuario')
    .addUserOption(option =>
      option.setName('usuario')
        .setDescription('El usuario a consultar')
        .setRequired(true)
    ),
  new SlashCommandBuilder()
    .setName('config')
    .setDescription('Configuración del servidor')
    .addSubcommand(sub =>
      sub.setName('prefix')
        .setDescription('Cambiar el prefijo')
        .addStringOption(opt =>
          opt.setName('nuevo').setDescription('Nuevo prefijo').setRequired(true)
        )
    )
];

const rest = new REST().setToken(process.env.DISCORD_TOKEN);

(async () => {
  // Registro global (tarda ~1 hora en propagarse)
  await rest.put(
    Routes.applicationCommands(process.env.CLIENT_ID),
    { body: commands.map(c => c.toJSON()) }
  );
  console.log('Comandos registrados globalmente');

  // Registro por guild (instantáneo, ideal para desarrollo)
  await rest.put(
    Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID),
    { body: commands.map(c => c.toJSON()) }
  );
  console.log('Comandos registrados en guild de desarrollo');
})();

Paso 2: Manejar interacciones

javascript
client.on('interactionCreate', async interaction => {
  if (!interaction.isChatInputCommand()) return;

  const { commandName } = interaction;

  if (commandName === 'ping') {
    const latency = Date.now() - interaction.createdTimestamp;
    await interaction.reply(`Pong! Latencia: ${latency}ms`);
  }

  if (commandName === 'info') {
    const user = interaction.options.getUser('usuario');
    await interaction.reply(`Usuario: ${user.tag}\nID: ${user.id}`);
  }
});

Paso 3: Opciones avanzadas

Tipos de opciones disponibles:

javascript
// String con choices predefinidos
.addStringOption(opt =>
  opt.setName('color')
    .setDescription('Elegí un color')
    .addChoices(
      { name: 'Rojo', value: 'red' },
      { name: 'Azul', value: 'blue' }
    )
)

// Integer con rango
.addIntegerOption(opt =>
  opt.setName('cantidad')
    .setDescription('Cantidad')
    .setMinValue(1)
    .setMaxValue(100)
)

Paso 4: Autocompletado

javascript
// En el builder
.addStringOption(opt =>
  opt.setName('juego')
    .setDescription('Nombre del juego')
    .setAutocomplete(true)
)

// En el handler
client.on('interactionCreate', async interaction => {
  if (interaction.isAutocomplete()) {
    const focused = interaction.options.getFocused();
    const choices = ['Minecraft', 'FiveM', 'CS2', 'Valorant'];
    const filtered = choices.filter(c =>
      c.toLowerCase().startsWith(focused.toLowerCase())
    );
    await interaction.respond(
      filtered.map(c => ({ name: c, value: c }))
    );
  }
});

Recomendaciones

  • Usá registro por guild durante desarrollo (es instantáneo)
  • Registrá globalmente solo cuando el comando esté listo para producción
  • Implementá manejo de errores en cada comando
  • Usá interaction.deferReply() si el comando tarda más de 3 segundos

¿Te resultó útil esta guía?