original_docstring: 
          Add multiple songs to the queue
          entries must be a list of dicts with id set to the part that will be
          formatted to base url. if you want to provide arbitrary links you can
          use "%s" as base url and entries is a list of dicts with the id key
          set to the wanted url
          
docstring: Add multiple songs to the queue
  entries must be a list of dicts with id set to the part that will be
  formatted to base url. if you want to provide arbitrary links you can
  use "%s" as base url and entries is a list of dicts with the id key
  set to the wanted url
docstring_tokens: Add multiple songs to the queue entries must be a list of dicts with id set to the part that will be formatted to base url . if you want to provide arbitrary links you can use " %s " as base url and entries is a list of dicts with the id key set to the wanted url
code: async def add_songs(self, entries, title, maxlen, priority=False, channel=None,
                          no_message=False, base_url='https://www.youtube.com/watch?v=%s', **metadata):
          """
          Add multiple songs to the queue
          entries must be a list of dicts with id set to the part that will be
          formatted to base url. if you want to provide arbitrary links you can
          use "%s" as base url and entries is a list of dicts with the id key
          set to the wanted url
          """
          size = len(entries)
          if size > maxlen >= 0:  # Max playlist size
              await self.send(f'Playlist is too big. Max size is {maxlen}', channel=channel)
              return
  
          url = base_url
          if priority:
              await self.send('Playlists queued with playnow will be reversed except for the first song',
                              delete_after=60, channel=channel)
  
          message = await self.send(f'Processing {size} songs', channel=channel)
          t = time.time()
          songs = deque()
          first = True
          progress = 0
  
          async def progress_info():
              nonlocal message
              if message is None:
                  return
  
              while progress <= size:
                  try:
                      await asyncio.sleep(3)
                      t2 = time.time() - t
                      eta = progress / t2
                      if eta == 0:
                          eta = 'Undefined'
                      else:
                          eta = seconds2str(max(size / eta - t2, 0))
  
                      s = 'Loading playlist. Progress {}/{} {:.02%} \nETA {}'.format(progress, size, progress/size, eta)
                      await message.edit(content=s)
                  except asyncio.CancelledError:
                      await message.delete()
                      return
                  except discord.ClientException:
                      logger.exception('Failed to post progress')
                      return
  
              await message.delete()
  
          task = self.bot.loop.create_task(progress_info())
  
          async def _on_error(e):
              try:
                  if not no_message:
                      # skipcq: PYL-W0631
                      # We want to get the error for the current entry in the loop so
                      # we access the loop variable here
                      await channel.send('Failed to process {}'.format(entry.get('id')))
              except discord.HTTPException:
                  pass
  
              return False
  
          for entry in entries:
              entry_url = entry['url']
              if not valid_url(entry_url):
                  if entry['ie_key'].lower() != 'youtube':
                      await channel.send('Playlists currently not supported for this site')
                      return
  
                  entry_url = url % entry['id']
  
              progress += 1
  
              info = await self.downloader.extract_info(self.bot.loop,
                                                        url=entry_url,
                                                        download=False,
                                                        on_error=_on_error)
              if info is False or info is None:
                  continue
  
              if not info:
                  try:
                      if not no_message:
                          await channel.send('Failed to process {}'.format(entry.get('id')))
                  except discord.HTTPException:
                      pass
                  continue
  
              song = Song(playlist=self, config=self.bot.config, **metadata)
              song.info_from_dict(**info)
  
              if not priority:
                  await self._append_song(song)
              else:
                  if first:
                      await self._append_song(song, priority=priority)
                      first = False
                  else:
                      songs.append(song)
  
          task.cancel()
  
          if songs:
              await self._append_song(songs.popleft(), priority=priority)
              songs.reverse()
              for song in songs:
                  self.playlist.appendleft(song)
  
          if not no_message:
              if priority:
                  msg = 'Enqueued playlist %s to the top' % title
              else:
                  msg = 'Enqueued playlist %s' % title
              return await self.send(msg, delete_after=60, channel=channel)
code_tokens: async def add_songs ( self , entries , title , maxlen , priority = False , channel = None , no_message = False , base_url = 'https://www.youtube.com/watch?v=%s' , ** metadata ) : size = len ( entries ) if size > maxlen >= 0 : await self . send ( f'Playlist is too big. Max size is {maxlen}' , channel = channel ) return url = base_url if priority : await self . send ( 'Playlists queued with playnow will be reversed except for the first song' , delete_after = 60 , channel = channel ) message = await self . send ( f'Processing {size} songs' , channel = channel ) t = time . time ( ) songs = deque ( ) first = True progress = 0 async def progress_info ( ) : nonlocal message if message is None : return while progress <= size : try : await asyncio . sleep ( 3 ) t2 = time . time ( ) - t eta = progress / t2 if eta == 0 : eta = 'Undefined' else : eta = seconds2str ( max ( size / eta - t2 , 0 ) ) s = 'Loading playlist. Progress {}/{} {:.02%} \nETA {}' . format ( progress , size , progress / size , eta ) await message . edit ( content = s ) except asyncio . CancelledError : await message . delete ( ) return except discord . ClientException : logger . exception ( 'Failed to post progress' ) return await message . delete ( ) task = self . bot . loop . create_task ( progress_info ( ) ) async def _on_error ( e ) : try : if not no_message : await channel . send ( 'Failed to process {}' . format ( entry . get ( 'id' ) ) ) except discord . HTTPException : pass return False for entry in entries : entry_url = entry [ 'url' ] if not valid_url ( entry_url ) : if entry [ 'ie_key' ] . lower ( ) != 'youtube' : await channel . send ( 'Playlists currently not supported for this site' ) return entry_url = url % entry [ 'id' ] progress += 1 info = await self . downloader . extract_info ( self . bot . loop , url = entry_url , download = False , on_error = _on_error ) if info is False or info is None : continue if not info : try : if not no_message : await channel . send ( 'Failed to process {}' . format ( entry . get ( 'id' ) ) ) except discord . HTTPException : pass continue song = Song ( playlist = self , config = self . bot . config , ** metadata ) song . info_from_dict ( ** info ) if not priority : await self . _append_song ( song ) else : if first : await self . _append_song ( song , priority = priority ) first = False else : songs . append ( song ) task . cancel ( ) if songs : await self . _append_song ( songs . popleft ( ) , priority = priority ) songs . reverse ( ) for song in songs : self . playlist . appendleft ( song ) if not no_message : if priority : msg = 'Enqueued playlist %s to the top' % title else : msg = 'Enqueued playlist %s' % title return await self . send ( msg , delete_after = 60 , channel = channel )
short_docstring: Add multiple songs to the queue
  entries must be a list of dicts with id set to the part that will be
  formatted to base url.
short_docstring_tokens: Add multiple songs to the queue entries must be a list of dicts with id set to the part that will be formatted to base url .
comment: """
          Add multiple songs to the queue
          entries must be a list of dicts with id set to the part that will be
          formatted to base url. if you want to provide arbitrary links you can
          use "%s" as base url and entries is a list of dicts with the id key
          set to the wanted url
          """$SEP$# Max playlist size$SEP$# skipcq: PYL-W0631$SEP$# We want to get the error for the current entry in the loop so$SEP$# we access the loop variable here