-2

I have been trying to make a queue command. This successfully appends input to the dict, like ['song1', 'song2']. But attempts to play the next song without waiting for the current song to finish, resulting in already playing error.

async def queue(ctx):
 ctx.message.guild.name = []
 await ctx.message.channel.send('**-start of queue-**')
 await ctx.message.channel.send('**-type end when done-**')
 def ch(m):
  return m.author == ctx.message.author and m.channel == ctx.message.channel
 while True:
  song = await client.wait_for('message', check=ch, timeout=30)
  song_str = str(song.content)
  song_f = song_str.translate({ord(c): None for c in string.whitespace})
  if song_f == 'end':
   print(ctx.message.guild.name)
   break
  ctx.message.guild.name.append(song_str)
 vc = ctx.message.guild.voice_client
 for song in ctx.message.guild.name:
  player = await YTDLSource.from_url(song, loop=client.loop)
  print(song)
  vc.play(player)

Lemon
  • 11
  • 2
  • I managed to make it work, but it isn't a real solution, I do asyncio.sleep for the length of the song + 20, so it sleeps until the song ends, then attempts to play the next, but this can fail, if it takes more than 20 sec to download, this isn't really a solution! – Lemon Jun 01 '20 at 04:57

1 Answers1

1

Here's a way to do it :
With this code, your bot won't download the song and he'll be able to play songs from links and youtube search.

import discord
from discord.ext import commands
from discord.utils import get

import youtube_dl
import requests

song_queue = []
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist':'True'}

#Search videos from key-words or links
def search(arg):
    try: requests.get("".join(arg))
    except: arg = " ".join(arg)
    else: arg = "".join(arg)
    with youtube_dl.YoutubeDL(YDL_OPTIONS ) as ydl:
        info = ydl.extract_info(f"ytsearch:{arg}", download=False)['entries'][0]
        
    return {'source': info['formats'][0]['url'], 'title': info['title']}

#Plays the next song in the queue
def play_next(ctx):
    voice = get(client.voice_clients, guild=ctx.guild)
    if len(song_queue) > 1:
        del song_queue[0]
        voice.play(discord.FFmpegPCMAudio(song_queue[0][source], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
        voice.is_playing()

@client.command()
async def play(ctx, *arg):
    channel = ctx.message.author.voice.channel

    if channel:
        voice = get(client.voice_clients, guild=ctx.guild)
        song = search(arg)
        song_queue.append(song)

        if voice and voice.is_connected():
            await voice.move_to(channel)
        else: 
            voice = await channel.connect()

        if not voice.is_playing():
           voice.play(discord.FFmpegPCMAudio(song[0]['source'], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
            voice.is_playing()
        else:
            await ctx.send("Added to queue")
    else:
        await ctx.send("You're not connected to any channel!")
MrSpaar
  • 3,979
  • 2
  • 10
  • 25