From 8ac80c216fc1d3ec7d62e12d3c8cac223a394939 Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Fri, 25 Mar 2022 14:31:37 -0400 Subject: [PATCH] Adding Reset and Shuffle Controller and some fix --- Commands/Music.py | 43 ++++----- Controllers/AbstractController.py | 24 ++++- Controllers/LoopController.py | 3 +- Controllers/PlayerController.py | 8 +- Controllers/QueueController.py | 11 +-- Controllers/ResetController.py | 20 ++++ Controllers/ShuffleController.py | 26 +++++ Music/Player.py | 151 ------------------------------ Views/Embeds.py | 33 +++++-- 9 files changed, 128 insertions(+), 191 deletions(-) create mode 100644 Controllers/ResetController.py create mode 100644 Controllers/ShuffleController.py diff --git a/Commands/Music.py b/Commands/Music.py index 35e639a..5186159 100644 --- a/Commands/Music.py +++ b/Commands/Music.py @@ -1,4 +1,3 @@ -from msilib.schema import ControlEvent from typing import Dict from discord import Guild, Client, Embed from discord.ext import commands @@ -10,6 +9,8 @@ from Controllers.MoveController import MoveController from Controllers.NowPlayingController import NowPlayingController from Controllers.PlayerController import PlayersController from Controllers.RemoveController import RemoveController +from Controllers.ResetController import ResetController +from Controllers.ShuffleController import ShuffleController from Music.Player import Player from Utils.Utils import is_connected from Controllers.SkipController import SkipController @@ -70,12 +71,11 @@ class Music(commands.Cog): @commands.command(name="queue", help=helper.HELP_QUEUE, description=helper.HELP_QUEUE_LONG, aliases=['q', 'fila']) async def queue(self, ctx: Context) -> None: - player = self.__get_player(ctx) - if player is None: - return + controller = QueueController(ctx, self.__bot) - embed = await player.queue() - await ctx.send(embed=embed) + response = await controller.run() + view2 = EmbedView(response) + await view2.run() @commands.command(name="skip", help=helper.HELP_SKIP, description=helper.HELP_SKIP_LONG, aliases=['s', 'pular']) async def skip(self, ctx: Context) -> None: @@ -175,12 +175,13 @@ class Music(commands.Cog): @commands.command(name='shuffle', help=helper.HELP_SHUFFLE, description=helper.HELP_SHUFFLE_LONG, aliases=['aleatorio']) async def shuffle(self, ctx: Context) -> None: - player = self.__get_player(ctx) - if player is None: - return - else: - description = await player.shuffle() - await self.__send_embed(ctx, self.__config.SONG_PLAYER, description, 'blue') + controller = ShuffleController(ctx, self.__bot) + + response = await controller.run() + view1 = EmbedView(response) + view2 = EmoteView(response) + await view1.run() + await view2.run() @commands.command(name='move', help=helper.HELP_MOVE, description=helper.HELP_MOVE_LONG, aliases=['m', 'mover']) async def move(self, ctx: Context, pos1, pos2='1') -> None: @@ -204,19 +205,13 @@ class Music(commands.Cog): @commands.command(name='reset', help=helper.HELP_RESET, description=helper.HELP_RESET_LONG, aliases=['resetar']) async def reset(self, ctx: Context) -> None: - player = self.__get_player(ctx) - try: - await player.force_stop() - await player.stop() - self.__guilds[ctx.guild] = Player(self.__bot, ctx.guild) - player = self.__get_player(ctx) - await player.force_stop() - except Exception as e: - print(f'DEVELOPER NOTE -> Reset Error: {e}') + controller = ResetController(ctx, self.__bot) - self.__guilds[ctx.guild] = Player(self.__bot, ctx.guild) - player = self.__get_player(ctx) - print(f'Player for guild {ctx.guild} created') + response = await controller.run() + view1 = EmbedView(response) + view2 = EmoteView(response) + await view1.run() + await view2.run() async def __send_embed(self, ctx: Context, title='', description='', colour='grey') -> None: try: diff --git a/Controllers/AbstractController.py b/Controllers/AbstractController.py index 7c0ba20..8f53a88 100644 --- a/Controllers/AbstractController.py +++ b/Controllers/AbstractController.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod +from typing import List from discord.ext.commands import Context -from discord import Client, Guild +from discord import Client, Guild, ClientUser, Member from Controllers.PlayerController import PlayersController from Music.Player import Player from Controllers.ControllerResponse import ControllerResponse @@ -16,14 +17,29 @@ class AbstractController(ABC): self.__player: Player = self.__controller.get_player(ctx.guild) self.__guild: Guild = ctx.guild self.__ctx: Context = ctx + self.__bot_user: ClientUser = self.__bot.user + self.__id = self.__bot_user.id self.__config = Configs() self.__helper = Helper() self.__embeds = Embeds() + self.__bot_member: Member = self.__get_member() @abstractmethod async def run(self) -> ControllerResponse: pass + @property + def id(self) -> int: + return self.__id + + @property + def bot_member(self) -> Member: + return self.__bot_member + + @property + def bot_user(self) -> ClientUser: + return self.__bot_user + @property def guild(self) -> Guild: return self.__guild @@ -55,3 +71,9 @@ class AbstractController(ABC): @property def embeds(self) -> Embeds: return self.__embeds + + def __get_member(self) -> Member: + guild_members: List[Member] = self.__guild.members + for member in guild_members: + if member.id == self.__id: + return member diff --git a/Controllers/LoopController.py b/Controllers/LoopController.py index a7574f8..843e4b2 100644 --- a/Controllers/LoopController.py +++ b/Controllers/LoopController.py @@ -30,11 +30,10 @@ class LoopController(AbstractController): embed = self.embeds.LOOP_ALL_ACTIVATED() return ControllerResponse(self.ctx, embed) elif args == 'off': - self.player.playlist.loop_all() + self.player.playlist.loop_off() embed = self.embeds.LOOP_DISABLE() return ControllerResponse(self.ctx, embed) else: - self.player.playlist.loop_all() error = BadCommandUsage() embed = self.embeds.BAD_LOOP_USE() return ControllerResponse(self.ctx, embed, error) diff --git a/Controllers/PlayerController.py b/Controllers/PlayerController.py index 2aa9b18..a6fd1a9 100644 --- a/Controllers/PlayerController.py +++ b/Controllers/PlayerController.py @@ -1,6 +1,6 @@ from typing import Dict, List, Union from Config.Singleton import Singleton -from discord import Guild, Client, VoiceClient +from discord import Guild, Client, VoiceClient, Member from Music.Player import Player @@ -43,3 +43,9 @@ class PlayersController(Singleton): print(f'Player for guild {guild.name} created') return players + + def __get_guild_bot_member(self, guild: Guild) -> Member: + members: List[Member] = guild.members + for member in members: + if member.id == self.__bot.user.id: + return member diff --git a/Controllers/QueueController.py b/Controllers/QueueController.py index 4d2aa25..231ea63 100644 --- a/Controllers/QueueController.py +++ b/Controllers/QueueController.py @@ -13,23 +13,22 @@ class QueueController(AbstractController): async def run(self) -> ControllerResponse: if self.player.playlist.looping_one: - info = self.player.playlist.current - embed = self.embeds.ONE_SONG_LOOPING(info) + song = self.player.playlist.current + embed = self.embeds.ONE_SONG_LOOPING(song.info) return ControllerResponse(self.ctx, embed) songs_preload = self.player.playlist.songs_to_preload if len(songs_preload) == 0: - embed = self.embeds.EMPTY_QUEUE + embed = self.embeds.EMPTY_QUEUE() return ControllerResponse(self.ctx, embed) await self.__down.preload(songs_preload) if self.player.playlist.looping_all: - title = self.__config.ALL_SONGS_LOOPING + title = self.config.ALL_SONGS_LOOPING else: - title = self.__config.QUEUE_TITLE + title = self.config.QUEUE_TITLE - title = self.config.QUEUE_TITLE total_time = format_time(sum([int(song.duration if song.duration else 0) for song in songs_preload])) total_songs = len(self.player.playlist) diff --git a/Controllers/ResetController.py b/Controllers/ResetController.py new file mode 100644 index 0000000..43e0aa6 --- /dev/null +++ b/Controllers/ResetController.py @@ -0,0 +1,20 @@ +from discord.ext.commands import Context +from discord import Client, Member +from Controllers.AbstractController import AbstractController +from Controllers.ControllerResponse import ControllerResponse +from Controllers.PlayerController import PlayersController + + +class ResetController(AbstractController): + def __init__(self, ctx: Context, bot: Client) -> None: + super().__init__(ctx, bot) + self.__controller = PlayersController(self.bot) + + async def run(self) -> ControllerResponse: + try: + await self.player.force_stop() + await self.bot_member.move_to(None) + self.__controller.reset_player(self.guild) + return ControllerResponse(self.ctx) + except Exception as e: + print(f'DEVELOPER NOTE -> Reset Error: {e}') diff --git a/Controllers/ShuffleController.py b/Controllers/ShuffleController.py new file mode 100644 index 0000000..c01195e --- /dev/null +++ b/Controllers/ShuffleController.py @@ -0,0 +1,26 @@ +from discord.ext.commands import Context +from discord import Client +from Controllers.AbstractController import AbstractController +from Controllers.ControllerResponse import ControllerResponse +from Exceptions.Exceptions import UnknownError +from Music.Downloader import Downloader + + +class ShuffleController(AbstractController): + def __init__(self, ctx: Context, bot: Client) -> None: + super().__init__(ctx, bot) + self.__down = Downloader() + + async def run(self) -> ControllerResponse: + try: + self.player.playlist.shuffle() + songs = self.player.playlist.songs_to_preload + + await self.__down.preload(songs) + embed = self.embeds.SONGS_SHUFFLED() + return ControllerResponse(self.ctx, embed) + except Exception as e: + print(f'DEVELOPER NOTE -> Error Shuffling: {e}') + error = UnknownError() + embed = self.embeds.ERROR_SHUFFLING() + return ControllerResponse(self.ctx, embed, error) diff --git a/Music/Player.py b/Music/Player.py index 079c813..68ed5d3 100644 --- a/Music/Player.py +++ b/Music/Player.py @@ -176,62 +176,6 @@ class Player(commands.Cog): await self.__play_music(ctx, song) - async def queue(self) -> Embed: - if self.__playlist.looping_one: - info = self.__playlist.current.info - title = self.__config.ONE_SONG_LOOPING - return self.__format_embed(info, title) - - songs_preload = self.__playlist.songs_to_preload - - if len(songs_preload) == 0: - title = self.__config.SONG_PLAYER - text = self.__config.EMPTY_QUEUE - - else: - if self.__playlist.looping_all: - title = self.__config.ALL_SONGS_LOOPING - else: - title = self.__config.QUEUE_TITLE - - await self.__down.preload(songs_preload) - - total_time = format_time(sum([int(song.duration if song.duration else 0) - for song in songs_preload])) - total_songs = len(self.__playlist) - - text = f'šŸ“œ Queue length: {total_songs} | āŒ› Duration: `{total_time}` downloaded \n\n' - - for pos, song in enumerate(songs_preload, start=1): - song_name = song.title if song.title else self.__config.SONG_DOWNLOADING - text += f"**`{pos}` - ** {song_name} - `{format_time(song.duration)}`\n" - - embed = Embed( - title=title, - description=text, - colour=self.__config.COLOURS['blue'] - ) - - return embed - - def history(self) -> Embed: - history = self.__playlist.songs_history - - if len(history) == 0: - text = self.__config.HISTORY_EMPTY - - else: - text = f'\nšŸ“œ History Length: {len(history)} | Max: {self.__config.MAX_SONGS_HISTORY}\n' - for pos, song in enumerate(history, start=1): - text += f"**`{pos}` - ** {song.title} - `{format_time(song.duration)}`\n" - - embed = Embed( - title=self.__config.HISTORY_TITLE, - description=text, - colour=self.__config.COLOURS['blue'] - ) - return embed - async def stop(self) -> bool: if self.__guild.voice_client is None: return False @@ -255,101 +199,6 @@ class Player(commands.Cog): except Exception as e: print(f'DEVELOPER NOTE -> Force Stop Error: {e}') - async def pause(self) -> bool: - if self.__guild.voice_client == None: - return False - - if self.__guild.voice_client.is_playing(): - self.__guild.voice_client.pause() - return True - - async def resume(self) -> bool: - if self.__guild.voice_client == None: - return False - - if self.__guild.voice_client.is_paused(): - self.__guild.voice_client.resume() - return True - - async def loop(self, args: str) -> str: - args = args.lower() - if self.__playlist.current == None: - return self.__config.PLAYER_NOT_PLAYING - - if args == 'one': - description = self.__playlist.loop_one() - elif args == 'all': - description = self.__playlist.loop_all() - elif args == 'off': - description = self.__playlist.loop_off() - else: - raise commands.UserInputError(self.__config.MY_ERROR_BAD_COMMAND) - - return description - - async def clear(self) -> None: - self.__playlist.clear() - - async def now_playing(self) -> Embed: - if not self.__playing: - embed = Embed( - title=self.__config.SONG_PLAYER, - description=self.__config.PLAYER_NOT_PLAYING, - colour=self.__config.COLOURS['blue'] - ) - return embed - - if self.__playlist.looping_one: - title = self.__config.ONE_SONG_LOOPING - else: - title = self.__config.SONG_PLAYING - - current_song = self.__playlist.current - embed = self.__format_embed(current_song.info, title) - - return embed - - async def shuffle(self) -> str: - try: - self.__playlist.shuffle() - songs = self.__playlist.songs_to_preload - - await self.__down.preload(songs) - return self.__config.SONGS_SHUFFLED - except: - return self.__config.ERROR_SHUFFLING - - async def move(self, pos1, pos2='1') -> str: - if not self.__playing: - return self.__config.PLAYER_NOT_PLAYING - - try: - pos1 = int(pos1) - pos2 = int(pos2) - - except: - return self.__config.ERROR_NUMBER - - result = self.__playlist.move_songs(pos1, pos2) - - songs = self.__playlist.songs_to_preload - await self.__down.preload(songs) - return result - - async def remove(self, position) -> str: - """Remove a song from the queue in the position""" - if not self.__playing: - return self.__config.PLAYER_NOT_PLAYING - - try: - position = int(position) - - except: - return self.__config.ERROR_NUMBER - - result = self.__playlist.remove_song(position) - return result - def __format_embed(self, info: dict, title='', position='Playing Now') -> Embed: """Configure the embed to show the song information""" embedvc = Embed( diff --git a/Views/Embeds.py b/Views/Embeds.py index 7b3036f..5c6b237 100644 --- a/Views/Embeds.py +++ b/Views/Embeds.py @@ -171,26 +171,47 @@ class Embeds: ) return embed - def LOOP_ONE_ACTIVATED(self) -> Embed: + def ERROR_SHUFFLING(self) -> Embed: embed = Embed( title=self.__config.SONG_PLAYER, - description=self.__config.LOOP_ONE_ACTIVATE, + description=self.__config.ERROR_SHUFFLING, + colour=self.__colors.BLACK + ) + return embed + + def SONGS_SHUFFLED(self) -> Embed: + embed = Embed( + title=self.__config.SONG_PLAYER, + description=self.__config.SONGS_SHUFFLED, + colour=self.__colors.BLUE + ) + return embed + + def LOOP_ONE_ACTIVATED(self) -> Embed: + embed = Embed( + title=self.__config.LOOP_ONE_ACTIVATE, colour=self.__colors.BLUE ) return embed def LOOP_ALL_ACTIVATED(self) -> Embed: embed = Embed( - title=self.__config.SONG_PLAYER, - description=self.__config.LOOP_ALL_ACTIVATE, + title=self.__config.LOOP_ALL_ACTIVATE, colour=self.__colors.BLUE ) return embed + def ERROR_DUE_LOOP_ONE_ON(self) -> Embed: + embed = Embed( + title=self.__config.BAD_COMMAND_TITLE, + description=self.__config.ERROR_DUE_LOOP_ONE_ON, + colour=self.__colors.BLACK + ) + return embed + def LOOP_DISABLE(self) -> Embed: embed = Embed( - title=self.__config.SONG_PLAYER, - description=self.__config.LOOP_DISABLE, + title=self.__config.LOOP_DISABLE, colour=self.__colors.BLUE ) return embed