pythondiscorddiscord.py

discord.py Giveaway Bot Issue


Everything currently in the code is fine, but on the "You've already entered this giveaway!" message there is a "Leave Giveaway" button that lets you leave the giveaway if you already entered it. But the problem is when I press the "Leave Giveaway" button It does not update the 🎉 button label correctly, I've tried many thing. Does anybody know a fix?

class GiveawayView(discord.ui.View):
    def __init__(self, required_messages=None, required_role=None, host=None):
        super().__init__(timeout=None)
        self.participants = {}
        self.required_messages = required_messages
        self.required_role = required_role
        self.host = host

    @discord.ui.button(label="0", emoji="🎉", style=discord.ButtonStyle.blurple, custom_id="enter_giveaway")
    async def enter_giveaway(self, interaction: discord.Interaction, button: discord.ui.Button):
        user = interaction.user

        if user.id in self.participants:
            leave_button = discord.ui.Button(label="Leave Giveaway", style=discord.ButtonStyle.red, custom_id="leave_giveaway")
            leave_button.callback = self.leave_giveaway
            await interaction.response.send_message(
                "You've already entered this giveaway!",
                view=discord.ui.View().add_item(leave_button),
                ephemeral=True
            )
            return

        if self.required_role and self.required_role not in user.roles:
            await interaction.response.send_message(f"You must have the {self.required_role.mention} role to enter!", ephemeral=True)
            return

        if self.required_messages:
            user_message_count = await self.count_user_messages_today(interaction.channel, user)
            if user_message_count < self.required_messages:
                await interaction.response.send_message(f"You must have sent at least {self.required_messages} messages today to enter!", ephemeral=True)
                return

        self.participants[user.id] = user
        button.label = str(len(self.participants))
        await interaction.response.edit_message(view=self)
        await interaction.followup.send("🎉 Giveaway successfully entered!", ephemeral=True)

    @discord.ui.button(label="Participants", emoji="👥", style=discord.ButtonStyle.gray, custom_id="view_participants")
    async def view_participants(self, interaction: discord.Interaction, button: discord.ui.Button):
        if not self.participants:
            await interaction.response.send_message("No participants have entered yet!", ephemeral=True)
            return

        participants_list = list(self.participants.values())
        participant_mentions = "\n".join([f"{participant.mention} (ID: {participant.id})" for participant in participants_list])

        embed = discord.Embed(title="Giveaway Participants", description=participant_mentions or "No participants yet")
        await interaction.response.send_message(embed=embed, ephemeral=True)

    async def leave_giveaway(self, interaction: discord.Interaction):
        user = interaction.user

        if user.id not in self.participants:
            await interaction.response.send_message("You are not in this giveaway.", ephemeral=True)
            return

        del self.participants[user.id]
        self.children[0].label = str(len(self.participants))

        leave_button = discord.ui.Button(label="Leave Giveaway", style=discord.ButtonStyle.red, disabled=True)
        leave_view = discord.ui.View(timeout=0)
        leave_view.add_item(leave_button)

        await interaction.response.edit_message(view=leave_view)
        await interaction.followup.send("🎉 You have left the giveaway!", ephemeral=True)

    async def count_user_messages_today(self, channel: discord.TextChannel, user: discord.Member):
        count = 0
        today = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        async for message in channel.history(limit=None, after=today):
            if message.author == user:
                count += 1
        return count

I expected it to just remove me from the label but nothing happened when I press the button. I am also not getting any error.


Solution

  • In this line of code you are changing the button's label

    self.children[0].label = str(len(self.participants))
    

    However, you need to bear in mind that this operation only affects the instance of GiveawayView stored in your bot's memory. For this change to take effect in the Discord message, you need to synchronise the view, which you can do by editing the Discord message.

    self.children[0].label = str(len(self.participants))
    
    leave_button = discord.ui.Button(label="Leave Giveaway", style=discord.ButtonStyle.red, disabled=True)
    leave_view = discord.ui.View(timeout=0)
    leave_view.add_item(leave_button)
    
    await interaction.response.edit_message(view=leave_view)
    await interaction.followup.send("🎉 You have left the giveaway!", ephemeral=True)
        
    # updating view in discord side
    await interaction.edit_original_response(view=self)