Nextcord开发Discord机器人多次编辑按钮样式的报错问题
问题根因
你遇到的三类报错核心原因非常明确,和库本身bug无关,是对Nextcord交互响应生命周期、消息对象机制不熟悉导致的:
InteractionResponded和40060 Interaction has already been acknowledged报错:Discord对每一次按钮点击交互,仅允许调用一次interaction.response下的初始响应方法,服务端会记录每个交互ID的响应状态,手动修改_responded这类库内部私有属性没有任何作用,无法绕过服务端校验。10008 Unknown Message报错:interaction.message是交互触发瞬间携带的消息快照对象,不是服务端存储的最新消息实例。当你第一次调用响应方法编辑消息后,这个旧快照的ID、关联权限状态已经和服务端最新消息不匹配(尤其是发送的是ephemeral仅用户可见临时消息时,旧快照根本没有编辑新消息的权限),拿旧对象调用edit自然会返回找不到消息的错误。
可行实现方案
不要修改任何库内部私有属性,严格按照交互生命周期操作即可实现多次修改按钮样式的需求,参考以下实现逻辑:
核心规则
- 每一次按钮点击触发的新交互,第一次回应用户必须走
interaction.response方法,不能直接调消息编辑。 - 第一次响应完成后,立刻通过
interaction.original_message()拿到服务端返回的最新消息对象存下来,后续所有对该消息的编辑操作,都用这个拿到的最新对象调用edit,绝对不要用interaction.message这个旧快照。 - 不要每次编辑都新建View实例,直接修改当前View内对应Button的样式、状态属性,再把当前View实例传给edit方法即可。
可运行代码示例
class ChoicesBtn(nextcord.ui.Button): def __init__(self, label: str): super().__init__( style=nextcord.ButtonStyle.secondary, label=label, row=0 ) async def callback(self, interaction: nextcord.Interaction): # 先修改当前按钮的样式 if self.style == nextcord.ButtonStyle.success: self.style = nextcord.ButtonStyle.secondary else: self.style = nextcord.ButtonStyle.success # 判断当前交互是否已经做过初始响应 if not interaction.response.is_done(): # 第一次响应走response通道 await interaction.response.edit_message(view=self.view) # 响应完成后拿到最新消息对象存到view属性里,后续复用 self.view.last_message = await interaction.original_message() else: # 已经响应过的情况,直接用存好的最新消息对象编辑 await self.view.last_message.edit(view=self.view) class ChoicesView(nextcord.ui.View): def __init__(self): super().__init__(timeout=180) # 初始化存最新消息对象的属性 self.last_message = None # 加按钮 self.add_item(ChoicesBtn(label="Party")) self.add_item(ChoicesBtn(label="Birth"))
常见避坑点
- 如果你发的是ephemeral临时消息,只能通过
interaction.original_message()拿到的对象编辑,不能通过频道ID、消息ID去抓消息编辑,这类消息不会存到公开频道消息列表里。 - 交互token的有效期是15分钟,超时后无法再通过交互对象编辑消息,如果需要更长的编辑周期,需要在发消息时就把返回的消息ID、频道ID存到数据库,后续通过bot账号直接获取频道消息对象编辑。
- 编辑View的时候不要遗漏组件,如果你传的新View里少了按钮,对应按钮会直接从消息上消失。
内容的提问来源于stack exchange,提问作者argaiv
相关产品推荐
相关产品推荐

