The bot has play command that does 3 things it joins the voice channel if it isn’t in the voice channel already, it plays songs(obviously) and it stores the songs in a dict called queues if the bot is already playing a song to then play it when the song ends. To do something like this you need the after
statment on the voiceClients play
command and it seems to be behaving quit weirdly. I’ve put some print
commands to test the bot and it seems that the function that I put on the after statment is firing right away rather then when the song ends, I don’t know if this is a bug or if I’m doing something wrong… anyway here’s the code:
this is the function that plays after the play command
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])
and here is the play command
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))
Advertisement
Answer
Ah, you have committed one of the classic Python blunders. Look at this line:
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=continue(ctx))
When that line runs, the first thing it’s going to do is call your function continue
. It will then pass the RESULT of that function call to the play
function. You don’t want to CALL the function, you want to pass the function object:
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=continue)
If you really need the context in there, you’ll have to use a lambda:
ctx.message.guild.voice_client.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after=lambda: continue(ctx))