机器人有播放命令,可以做3件事,如果它还没有在语音通道中,它会加入语音通道,它会播放歌曲(显然),如果机器人已经在播放歌曲,它会将歌曲存储在一个名为队列的脚本中,然后在歌曲结束时播放它。要做到这一点,您需要在voiceClientsplay
命令上的statment之后的,它似乎表现得很奇怪。我已经放了一些
print
命令来测试机器人,似乎我放在后语句上的函数正在立即触发,而不是当歌曲结束时,我不知道这是bug还是我做错了什么…无论如何,这是代码:
这是play命令后播放的函数
def continue(ctx):
queues[ctx.guild.id].pop(0)
print(f'function continue: {queues}')
if len(queues[ctx.guild.id]) == 0:
return
Songs.play(ctx=ctx ,song=queues[ctx.guild.id][0])
这是播放命令
class Songs(commands.Cog):
def __init__(self, bot):
self.client = client
@commands.command()
async def play(self, ctx, *, song):
if ctx.voice_client is None:
await ctx.message.author.voice.channel.connect()
else:
if ctx.voice_client.channel != ctx.message.author.voice.channel:
await ctx.send('You are not in the same channel as the bot!')
return
if ctx.guild.id in queues:
queues[ctx.guild.id].append(song)
else:
queues[ctx.guild.id] = [song]
print(f'function play: {queues}')
if ctx.voice_client.is_playing():
await ctx.send('Song added to queue! :thumbsup:')
return
ydl_opts = {'format': 'bestaudio'}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
if musica.startswith('https'):
info = ydl.extract_info(song, download=False)
URL = info['formats'][0]['url']
else:
info = ydl.extract_info(f'ytsearch:{song}', download=False)
URL = info['entries'][0]['formats'][0]['url']
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=continue(ctx))
啊,你犯了一个典型的Python错误。看看这句话:
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=continue(ctx))
当该行运行时,它要做的第一件事就是调用您的函数继续
。然后它会将该函数调用的RESULT传递给play
函数。你不想调用函数,你想传递函数对象:
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=continue)
如果你真的需要这里的上下文,你必须使用lambda:
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=lambda: continue(ctx))
在代码片段的最后一行:
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=continue(ctx))
关键字参数之后的需要一个可调用的。你没有给它。你正在调用一个函数
之后的继续
(顺便说一句,这不是一个很好的函数名称,因为你隐藏了builtin关键字),并将返回值绑定到。由于您的可调用对象必须接受参数
ctx
,因此快速解决方法是传入lambda:
after=lambda: continue(ctx)