i have a view class for confirmation which i am using in multiple commands but is behaving weirdly like sometimes when i use command buttons on response message are already disaled and sometimes when i do click/use button, even after that it calls on_timeout and edit my message to timed out.
heres my view class:
confirm = Button(label="Confirm", emoji=tick, style=discord.ButtonStyle.green, custom_id="confirm")
class ConfirmView(View):
def __init__(self, ctx, timeout):
self.ctx = ctx
super().__init__(timeout=timeout)
async def on_timeout(self) -> None:
for i in self.children:
i.disabled = True
await self.message.edit(content="Timeout You took too long to respond!", view=None)
async def interaction_check(self, interaction) -> bool:
if interaction.user.id == self.ctx.author.id:
return True
await interaction.response.send_message("You cannot interact with this view.", ephemeral=True)
return False
class Cancel(Button):
def __init__(self):
super().__init__(label="Cancel", emoji=cross, style=discord.ButtonStyle.red, custom_id="cancel")
async def callback(self, interaction):
await interaction.response.edit_message(content="Cancelled!", view=None)
cancel = Cancel()
heres my command examples:
@client.command()
async def my_command_1(ctx):
async def callback(interaction):
# do my stuff here
view = ConfirmView(ctx=ctx, timeout=30)
view.add_item(confirm)
view.add_item(cancel)
confirm.callback = callback
view.message = await ctx.send("One", view=view)
@client.command()
async def my_command_2(ctx):
async def callback(interaction):
# do my stuff here
view = ConfirmView(ctx=ctx, timeout=30)
view.add_item(confirm)
view.add_item(cancel)
confirm.callback = callback
view.message = await ctx.send("Two", view=view)
@client.command()
async def my_command_3(ctx):
async def callback(interaction):
# do my stuff here
view = ConfirmView(ctx=ctx, timeout=30)
view.add_item(confirm)
view.add_item(cancel)
confirm.callback = callback
view.message = await ctx.send("Three", view=view)
There are two problems that you have mentioned; timing out after clicking the button and buttons being disabled.
1. Timing out even after clicking the buttons
This occurs because of how the view timeout works. From the documentation,
A way to disable on_timeout event, is to stop listening to interaction events in the view all together, with the stop method. In your callbacks,
2. Disabling after timeout
The logic from your code seems a bit off. You are setting all the buttons to be disabled, but then edit the message to not have any buttons at all?
The "acting weird" you're talking about is actually,
Say you run command_1, and let it timeout. Then run command_2, the buttons will be disabled. But you would notice that they won't be disabled anymore after restart.
To understand this further, we have to look into how object-oriented programming works.
When you add these buttons with
add_item, these buttons become part of the view's children. In theon_timeout, you set all the children to be disabled. This unexpectedly also causes the buttonscancelandconfirmto retain the attributedisabled=True.So now, when you use the class again, the buttons will be disabled, until you restart the code, where everything becomes enabled again.
You can see this by adding a print statement.
Running command_1, letting it timeout, then running command_2, would show that the
disabledis equal to True in thecancelvariable itself.To avoid this, you can create a new instance of the buttons.