pythondiscord.py

discord.ui.View timeout


When pressing the button whose time has expired, the message "time has expired, repeat the command was written". How to implement it on discord.py?

I tried to read the documentation, nothing helped me, I know that some bots have such functionality

I tried it like this

import discord
from discord.ext import commands

class MyView(discord.ui.View):
    def __init__(self, timeout=10):
        super().__init__(timeout=timeout)
        self.timeout_reached = False

    async def on_timeout(self):
        self.timeout_reached = True

    async def on_error(self, error, item, interaction: discord.Interaction):
        if self.is_finished():
            await interaction.followup.send('Times up!', ephemeral=True)
        else:
            await interaction.followup.send('An error occurred!', ephemeral=True)

    @discord.ui.button(label='Random Button', style=discord.ButtonStyle.primary)
    async def random_button(self, interaction: discord.Interaction, button: discord.ui.Button):
        if self.is_finished():
            await interaction.response.send_message('Times up!', ephemeral=True)
        else:
            await interaction.response.send_message('The button has been pressed!', ephemeral=True)

class ExampleCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def random_button(self, ctx):
        view = MyView()
        await ctx.send('Press the button!', view=view)

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


Solution

  • Sadly the on_timeout method doesn't get any arguments. You can store your latest interaction in a instance variable, and then use it to send a message.

    class MyView(discord.ui.View):
        def __init__(self, timeout: int = 10) -> None:
            super().__init__(timeout=timeout)
            self.latest_interaction = None
    
        async def on_timeout(self) -> None:
            if self.latest_interaction is not None:
                await self.latest_interaction.followup.send("Retry")
    
        async def interaction_check(self, interaction: Interaction) -> bool:
            result = await super().interaction_check(interaction)
            # store the interaction in our instance variables
            self.latest_interaction = interaction
            if not result:
                await interaction.response.defer()
            return result   
    
        async def on_error(self, error, item, interaction: discord.Interaction) -> None:
            await interaction.followup.send('An error occurred!', ephemeral=True)
    
        @discord.ui.button(label='Random Button', style=discord.ButtonStyle.primary)
        async def random_button(self, interaction: discord.Interaction, button: discord.ui.Button) -> None:
            ...
    

    References: