pythonasynchronousasync-awaitdiscord.pyytdl

Play all songs in a queue


This is the code that I have:

@commands.command(pass_context=True, aliases= ["aq"])
async def add_queue(self, ctx, *, url):
  a = ctx.message.guild.id
  b = servers[a]
  global queue
  try: 
    b[len(b)] = url 
    user = ctx.message.author.mention
    await ctx.send(f'``{url}`` was added to the queue by {user}!')
  except:
    await ctx.send(f"Couldnt add {url} to the queue!")

@commands.command(pass_context=True, aliases= ["qp"], case_insensitive=True)
async def pq(self,ctx, number):
  a = ctx.message.guild.id
  b = servers[a]
  if int(number) in b:
    source = b[int(number)]
    self.cur_song_id = int(number)
    await ctx.send(f"**Now Playing:** {source}")
    await self.transformer(ctx, source)
    
async def transformer(self,ctx, url):
  player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=True)
  if not ctx.message.author.voice:
    await ctx.send("You are not connected to a voice channel!")
    return
  elif ctx.voice_client and ctx.voice_client.is_connected():
    print('Already connected to voice')
    pass
  else:
    channel = ctx.message.author.voice.channel
    await ctx.send(f'Connected to ``{channel}``')
    await channel.connect()
  ctx.voice_client.play(player)

I can create a separate queue for each server and add songs to it by the command:

-aq song_name

example queue:

Your current queue is {0: 'abcdefu', 1: 'stereo hearts', 2: 'shivers'}

I can play the songs in the queue with the command:

-pq 0 or -pq 1 or -pq 2

But the problem is that the bot only plays the one song and stops after it finishes, and I want the bot to play the next song after the current song finishes and keep going until the last song in the queue is played.

Please help me out with this....

Thanks In Advance!!!


Solution

  • So, to solve my problem, I implemented this code and it works.

    I passed my queue which is a dictionary, to transformer function, and a number which is defaulted to 0 (for queue to play from the start).

    And using after parameter in play function, I kept calling the function and kept iterating the number as long as it is less than the length of the queue.

    It auto-plays the songs in the queue.

    I know this code works but, if any improvements can be made, I'm open to suggestions.

    async def transformer(self,ctx, number, que):
      player = await YTDLSource.from_url(que[number], loop=self.bot.loop,stream=True)
      await ctx.send(f"**Now Playing:** {que[number]}")
      ctx.voice_client.play(player, after=lambda e: asyncio.run_coroutine_threadsafe(self.transformer(ctx,number+1 , que),self.bot.loop) if number < len(que) else ctx.voice_client.pause())
    

    Thanks!.