使用discord.ui分页帮助菜单成功切换却触发交互失败错误
问题描述
开发了带分页功能的Embed帮助菜单,切换页面时内容能成功切换,但Embed下方会显示“This interaction failed”错误。已尝试使用interaction.response.defer()和ctx.defer()延迟交互,但问题仍未解决,控制台无其他错误信息。
相关代码:
class HelpMenu(View): try: def __init__(self, ctx, data): super().__init__() self.ctx: commands.Context = ctx self.data = data self.current_page = 0 self.per_page = 5 self.timeout = None self.message = None async def show_page(self): embed = discord.Embed( title="Help", description="List of available commands", color=discord.Color.blurple(), ) embed.set_footer( text=f"Page {self.current_page + 1}/{self.get_max_pages()}" ) start_index = self.current_page * self.per_page end_index = start_index + self.per_page for name, value in self.data[start_index:end_index]: embed.add_field(name=name, value=value, inline=False) if self.message is None: self.message = await self.ctx.send(embed=embed, view=self) else: await self.message.edit(embed=embed) def get_max_pages(self): return (len(self.data) + self.per_page - 1) // self.per_page @discord.ui.button(label="↩", style=discord.ButtonStyle.primary) async def previous_page( self, button: discord.ui.Button, interaction: discord.Interaction ): if self.current_page > 0: self.current_page -= 1 await self.show_page() await self.ctx.defer() await interaction.response.defer() @discord.ui.button(label="↪", style=discord.ButtonStyle.primary) async def next_page( self, button: discord.ui.Button, interaction: discord.Interaction ): if self.current_page < self.get_max_pages() - 1: self.current_page += 1 await self.show_page() await self.ctx.defer() await interaction.response.defer() except Exception as e: print(e) @client.command(description="Shows this embed.") async def help(ctx): try: commands_list = client.commands data = [(command.name, command.description) for command in commands_list] menu = HelpMenu(ctx, data) await menu.show_page() except Exception as e: print(e)
问题原因与修复方案
1. 错误的交互响应逻辑
按钮回调中同时调用ctx.defer()和interaction.response.defer()属于重复响应:ctx.defer()是针对命令的延迟响应,不适用于按钮交互场景;双重defer会让Discord无法正确识别交互状态,从而触发失败提示。
另外,修改消息后必须对交互请求给出明确响应,确保Discord收到处理反馈。
2. 不合理的异常捕获范围
将整个HelpMenu类包裹在try-except中,会干扰类方法(尤其是按钮回调)的正常注册,导致Discord无法识别按钮交互逻辑。
修复后的代码
class HelpMenu(View): def __init__(self, ctx, data): super().__init__() self.ctx: commands.Context = ctx self.data = data self.current_page = 0 self.per_page = 5 self.timeout = None self.message = None async def show_page(self): embed = discord.Embed( title="Help", description="List of available commands", color=discord.Color.blurple(), ) embed.set_footer( text=f"Page {self.current_page + 1}/{self.get_max_pages()}" ) start_index = self.current_page * self.per_page end_index = start_index + self.per_page for name, value in self.data[start_index:end_index]: embed.add_field(name=name, value=value, inline=False) if self.message is None: self.message = await self.ctx.send(embed=embed, view=self) else: await self.message.edit(embed=embed) def get_max_pages(self): return (len(self.data) + self.per_page - 1) // self.per_page @discord.ui.button(label="↩", style=discord.ButtonStyle.primary) async def previous_page( self, button: discord.ui.Button, interaction: discord.Interaction ): try: if self.current_page > 0: self.current_page -= 1 await self.show_page() # 仅对按钮交互给出响应,告知Discord已处理请求 await interaction.response.defer(ephemeral=False) except Exception as e: print(e) @discord.ui.button(label="↪", style=discord.ButtonStyle.primary) async def next_page( self, button: discord.ui.Button, interaction: discord.Interaction ): try: if self.current_page < self.get_max_pages() - 1: self.current_page += 1 await self.show_page() await interaction.response.defer(ephemeral=False) except Exception as e: print(e) @client.command(description="Shows this embed.") async def help(ctx): try: commands_list = client.commands data = [(command.name, command.description) for command in commands_list] menu = HelpMenu(ctx, data) await menu.show_page() except Exception as e: print(e)
核心修改点
- 移除包裹整个类的
try-except,改为在按钮回调内部捕获异常,避免干扰方法注册。 - 删除
ctx.defer(),仅保留interaction.response.defer()处理按钮交互的响应需求。 - 确保每次按钮点击后都明确响应交互请求,避免Discord因超时未收到反馈而提示失败。
内容的提问来源于stack exchange,提问作者Bonk
相关产品推荐
相关产品推荐

