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

求助:使用app_commands迁移Discord Bot play斜杠命令遇AttributeError

问题解决:将discord.py前缀play命令迁移为斜杠命令

核心问题原因

旧前缀命令中,commands.command框架支持自动将用户输入的字符串解析为wavelink.YouTubeTrack类型,但app_commands(斜杠命令)没有内置这个解析能力,你直接传入字符串给vc.play()或队列,导致wavelink尝试访问字符串的id属性(只有Track对象才有),引发AttributeError。

修正后的完整代码

from discord import app_commands, Interaction, Embed, Color
import wavelink

@app_commands.command(name="play", description="Play a song from YouTube.")
async def play(self, interaction: Interaction, search: str):
    # 先检查用户是否在语音频道
    if not interaction.user.voice or not interaction.user.voice.channel:
        return await interaction.response.send_message("你得先加入一个语音频道啊!")
    
    # 处理语音客户端连接
    if not interaction.guild.voice_client:
        vc: wavelink.Player = await interaction.user.voice.channel.connect(cls=wavelink.Player)
    else:
        vc: wavelink.Player = interaction.guild.voice_client
        # 确保Bot和用户在同一个频道
        if vc.channel != interaction.user.voice.channel:
            return await interaction.response.send_message("我已经在别的语音频道啦!")
    
    # 延迟响应,避免搜索超时导致交互失败
    await interaction.response.defer()
    
    # 手动搜索YouTube曲目
    try:
        tracks = await wavelink.YouTubeTrack.search(search)
        if not tracks:
            return await interaction.followup.send("没找到对应的歌曲哦!")
        track = tracks[0]  # 取搜索结果的第一首
    except Exception as e:
        return await interaction.followup.send(f"搜索出错了:{str(e)}")
    
    # 处理播放/入队逻辑
    if vc.is_playing() or not vc.queue.is_empty:
        await vc.queue.put_wait(track)
        embed = Embed(title="已加入队列", description=f"`{track.title}`", color=Color.purple())
        await interaction.followup.send(embed=embed)
    else:
        await vc.play(track)
        embed = Embed(title="正在播放", description=f"`{track.title}`", color=Color.blue())
        await interaction.followup.send(embed=embed)
    
    vc.ctx = interaction  # 把交互对象绑定到播放器(如果后续需要用到)

关键修正点说明

  • 类型解析替代:通过wavelink.YouTubeTrack.search()手动将用户输入的字符串转换为YouTubeTrack对象,这是解决AttributeError的核心。
  • 交互响应时机:因为搜索歌曲是异步操作,耗时可能超过3秒,所以先调用await interaction.response.defer()延迟响应,后续用followup.send()发送结果,避免Discord判定命令超时。
  • 语音频道逻辑修正:
    • 先检查用户是否在语音频道,逻辑更合理;
    • 新增Bot和用户是否在同一频道的判断,避免混乱;
    • 修正了原代码中getattr(interaction.user.voice.channel, "channel", None)的错误判断,直接检查interaction.user.voice即可。
  • 错误处理:新增搜索失败的异常捕获和无结果的判断,提升命令健壮性。

内容的提问来源于stack exchange,提问作者Frodox

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:44:54