Categoría: Bots de Discord
Crear un bot de Discord#5¡Implementa interacciones con botones (Button)!
Esta entrada es una traducción del original en coreano.
Índice8 secciones
¡Hola! Soy Mojangcam 😎
En el episodio #4 enviamos embeds con Slash Commands, ¿verdad? Esta vez vamos un paso más allá y añadiremos botones (Button) en los que se puede hacer clic a los mensajes. ¡Vamos a crear un bot que reacciona cuando pulsas un botón, un auténtico "bot interactivo"!
Cuando lo termines, podrás hacer cosas como estas:
- Dar opciones al usuario con los botones ✅ Confirmar / ❌ Cancelar
- 🎫 Funciones de un solo clic, como crear tickets o asignar roles
- Enviar respuestas que solo ve la persona que pulsó el botón
📌 Lo que necesitas
- Python 3.8 o superior
- discord.py 2.x (¡los botones están disponibles desde la 2.0!)
- Token del bot + el bot ya invitado a tu servidor (¡mira el episodio 1!)
pip install -U discord.pySi tu versión es antigua, actualízala sí o sí. Puedes comprobar la versión con pip show discord.py.
📌 Paso 1 - La clave de los botones: entender View
En discord.py, los botones no se pueden usar solos: se meten en un contenedor llamado View y se envían junto con el mensaje.
discord.ui.View→ la caja que contiene botones, menús desplegables, etc. 📦- El decorador
discord.ui.button→ crea un botón dentro de la View y lo conecta con la función que se ejecuta al pulsarlo
¡Veamos primero la estructura!
import discord
class MyView(discord.ui.View):
@discord.ui.button(label="¡Púlsame!", style=discord.ButtonStyle.primary)
async def my_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_message("¡Se pulsó el botón!")⚠️ El orden de los parámetros de la función callback es (self, interaction, button). Es fácil confundirse porque en los ejemplos de otras librerías (pycord, etc.) el orden es el contrario, ¡así que ten cuidado!
📌 Paso 2 - Los estilos de botón
Hay 5 colores de botón que puedes poner en style=.
| Estilo | Color | Ejemplo de uso |
|---|---|---|
ButtonStyle.primary |
Azul | Acción principal |
ButtonStyle.secondary |
Gris | Acción secundaria |
ButtonStyle.success |
Verde | Confirmar/aceptar |
ButtonStyle.danger |
Rojo | Eliminar/rechazar |
ButtonStyle.link |
Enlace | Abrir una URL (requiere url=, sin callback) |
📌 Paso 3 - Crear botones de Confirmar/Cancelar
Vamos a crear el patrón Confirmar/Cancelar, el que más se usa en la práctica.
class ConfirmView(discord.ui.View):
def __init__(self):
super().__init__(timeout=60) # Desactiva los botones tras 60 segundos
@discord.ui.button(label="Confirmar", style=discord.ButtonStyle.success)
async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="✅ ¡Confirmado!", view=None)
@discord.ui.button(label="Cancelar", style=discord.ButtonStyle.danger)
async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="❌ Cancelado.", view=None)Puntos clave 💡
timeout=60: pasados 60 segundos, los botones dejan de funcionar (el valor por defecto es 180 segundos)edit_message(..., view=None): al pulsar un botón, se edita el mensaje original y se quitan los botonesinteraction.responsesolo puede responder una vez y dentro de 3 segundos. Si quieres enviar algo más, ¡usainteraction.followup.send()!
📌 Paso 4 - Código completo (puedes copiar y pegar)
Esta es la versión final, combinada con un Slash Command.
import discord
from discord.ext import commands
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="/", intents=intents)
class ConfirmView(discord.ui.View):
def __init__(self):
super().__init__(timeout=60)
@discord.ui.button(label="Confirmar", style=discord.ButtonStyle.success)
async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="✅ ¡Confirmado!", view=None)
@discord.ui.button(label="Cancelar", style=discord.ButtonStyle.danger)
async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="❌ Cancelado.", view=None)
@bot.event
async def on_ready():
await bot.tree.sync()
print(f"¡El bot {bot.user} está listo!")
@bot.tree.command(name="확인", description="Envía los botones Confirmar/Cancelar")
async def confirm_command(interaction: discord.Interaction):
await interaction.response.send_message("¿Continuamos?", view=ConfirmView())
bot.run("Token")📌 Comprobar el resultado
Ejecuta el bot y escribe /확인 (confirmar) en un canal de Discord: ¡aparecerá el mensaje "¿Continuamos?" con un botón verde de Confirmar y uno rojo de Cancelar! Al pulsar un botón, el mensaje cambia a "✅ ¡Confirmado!" y los botones desaparecen.
📌 Errores frecuentes
1. Pulso el botón y aparece "La interacción ha fallado"
Ocurre cuando el callback no responde en 3 segundos. Si el proceso tarda, llama primero a await interaction.response.defer().
2. TypeError: ... missing 1 required positional argument
¡Es un problema del orden de los parámetros del callback! En discord.py 2.x el orden es (self, interaction, button). Si escribes (self, button, interaction), aparece este error.
3. Al reiniciar el bot, los botones de los mensajes anteriores ya no funcionan
Por defecto, una View solo existe en memoria. Para que siga funcionando después de reiniciar, tienes que crear una persistent view con timeout=None + custom_id y registrarla con bot.add_view(). (¡Esto lo veremos más adelante en un episodio avanzado!)
📌 Para terminar
Hoy implementamos interacciones de clic con las View y los botones de discord.py.
- Los botones se envían dentro de una View
- 5 estilos (primary/secondary/success/danger/link)
- ¡Responde en 3 segundos y solo una vez!
En el próximo episodio vamos a crear un menú desplegable (Select Menu). ¡No te lo pierdas! 🙌
📚 Serie Crear un bot de Discord
- Domina por completo los Slash Commands
- Añade opciones (argumentos) a tus Slash Commands
- Añade subcomandos a tus Slash Commands
- Envía embeds con Slash Commands
- Implementa interacciones con botones (Button) ← ¡estás leyendo este!
Serie · Parte 5 de 32
Crear un bot de Discord
- #1Crear un bot de Discord - ¡Domina por completo los Slash Commands!
- #2¡Añade opciones (argumentos) a tus Slash Commands!
- #3¡Añade subcomandos (Subcommand) a tus Slash Commands!
- #4¡Envía embeds con Slash Commands!
- #5¡Implementa interacciones con botones (Button)!Estás aquí
- #6¡Implementa menús desplegables (Select Menu)!
- #7Pide texto al usuario con un modal (Modal) (ejemplo en Python)
- #8Decora embeds (Embed) con imágenes y campos (ejemplo en Python)
- #9¡Integra la IA (API de Claude y ChatGPT)! (ejemplo en Python)
- #10¡Añade soporte multilingüe (i18n)! (ejemplo en Python)
- #11¡Crea un panel web con Flask! (ejemplo en Python)
- #12¡Gestiona los cooldowns y permisos de tus comandos! (ejemplo en Python)
- #13¡Administra tu servidor automatizando roles y canales! (ejemplo en Python)
- #14¡Guarda tus datos! JSON vs SQLite (ejemplo en Python)
- #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제) (en coreano)
- #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제) (en coreano)
- #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제) (en coreano)
- #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제) (en coreano)
- #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제) (en coreano)
- #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제) (en coreano)
- #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제) (en coreano)
- #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제) (en coreano)
- #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제) (en coreano)
- #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제) (en coreano)
- #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제) (en coreano)
- #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제) (en coreano)
- #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제) (en coreano)
- #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제) (en coreano)
- #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제) (en coreano)
- #30¡Crea un bot de encuestas y votaciones (Poll)! Encuestas nativas + botones con recuento en tiempo real (ejemplo en Python) 🗳️
- #32¡Crea un canal de registros y auditoría (Audit Log) del servidor! Registra automáticamente mensajes borrados y editados, entradas, salidas y expulsiones (ejemplo en Python) 🕵️
- #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉 (en coreano)
