求助:使用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
相关产品推荐
相关产品推荐

