Discord Bot con Claude Code
Aprende sobre Discord Bot usando Claude Code. Incluye consejos practicos y ejemplos de codigo.
Optimizando el desarrollo de Discord Bot con Claude Code
Los Discord Bots se utilizan ampliamente para la gestion de comunidades, administracion de servidores de juegos, distribucion de notificaciones y mas. Con la biblioteca discord.js puedes desarrollar comodamente en TypeScript, pero el procesamiento de interacciones y la gestion de permisos requieren mucha implementacion. Aprovecha Claude Code para construir eficientemente un Discord Bot con funcionalidades avanzadas.
Configuracion del proyecto
> Crea un proyecto de Discord Bot.
> Con discord.js v14, TypeScript y estructura de manejador de comandos.
npm init -y
npm install discord.js
npm install -D typescript @types/node tsx
// src/index.ts
import { Client, GatewayIntentBits, Collection, Events } from 'discord.js';
import { registerCommands } from './commands';
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
],
});
client.commands = new Collection();
client.once(Events.ClientReady, (c) => {
console.log(`Conectado como ${c.user.tag}`);
});
// Manejador de comandos
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
const reply = {
content: 'Ocurrio un error al ejecutar el comando.',
ephemeral: true,
};
if (interaction.replied || interaction.deferred) {
await interaction.followUp(reply);
} else {
await interaction.reply(reply);
}
}
});
registerCommands(client);
client.login(process.env.DISCORD_TOKEN);
Implementacion de comandos slash
> Implementa una funcion de votacion con el comando /poll.
> Que se pueda votar con botones.
// src/commands/poll.ts
import {
SlashCommandBuilder,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
EmbedBuilder,
ChatInputCommandInteraction,
ButtonInteraction,
} from 'discord.js';
const polls = new Map<string, { question: string; votes: Map<string, Set<string>> }>();
export const data = new SlashCommandBuilder()
.setName('poll')
.setDescription('Crear una votacion')
.addStringOption((opt) =>
opt.setName('question').setDescription('Pregunta').setRequired(true)
)
.addStringOption((opt) =>
opt.setName('option1').setDescription('Opcion 1').setRequired(true)
)
.addStringOption((opt) =>
opt.setName('option2').setDescription('Opcion 2').setRequired(true)
)
.addStringOption((opt) =>
opt.setName('option3').setDescription('Opcion 3').setRequired(false)
);
export async function execute(interaction: ChatInputCommandInteraction) {
const question = interaction.options.getString('question', true);
const options = [
interaction.options.getString('option1', true),
interaction.options.getString('option2', true),
interaction.options.getString('option3'),
].filter(Boolean) as string[];
const pollId = `poll-${Date.now()}`;
const votes = new Map<string, Set<string>>();
options.forEach((opt) => votes.set(opt, new Set()));
polls.set(pollId, { question, votes });
const embed = new EmbedBuilder()
.setTitle('📊 ' + question)
.setColor(0x6366f1)
.setDescription(
options.map((opt) => `**${opt}**: 0 votos`).join('\n')
)
.setFooter({ text: `Poll ID: ${pollId}` });
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
...options.map((opt, i) =>
new ButtonBuilder()
.setCustomId(`${pollId}:${opt}`)
.setLabel(opt)
.setStyle(ButtonStyle.Primary)
)
);
await interaction.reply({ embeds: [embed], components: [row] });
}
// Manejador de botones
export async function handlePollButton(interaction: ButtonInteraction) {
const [pollId, option] = interaction.customId.split(':');
const poll = polls.get(pollId);
if (!poll) return;
const userId = interaction.user.id;
// Eliminar voto existente
for (const voters of poll.votes.values()) {
voters.delete(userId);
}
// Agregar nuevo voto
poll.votes.get(option)?.add(userId);
const description = Array.from(poll.votes.entries())
.map(([opt, voters]) => {
const count = voters.size;
const bar = '█'.repeat(count) || '░';
return `**${opt}**: ${count} votos ${bar}`;
})
.join('\n');
const embed = new EmbedBuilder()
.setTitle('📊 ' + poll.question)
.setColor(0x6366f1)
.setDescription(description)
.setFooter({ text: `Poll ID: ${pollId}` });
await interaction.update({ embeds: [embed] });
}
Mensajes Embed
> Crea un comando que muestre la informacion del servidor.
> Mostrar en formato Embed enriquecido.
// src/commands/serverinfo.ts
import {
SlashCommandBuilder,
EmbedBuilder,
ChatInputCommandInteraction,
} from 'discord.js';
export const data = new SlashCommandBuilder()
.setName('serverinfo')
.setDescription('Muestra la informacion del servidor');
export async function execute(interaction: ChatInputCommandInteraction) {
const guild = interaction.guild;
if (!guild) return;
const embed = new EmbedBuilder()
.setTitle(guild.name)
.setThumbnail(guild.iconURL() || '')
.setColor(0x6366f1)
.addFields(
{ name: 'Miembros', value: `${guild.memberCount}`, inline: true },
{ name: 'Canales', value: `${guild.channels.cache.size}`, inline: true },
{ name: 'Roles', value: `${guild.roles.cache.size}`, inline: true },
{ name: 'Fecha de creacion', value: guild.createdAt.toLocaleDateString('es-ES'), inline: true },
{ name: 'Boost', value: `Nv.${guild.premiumTier} (${guild.premiumSubscriptionCount} veces)`, inline: true },
)
.setTimestamp();
await interaction.reply({ embeds: [embed] });
}
Registro de comandos
// src/commands/index.ts
import { REST, Routes, Client } from 'discord.js';
import * as poll from './poll';
import * as serverinfo from './serverinfo';
const commands = [poll, serverinfo];
export function registerCommands(client: Client) {
for (const command of commands) {
client.commands.set(command.data.name, command);
}
}
// Registrar comandos slash en Discord
export async function deployCommands() {
const rest = new REST().setToken(process.env.DISCORD_TOKEN!);
const body = commands.map((c) => c.data.toJSON());
await rest.put(
Routes.applicationCommands(process.env.DISCORD_CLIENT_ID!),
{ body }
);
console.log('Comandos desplegados');
}
Resumen
Combinando discord.js con Claude Code, puedes construir eficientemente Discord Bots interactivos. Consulta tambien la guia de desarrollo de chatbot y los fundamentos de desarrollo de API.
Para mas detalles sobre discord.js, consulta la guia oficial de discord.js.
PDF gratuito: Hoja de trucos de Claude Code en 5 minutos
Solo deja tu correo y te enviaremos al instante la hoja de trucos en una página A4.
Cuidamos tus datos personales y nunca enviamos spam.
Sobre el autor
Masa
Ingeniero apasionado por Claude Code. Dirige claudecode-lab.com, un medio tecnológico en 10 idiomas con más de 2.000 páginas.
Artículos relacionados
7 comprobaciones antes de publicar cada día un artículo multilingüe sobre Claude Code
Una lista práctica para publicar artículos multilingües sobre Claude Code todos los días sin olvidar idiomas, romper CTAs ni dejar páginas antiguas en producción.
Que es Codex Automations y como dejar que la IA gestione contenido mientras duermes
Guia practica para usar Codex Automations en analitica, articulos, CTA, despliegue y monetizacion.
Claude Code × GCP Cloud Functions Guía Completa | Desarrollo Serverless Ultrarrápido
Optimiza GCP Cloud Functions con Claude Code. Implementa triggers HTTP/Pub/Sub/Firestore, pruebas locales y automatización de despliegues con ejemplos de código reales de la experiencia de Masa.