2
votes

I am a beginner programmer (or so it seems to me) and I need help implementing a queue in a music bot.

At the moment, the queue works fine only when there is one song in it. If there are more songs, then the "recursion" starts (after = await serverQueue (voice, message) from def play and await play (queue.pop (0), voice, message) from queue), and all songs just skipped.

import discord
import nacl
import ffmpeg
from discord import FFmpegPCMAudio
from discord.utils import get
from youtube_dl import YoutubeDL

client = discord.Client()

async def join(message):
    ##Connect to channel
    connection = message.author.guild.voice_client
    idUserChannel = message.author.voice.channel.id
    idBotChannel = 0
    if connection:
        idBotChannel = client.voice_clients[0].channel.id
    if (connection) and (idBotChannel != idUserChannel) :
        await message.channel.send('**Moving to** ' + str(message.author.voice.channel))
        await connection.move_to(message.author.voice.channel)
    elif (idBotChannel != idUserChannel):
        await message.channel.send('**Connect to** ' + str(message.author.voice.channel))
        await message.author.voice.channel.connect()
        
async def play(video_link, voice, message):
    ##Playing songs
    ydl_opts = {'format': 'bestaudio', 'noplaylist':'True'}
    FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
    with YoutubeDL(ydl_opts) as ydl:
        info = ydl.extract_info(video_link, download = False)
    print(info.get('title'))
    URL = info['formats'][0]['url']
    print(URL)
    voice.play(FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after = await serverQueue(voice, message))
    voice.is_playing()
    await message.channel.send('**Now playing** - ' + info.get('title'))

async def skip(voice, message):
    ##Skip
    voice.stop()
    await serverQueue(voice, message)
    await message.channel.send('**Successfully skiped** - ' + info.get('title'))
    
##Queue
queue = []
async def serverQueue(voice, message):
    if queue != [] and not voice.is_playing():
        await play(queue.pop(0), voice, message)
        print('queue - ' + str(queue))

@client.event
async def on_message(message):
    if message.author == client.user:
        return
        
    if message.content.startswith('&' + 'join'):
        await join(message)
        
    ##Connect and play
    if message.content.startswith('&' + 'play'):
        await join(message)
        voice = get(client.voice_clients, guild = message.channel.guild)
        msg = message.content[1:].split()
        video_link = msg[1]
        if not voice.is_playing():
            await play(video_link, voice, message)
        else:
            await message.channel.send('Added to queue successfully')
            queue.append(video_link)

    ##Skip
    if message.content.startswith('&' + 'skip'):
        voice = get(client.voice_clients, guild = message.channel.guild)
        await skip(voice, message)

I tried to work around this in different ways, for example, introduced a second variable, but this did not lead to success. I would be grateful for any help.

1
I noticed that the program is missing this code after = lambda c: await serverQueue(voice, message), but this does not solve the problem, an error SyntaxError: 'await' outside async function is displayed.CrazyMolecule
Judging by your bot, you should try and use discord.ext.commands. It will really help you in managing bot commands.Frederick Reynolds
Can you tell me where I can read about this?CrazyMolecule

1 Answers

0
votes
async def play(video_link, voice, message):
    ##Воспроизведение песенок
    ydl_opts = {'format': 'bestaudio', 'noplaylist':'True'}
    FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
    with YoutubeDL(ydl_opts) as ydl:
        info = ydl.extract_info(video_link, download = False)
    print(info.get('title'))
    URL = info['formats'][0]['url']
    voice.play(FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after = lambda e: myAfter(voice, message))
    voice.is_playing()
    await message.channel.send('**Сейчас играет** - ' + info.get('title'))

async def myAfter(voice, message):
    coro = await musicQueue(voice, message)
    asyncio.run_coroutine_threadsafe(coro).result()