diff --git a/poetry.lock b/poetry.lock index 653e5c50..ea403a6f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -586,7 +586,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.6.5" +version = "5.6.6" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -867,7 +867,7 @@ python-versions = "*" version = "2020.3.24" [metadata] -content-hash = "f0931c9aade41f1ac239401a324cb550f0961b83c1759b5a84effb10e1bba7f2" +content-hash = "424a17455e19b7aa11d52d3a37548275adae578539f501d59c111b7f43c79dc1" python-versions = "^3.8" [metadata.files] @@ -1311,8 +1311,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.6.5-py3-none-any.whl", hash = "sha256:ee5d1774fc507cc1be291fefe5716ee7e6bec80ccf1ffd5a6d2278721c7a477b"}, - {file = "royalnet-5.6.5.tar.gz", hash = "sha256:4555bbdf2bc4c75e90f2b465a022178ad6cd6302906c0c5adfe7a7d6e1dbcb06"}, + {file = "royalnet-5.6.6-py3-none-any.whl", hash = "sha256:2793af4c09c364403400012a1b6e76cb012ab90c105bd512e6d21219d9ec2bbd"}, + {file = "royalnet-5.6.6.tar.gz", hash = "sha256:c2fc05049cd1a5185941458cf519ad46d871e475d0bb5e2ead968f148d27d836"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 30d27335..f2cb4d8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "~5.6.5" + version = "~5.6.6" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/utils/royalpool.py b/royalpack/utils/royalpool.py new file mode 100644 index 00000000..c594ca3c --- /dev/null +++ b/royalpack/utils/royalpool.py @@ -0,0 +1,55 @@ +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 +import random + + +log = logging.getLogger(__name__) + + +class RoyalPool(Playable): + """A pool of :class:`YtdlDiscord` that will be played in a loop.""" + def __init__(self, start_with: Optional[List[YtdlDiscord]] = None): + super().__init__() + self.full_pool: List[YtdlDiscord] = [] + self.remaining_pool: List[YtdlDiscord] = [] + self.now_playing: Optional[YtdlDiscord] = None + if start_with is not None: + self.full_pool = [*self.full_pool, *start_with] + log.debug(f"Created new {self.__class__.__qualname__} containing: {self.full_pool}") + + async def _generator(self) \ + -> AsyncGenerator[Optional["discord.AudioSource"], Tuple[Tuple[Any, ...], Dict[str, Any]]]: + yield + while True: + if len(self.remaining_pool) == 0: + if len(self.full_pool) == 0: + log.debug(f"Nothing in the pool, yielding None...") + yield None + continue + else: + self.remaining_pool = self.full_pool.copy() + random.shuffle(self.remaining_pool) + else: + log.debug(f"Dequeuing an item...") + # Get the first YtdlDiscord of the queue + self.now_playing: YtdlDiscord = self.remaining_pool.pop(0) + 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 + + async def destroy(self): + for file in self.full_pool: + log.debug(f"Deleting: {file}") + await file.delete_asap() + log.debug(f"Deleting: {file.ytdl_file}") + await file.ytdl_file.delete_asap() + log.debug(f"Deleted successfully!") + self.full_pool = [] + self.remaining_pool = [] + self.now_playing = None diff --git a/royalpack/utils/royalqueue.py b/royalpack/utils/royalqueue.py index 310ba55b..f1be3e96 100644 --- a/royalpack/utils/royalqueue.py +++ b/royalpack/utils/royalqueue.py @@ -44,3 +44,18 @@ class RoyalQueue(Playable): await self.now_playing.ytdl_file.delete_asap() log.debug(f"Deleted successfully!") self.now_playing = None + + async def destroy(self): + 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 + for file in self.contents: + log.debug(f"Deleting: {file}") + await file.delete_asap() + log.debug(f"Deleting: {file.ytdl_file}") + await file.ytdl_file.delete_asap() + log.debug(f"Deleted successfully!") + self.contents = []