Creating a Discord Bot for Poster Generation using BeatPrints

A step-by-step guide on creating a Discord bot that generates song posters using the BeatPrints library in Python.

May 29, 2025
tag

discord

python

beatprints

Make sure the python script is running and the bot is up before trying out the commands

Installing the dependencies

For creating the discord bot and for its functionalities, we are going to use the following libraries :

pip install discord.py BeatPrints python-dotenv

Creating a bot in Discord Developers Portal

Inviting the bot to a server

Creating a basic program

import discord
from discord.ext import commands
from dotenv import load_dotenv
import os

load_dotenv()
TOKEN = os.getenv("DISCORD_TOKEN")

intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)

@bot.event
async def on_ready():
    print(f"Logged in as {bot.user} (ID: {bot.user.id})")

@bot.command()
async def ping(ctx):
    await ctx.send("pong")

bot.run(TOKEN)
DISCORD_TOKEN=163jhdgl830XXXXXXXXXX

Using the bot for poster generation

example poster

Code

├─cogs
│ ├── devinfo.py
│ ├── help.py
│ ├── moderation.py
│ └── poster.py
├── flake.lock
├── flake.nix
├── main.py
└── requirements.txt

main.py

import os
import discord
from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()

TOKEN = os.getenv("DISCORD_TOKEN")

intents = discord.Intents.default()
intents.messages = True
intents.message_content = True

bot = commands.Bot(command_prefix="!", intents=intents, help_command=None)

@bot.event
async def on_ready():
    print(f"Logged in as {bot.user}")

# Load cogs
async def load_cogs():
	# Make sure the filename matches the cogs.<extension>
    await bot.load_extension("cogs.poster")

async def main():
    async with bot:
        await load_cogs()
        await bot.start(TOKEN)


@bot.command(name="ping")
async def ping(ctx):
    await ctx.send("Pong!")


import asyncio

asyncio.run(main())

poster.py

import glob
import os
import shlex

import discord
from BeatPrints import lyrics, poster, spotify
from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()

CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID")
CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET")


class BeatPrints(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.ly = lyrics.Lyrics()
        self.ps = poster.Poster("./")
        self.sp = spotify.Spotify(CLIENT_ID, CLIENT_SECRET)

    @commands.command(name="poster")
    async def generate_poster(self, ctx, *, args: str):
        # Send initial loading message
        loading_message = await ctx.send("🎨 Generating poster... Please wait.")

        try:
            # Parse arguments with shlex to support quoted song names
            tokens = shlex.split(args)
            line_range = "1-4"
            track_name_parts = []

            for token in tokens:
                if token.startswith("--lines="):
                    line_range = token.split("=", 1)[1]
                else:
                    track_name_parts.append(token)

            track_name = " ".join(track_name_parts)
            if not track_name:
                await loading_message.edit(content="❌ You must provide a song name.")
                return

            search = self.sp.get_track(track_name, limit=1)
            if not search:
                await loading_message.edit(content="❌ Couldn't find that track.")
                return

            metadata = search[0]
            lyrics_data = self.ly.get_lyrics(metadata)

            try:
                highlighted = (
                    lyrics_data
                    if self.ly.check_instrumental(metadata)
                    else self.ly.select_lines(lyrics_data, line_range)
                )
            except Exception:
                highlighted = (
                    lyrics_data
                    if self.ly.check_instrumental(metadata)
                    else self.ly.select_lines(lyrics_data, "1-5")
                )

            # Generate the track poster and save it in the current directory
            self.ps.track(metadata, highlighted, False, "Light")

            # Find the generated PNG file in the current directory
            png_files = glob.glob(os.path.join(os.getcwd(), "*.png"))

            if not png_files:
                await loading_message.edit(
                    content="❌ Failed to generate poster or no PNG file found."
                )
                return

            # Send the first .png file found
            file_to_send = png_files[0]
            await ctx.send(file=discord.File(file_to_send))

            # Remove all .png files from the current directory
            for file in png_files:
                os.remove(file)
                print(f"Deleted {file}")

            await loading_message.edit(content="✅ Poster generated")

        except Exception as e:
            print("Error generating poster:", e)
            await loading_message.edit(
                content="⚠️ Something went wrong generating the poster."
            )


async def setup(bot):
    await bot.add_cog(BeatPrints(bot))

Poster Generation

generated poster

Hosting

All Services Nominal

github linkedin mail instagram