Музыкальный бот Discord — очередь (discord.py )

#python-3.x #discord.py

#python-3.x #discord.py

Вопрос:

Я начинающий программист (или мне так кажется), и мне нужна помощь в реализации очереди в музыкальном боте.

На данный момент очередь работает нормально только тогда, когда в ней есть одна песня. Если песен больше, то начинается «рекурсия» (after = await serverQueue (voice, message) из def play и await play (queue.pop (0), voice, message) из очереди), и все песни просто пропускаются.

 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('amp;'   'join'):
        await join(message)
        
    ##Connect and play
    if message.content.startswith('amp;'   '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('amp;'   'skip'):
        voice = get(client.voice_clients, guild = message.channel.guild)
        await skip(voice, message)
 

Я пытался обойти это разными способами, например, ввел вторую переменную, но это не привело к успеху. Я был бы благодарен за любую помощь.

Комментарии:

1. Я заметил, что в программе отсутствует этот код after = lambda c: await serverQueue(voice, message) , но это не решает проблему, SyntaxError: 'await' outside async function отображается ошибка.

2. Судя по вашему боту, вы должны попробовать и использовать discord.ext.commands . Это действительно поможет вам в управлении командами бота.

3. Можете ли вы сказать мне, где я могу прочитать об этом?

4. discordpy.readthedocs.io/en/latest/ext/commands/commands.html

Ответ №1:

 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()