简体   繁体   中英

How can I play a list of songs with my discord bot (discord.py)

I have tried creating a dictionary and storing a list of .create_ytdl_player() instances to each discord server id.

I just need to know how to make the players play after the previous one has finished.

I figure I would have to use .is_playing() or .is_done() but I don't know how to use them. Can someone help?

I'll answer the question with code that works for a single instance (although it shouldn't be hard to edit it for multiple instances by fetching the right player and voice_channel objects from the dictionary).

You have to first make a queue that store the urls that your player will play your objects in. I assume that you should also make a dictionary of queues to store the different urls for the different servers.

To help manage your stream_player workflow, first declare a voice and player object in the outermost scope.

self.player = None
self.voice = None

The voice object should be set after the bot joins a voice channel:

mvoice = await client.join_voice_channel(voice channel id here)
self.voice = mvoice

We then have to make two functions as Python does not support async lamdas while managing the stream player can only be done from a async function. The play_music function should be called by the bot whenever the user types the relevant command:

#pass the url into here when a user calls the bot
async def play_music(client, message, url=None):
    if url is None:
    #function is being called from after (this will be explained in the next function)
        if queue.size() > 0:
            #fetch from queue
            url = queue.dequeue()
        else:
            #Unset stored objects, also possibly disconnect from voice channel here
            self.player = None
            self.voice = None
            return
    if self.player is None:
        #no one is using the stream player, we can start playback immediately
        self.player = await self.voice.create_ytdl_player(url, after=lambda: play_next(client, message))
        self.player.start()
    else:
        if self.player.is_playing():
            #called by the user to add a song
            queue.enqueue(url)
        else:
            #this section happens when a song has finished, we play the next song here
            self.player = await self.voice.create_ytdl_player(url, after=lambda: play_next(client, message))
            self.player.start()

The play_next function will be called from the finalizer after the stream player has finished a song and will call the above function again but without the url argument.

def play_next(client, message):
    asyncio.run_coroutine_threadsafe(play_music(client, message), client.loop)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM