From c41a6a6c8a4bf3154fd1d234b02e5df998763d07 Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Tue, 11 Jan 2022 21:40:20 -0400 Subject: [PATCH 1/6] Adding new config variables to prev command --- .gitignore | 1 + config/config.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/.gitignore b/.gitignore index 9c83cbc..20f29c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +assets/ __pycache__ .env .cache diff --git a/config/config.py b/config/config.py index e69aa64..060b7e4 100644 --- a/config/config.py +++ b/config/config.py @@ -21,6 +21,7 @@ MAX_API_CETUS_TRIES = 10 MAX_API_CAMBION_TRIES = 10 MAX_API_FISSURES_TRIES = 10 MAX_PRELOAD_SONGS = 10 +MAX_SONGS_HISTORY = 10 SONGINFO_UPLOADER = "Uploader: " SONGINFO_DURATION = "Duration: " @@ -34,8 +35,10 @@ HELP_LOOP = '(one/all/off) - Control the loop of songs.' HELP_NP = 'Show the info of the current song.' HELP_QUEUE = f'Show the first {MAX_PRELOAD_SONGS} songs in queue.' HELP_PAUSE = 'Pauses the song player.' +HELP_PREV = 'Return to play the previous song.' HELP_SHUFFLE = 'Shuffle the songs playing.' HELP_PLAY = '(title/youtube/spotify) - Plays a song.' +HELP_HISTORY = f'Show the last {MAX_SONGS_HISTORY} played songs history' HELP_MOVE = '(x, y) - Moves a song from position x to y in queue.' HELP_REMOVE = '(x, -1) - Remove a song in the position x or -1 for the last song.' HELP_RESET = 'Reset the Player of a server.' @@ -61,6 +64,10 @@ SONG_RESUMED = '▶️ Song playing' EMPTY_QUEUE = f'❌ Song queue is empty, use {BOT_PREFIX}play to add new songs' SONG_DOWNLOADING = '📥 Downloading...' +HISTORY_TITLE = '🎧 Played Songs' +HISTORY_EMPTY = '❌ There is no musics in history' + + SONGS_SHUFFLED = '🔀 Songs shuffled successfully' ERROR_SHUFFLING = '❌ Error while shuffling the songs' ERROR_MOVING = '❌ Error while moving the songs' @@ -71,6 +78,8 @@ COMMAND_NOT_FOUND = f'❌ Command not found, type {BOT_PREFIX}help to see all co UNKNOWN_ERROR = '❌ Unknown Error' ERROR_MISSING_ARGUMENTS = f'❌ Missing arguments in this function. Type {BOT_PREFIX}help to see all commands' ERROR_WHILE_REQUESTING = 'O banco de dados dos cara tá off, bando de vagabundo, tenta depois aí bicho' +NOT_PREVIOUS = '❌ There is none previous song to play' +PLAYER_NOT_PLAYING = f'❌ No song playing. Use {BOT_PREFIX}play to start the player' SONG_MOVED_SUCCESSFULLY = 'Song `{}` in position `{}` moved with `{}` in position `{}` successfully' SONG_REMOVED_SUCCESSFULLY = 'Song `{}` removed successfully' @@ -83,6 +92,7 @@ LOOP_ALL_ACTIVATE = '🔁 Looping all songs' LOOP_ONE_ACTIVATE = '🔂 Looping the current song' LOOP_DISABLE = '➡️ Loop disabled' LOOP_ALREADY_DISABLE = '❌ Loop is already disabled' +LOOP_ON = f'❌ This command cannot be invoked with any loop activated. Use {BOT_PREFIX}loop off to disable loop' SONGS_PLAYING_TITLES = [ONE_SONG_LOOPING, ALL_SONGS_LOOPING, SONG_PLAYING] From 5063c45e875c41c683889e52208e9551c71e4512 Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Tue, 11 Jan 2022 21:46:09 -0400 Subject: [PATCH 2/6] Adding prev and history command --- vulkan/commands/Music.py | 25 ++++++++++++++- vulkan/music/Player.py | 69 ++++++++++++++++++++++++++++++++++++++-- vulkan/music/Playlist.py | 58 +++++++++++++++++++++++++-------- 3 files changed, 135 insertions(+), 17 deletions(-) diff --git a/vulkan/commands/Music.py b/vulkan/commands/Music.py index 537a613..e7935b8 100644 --- a/vulkan/commands/Music.py +++ b/vulkan/commands/Music.py @@ -49,7 +49,7 @@ class Music(commands.Cog): if player == None: return else: - await player.skip() + await player.skip(ctx) @commands.command(name='stop', help=config.HELP_STOP, aliases=['parar']) async def stop(self, ctx) -> None: @@ -79,6 +79,29 @@ class Music(commands.Cog): if success: await self.__send_embed(ctx, config.SONG_PLAYER, config.SONG_RESUMED, 'blue') + @commands.command(name='prev', help=config.HELP_PREV, aliases=['anterior']) + async def prev(self, ctx) -> None: + player = self.__get_player(ctx) + if player == None: + return + + if is_connected(ctx) == None: + success = await player.connect(ctx) + if success == False: + await self.__send_embed(ctx, config.ERROR_TITLE, config.NO_CHANNEL, 'red') + return + + await player.play_prev(ctx) + + @commands.command(name='history', help=config.HELP_HISTORY, aliases=['historico']) + async def history(self, ctx) -> None: + player = self.__get_player(ctx) + if player == None: + return + else: + embed = player.history() + await ctx.send(embed=embed) + @commands.command(name='loop', help=config.HELP_LOOP, aliases=['l', 'repeat']) async def loop(self, ctx, args: str) -> None: player = self.__get_player(ctx) diff --git a/vulkan/music/Player.py b/vulkan/music/Player.py index 5a813b3..1d70a34 100644 --- a/vulkan/music/Player.py +++ b/vulkan/music/Player.py @@ -22,11 +22,14 @@ class Player(commands.Cog): self.__timer = Timer(self.__timeout_handler) self.__playing = False + # Flag to control if the player should stop totally the playing + self.__force_stop = False + self.YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist': 'True'} self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'} - async def connect(self, ctx) -> None: + async def connect(self, ctx) -> bool: if not ctx.author.voice: return False @@ -35,6 +38,10 @@ class Player(commands.Cog): return True def __play_next(self, error, ctx) -> None: + if self.__force_stop: # If it's forced to stop player + self.__force_stop = False + return + song = self.__playlist.next_song() if song != None: @@ -125,6 +132,34 @@ class Player(commands.Cog): first_song = self.__playlist.next_song() await self.__play_music(ctx, first_song) + async def play_prev(self, ctx) -> None: + """Stop the currently playing cycle, load the previous song and play""" + if self.__playlist.looping_one or self.__playlist.looping_all: # Do not allow play if loop + embed = discord.Embed( + title=config.SONG_PLAYER, + description=config.LOOP_ON, + colour=config.COLOURS['blue'] + ) + await ctx.send(embed=embed) + return + + song = self.__playlist.prev_song() # Prepare the prev song to play again + if song == None: + embed = discord.Embed( + title=config.SONG_PLAYER, + description=config.NOT_PREVIOUS, + colour=config.COLOURS['blue'] + ) + await ctx.send(embed=embed) + else: + if self.__guild.voice_client.is_playing() or self.__guild.voice_client.is_paused(): + # Will forbidden next_song to execute after stopping current player + self.__force_stop = True + self.__guild.voice_client.stop() + self.__playing = False + + await self.__play_music(ctx, song) + async def queue(self) -> discord.Embed: if self.__playlist.looping_one: info = self.__playlist.current.info @@ -163,13 +198,40 @@ class Player(commands.Cog): return embed - async def skip(self) -> bool: + async def skip(self, ctx) -> bool: + if self.__playlist.looping_one: + embed = discord.Embed( + title=config.SONG_PLAYER, + description=config.LOOP_ON, + colour=config.COLOURS['blue'] + ) + await ctx.send(embed=embed) + return False + if self.__guild.voice_client != None: self.__guild.voice_client.stop() return True else: return False + def history(self) -> discord.Embed: + history = self.__playlist.songs_history + + if len(history) == 0: + text = config.HISTORY_EMPTY + + else: + text = f'\n📜 History Length: {len(history)} | Max: {config.MAX_SONGS_HISTORY}\n' + for pos, song in enumerate(history, start=1): + text += f"**`{pos}` - ** {song.title} - `{format_time(song.duration)}`\n" + + embed = discord.Embed( + title=config.HISTORY_TITLE, + description=text, + colour=config.COLOURS['blue'] + ) + return embed + async def stop(self) -> bool: if self.__guild.voice_client == None: return False @@ -199,6 +261,9 @@ class Player(commands.Cog): async def loop(self, args: str) -> str: args = args.lower() + if self.__playlist.current == None: + return config.PLAYER_NOT_PLAYING + if args == 'one': description = self.__playlist.loop_one() elif args == 'all': diff --git a/vulkan/music/Playlist.py b/vulkan/music/Playlist.py index 7329f4b..1745fb1 100644 --- a/vulkan/music/Playlist.py +++ b/vulkan/music/Playlist.py @@ -12,13 +12,16 @@ class Playlist(IPlaylist): def __init__(self) -> None: self.__queue = deque() # Store the musics to play self.__songs_history = deque() # Store the musics played - self.__name_history = deque() # Store the name of musics played self.__looping_one = False self.__looping_all = False self.__current: Song = None + @property + def songs_history(self) -> deque: + return self.__songs_history + @property def looping_one(self) -> bool: return self.__looping_one @@ -39,28 +42,46 @@ class Playlist(IPlaylist): return len(self.__queue) def next_song(self) -> Song: - """Return the next song to play""" + """Return the next song to play in a normal playlist flow""" if self.__current == None and len(self.__queue) == 0: return None played_song = self.__current - if self.__looping_one: # Insert the current song to play again - self.__queue.appendleft(played_song) + # Att played song info + if played_song != None: + if not self.__looping_one and not self.__looping_all: + if played_song.problematic == False: + self.__songs_history.appendleft(played_song) - if self.__looping_all: # Insert the current song in the end of queue - self.__queue.append(played_song) + if len(self.__songs_history) > config.MAX_SONGS_HISTORY: + self.__songs_history.pop() # Remove the older - while True: - if len(self.__queue) == 0: - return None + elif self.__looping_one: # Insert the current song to play again + self.__queue.appendleft(played_song) - self.__current = self.__queue[0] - self.__queue.popleft() - self.__name_history.append(self.__current.identifier) - self.__songs_history.append(self.__current) + elif self.__looping_all: # Insert the current song in the end of queue + self.__queue.append(played_song) - return self.__current + # Get the new song + if len(self.__queue) == 0: + return None + + self.__current = self.__queue.popleft() + + return self.__current + + def prev_song(self) -> Song: + """If playing return it to queue and return the previous song to play""" + if len(self.__songs_history) == 0: + return None + else: + if self.__current != None: + self.__queue.appendleft(self.__current) + + last_song = self.__songs_history.popleft() # Get the last song + self.__current = last_song + return self.__current # return the song def add_song(self, identifier: str, requester: str) -> Song: """Create a song object, add to queue and return it""" @@ -164,3 +185,12 @@ class Playlist(IPlaylist): song_name = song.title if song.title else song.identifier return config.SONG_REMOVED_SUCCESSFULLY.format(song_name) + + def history(self) -> list: + """Return a list with the song title of all played songs""" + titles = [] + for song in self.__songs_history: + title = song.title if song.title else 'Unknown' + titles.append(title) + + return titles From ea5245cf95ac4f71032b95498db2eca0aee83b31 Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Wed, 12 Jan 2022 09:40:25 -0400 Subject: [PATCH 3/6] Removing some useless modules and spliting config file to help file too --- config/config.py | 79 +++++++----------------- config/help.py | 43 +++++++++++++ vulkan/commands/Phrases.py | 60 ------------------ vulkan/commands/Warframe.py | 118 ------------------------------------ 4 files changed, 65 insertions(+), 235 deletions(-) create mode 100644 config/help.py delete mode 100644 vulkan/commands/Phrases.py delete mode 100644 vulkan/commands/Warframe.py diff --git a/config/config.py b/config/config.py index 060b7e4..1efbb78 100644 --- a/config/config.py +++ b/config/config.py @@ -1,13 +1,8 @@ from decouple import config -CETUS_API = config('CETUS_API') -CAMBION_API = config('CAMBION_API') -FISSURES_API = config('FISSURES_API') BOT_TOKEN = config('BOT_TOKEN') SPOTIFY_ID = config('SPOTIFY_ID') SPOTIFY_SECRET = config('SPOTIFY_SECRET') -SECRET_MESSAGE = config('SECRET_MESSAGE') -PHRASES_API = config('PHRASES_API') BOT_PREFIX = '!' VC_TIMEOUT = 600 @@ -16,43 +11,17 @@ STARTUP_MESSAGE = 'Starting Vulkan...' STARTUP_COMPLETE_MESSAGE = 'Vulkan is now operating.' MAX_PLAYLIST_LENGTH = 50 -MAX_API_PHRASES_TRIES = 10 -MAX_API_CETUS_TRIES = 10 -MAX_API_CAMBION_TRIES = 10 -MAX_API_FISSURES_TRIES = 10 MAX_PRELOAD_SONGS = 10 -MAX_SONGS_HISTORY = 10 +MAX_SONGS_HISTORY = 15 + +INVITE_MESSAGE = 'To invite Vulkan to your own server, click [here]({})' SONGINFO_UPLOADER = "Uploader: " SONGINFO_DURATION = "Duration: " SONGINFO_REQUESTER = 'Requester: ' -HELP_SKIP = 'Skip the current playing song.' -HELP_RESUME = 'Resumes the song player.' -HELP_CLEAR = 'Clear the queue.' -HELP_STOP = 'Stop the song player, removing Vulkan from voice channel.' -HELP_LOOP = '(one/all/off) - Control the loop of songs.' -HELP_NP = 'Show the info of the current song.' -HELP_QUEUE = f'Show the first {MAX_PRELOAD_SONGS} songs in queue.' -HELP_PAUSE = 'Pauses the song player.' -HELP_PREV = 'Return to play the previous song.' -HELP_SHUFFLE = 'Shuffle the songs playing.' -HELP_PLAY = '(title/youtube/spotify) - Plays a song.' -HELP_HISTORY = f'Show the last {MAX_SONGS_HISTORY} played songs history' -HELP_MOVE = '(x, y) - Moves a song from position x to y in queue.' -HELP_REMOVE = '(x, -1) - Remove a song in the position x or -1 for the last song.' -HELP_RESET = 'Reset the Player of a server.' -HELP_WARFRAME = f'({BOT_PREFIX}warframe help for more).' -HELP_RANDOM = '(x) - Return a random number between 1 and x.' -HELP_ESCOLHA = '(x, y, z...) - Choose randomly one item passed.' -HELP_CARA = 'Return cara or coroa.' -HELP_DROP = '(user_name) - Try to remove the user from the current voice channel.' -HELP_FRASE = "Send a randomly phrase, perhaps you get the secret." -HELP_HELP = 'This command :)' -HELP_LONG_LOOP = 'Loop Command Help\nOne - Start looping the current song\nAll - Start looping all songs in queue\nOff - Disable the song loop' - SONGS_ADDED = 'You added {} songs to the queue' -SONG_ADDED = 'You added the song {} to the queue' +SONG_ADDED = 'You added the song `{}` to the queue' SONG_ADDED_TWO = '🎧 Song added to the queue' SONG_PLAYING = '🎧 Song playing now' SONG_PLAYER = '🎧 Song Player' @@ -61,25 +30,11 @@ ONE_SONG_LOOPING = '🎧 Looping One Song' ALL_SONGS_LOOPING = '🎧 Looping All Songs' SONG_PAUSED = '⏸️ Song paused' SONG_RESUMED = '▶️ Song playing' -EMPTY_QUEUE = f'❌ Song queue is empty, use {BOT_PREFIX}play to add new songs' +EMPTY_QUEUE = f'📜 Song queue is empty, use {BOT_PREFIX}play to add new songs' SONG_DOWNLOADING = '📥 Downloading...' HISTORY_TITLE = '🎧 Played Songs' -HISTORY_EMPTY = '❌ There is no musics in history' - - -SONGS_SHUFFLED = '🔀 Songs shuffled successfully' -ERROR_SHUFFLING = '❌ Error while shuffling the songs' -ERROR_MOVING = '❌ Error while moving the songs' -LENGTH_ERROR = '❌ Numbers must be between 1 and queue length, use -1 for the last song' -ERROR_NUMBER = '❌ This command require a number' -ERROR_PLAYING = '❌ Error while playing songs' -COMMAND_NOT_FOUND = f'❌ Command not found, type {BOT_PREFIX}help to see all commands' -UNKNOWN_ERROR = '❌ Unknown Error' -ERROR_MISSING_ARGUMENTS = f'❌ Missing arguments in this function. Type {BOT_PREFIX}help to see all commands' -ERROR_WHILE_REQUESTING = 'O banco de dados dos cara tá off, bando de vagabundo, tenta depois aí bicho' -NOT_PREVIOUS = '❌ There is none previous song to play' -PLAYER_NOT_PLAYING = f'❌ No song playing. Use {BOT_PREFIX}play to start the player' +HISTORY_EMPTY = '📜 There is no musics in history' SONG_MOVED_SUCCESSFULLY = 'Song `{}` in position `{}` moved with `{}` in position `{}` successfully' SONG_REMOVED_SUCCESSFULLY = 'Song `{}` removed successfully' @@ -94,14 +49,24 @@ LOOP_DISABLE = '➡️ Loop disabled' LOOP_ALREADY_DISABLE = '❌ Loop is already disabled' LOOP_ON = f'❌ This command cannot be invoked with any loop activated. Use {BOT_PREFIX}loop off to disable loop' -SONGS_PLAYING_TITLES = [ONE_SONG_LOOPING, ALL_SONGS_LOOPING, SONG_PLAYING] - +SONGS_SHUFFLED = '🔀 Songs shuffled successfully' +ERROR_SHUFFLING = '❌ Error while shuffling the songs' +ERROR_MOVING = '❌ Error while moving the songs' +LENGTH_ERROR = '❌ Numbers must be between 1 and queue length, use -1 for the last song' +ERROR_NUMBER = '❌ This command require a number' +ERROR_PLAYING = '❌ Error while playing songs' +COMMAND_NOT_FOUND = f'❌ Command not found, type {BOT_PREFIX}help to see all commands' +UNKNOWN_ERROR = f'❌ Unknown Error, if needed, use {BOT_PREFIX}reset to reset the player of your server' +ERROR_MISSING_ARGUMENTS = f'❌ Missing arguments in this function. Type {BOT_PREFIX}help to see all commands' +NOT_PREVIOUS = '❌ There is none previous song to play' +PLAYER_NOT_PLAYING = f'❌ No song playing. Use {BOT_PREFIX}play to start the player' +IMPOSSIBLE_MOVE = 'That is impossible :(' ERROR_TITLE = 'Error :-(' NO_CHANNEL = 'To play some music, connect to any voice channel first.' -NO_GUILD = f'This server are not connected to Vulkan, try {BOT_PREFIX}reset' -INVALID_INPUT = 'This type of input was too strange, try something better' -DOWNLOADING_ERROR = 'An error occurred while downloading' -EXTRACTING_ERROR = 'An error ocurred while searching for the songs' +NO_GUILD = f'This server does not has a Player, try {BOT_PREFIX}reset' +INVALID_INPUT = f'This type of input was too strange, try something better or type {BOT_PREFIX}help play' +DOWNLOADING_ERROR = '❌ An error occurred while downloading' +EXTRACTING_ERROR = '❌ An error ocurred while searching for the songs' COLOURS = { 'red': 0xDC143C, diff --git a/config/help.py b/config/help.py new file mode 100644 index 0000000..f58fa4e --- /dev/null +++ b/config/help.py @@ -0,0 +1,43 @@ +from config.config import * + +HELP_SKIP = 'Skip the current playing song.' +HELP_SKIP_LONG = 'Skip the playing of the current song, does not work if loop one is activated. \n\nArguments: None.' +HELP_RESUME = 'Resumes the song player.' +HELP_RESUME_LONG = 'If the player if paused, return the playing. \n\nArguments: None.' +HELP_CLEAR = 'Clear the queue and songs history.' +HELP_CLEAR_LONG = 'Clear the songs queue and songs history. \n\nArguments: None.' +HELP_STOP = 'Stop the song player.' +HELP_STOP_LONG = 'Stop the song player, clear queue and history and remove Vulkan from voice channel.\n\nArguments: None.' +HELP_LOOP = 'Control the loop of songs.' +HELP_LOOP_LONG = 'Controll the loop of songs.\n\n Require: A song being played.\nArguments:\nOne - Start looping the current song. \ + \nAll - Start looping all songs in queue.\nOff - Disable loop.' +HELP_NP = 'Show the info of the current song.' +HELP_NP_LONG = 'Show the information of the song being played.\n\nRequire: A song being played.\nArguments: None.' +HELP_QUEUE = f'Show the first {MAX_PRELOAD_SONGS} songs in queue.' +HELP_QUEUE_LONG = f'Show the first {MAX_PRELOAD_SONGS} song in the queue.\n\nArguments: None.' +HELP_PAUSE = 'Pauses the song player.' +HELP_PAUSE_LONG = 'If playing, pauses the song player.\n\nArguments: None' +HELP_PREV = 'Play the previous song.' +HELP_PREV_LONG = 'Play the previous song. If playing, the current song will return to queue.\n\nRequire: Loop to be disable.\nArguments: None.' +HELP_SHUFFLE = 'Shuffle the songs playing.' +HELP_SHUFFLE_LONG = 'Randomly shuffle the songs in the queue.\n\nArguments: None.' +HELP_PLAY = 'Plays a song.' +HELP_PLAY_LONG = 'Play a song in discord. \n\nRequire: You to be connected to a voice channel.\nArguments: Youtube or Spotify song/playlist link or the title of the song to be searched in Youtube.' +HELP_HISTORY = f'Show the history of played songs.' +HELP_HISTORY_LONG = f'Show the last {MAX_SONGS_HISTORY} played songs' +HELP_MOVE = 'Moves a song from position x to y in queue.' +HELP_MOVE_LONG = 'Moves a song from position x to position y in queue.\n\nRequire: Positions to be both valid numbers.\nArguments: 1º Number => Initial position, 2º Number => Destination position. Both numbers could be -1 to refer to the last song in queue.\nDefault: By default, if the second number is not passed, it will be 1, moving the selected song to 1º position.' +HELP_REMOVE = 'Remove a song in position x.' +HELP_REMOVE_LONG = 'Remove a song from queue in the position passed.\n\nRequire: Position to be a valid number.\nArguments: 1º Number => Position in queue of the song.' +HELP_RESET = 'Reset the Player of the server.' +HELP_RESET_LONG = 'Reset the Player of the server. Recommended if you find any type of error.\n\nArguments: None' +HELP_HELP = f'Use {BOT_PREFIX}help "command" for more info.' +HELP_HELP_LONG = f'Use {BOT_PREFIX}help command for more info about the command selected.' +HELP_INVITE = 'Send the invite URL to call Vulkan to your server.' +HELP_INVITE_LONG = 'Send an message in text channel with a URL to be used to invite Vulkan to your own server.\n\nArguments: None.' +HELP_RANDOM = 'Return a random number between 1 and x.' +HELP_RANDOM_LONG = 'Send a randomly selected number between 1 and the number you pass.\n\nRequired: Number to be a valid number.\nArguments: 1º Any number to be used as range.' +HELP_CHOOSE = 'Choose randomly one item passed.' +HELP_CHOOSE_LONG = 'Choose randomly one item passed in this command.\n\nRequire: Itens to be separated by comma.\nArguments: As much as you want.' +HELP_CARA = 'Return cara or coroa.' +HELP_CARA_LONG = 'Return cara or coroa.' diff --git a/vulkan/commands/Phrases.py b/vulkan/commands/Phrases.py deleted file mode 100644 index a20216e..0000000 --- a/vulkan/commands/Phrases.py +++ /dev/null @@ -1,60 +0,0 @@ -from discord.client import Client -import requests -import json -from config import config -from discord.ext import commands -from random import random as rand - - -class Phrases(commands.Cog): - """Deal with the generation of motivational phrases""" - - def __init__(self, bot: Client): - self.__bot = bot - - @commands.command(name='frase', help=config.HELP_FRASE) - async def phrase(self, ctx): - """Send some phrase to the requester""" - secret = await self.__calculate_rgn() - if secret != None: - await ctx.send(secret) - else: - phrase = await self.__get_phrase() - await ctx.send(phrase) - - async def __calculate_rgn(self): - """Calculate the chance from the phrase function return a secret custom message""" - x = rand() - if x < 0.15: - return config.SECRET_MESSAGE - else: - return None - - async def __get_phrase(self): - """Get the phrase from the server""" - tries = 0 - while True: - tries += 1 - if tries > config.MAX_API_PHRASES_TRIES: - return config.ERROR_WHILE_REQUEST - return 'O banco de dados dos cara tá off, bando de vagabundo, tenta depois aí bicho' - - try: - response = requests.get(config.PHRASES_API) - data = json.loads(response.content) - - phrase = data['quoteText'] - author = data['quoteAuthor'] - - if phrase == '' or author == '': - continue - - text = f'{phrase} \nBy: {author}' - - return text - except: - continue - - -def setup(bot): - bot.add_cog(Phrases(bot)) diff --git a/vulkan/commands/Warframe.py b/vulkan/commands/Warframe.py deleted file mode 100644 index 197777a..0000000 --- a/vulkan/commands/Warframe.py +++ /dev/null @@ -1,118 +0,0 @@ -import requests -import json -import discord -from discord.ext import commands -from config import config -from discord import Embed - - -class Warframe(commands.Cog): - """Deal with the generation of warframe data""" - - def __init__(self, bot: discord.Client): - self.__bot = bot - self.__open_functions = ['cetus', 'cambion', 'fissures'] - - @commands.command(name='warframe', help=config.HELP_WARFRAME) - async def warframe(self, ctx, arg) -> Embed: - if arg in self.__open_functions: - function = getattr(Warframe, f'_Warframe__{arg}') - embed = await function(self) - - await ctx.send(embed=embed) - else: - info = f'Warframe commands: {self.__open_functions}' - - embed = Embed( - title='Invalid Command', - description=info, - colour=config.COLOURS['blue'] - ) - await ctx.send(embed=embed) - - async def __cetus(self) -> Embed: - description = await self.__get_cetus() - embed = discord.Embed( - title='Warframe Cetus Timing', - description=description, - colour=config.COLOURS['blue'] - ) - return embed - - async def __get_cetus(self) -> str: - """Return the information of the Warframe API""" - tries = 0 - while True: - tries += 1 - if tries > config.MAX_API_CETUS_TRIES: - return 'Os DE baiano não tão com o banco de dados ligado' - - try: - response = requests.get(config.CETUS_API) - data = json.loads(response.content) - short = data['shortString'] - - return short - - except Exception as e: - continue - - async def __cambion(self) -> Embed: - description = await self.__get_cambion() - embed = discord.Embed( - title='Warframe Cambion Timing', - description=description, - colour=config.COLOURS['blue'] - ) - return embed - - async def __get_cambion(self) -> str: - """Return the information of the Warframe API""" - tries = 0 - while True: - tries += 1 - if tries > config.MAX_API_CAMBION_TRIES: - return 'Os DE baiano não tão com o banco de dados ligado' - - try: - response = requests.get(config.CAMBION_API) - data = json.loads(response.content) - - info = f'**Active:** {data["active"]}\n**Time Left:** {data["timeLeft"]}' - - return info - except: - continue - - async def __fissures(self) -> Embed: - description = await self.__get_fissures() - embed = discord.Embed( - title='Warframe Fissures Status', - description=description, - colour=config.COLOURS['blue'] - ) - return embed - - async def __get_fissures(self) -> str: - """Return the information of the Warframe API""" - tries = 0 - while True: - tries += 1 - if tries > config.MAX_API_FISSURES_TRIES: - return 'Os DE baiano não tão com o banco de dados ligado' - - try: - response = requests.get(config.FISSURES_API) - data = json.loads(response.content) - - info = '' - for pos, fissure in enumerate(data, start=1): - info += f'`{pos}` - **Mission:** {fissure["missionType"]} | **Type:** {fissure["tier"]} | **Timing:** {fissure["eta"]} | **Storm:** {fissure["isStorm"]}\n' - - return info - except Exception as e: - continue - - -def setup(bot): - bot.add_cog(Warframe(bot)) From 5b4c5b49f18ac962d40d33a288bb1d58c485fa64 Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Wed, 12 Jan 2022 09:41:35 -0400 Subject: [PATCH 4/6] Updating help command in Vulkan --- vulkan/commands/Control.py | 96 ++++++++++++++++++++++++++------------ vulkan/commands/Music.py | 54 ++++++++++++++------- vulkan/commands/Random.py | 31 ++++++------ 3 files changed, 118 insertions(+), 63 deletions(-) diff --git a/vulkan/commands/Control.py b/vulkan/commands/Control.py index 9ddf769..14bf07a 100644 --- a/vulkan/commands/Control.py +++ b/vulkan/commands/Control.py @@ -3,6 +3,7 @@ from discord import Client from discord.ext.commands.errors import CommandNotFound, MissingRequiredArgument from discord.ext import commands from config import config +from config import help class Control(commands.Cog): @@ -11,11 +12,12 @@ class Control(commands.Cog): def __init__(self, bot: Client): self.__bot = bot self.__comandos = { - 'MUSIC': ['resume', 'pause', 'loop', 'stop', 'skip', 'play', 'queue', 'clear', 'np', 'shuffle', 'move', 'remove', 'reset'], - 'WARFRAME': ['warframe'], - 'RANDOM': ['escolha', 'cara', 'random'], - 'HELP': ['help'], - 'OTHERS': ['frase'] + 'MUSIC': ['resume', 'pause', 'loop', 'stop', + 'skip', 'play', 'queue', 'clear', + 'np', 'shuffle', 'move', 'remove', + 'reset', 'prev', 'history'], + 'RANDOM': ['choose', 'cara', 'random'] + } @commands.Cog.listener() @@ -42,6 +44,7 @@ class Control(commands.Cog): ) await ctx.send(embed=embed) else: + print(error) embed = discord.Embed( title=config.ERROR_TITLE, description=config.UNKNOWN_ERROR, @@ -49,37 +52,70 @@ class Control(commands.Cog): ) await ctx.send(embed=embed) - @commands.command(name="help", help=config.HELP_HELP, aliases=['h', 'ajuda']) - async def help_msg(self, ctx): - helptxt = '' - help_music = '🎧 `MUSIC`\n' - help_random = '🎲 `RANDOM`\n' - help_warframe = '🎮 `WARFRAME`\n' - help_help = '👾 `HELP`\n' - help_others = '🕹️ `OTHERS`\n' + @commands.command(name="help", help=help.HELP_HELP, description=help.HELP_HELP_LONG, aliases=['h', 'ajuda']) + async def help_msg(self, ctx, command_help=''): + if command_help != '': + for command in self.__bot.commands: + if command.name == command_help: + txt = command.description if command.description else command.help - for command in self.__bot.commands: - if command.name in self.__comandos['MUSIC']: - help_music += f'**{command}** - {command.help}\n' - elif command.name in self.__comandos['HELP']: - help_help += f'**{command}** - {command.help}\n' - elif command.name in self.__comandos['OTHERS']: - help_others += f'**{command}** - {command.help}\n' - elif command.name in self.__comandos['WARFRAME']: - help_warframe += f'**{command}** - {command.help}\n' - else: - help_random += f'**{command}** - {command.help}\n' + embedhelp = discord.Embed( + title=f'**Description of {command_help}** command', + description=txt, + colour=config.COLOURS['blue'] + ) - helptxt = f'{help_music}\n{help_warframe}\n{help_random}\n{help_others}\n{help_help}' + await ctx.send(embed=embedhelp) + return - embedhelp = discord.Embed( - title=f'**Available Commands of {self.__bot.user.name}**', - description=helptxt, + embedhelp = discord.Embed( + title='Command Help', + description=f'Command {command_help} Not Found', + colour=config.COLOURS['red'] + ) + + await ctx.send(embed=embedhelp) + else: + + helptxt = '' + help_music = '🎧 `MUSIC`\n' + help_random = '🎲 `RANDOM`\n' + help_help = '👾 `HELP`\n' + + for command in self.__bot.commands: + if command.name in self.__comandos['MUSIC']: + help_music += f'**{command}** - {command.help}\n' + + elif command.name in self.__comandos['RANDOM']: + help_random += f'**{command}** - {command.help}\n' + + else: + help_help += f'**{command}** - {command.help}\n' + + helptxt = f'\n{help_music}\n{help_help}\n{help_random}' + + embedhelp = discord.Embed( + title=f'**Available Commands of {self.__bot.user.name}**', + description=helptxt, + colour=config.COLOURS['blue'] + ) + + embedhelp.set_thumbnail(url=self.__bot.user.avatar_url) + await ctx.send(embed=embedhelp) + + @commands.command(name='invite', help=help.HELP_INVITE, description=help.HELP_INVITE_LONG) + async def invite_bot(self, ctx): + invite_url = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot>)'.format( + self.__bot.user.id) + txt = config.INVITE_MESSAGE.format(invite_url) + + embed = discord.Embed( + title="Invite Vulkan", + description=txt, colour=config.COLOURS['blue'] ) - embedhelp.set_thumbnail(url=self.__bot.user.avatar_url) - await ctx.send(embed=embedhelp) + await ctx.send(embed=embed) def setup(bot): diff --git a/vulkan/commands/Music.py b/vulkan/commands/Music.py index e7935b8..9b893d4 100644 --- a/vulkan/commands/Music.py +++ b/vulkan/commands/Music.py @@ -2,6 +2,7 @@ import discord from discord.ext import commands from config import config +from config import help from vulkan.music.Player import Player from vulkan.music.utils import * @@ -13,10 +14,25 @@ class Music(commands.Cog): @commands.Cog.listener() async def on_ready(self) -> None: + """Load a player for each guild that the Bot are""" for guild in self.__bot.guilds: self.__guilds[guild] = Player(self.__bot, guild) + print(f'Player for guild {guild.name} created') - @commands.command(name="play", help=config.HELP_PLAY, aliases=['p', 'tocar']) + @commands.Cog.listener() + async def on_guild_join(self, guild) -> None: + """Load a player when joining a guild""" + self.__guilds[guild] = Player(self.__bot, guild) + print(f'Player for guild {guild.name} created') + + @commands.Cog.listener() + async def on_guild_remove(self, guild) -> None: + """Removes the player of the guild if banned""" + if guild in self.__guilds.keys(): + self.__guilds.pop(guild, None) + print(f'Player for guild {guild.name} destroyed') + + @commands.command(name="play", help=help.HELP_PLAY, description=help.HELP_PLAY_LONG, aliases=['p', 'tocar']) async def play(self, ctx, *args) -> None: track = " ".join(args) requester = ctx.author.name @@ -29,12 +45,12 @@ class Music(commands.Cog): if is_connected(ctx) == None: success = await player.connect(ctx) if success == False: - await self.__send_embed(ctx, config.ERROR_TITLE, config.NO_CHANNEL, 'red') + await self.__send_embed(ctx, config.IMPOSSIBLE_MOVE, config.NO_CHANNEL, 'red') return await player.play(ctx, track, requester) - @commands.command(name="queue", help=config.HELP_QUEUE, aliases=['q', 'fila']) + @commands.command(name="queue", help=help.HELP_QUEUE, description=help.HELP_QUEUE_LONG, aliases=['q', 'fila']) async def queue(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -43,7 +59,7 @@ class Music(commands.Cog): embed = await player.queue() await ctx.send(embed=embed) - @commands.command(name="skip", help=config.HELP_SKIP, aliases=['s', 'pular']) + @commands.command(name="skip", help=help.HELP_SKIP, description=help.HELP_SKIP_LONG, aliases=['s', 'pular']) async def skip(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -51,7 +67,7 @@ class Music(commands.Cog): else: await player.skip(ctx) - @commands.command(name='stop', help=config.HELP_STOP, aliases=['parar']) + @commands.command(name='stop', help=help.HELP_STOP, description=help.HELP_STOP_LONG, aliases=['parar']) async def stop(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -59,7 +75,7 @@ class Music(commands.Cog): else: await player.stop() - @commands.command(name='pause', help=config.HELP_PAUSE, aliases=['pausar']) + @commands.command(name='pause', help=help.HELP_PAUSE, description=help.HELP_PAUSE_LONG, aliases=['pausar']) async def pause(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -69,7 +85,7 @@ class Music(commands.Cog): if success: await self.__send_embed(ctx, config.SONG_PLAYER, config.SONG_PAUSED, 'blue') - @commands.command(name='resume', help=config.HELP_RESUME, aliases=['soltar']) + @commands.command(name='resume', help=help.HELP_RESUME, description=help.HELP_RESUME_LONG, aliases=['soltar']) async def resume(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -79,7 +95,7 @@ class Music(commands.Cog): if success: await self.__send_embed(ctx, config.SONG_PLAYER, config.SONG_RESUMED, 'blue') - @commands.command(name='prev', help=config.HELP_PREV, aliases=['anterior']) + @commands.command(name='prev', help=help.HELP_PREV, description=help.HELP_PREV_LONG, aliases=['anterior']) async def prev(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -88,12 +104,12 @@ class Music(commands.Cog): if is_connected(ctx) == None: success = await player.connect(ctx) if success == False: - await self.__send_embed(ctx, config.ERROR_TITLE, config.NO_CHANNEL, 'red') + await self.__send_embed(ctx, config.IMPOSSIBLE_MOVE, config.NO_CHANNEL, 'red') return await player.play_prev(ctx) - @commands.command(name='history', help=config.HELP_HISTORY, aliases=['historico']) + @commands.command(name='history', help=help.HELP_HISTORY, description=help.HELP_HISTORY_LONG, aliases=['historico']) async def history(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -102,7 +118,7 @@ class Music(commands.Cog): embed = player.history() await ctx.send(embed=embed) - @commands.command(name='loop', help=config.HELP_LOOP, aliases=['l', 'repeat']) + @commands.command(name='loop', help=help.HELP_LOOP, description=help.HELP_LOOP_LONG, aliases=['l', 'repeat']) async def loop(self, ctx, args: str) -> None: player = self.__get_player(ctx) if player == None: @@ -111,7 +127,7 @@ class Music(commands.Cog): description = await player.loop(args) await self.__send_embed(ctx, config.SONG_PLAYER, description, 'blue') - @commands.command(name='clear', help=config.HELP_CLEAR, aliases=['c', 'limpar']) + @commands.command(name='clear', help=help.HELP_CLEAR, description=help.HELP_CLEAR_LONG, aliases=['c', 'limpar']) async def clear(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -119,7 +135,7 @@ class Music(commands.Cog): else: await player.clear() - @commands.command(name='np', help=config.HELP_NP, aliases=['playing', 'now']) + @commands.command(name='np', help=help.HELP_NP, description=help.HELP_NP_LONG, aliases=['playing', 'now']) async def now_playing(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -129,7 +145,7 @@ class Music(commands.Cog): await self.__clean_messages(ctx) await ctx.send(embed=embed) - @commands.command(name='shuffle', help=config.HELP_SHUFFLE, aliases=['aleatorio']) + @commands.command(name='shuffle', help=help.HELP_SHUFFLE, description=help.HELP_SHUFFLE_LONG, aliases=['aleatorio']) async def shuffle(self, ctx) -> None: player = self.__get_player(ctx) if player == None: @@ -138,7 +154,7 @@ class Music(commands.Cog): description = await player.shuffle() await self.__send_embed(ctx, config.SONG_PLAYER, description, 'blue') - @commands.command(name='move', help=config.HELP_MOVE, aliases=['m', 'mover']) + @commands.command(name='move', help=help.HELP_MOVE, description=help.HELP_MOVE_LONG, aliases=['m', 'mover']) async def move(self, ctx, pos1, pos2='1') -> None: player = self.__get_player(ctx) if player == None: @@ -147,7 +163,7 @@ class Music(commands.Cog): description = await player.move(pos1, pos2) await self.__send_embed(ctx, config.SONG_PLAYER, description, 'blue') - @commands.command(name='remove', help=config.HELP_REMOVE, aliases=['remover']) + @commands.command(name='remove', help=help.HELP_REMOVE, description=help.HELP_REMOVE_LONG, aliases=['remover']) async def remove(self, ctx, position) -> None: player = self.__get_player(ctx) if player == None: @@ -156,7 +172,7 @@ class Music(commands.Cog): description = await player.remove(position) await self.__send_embed(ctx, config.SONG_PLAYER, description, 'blue') - @commands.command(name='reset', help=config.HELP_RESET, aliases=['resetar']) + @commands.command(name='reset', help=help.HELP_RESET, description=help.HELP_RESET_LONG, aliases=['resetar']) async def reset(self, ctx) -> None: player = self.__get_player(ctx) if player != None: @@ -185,7 +201,9 @@ class Music(commands.Cog): if message.author == self.__bot.user: if len(message.embeds) > 0: embed = message.embeds[0] - if embed.title in config.SONGS_PLAYING_TITLES: + fields = embed.fields + + if fields != discord.Embed.EmptyEmbed: await message.delete() except: continue diff --git a/vulkan/commands/Random.py b/vulkan/commands/Random.py index 546fefa..2f7ac34 100644 --- a/vulkan/commands/Random.py +++ b/vulkan/commands/Random.py @@ -2,6 +2,7 @@ from random import randint, random import discord from discord.ext import commands from config import config +from config import help class Random(commands.Cog): @@ -10,14 +11,14 @@ class Random(commands.Cog): def __init__(self, bot): self.__bot = bot - @commands.command(name='random', help=config.HELP_RANDOM) - async def random(self, ctx, arg: str): + @commands.command(name='random', help=help.HELP_RANDOM, description=help.HELP_RANDOM_LONG) + async def random(self, ctx, arg: str) -> None: try: arg = int(arg) - except Exception as e: + except: embed = discord.Embed( - description='Manda um número aí ow animal', + description=config.ERROR_NUMBER, colour=config.COLOURS['red'] ) await ctx.send(embed=embed) @@ -32,14 +33,14 @@ class Random(commands.Cog): x = randint(a, b) embed = discord.Embed( - title=f'Número Aleatório entre {a, b}', + title=f'Random number between [{a, b}]', description=x, colour=config.COLOURS['green'] ) await ctx.send(embed=embed) - @commands.command(name='cara', help=config.HELP_CARA) - async def cara(self, ctx): + @commands.command(name='cara', help=help.HELP_CARA, description=help.HELP_CARA_LONG) + async def cara(self, ctx) -> None: x = random() if x < 0.5: result = 'cara' @@ -48,13 +49,13 @@ class Random(commands.Cog): embed = discord.Embed( title='Cara Cora', - description=f'Resultado: {result}', + description=f'Result: {result}', colour=config.COLOURS['green'] ) await ctx.send(embed=embed) - @commands.command(name='escolha', help=config.HELP_ESCOLHA) - async def escolher(self, ctx, *args: str): + @commands.command(name='choose', help=help.HELP_CHOOSE, description=help.HELP_CHOOSE_LONG) + async def choose(self, ctx, *args: str) -> None: try: user_input = " ".join(args) itens = user_input.split(sep=',') @@ -62,16 +63,16 @@ class Random(commands.Cog): index = randint(0, len(itens)-1) embed = discord.Embed( - title='Escolha de algo', + title='Choose something', description=itens[index], colour=config.COLOURS['green'] ) await ctx.send(embed=embed) - except Exception as e: + except: embed = discord.Embed( - title='Escolha de algo', - description='Erro: Envie várias coisas separadas por vírgula', - colour=config.COLOURS['green'] + title='Choose something.', + description=f'Error: Use {config.BOT_PREFIX}help choose to understand this command.', + colour=config.COLOURS['red'] ) await ctx.send(embed=embed) From 173b6a7b43d4aa66f783325ec92d96b03390a6b8 Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Wed, 12 Jan 2022 10:41:31 -0400 Subject: [PATCH 5/6] Stability Update --- vulkan/commands/Control.py | 2 +- vulkan/music/Player.py | 14 ++++++++++++++ vulkan/music/utils.py | 6 +++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/vulkan/commands/Control.py b/vulkan/commands/Control.py index 14bf07a..3c96450 100644 --- a/vulkan/commands/Control.py +++ b/vulkan/commands/Control.py @@ -105,7 +105,7 @@ class Control(commands.Cog): @commands.command(name='invite', help=help.HELP_INVITE, description=help.HELP_INVITE_LONG) async def invite_bot(self, ctx): - invite_url = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot>)'.format( + invite_url = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot>'.format( self.__bot.user.id) txt = config.INVITE_MESSAGE.format(invite_url) diff --git a/vulkan/music/Player.py b/vulkan/music/Player.py index 1d70a34..f94d144 100644 --- a/vulkan/music/Player.py +++ b/vulkan/music/Player.py @@ -279,6 +279,14 @@ class Player(commands.Cog): self.__playlist.clear() async def now_playing(self) -> discord.Embed: + if not self.__playing: + embed = discord.Embed( + title=config.SONG_PLAYER, + description=config.PLAYER_NOT_PLAYING, + colour=config.COLOURS['blue'] + ) + return embed + if self.__playlist.looping_one: title = config.ONE_SONG_LOOPING else: @@ -300,6 +308,9 @@ class Player(commands.Cog): return config.ERROR_SHUFFLING async def move(self, pos1, pos2='1') -> str: + if not self.__playing: + return config.PLAYER_NOT_PLAYING + try: pos1 = int(pos1) pos2 = int(pos2) @@ -315,6 +326,9 @@ class Player(commands.Cog): async def remove(self, position) -> str: """Remove a song from the queue in the position""" + if not self.__playing: + return config.PLAYER_NOT_PLAYING + try: position = int(position) diff --git a/vulkan/music/utils.py b/vulkan/music/utils.py index 7211eb0..8faed81 100644 --- a/vulkan/music/utils.py +++ b/vulkan/music/utils.py @@ -6,7 +6,11 @@ from config import config def is_connected(ctx): try: voice_channel = ctx.guild.voice_client.channel - return voice_channel + + if not ctx.guild.voice_client.is_connected(): + return None + else: + return voice_channel except: return None From 0d606361da6e34f3d567fdd142462282fa2cd1df Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Wed, 12 Jan 2022 11:31:15 -0400 Subject: [PATCH 6/6] Refactoring clean messages --- vulkan/commands/Music.py | 6 +++--- vulkan/music/Player.py | 2 +- vulkan/music/Playlist.py | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/vulkan/commands/Music.py b/vulkan/commands/Music.py index 9b893d4..cf949d5 100644 --- a/vulkan/commands/Music.py +++ b/vulkan/commands/Music.py @@ -201,10 +201,10 @@ class Music(commands.Cog): if message.author == self.__bot.user: if len(message.embeds) > 0: embed = message.embeds[0] - fields = embed.fields + if len(embed.fields) > 0: + if embed.fields[0].name == 'Uploader:': + await message.delete() - if fields != discord.Embed.EmptyEmbed: - await message.delete() except: continue diff --git a/vulkan/music/Player.py b/vulkan/music/Player.py index f94d144..93bd89d 100644 --- a/vulkan/music/Player.py +++ b/vulkan/music/Player.py @@ -271,7 +271,7 @@ class Player(commands.Cog): elif args == 'off': description = self.__playlist.loop_off() else: - description = config.HELP_LONG_LOOP + description = help.HELP_LONG_LOOP return description diff --git a/vulkan/music/Playlist.py b/vulkan/music/Playlist.py index 1745fb1..8d5c744 100644 --- a/vulkan/music/Playlist.py +++ b/vulkan/music/Playlist.py @@ -100,7 +100,6 @@ class Playlist(IPlaylist): def clear(self) -> None: """Clear the songs to play song history""" self.__queue.clear() - self.__songs_history.clear() def loop_one(self) -> str: """Try to start the loop of the current song