如何重启Python Discord Bot后仍保留Embed按钮交互功能?
解决Discord Bot重启后旧按钮交互失效的问题
问题根源很明确:你当前用的普通View是存在Bot内存里的,一旦Bot重启或代码更新,内存里的按钮回调关联就会丢失,Discord发送交互请求时Bot找不到对应的处理逻辑,自然就会失败。
不用重新发送Embed,最高效的解决方案是使用持久化视图(Persistent Views),让Bot重启后仍能识别旧消息里的按钮并处理交互,具体步骤如下:
1. 定义带持久化标识的自定义View类
继承discord.ui.View,给每个按钮设置固定的custom_id(这是Bot识别旧按钮的关键),同时设置timeout=None让视图永久有效:
import os import discord class TicketCloseView(discord.ui.View): def __init__(self): # 设置timeout为None,让视图长期有效 super().__init__(timeout=None) # 重新打开工单按钮 @discord.ui.button( label=os.getenv("CLOSE_TICKET_COMMAND_OPEN_TICKET"), style=discord.ButtonStyle.secondary, # 固定的自定义ID,重启后Bot能通过这个ID匹配回调 custom_id="ticket_close_open_btn" ) async def open_ticket_callback(self, interaction: discord.Interaction, button: discord.ui.Button): # 这里写你原来的重新打开工单逻辑 await interaction.response.send_message("正在重新打开你的工单...", ephemeral=True) # 你的业务代码... # 删除工单按钮 @discord.ui.button( label=os.getenv("CLOSE_TICKET_COMMAND_DELETE_TICKET"), style=discord.ButtonStyle.danger, custom_id="ticket_close_delete_btn" ) async def delete_ticket_callback(self, interaction: discord.Interaction, button: discord.ui.Button): # 这里写你原来的删除工单逻辑 await interaction.response.send_message("正在删除工单...", ephemeral=True) # 你的业务代码...
2. 发送消息时使用这个持久化视图
替换你原来的menu,直接实例化自定义视图:
embed = discord.Embed( title="", description=os.getenv("CLOSE_TICKET_COMMAND_CLOSED_BY").format(user=interaction.user.mention), color=discord.Color(5308575) ) # 使用自定义的持久化视图 await channel.send(embed=embed, view=TicketCloseView())
3. Bot启动时注册持久化视图
在Bot初始化完成后,注册这个视图,确保重启后Bot能自动关联旧按钮的回调:
# 假设你的Bot实例是bot bot.add_view(TicketCloseView())
关键注意事项
custom_id必须唯一且固定,不能用随机数或动态生成的值(除非你有特殊的匹配逻辑),否则重启后无法识别旧按钮- 如果后续需要修改按钮的文字或样式,重启后新发送的按钮会生效,但旧按钮的外观还是原来的,但回调逻辑依然能正常触发
- 如果你需要更新旧消息里的按钮样式,可以通过编辑消息替换视图,但仅需保证
custom_id不变,回调就不会受影响
内容的提问来源于stack exchange,提问作者Aweb
相关产品推荐
相关产品推荐

