You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 22:29:57