[Python] trying to build a Discord starboard system using sqlalchemy

Discussão em 'Python' iniciado por Stack, Julho 29, 2025.

  1. Stack

    Stack Membro Participativo

    well don't be mad please but let me share my problem. i try to make a Discord bot using SQLalchemy for the database. in first, i'll start by noting than the db isn't the problem, as other functions connect perfectly to the db and interact with them. for context, i'll join two entities i use in my project :

    class Starboard(Base):
    __tablename__ = 'starboards'

    id = Column(Integer, primary_key=True, autoincrement=True)
    channel_id = Column(Integer, nullable=False, unique=True)
    emoji_name = Column(String, nullable=False, unique=True)
    emoji_count = Column(Integer, default=0)

    def __repr__(self):
    return f"<Starboard(id={self.id}, channel_id={self.channel_id}, emoji_name={self.emoji_name}, star_count={self.emoji_count})>"

    class StarboardContent(Base):
    __tablename__ = "starboard_content"

    id = Column(Integer, primary_key=True)
    starboard_id = Column(Integer, nullable=False)
    emoji_count = Column(Integer, default=0)

    def vote(self):
    self.emoji_count += 1
    return self.emoji_count

    def unvote(self):
    if self.emoji_count > 0:
    self.emoji_count -= 1
    return self.emoji_count

    def __repr__(self):
    return f"<StarboardImage(id={self.id}, starboard_id={self.starboard_id}, image_message_id={self.image_message_id})>"


    then, with these models, i got a function made to handle reactions, called by both listeners on_reaction_add() and on_reaction_remove(). the problem i got is than the function doesn't seems to be called, as when i use prints inside it, they don't display in the console. you'll can find the function here, but i apologize as it's a "big" function splitted in few ones :

    async def handle_starboard_reaction(reaction: discord.Reaction):
    with Session(engine) as session:
    res_starboard = await get_starboard_entry(session, reaction)
    if not res_starboard:
    print(f"No starboard found for emoji {reaction.emoji.name}, aborting.")
    return

    # Prevent duplicate entries for the same message and emoji
    if int(res_starboard.channel_id) == reaction.message.channel.id:
    print("Can't send a starboard message to the same channel.")
    return

    res_fav = await get_starboard_content_entry(
    session, res_starboard.id, reaction.message.id
    )
    if not res_fav:
    # Create a new entry
    res_fav = StarboardContent(
    message_id=reaction.message.id,
    starboard_id=res_starboard.id,
    emoji_count=reaction.count,
    )
    session.add(res_fav)
    # Create and send embed
    fav_emb = await create_fav_embed(reaction)
    starboard_channel = await reaction.message.guild.fetch_channel(
    res_starboard.channel_id
    )
    if starboard_channel and isinstance(
    starboard_channel, discord.TextChannel
    ):
    starboard_msg = await starboard_channel.send(embed=fav_emb)
    res_fav.starboard_message_id = (
    starboard_msg.id
    )
    session.commit()
    print(f"New starboard entry created: {res_fav}")
    else:
    # update existing entry
    old_count = res_fav.emoji_count
    res_fav.emoji_count = reaction.count
    # update the starboard message if it exists
    if res_fav.starboard_message_id:
    try:
    starboard_channel = await reaction.message.guild.fetch_channel(
    res_starboard.channel_id
    )
    if starboard_channel and isinstance(
    starboard_channel, discord.TextChannel
    ):
    starboard_msg = await starboard_channel.fetch_message(
    res_fav.starboard_message_id
    )
    updated_embed = await create_fav_embed(reaction)
    await starboard_msg.edit(embed=updated_embed)
    except discord.NotFound:
    print(
    f"Starboard message {res_fav.starboard_message_id} not found, it may have been deleted"
    )
    res_fav.starboard_message_id = None
    session.commit()
    print(f"Starboard entry updated: {old_count} -> {res_fav.emoji_count}")

    async def get_starboard_entry(session: Session, reaction: discord.Reaction):
    stmt = select(Starboard).where(Starboard.emoji_name.like(reaction.emoji.name))
    return session.execute(stmt).scalars().first()

    async def get_starboard_content_entry(
    session: Session, starboard_id: int, message_id: int
    ):
    stmt = select(StarboardContent).where(
    StarboardContent.starboard_id == starboard_id,
    StarboardContent.message_id == message_id,
    )
    return session.execute(stmt).scalars().first()

    async def create_fav_embed(reaction: discord.Reaction) -> discord.Embed:
    fav_emb = discord.Embed(
    title=f"New fav : {reaction.count} {reaction.emoji}",
    description=f"{reaction.message.author.mention} - {reaction.message.channel.mention}",
    color=discord.Color.gold(),
    )
    fav_emb.set_thumbnail(url=reaction.message.author.display_avatar.url)
    fav_emb.add_field(
    name="Message", value=reaction.message.content or "No content"
    )

    fav_emb.add_field(
    name="Lien",
    value=f"[Aller au message]({reaction.message.jump_url})",
    inline=False,
    )
    if reaction.message.attachments:
    fav_emb.set_image(url=reaction.message.attachments[0].url)
    if len(reaction.message.attachments) > 1:
    fav_emb.add_field(
    name="Autres images",
    value="voir le message original pour plus d'images.",
    )
    return fav_emb


    here it is. don't hesitate to ask if you don't understand something or need further informations, i'll do my best to give you the infos you need.


    sysinfo:

    OS: Win11

    Python : 3.11.9

    # requirements.txt
    discord.py==2.5.2
    python-dotenv==1.1.1
    SQLAlchemy==2.0.41

    Continue reading...

Compartilhe esta Página