Search code examples
pythonfunctiondiscord.pybotswait

How can I make one part of my code wait for another function to return a Boolean value and then continue execution?


So I'm making a discord music bot in python using discord.py library. I want to create a queue of songs by creating a function trough which the source to the requested song has to pass. The function checks if the client is currently playing any audio by using if vc.is_playing() == True: and if yes then it should wait until vc.is_playing() == False: . After the audio is finished playing the function will return the source and another song starts playing.

The question is: How can I make one part of the code wait for another part to finish executing (finish playing audio) and then continue with the execution normally?

Here is the code of the incomplete function that should do the waiting:

async def wait_for_url(self, ctx, source, title):
        vc = ctx.voice_client
        while True:
            if vc.is_playing() == True:
                print("@Inside function - 1!@")
                **# Something that waits for client to stop playing should go here!**
                print("@Inside function - 2 - waiting should be over!@")
                time.sleep(5)
                url_final_u = source
                title_u = title
                print("@Inside function - 3 - returning!@")
                return url_final_u and title_u
            else:
                print("@Inside function - A - else condition met!@")
                url_final_u = source
                title_u = title
                return url_final_u and title_u

I will also provide code of the part of my /play command where the above function should be implemented:

vc = ctx.voice_client                                                   
self.queue_list.append(url_final_u)                                    
await ctx.send(f"{title_u} has been added to the queue!") 
                                                                          
if len(self.queue_list) > 0:                           
     print("@Before function!")                          
     await self.wait_for_url(ctx, url_final_u, title_u)
     ** # <--- This is the function in question.** 
     print("@After function!@")                       
     if vc.is_playing() == False:
                        
         time.sleep(5)

         await self.play_music(ctx, url_final_u, title_u)

All this code is inside a class commands(commands.Cog) cog.

I tried to look into os.wait() function and even tried asking GPT 3.5 which had suggested to use threading module with its .wait() function and wrote an example code. But when i tried to implement that it just didn't wait for the client to stop playing.

That is if I used threading correctly as I'm quite new to programming and might have just missed something very obvious, so i will gladly welcome every suggestion that will help me solve this problem.


Solution

  • This may help you

    • Use asyncio.sleep instead of time.sleep
    • Use asyncio.create_task
    async def wait_for_url(self, ctx, source, title):
        vc = ctx.voice_client
        while vc.is_playing():
            await asyncio.sleep(1)
    
        url_final_u = source
        title_u = title
        return url_final_u, title_u
    
    async def play_music_with_queue(self, ctx, url_final_u, title_u):
        vc = ctx.voice_client
        self.queue_list.append((url_final_u, title_u))
        await ctx.send(f"{title_u} has been added to the queue!")
    
        if not vc.is_playing() and not vc.is_paused():
            await asyncio.create_task(self.wait_for_url(ctx, url_final_u, title_u))
    
            if not vc.is_playing() and not vc.is_paused():
                await self.play_music(ctx, url_final_u, title_u)
    

    Note: Call play_music_with_queue() in your code instead of calling play_music() directly.