discord.py Music Bot: How to Combine a Play and Queue Command

Solution 1:

You need some sort of queue system where song requests are stored in the queue and a loop that checks if any item is in the queue, grabbing the first item in the queue if it's available. If no songs are in the queue, then the loop waits until a song is added. You can use asyncio.Queue() and asyncio.Event() to do this.

import asyncio
from discord.ext import commands

client = commands.Bot(command_prefix='!')
songs = asyncio.Queue()
play_next_song = asyncio.Event()


@client.event
async def on_ready():
    print('client ready')


async def audio_player_task():
    while True:
        play_next_song.clear()
        current = await songs.get()
        current.start()
        await play_next_song.wait()


def toggle_next():
    client.loop.call_soon_threadsafe(play_next_song.set)


@client.command(pass_context=True)
async def play(ctx, url):
    if not client.is_voice_connected(ctx.message.server):
        voice = await client.join_voice_channel(ctx.message.author.voice_channel)
    else:
        voice = client.voice_client_in(ctx.message.server)

    player = await voice.create_ytdl_player(url, after=toggle_next)
    await songs.put(player)

client.loop.create_task(audio_player_task())

client.run('token')