discord.py开发Discord音乐机器人:歌曲队列与歌名搜索问题咨询
Discord.py音乐机器人功能修复方案
修复内容说明
针对你提到的两个核心问题,直接对现有代码做如下修改即可实现需求:
第一步:新增全局配置与自动切歌逻辑
在client = commands.Bot(command_prefix='!')代码行之前添加如下内容:
# 按服务器存储播放队列,key为服务器id,value为歌曲队列列表 queues = {} async def next_song(ctx): # 当前服务器队列不为空则播放下一首 if queues.get(ctx.guild.id, []): next_player = queues[ctx.guild.id].pop(0) voice_channel = ctx.guild.voice_client voice_channel.play(next_player, after=lambda e: asyncio.run_coroutine_threadsafe(next_song(ctx), client.loop) if e is None else print(f'播放错误: {e}')) await ctx.send(f'**现在播放:** {next_player.title}')
第二步:修改play命令实现队列+歌名搜索
你之前歌名搜索不准的核心原因是play命令仅接收单个参数,带空格的歌名会被截断,修改为接收完整搜索内容即可,同时添加队列逻辑,替换原有play命令代码:
@client.command(name='play', help='输入歌曲名或YouTube链接播放/加入队列') async def play(ctx, *, search_query): # 检查用户是否在语音频道 if not ctx.message.author.voice: await ctx.send("你还没有加入语音频道") return channel = ctx.message.author.voice.channel # 初始化当前服务器队列 if ctx.guild.id not in queues: queues[ctx.guild.id] = [] # 机器人不在语音频道则加入 if not ctx.guild.voice_client: await channel.connect() voice_channel = ctx.guild.voice_client async with ctx.typing(): # 直接传入搜索词,youtube_dl配置的default_search: auto会自动搜索匹配度最高的歌曲 player = await YTDLSource.from_url(search_query, loop=client.loop, stream=True) # 当前正在播放则加入队列,否则直接播放 if voice_channel.is_playing() or voice_channel.is_paused(): queues[ctx.guild.id].append(player) await ctx.send(f'**已加入队列:** {player.title} (队列第{len(queues[ctx.guild.id])}位)') else: voice_channel.play(player, after=lambda e: asyncio.run_coroutine_threadsafe(next_song(ctx), client.loop) if e is None else print(f'播放错误: {e}')) await ctx.send(f'**现在播放:** {player.title}')
第三步:优化stop和leave命令适配队列逻辑
替换原有stop命令:
@client.command(name='stop', help='停止播放并清空队列') async def stop(ctx): voice_client = ctx.message.guild.voice_client if voice_client: # 清空当前服务器队列 if ctx.guild.id in queues: queues[ctx.guild.id].clear() await voice_client.stop()
替换原有leave命令,加清空队列逻辑:
@client.command() async def leave(ctx): # 清空当前服务器队列 if ctx.guild.id in queues: queues.pop(ctx.guild.id) # 清空本地缓存文件 for song in os.listdir(folder): file_path = os.path.join(folder, song) try: if os.path.isfile(file_path) or os.path.islink(file_path): os.unlink(file_path) elif os.path.isdir(file_path): shutil.rmtree(file_path) except Exception as e: print('Failed to delete %s. Reason %s' % (file_path, e)) voice = discord.utils.get(client.voice_clients, guild=ctx.guild) if voice and voice.is_connected(): await voice.disconnect() else: await ctx.send("机器人未加入任何语音频道。")
功能验证
修改完成后即可实现:
- 直接输入
!play 完整歌曲名即可自动搜索匹配度最高的歌曲播放,无需拼接下划线 - 播放过程中调用
!play命令会自动将歌曲加入队列,当前歌曲播放完成后自动播放下一首 - 无需每次播放新歌曲都手动踢出机器人重连
内容的提问来源于stack exchange,提问作者Daniel Reyes
相关产品推荐
相关产品推荐

