Discord.py按钮点击事件无响应问题求助
Discord按钮点击事件无法捕获,触发超时且显示“交互失败”
我写了一个测试按钮命令,但机器人始终无法捕获按钮点击事件,即使移除检查条件、自定义ID等设置,仍会触发超时,点击按钮后显示“交互失败”。我希望在命令内保留按钮及事件监听逻辑,点击按钮后机器人能发送“You pressed the button!”,但实际总是触发超时。
测试代码如下:
@tree.command(name="button", description="testing") async def button(interaction): view = discord.ui.View() # make a view style = discord.ButtonStyle.primary # makes the button blue item = discord.ui.Button(style=style, label="Click to continue!", custom_id="continue_button") # make the button view.add_item(item=item) # add button to view await interaction.response.send_message("Waiting until you press the button!", view=view) # send message with button def check(i): return i.user.id == interaction.user.id and i.custom_id == "continue_button" try: interaction, button = await client.wait_for("button_click", check=check, timeout=10) # when button is pressed await interaction.channel.send("You pressed the button!") except asyncio.TimeoutError: # button wasn't pressed before timeout await interaction.channel.send("You didn't press the button within the specified time.")
问题原因
discord.py v2.0及以上版本已移除button_click事件,改用View类绑定回调函数的方式处理按钮交互。你使用client.wait_for监听已废弃的事件,自然无法捕获点击,导致超时;同时未对按钮交互做出响应,Discord会判定为“交互失败”。
修复方案(两种方式)
方式1:使用View回调函数(推荐,符合v2.x规范)
将按钮逻辑封装在View类中,绑定回调函数处理点击:
import discord from discord import app_commands class ContinueView(discord.ui.View): def __init__(self, user_id): super().__init__(timeout=10) self.user_id = user_id async def interaction_check(self, interaction: discord.Interaction) -> bool: # 仅允许命令发起者点击按钮 return interaction.user.id == self.user_id @discord.ui.button(label="Click to continue!", style=discord.ButtonStyle.primary, custom_id="continue_button") async def continue_button(self, interaction: discord.Interaction, button: discord.ui.Button): # 响应按钮交互,避免“交互失败”提示 await interaction.response.send_message("You pressed the button!", ephemeral=False) self.stop() # 终止View超时计时 @tree.command(name="button", description="testing") async def button(interaction: discord.Interaction): view = ContinueView(user_id=interaction.user.id) await interaction.response.send_message("Waiting until you press the button!", view=view) # 等待View结束(按钮点击或超时) await view.wait() if not view.children[0].disabled: # 超时处理:禁用按钮并更新原消息 view.children[0].disabled = True await interaction.edit_original_response(view=view) await interaction.followup.send("You didn't press the button within the specified time.")
方式2:保留命令内监听逻辑(使用view.wait())
如果想在命令函数内处理后续逻辑,可通过标记变量记录按钮状态:
import discord from discord import app_commands import asyncio @tree.command(name="button", description="testing") async def button(interaction: discord.Interaction): view = discord.ui.View(timeout=10) button_clicked = False clicked_interaction = None async def button_callback(i: discord.Interaction): nonlocal button_clicked, clicked_interaction button_clicked = True clicked_interaction = i await i.response.send_message("You pressed the button!", ephemeral=False) view.stop() item = discord.ui.Button(style=discord.ButtonStyle.primary, label="Click to continue!", custom_id="continue_button") item.callback = button_callback view.add_item(item) await interaction.response.send_message("Waiting until you press the button!", view=view) # 等待View超时或按钮点击 await view.wait() if not button_clicked: # 超时处理:禁用按钮并提示 view.children[0].disabled = True await interaction.edit_original_response(view=view) await interaction.followup.send("You didn't press the button within the specified time.")
关键改动说明
- 替换废弃事件:弃用
client.wait_for("button_click"),改用View回调或view.wait()实现等待逻辑 - 强制交互响应:按钮点击后必须调用
interaction.response相关方法,否则Discord会显示“交互失败” - 用户验证:通过
interaction_check或回调内判断,确保只有命令发起者能操作按钮 - 超时优化:利用View自带的
timeout参数,超时后禁用按钮并更新原消息,避免无效按钮残留
内容的提问来源于stack exchange,提问作者IceFire03
相关产品推荐
相关产品推荐

