Discord.py重启部署后角色选择器与按钮失效问题求助
问题描述
我编写了一段discord.py代码,用于生成带角色选择器的Embed,用户可通过选择器获取对应角色。代码原本运行正常,但重新部署Bot后,所有按钮与角色选择器均失效,求解决方法(重点针对选择器)。
代码示例
@bot.command(name="add-role-pick") async def add_role_pick(ctx: commands.Context, max_value_select: int): embed_title = 'Тестовый заголовок' ### >>> view view = discord.ui.View(timeout=None) add_role_button = discord.ui.Button(label="Добавить роль", style=discord.ButtonStyle.primary) edit_title_button = discord.ui.Button(label="Изменить название", style=discord.ButtonStyle.secondary) edit_description_button = discord.ui.Button(label="Изменить описание", style=discord.ButtonStyle.secondary) send_button = discord.ui.Button(label="Отправить", style=discord.ButtonStyle.green) edit_image_button = discord.ui.Button(label="Добавить картинку", style=discord.ButtonStyle.secondary) async def select_callback(interaction: discord.Interaction): user = interaction.user print(select.options) for role_id in select.values: role = interaction.message.guild.get_role(int(role_id)) await user.add_roles(role) await interaction.response.send_message("Роли выданы", ephemeral=True) select = discord.ui.Select(placeholder="Выберите роль", min_values=1, max_values=max_value_select) select.callback = select_callback async def add_role_button_callback(interaction): await interaction.response.send_message("Введите название роли в селекте, затем упомяните роль", ephemeral=True) role_answer = await bot.wait_for("message", check=check) role_name = role_answer.content[:len(role_answer.content) - 23] role_id = role_answer.raw_role_mentions[0] await role_answer.delete() view.remove_item(select) select.add_option(value=role_id, label=role_name) if len(select.options) >= 2: view.add_item(select) await ctx.send('Роль добавлена', ephemeral=True) await resend_message() add_role_button.callback = add_role_button_callback async def send_button_callback(interaction): result_view = discord.ui.View(timeout=None) result_view.add_item(select) await bot.get_channel(981167385140682779).send(embed=result_embed, view=result_view) await interaction.response.send_message("Сообщение отправлено!", ephemeral=True) await embed_message.delete() send_button.callback = send_button_callback async def edit_title_button_callback(interaction: discord.Interaction): await interaction.response.send_message("Отправьте название Embed в чат", ephemeral=True) title_answer = await bot.wait_for("message", check=check) result_embed.title = title_answer.content await interaction.message.delete() await resend_message() edit_title_button.callback = edit_title_button_callback async def edit_description_button_callback(interaction: discord.Interaction): await interaction.response.send_message("Отправьте описание Embed в чат", ephemeral=True) description_answer = await bot.wait_for("message", check=check) result_embed.description = description_answer.content await interaction.message.delete() await resend_message() edit_description_button.callback = edit_description_button_callback async def edit_image_button_callback(interaction: discord.Interaction): await interaction.response.send_message("Отправьте ссылку на картинку в чат", ephemeral=True) image_answer = await bot.wait_for("message", check=check) result_embed.set_image(url=image_answer.content) await interaction.message.delete() await resend_message() edit_image_button.callback = edit_image_button_callback view.add_item(add_role_button) view.add_item(edit_title_button) view.add_item(edit_description_button) view.add_item(edit_image_button) view.add_item(send_button) ### <<< view author_id = ctx.message.author.id result_embed = discord.Embed(title=embed_title, color=discord.Color.from_rgb(32, 34, 37)) embed_message = await ctx.send(embed=result_embed, view=view, ephemeral=True) async def resend_message(): await embed_message.edit(embed=result_embed, view=view) def check(m): return author_id == m.author.id
解决方案
核心原因:持久视图未注册
discord.py中,设置timeout=None的持久化视图必须通过bot.add_view()注册,否则Bot重启后无法识别之前发送的交互组件,这是部署后组件失效的最常见原因。
具体修复步骤:
注册发送后的角色选择视图
修改send_button_callback函数,在发送消息前注册result_view:async def send_button_callback(interaction): result_view = discord.ui.View(timeout=None) result_view.add_item(select) # 注册视图,确保Bot重启后仍能响应交互 bot.add_view(result_view) await bot.get_channel(981167385140682779).send(embed=result_embed, view=result_view) await interaction.response.send_message("Сообщение отправлено!", ephemeral=True) await embed_message.delete()优化选择器动态修改逻辑
原代码中反复移除/添加选择器的逻辑容易出错,改为直接检查选择器是否已在视图中再添加:# 替换add_role_button_callback中的对应代码 select.add_option(value=role_id, label=role_name) # 仅当选择器不在视图中且选项数≥2时添加 if len(select.options) >= 2 and select not in view.children: view.add_item(select) await resend_message()验证Bot权限
重新部署后确认Bot拥有以下权限:Manage Roles:用于给用户添加角色Send Messages、Embed Links:发送Embed消息Use Application Commands:响应交互组件
改用类继承视图(推荐)
动态绑定回调的方式在持久化场景下不稳定,建议用类定义视图,便于维护和注册:class RoleSelectView(discord.ui.View): def __init__(self, max_values): super().__init__(timeout=None) self.select = discord.ui.Select(placeholder="Выберите роль", min_values=1, max_values=max_values) self.select.callback = self.select_callback self.add_item(self.select) async def select_callback(self, interaction: discord.Interaction): user = interaction.user for role_id in self.select.values: role = interaction.message.guild.get_role(int(role_id)) await user.add_roles(role) await interaction.response.send_message("Роли выданы", ephemeral=True)然后在发送时实例化并注册:
async def send_button_callback(interaction): result_view = RoleSelectView(max_value_select) bot.add_view(result_view) await bot.get_channel(981167385140682779).send(embed=result_embed, view=result_view) # 其余代码不变统一discord.py版本
确保部署环境与本地测试使用的discord.py版本一致,避免版本差异导致的兼容问题,推荐使用稳定版(如discord.py==2.3.2)。
内容的提问来源于stack exchange,提问作者metacore
相关产品推荐
相关产品推荐

