Disnake交互过期问题:如何刷新或延长交互时长修复音乐队列故障
解决Disnake音乐机器人15分钟后无法播放队列音乐的问题
核心原因
Discord的交互对象默认15分钟后过期,过期后无法再通过该对象发送消息或执行跟进操作。你的代码在队列循环时持续复用最初的交互对象,导致15分钟后操作失败。
解决方案
1. 延长交互超时时间
在定义slash命令时,通过timeout参数设置更长的超时时间(最大支持86400秒,即24小时),避免交互快速过期:
@slash_command(name="play", timeout=3600) # 设置为1小时超时 async def play(self, inter: disnake.ApplicationCommandInteraction, song: str): # 初始化队列、语音频道等逻辑 # 保存当前文本频道对象,供后续播放通知使用 self.text_channel = inter.channel await self.music_play_func(inter, author_vc)
2. 脱离原交互对象,改用文本频道发送消息
彻底摆脱对原交互对象的依赖,直接向保存的文本频道发送播放通知,不受交互过期限制:
修改music_play_func的发送逻辑:
async def music_play_func(self, author_vc): if len(self.queue) >= 1: link_or_name = "".join(self.queue[0]) self.queue.pop(0) # ... 省略yt-dlp获取歌曲信息的代码 ... embed_player = disnake.Embed( title="正在播放", description=info['title'], colour=0x69ff33 ) embed_player.add_field(name="时长", value=converted_duration, inline=True) embed_player.add_field(name="链接", value=link_or_name, inline=True) embed_player.set_footer(text=f"发起用户 {self.command_author.name}", icon_url=f"{self.command_author.avatar.url}") embed_player.set_image(url=f"https://img.youtube.com/vi/{image_index}/hqdefault.jpg") # 直接向保存的文本频道发送消息 await self.text_channel.send(embed=embed_player, delete_after=duration) loop = asyncio.get_running_loop() song = info['url'] author_vc.play( disnake.FFmpegPCMAudio(song, **self.FFMPEG_OPTIONS), after=lambda e: asyncio.run_coroutine_threadsafe(self.music_play_func(author_vc), loop) )
注:需要在类中新增self.command_author属性,在首次触发播放命令时保存发起用户信息。
3. 交互过期的兼容处理
如果需要保留交互操作的场景,可捕获交互过期异常,降级为频道发送:
try: if bot_inter.is_expired(): await bot_inter.followup.send(embed=embed_player, delete_after=duration, wait=True) else: await bot_inter.send(embed=embed_player, delete_after=duration) except disnake.errors.InteractionResponded: # 交互已过期或无法响应,切换到频道发送 await self.text_channel.send(embed=embed_player, delete_after=duration)
关键提示
- Discord交互一旦过期无法刷新,只能通过延长超时或切换发送方式解决。
- 使用
after回调时,确保通过asyncio.run_coroutine_threadsafe线程安全地调用协程,避免阻塞事件循环。
内容的提问来源于stack exchange,提问作者Friday 13th
相关产品推荐
相关产品推荐

