disnake.py无法修改超时时间,如何让选择菜单重启后仍可用?
问题解决方案
一、修改组件默认超时时间
disnake里的按钮、选择菜单这类组件,超时时间由对应的View实例控制,默认180秒,你可以通过两种方式修改:
1. 实例化View时直接指定超时
创建View对象时传入timeout参数(单位秒),设为None则永久不超时(注意长期运行可能占用内存):
import disnake from disnake.ext import commands bot = commands.Bot(command_prefix="!", intents=disnake.Intents.all()) @bot.command() async def apply(ctx): # 创建职位选择菜单 job_select = disnake.ui.Select( custom_id="temp_job_select", placeholder="选择要申请的职位", options=[ disnake.SelectOption(label="后端开发", value="backend"), disnake.SelectOption(label="UI设计", value="ui_design"), ] ) # 创建View并设置超时为300秒(5分钟) view = disnake.ui.View(timeout=300) view.add_item(job_select) await ctx.send("请选择申请职位:", view=view)
2. 自定义View类统一设置超时
如果多个组件需要相同的超时规则,继承disnake.ui.View并修改类的timeout属性:
class JobApplyView(disnake.ui.View): def __init__(self): super().__init__(timeout=600) # 全局设置为10分钟超时 # 添加选择菜单到View self.add_item(disnake.ui.Select( custom_id="temp_job_select", placeholder="选择要申请的职位", options=[ disnake.SelectOption(label="后端开发", value="backend"), disnake.SelectOption(label="UI设计", value="ui_design"), ] )) @bot.command() async def apply(ctx): view = JobApplyView() await ctx.send("请选择申请职位:", view=view)
二、实现重启后仍可用的选择菜单
要让组件在机器人重启后还能响应,必须用持久化组件,核心要满足三个条件:
- 组件必须设置固定且唯一的
custom_id - View类初始化时指定
persistent=True - 机器人启动时注册该View
完整代码示例
import disnake from disnake.ext import commands bot = commands.Bot(command_prefix="!", intents=disnake.Intents.all()) # 自定义持久化选择菜单View class PersistentJobSelectView(disnake.ui.View): def __init__(self): # 开启持久化,同时自定义超时(设为None则永久有效) super().__init__(timeout=None, persistent=True) # 绑定选择菜单的回调函数,通过custom_id关联 @disnake.ui.select(custom_id="persistent_job_selector") async def on_job_selected(self, select: disnake.ui.Select, interaction: disnake.Interaction): # 触发职位申请模态窗口 apply_modal = disnake.ui.Modal( title=f"申请{select.values[0]}职位", components=[ disnake.ui.TextInput(label="姓名", custom_id="applicant_name", style=disnake.TextInputStyle.short), disnake.ui.TextInput(label="联系方式", custom_id="applicant_contact", style=disnake.TextInputStyle.short), disnake.ui.TextInput(label="自我介绍", custom_id="applicant_intro", style=disnake.TextInputStyle.paragraph), ] ) await interaction.response.send_modal(apply_modal) # 处理模态窗口提交事件 @bot.listen("on_modal_submit") async def handle_application_submit(interaction: disnake.ModalInteraction): # 判断是否是职位申请的模态窗口 if interaction.message.components[0].children[0].custom_id == "persistent_job_selector": # 提取输入内容 name = interaction.text_values["applicant_name"] contact = interaction.text_values["applicant_contact"] intro = interaction.text_values["applicant_intro"] job = interaction.message.components[0].children[0].values[0] # 这里可以添加申请逻辑,比如发送到审核频道 await interaction.response.send_message(f"{name}你好,{job}职位申请已收到,我们会尽快联系你!", ephemeral=True) # 机器人启动时注册持久化View @bot.event async def on_ready(): print(f"已登录为 {bot.user}") # 注册View,确保重启后能识别组件交互 bot.add_view(PersistentJobSelectView()) # 发送持久化选择菜单的命令 @bot.command() async def setup_application(ctx): view = PersistentJobSelectView() await ctx.send("职位申请入口(机器人重启后仍可用):", view=view) bot.run("你的机器人TOKEN")
持久化组件关键注意事项
custom_id必须固定,不能动态生成,否则重启后机器人无法识别该组件- 必须在
on_ready事件中调用bot.add_view(),即使没有关联的消息,机器人也能监听组件交互 - 模态窗口属于临时交互,无法持久化,但可以通过持久化选择菜单触发
快速掌握disnake.interaction基础操作
interaction.response:用于回复用户交互,常用方法:send_message():发送普通消息send_modal():弹出模态窗口defer():延迟回复(避免交互超时)
interaction.message:获取触发交互的消息对象interaction.user:获取触发交互的用户对象interaction.text_values:仅模态窗口提交时可用,提取输入框内容
内容的提问来源于stack exchange,提问作者Mr Wing
相关产品推荐
相关产品推荐

