import logging from typing import Optional, List, AsyncGenerator, Tuple, Any, Dict from royalnet.bard.discord import YtdlDiscord from royalnet.serf.discord import Playable import discord log = logging.getLogger(__name__) class RoyalQueue(Playable): """A queue of :class:`YtdlDiscord` to be played in sequence.""" def __init__(self, start_with: Optional[List[YtdlDiscord]] = None): super().__init__() self.contents: List[YtdlDiscord] = [] self.now_playing: Optional[YtdlDiscord] = None if start_with is not None: self.contents = [*self.contents, *start_with] log.debug(f"Created new {self.__class__.__qualname__} containing: {self.contents}") async def _generator(self) \ -> AsyncGenerator[Optional["discord.AudioSource"], Tuple[Tuple[Any, ...], Dict[str, Any]]]: yield while True: log.debug(f"Dequeuing an item...") try: # Try to get the first YtdlDiscord of the queue self.now_playing: YtdlDiscord = self.contents.pop(0) except IndexError: # If there isn't anything, yield None log.debug(f"Nothing to dequeue, yielding None.") yield None continue log.debug(f"Yielding FileAudioSource from: {self.now_playing}") # Create a FileAudioSource from the YtdlDiscord # If the file hasn't been fetched / downloaded / converted yet, it will do so before yielding async with self.now_playing.spawn_audiosource() as fas: # Yield the resulting AudioSource yield fas # Delete the YtdlDiscord file log.debug(f"Deleting: {self.now_playing}") await self.now_playing.delete_asap() log.debug(f"Deleting: {self.now_playing.ytdl_file}") await self.now_playing.ytdl_file.delete_asap() log.debug(f"Deleted successfully!") self.now_playing = None