1

I'm making a discord music bot in Python and it is so far playing music. I wanted to add a queue feature so that if a song is playing at the moment, the song entered will be played after it has finished playing. The bot downloads the song, which it gets from a request (not in the code below), and renames it to "song.mp3". It then starts playing the song and when it's done it deletes the song so that the new one can be downloaded and also be called "song.mp3". My idea with the queue system here was, that the bot goes trough all the urls that are in the song_queue and when it's done with the first one, downloads the second and so on. While the bot is playing, I need to check when it can move to the next file and for that I used while voice.is_playing and the while is causing the problem because the other commands no longer work.


song_queue = []

@commands.command()
    async def play(self, ctx, *, url: str):
        if ctx.author.voice and ctx.author.voice.channel:
            channel = ctx.author.voice.channel

            if not self.bot_is_connected(ctx):
                await channel.connect()
        else:
            await ctx.send("`You are not connected to a voice channel.`")

        if ctx.author.voice and ctx.author.voice.channel:

            voice = discord.utils.get(self.client.voice_clients, guild=ctx.guild)

            video = get_url(f"{url}")
            song_queue.append(video)

            song_there = os.path.isfile("song.mp3")
            try:
                if song_there:
                    os.remove("song.mp3")
            except PermissionError:

            ydl_opts = {
                'format': 'bestaudio/best',
                'postprocessors': [{
                    'key': 'FFmpegExtractAudio',
                    'preferredcodec': 'mp3',
                    'preferredquality': '192',
                }],
            }

            for song in song_queue:

                with youtube_dl.YoutubeDL(ydl_opts) as ydl:
                    ydl.download([song])
                    meta = ydl.extract_info(song, download=False)
                    song_name = (meta["title"])

                for file in os.listdir("./"):
                    if file.endswith(".mp3"):
                        os.rename(file, "song.mp3")
                voice.play(discord.FFmpegPCMAudio("song.mp3"))

                while voice.is_playing(): #Makes other commands no longer work
                    print("playing...")
                    time.sleep(5)

                else:
                    song_queue.remove(song)
                    song_there = os.path.isfile("song.mp3")
                    if song_there:
                        os.remove("song.mp3")
Celltox
  • 127
  • 8

1 Answers1

0

What is causing your other commands to stop working is the use of time.sleep(). discord.py is an asynchronous library, which means that it handles being able to perform multiple functionalities at the same time to ensure that a bot is not blocked during its use, but adding a synchronous call like time.sleep() makes it stop its operations.

When you are working with asynchronous libraries it is best to look for the asynchronous version of other utilities as well so you do not fall into the temptation of using a blocking synchronous call within an asynchronous operation. In this case I recommend you to use asyncio.sleep(5) for your purpose. You will need to import asyncio as well to use that function.

References:

Shunya
  • 2,344
  • 4
  • 16
  • 28