Categoría: Bots de Discord

Crear un bot de Discord#8Decora embeds (Embed) con imágenes y campos (ejemplo en Python)

Esta entrada es una traducción del original en coreano.

Índice9 secciones

¡Hola! Soy Mojangcam 😎

En el #7 usamos un modal (Modal) para pedirle texto al usuario. ¡En este #8 vamos a ver los embeds (Embed), que hacen que los mensajes que envía tu bot se vean mucho más bonitos!

Un embed es un mensaje en forma de tarjeta que muestra de forma ordenada un título, una descripción, campos, imágenes y un color. Para información del servidor, tarjetas de perfil, anuncios o rankings de usuarios, queda mucho mejor que un texto plano. ¡Hoy lo resumo con un ejemplo que puedes copiar y pegar tal cual, incluyendo cómo ordenar los campos (Field) y cómo poner miniaturas e imágenes grandes!

📌 Lo que necesitas

  • Python 3.8+
  • discord.py 2.x (usamos las funciones más recientes de slash commands y embeds)
  • Token del bot e invitación al servidor ya hechos (si los configuraste en los episodios anteriores, ¡todo OK!)
cmake
pip install -U discord.py

💡 Esta serie usa siempre discord.py 2.x. Si tu versión es más antigua, los slash commands no funcionarán, así que actualiza con -U.

📌 Paso 1 - Crear un embed básico

El embed se crea con discord.Embed() como base, y luego le vas añadiendo campos e imágenes.

Código
embed = discord.Embed(
    title="📊 Información del servidor",
    description="¡He reunido la información básica de este servidor en un embed!",
    color=discord.Color.blurple(),
)

Vamos a verlo parte por parte 💡

  • title : el título en negrita que aparece arriba del todo en el embed.
  • description : el texto de descripción debajo del título.
  • color : el color de la línea vertical a la izquierda del embed. Puedes usar un preset como discord.Color.blurple() (el morado de Discord) o elegirlo tú mismo con discord.Color.from_rgb(88, 101, 242).

📌 Paso 2 - Añadir campos (Field) y ordenarlos

Con add_field() añades elementos con la forma "nombre : valor". El valor de inline decide si se colocan en horizontal.

Código
embed.add_field(name="Miembros", value="120", inline=True)
embed.add_field(name="Canales", value="18", inline=True)
embed.add_field(name="Fecha de creación", value="2024-03-01", inline=False)
  • inline=True : se coloca en horizontal, al lado de los otros campos inline. (Hasta 3 por línea)
  • inline=False : ocupa una línea entera. Va muy bien para usarlo como separador.
  • Si name / value es una cadena vacía, da error, así que asegúrate de rellenarlos.

📌 Paso 3 - Poner una miniatura y una imagen grande

Hay dos tipos de imagen. Como van en lugares distintos, elige la que mejor encaje con lo que necesitas.

Código
embed.set_thumbnail(url="https://picsum.photos/200")   # Imagen pequeña arriba a la derecha
embed.set_image(url="https://picsum.photos/600/200")   # Imagen grande abajo (banner)
embed.set_footer(text="Bot de Discord de Mojangcam")      # Texto pequeño al final
  • set_thumbnail : miniatura pequeña arriba a la derecha (para iconos de perfil o del servidor).
  • set_image : imagen de banner grande en la parte inferior del embed.
  • set_footer : texto pequeño y gris al final del todo (para indicar la fuente o el nombre del bot).
  • ⚠️ Las URL de imagen se muestran de forma más fiable si terminan en una extensión como .png o .jpg. Las direcciones sin extensión pueden no verse.

📌 Código completo (puedes copiar y pegar)

Python
# discord.py 2.x / Python 3.8+
import discord
from discord import app_commands

intents = discord.Intents.default()
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)

@client.event
async def on_ready():
    await tree.sync()  # Registra los slash commands
    print(f"¡{client.user} está listo!")

@tree.command(name="서버정보", description="Muestra la información del servidor en un embed")
async def server_info(interaction: discord.Interaction):
    guild = interaction.guild

    embed = discord.Embed(
        title=f"📊 Información del servidor {guild.name}",
        description="¡He reunido la información básica de este servidor en un embed!",
        color=discord.Color.blurple(),
    )
    embed.add_field(name="Miembros", value=f"{guild.member_count} miembros", inline=True)
    embed.add_field(name="Canales", value=f"{len(guild.channels)} canales", inline=True)
    embed.add_field(
        name="Fecha de creación",
        value=guild.created_at.strftime("%Y-%m-%d"),
        inline=False,
    )

    if guild.icon:  # Si el servidor tiene icono, lo usamos como miniatura
        embed.set_thumbnail(url=guild.icon.url)
    embed.set_image(url="https://picsum.photos/600/200")
    embed.set_footer(
        text="Bot de Discord de Mojangcam",
        icon_url=client.user.display_avatar.url,
    )

    await interaction.response.send_message(embed=embed)

client.run("TU_TOKEN_DEL_BOT")
  • guild : el objeto del servidor donde se ejecutó el comando. De aquí sacas directamente el nombre, el número de miembros y la fecha de creación.
  • member_count : obtiene automáticamente el número de miembros del servidor.
  • display_avatar.url : la dirección de la imagen de perfil del bot. La usamos como icono del footer.

📌 Resultado

Enciende el bot y escribe /서버정보 (información del servidor) en tu servidor: ¡aparecerá una tarjeta bonita con título + miembros y canales lado a lado + fecha de creación en una línea + miniatura e imagen de banner!

📌 Errores frecuentes

  1. La imagen no se ve — Causa: la URL no tiene extensión o es una dirección privada (requiere iniciar sesión). Solución: usa una URL de imagen pública que termine en .png o .jpg.
  2. HTTPException: In embeds.0.fields.0.value: This field is required — Causa: value es una cadena vacía. Solución: pon al menos un carácter en el valor del campo.
  3. /서버정보 no aparece — Causa: falta tree.sync() o el cambio todavía no se ha aplicado. Solución: comprueba que haces sync en on_ready. La sincronización global puede tardar hasta 1 hora, así que para hacer pruebas es más rápido sincronizar por servidor (guild).
  4. Los miembros salen como None y los canales como 0 (¡aquí me quedé atascado de verdad!) — Síntoma: no aparece ni el nombre del servidor, los miembros salen None, los canales 0, y solo la fecha de creación es correcta. Causa: el bot no está realmente dentro de ese servidor. Si añades la app solo con "Instalación de usuario (User Install)", el slash command aparece, pero el bot no es miembro del servidor y no puede acceder a su información (fetch_guild devuelve 404 Unknown Guild, código de error 10004). Solución: en el portal de desarrolladores → OAuth2 → URL Generator, marca los scopes bot + applications.commands para generar un enlace de invitación e invita al bot al servidor con ese enlace. ¡Si ves al bot en la lista de miembros del servidor, lo lograste! Vuelve a ejecutar /서버정보 y los miembros y canales se mostrarán correctamente.

💬 Para terminar

¡Hoy decoramos los mensajes del bot como tarjetas usando embeds (Embed), con título, descripción, color, orden de campos, miniatura e imagen de banner! Ahora puedes enviar tarjetas de información bonitas en lugar de texto plano 🙌

En el próximo #9 vamos a combinar botones + embeds para crear una "paginación de embeds" que permite pasar de página. ¡No te lo pierdas!

📚 Serie Crear un bot de Discord

  • #5 Interacciones con botones (Button)
  • #6 Menús desplegables (Select Menu)
  • #7 Pedir texto con un modal (Modal)
  • #8 Decorar embeds (Embed) con imágenes y campos ← ¡estás leyendo este!
  • #9 Paginación de embeds (próximamente)

Serie · Parte 8 de 32

Crear un bot de Discord

  1. #1Crear un bot de Discord - ¡Domina por completo los Slash Commands!
  2. #2¡Añade opciones (argumentos) a tus Slash Commands!
  3. #3¡Añade subcomandos (Subcommand) a tus Slash Commands!
  4. #4¡Envía embeds con Slash Commands!
  5. #5¡Implementa interacciones con botones (Button)!
  6. #6¡Implementa menús desplegables (Select Menu)!
  7. #7Pide texto al usuario con un modal (Modal) (ejemplo en Python)
  8. #8Decora embeds (Embed) con imágenes y campos (ejemplo en Python)Estás aquí
  9. #9¡Integra la IA (API de Claude y ChatGPT)! (ejemplo en Python)
  10. #10¡Añade soporte multilingüe (i18n)! (ejemplo en Python)
  11. #11¡Crea un panel web con Flask! (ejemplo en Python)
  12. #12¡Gestiona los cooldowns y permisos de tus comandos! (ejemplo en Python)
  13. #13¡Administra tu servidor automatizando roles y canales! (ejemplo en Python)
  14. #14¡Guarda tus datos! JSON vs SQLite (ejemplo en Python)
  15. #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제) (en coreano)
  16. #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제) (en coreano)
  17. #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제) (en coreano)
  18. #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제) (en coreano)
  19. #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제) (en coreano)
  20. #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제) (en coreano)
  21. #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제) (en coreano)
  22. #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제) (en coreano)
  23. #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제) (en coreano)
  24. #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제) (en coreano)
  25. #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제) (en coreano)
  26. #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제) (en coreano)
  27. #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제) (en coreano)
  28. #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제) (en coreano)
  29. #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제) (en coreano)
  30. #30¡Crea un bot de encuestas y votaciones (Poll)! Encuestas nativas + botones con recuento en tiempo real (ejemplo en Python) 🗳️
  31. #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) 🕵️
  32. #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉 (en coreano)
Ver las 32Contraer

Autor

Mojangcam

Un registro práctico de desarrollo e IT: código que escribo, servidores que mantengo y los errores que resuelvo por el camino.