mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Merge pull request #14 from RafaelSolVargas/stylish-update
Stylish update and Fixing Known Errors
This commit is contained in:
commit
37acd1a61b
@ -9,7 +9,7 @@ SPOTIFY_SECRET = config('SPOTIFY_SECRET')
|
||||
SECRET_MESSAGE = config('SECRET_MESSAGE')
|
||||
PHRASES_API = config('PHRASES_API')
|
||||
|
||||
BOT_PREFIX = '!'
|
||||
BOT_PREFIX = '$'
|
||||
VC_TIMEOUT = 600
|
||||
|
||||
STARTUP_MESSAGE = 'Starting Vulkan...'
|
||||
@ -26,34 +26,69 @@ 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_SHUFFLE = 'Shuffle the songs playing'
|
||||
HELP_PLAY = '(title/youtube/spotify) - Plays a song'
|
||||
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 guild'
|
||||
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 braba"
|
||||
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_SHUFFLE = 'Shuffle the songs playing.'
|
||||
HELP_PLAY = '(title/youtube/spotify) - Plays a song.'
|
||||
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_QUEUE_TITLE = 'Songs Queue'
|
||||
SONG_ADDED_TWO = '🎧 Song added to the queue'
|
||||
SONG_PLAYING = '🎧 Song playing now'
|
||||
SONG_PLAYER = '🎧 Song Player'
|
||||
QUEUE_TITLE = '🎧 Songs in Queue'
|
||||
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'
|
||||
SONG_DOWNLOADING = '📥 Downloading...'
|
||||
|
||||
ERROR_TITLE = 'Error :/'
|
||||
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'
|
||||
|
||||
SONG_MOVED_SUCCESSFULLY = 'Song `{}` in position `{}` moved with `{}` in position `{}` successfully'
|
||||
SONG_REMOVED_SUCCESSFULLY = 'Song `{}` removed successfully'
|
||||
|
||||
LOOP_ALL_ON = f'❌ Vulkan is looping all songs, use {BOT_PREFIX}loop off to disable this loop first'
|
||||
LOOP_ONE_ON = f'❌ Vulkan is looping one song, use {BOT_PREFIX}loop off to disable this loop first'
|
||||
LOOP_ALL_ALREADY_ON = '🔁 Vulkan is already looping all songs'
|
||||
LOOP_ONE_ALREADY_ON = '🔂 Vulkan is already looping the current song'
|
||||
LOOP_ALL_ACTIVATE = '🔁 Looping all songs'
|
||||
LOOP_ONE_ACTIVATE = '🔂 Looping the current song'
|
||||
LOOP_DISABLE = '➡️ Loop disabled'
|
||||
LOOP_ALREADY_DISABLE = '❌ Loop is already disabled'
|
||||
|
||||
SONGS_PLAYING_TITLES = [ONE_SONG_LOOPING, ALL_SONGS_LOOPING, SONG_PLAYING]
|
||||
|
||||
ERROR_TITLE = 'Error :-('
|
||||
NO_CHANNEL = 'To play some music, connect to any voice channel first.'
|
||||
NO_GUILD = 'This guild are not connected to Vulkan'
|
||||
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'
|
||||
|
||||
@ -15,7 +15,7 @@ class Control(commands.Cog):
|
||||
'WARFRAME': ['warframe'],
|
||||
'RANDOM': ['escolha', 'cara', 'random'],
|
||||
'HELP': ['help'],
|
||||
'OTHERS': ['frase', 'drop']
|
||||
'OTHERS': ['frase']
|
||||
}
|
||||
|
||||
@commands.Cog.listener()
|
||||
@ -27,21 +27,36 @@ class Control(commands.Cog):
|
||||
@commands.Cog.listener()
|
||||
async def on_command_error(self, ctx, error):
|
||||
if isinstance(error, MissingRequiredArgument):
|
||||
await ctx.channel.send(f'Falta argumentos. Digite {config.BOT_PREFIX}help para ver todos os comandos\n\nOu tente {config.BOT_PREFIX}command help para mais informações')
|
||||
elif isinstance(error, CommandNotFound):
|
||||
await ctx.channel.send(f'O comando não existe')
|
||||
else:
|
||||
await ctx.channel.send(f'Teve um erro aí bicho')
|
||||
raise error
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.ERROR_MISSING_ARGUMENTS,
|
||||
colour=config.COLOURS['red']
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="help", alisases=['ajuda'], help=config.HELP_HELP)
|
||||
elif isinstance(error, CommandNotFound):
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.COMMAND_NOT_FOUND,
|
||||
colour=config.COLOURS['red']
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.UNKNOWN_ERROR,
|
||||
colour=config.COLOURS['red']
|
||||
)
|
||||
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'
|
||||
help_music = '🎧 `MUSIC`\n'
|
||||
help_random = '🎲 `RANDOM`\n'
|
||||
help_warframe = '🎮 `WARFRAME`\n'
|
||||
help_help = '👾 `HELP`\n'
|
||||
help_others = '🕹️ `OTHERS`\n'
|
||||
|
||||
for command in self.__bot.commands:
|
||||
if command.name in self.__comandos['MUSIC']:
|
||||
@ -58,9 +73,9 @@ class Control(commands.Cog):
|
||||
helptxt = f'{help_music}\n{help_warframe}\n{help_random}\n{help_others}\n{help_help}'
|
||||
|
||||
embedhelp = discord.Embed(
|
||||
colour=config.COLOURS['grey'],
|
||||
title=f'Comandos do {self.__bot.user.name}',
|
||||
description=helptxt
|
||||
title=f'**Available Commands of {self.__bot.user.name}**',
|
||||
description=helptxt,
|
||||
colour=config.COLOURS['blue']
|
||||
)
|
||||
|
||||
embedhelp.set_thumbnail(url=self.__bot.user.avatar_url)
|
||||
|
||||
@ -7,35 +7,35 @@ from vulkan.music.utils import *
|
||||
|
||||
|
||||
class Music(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
def __init__(self, bot) -> None:
|
||||
self.__guilds = {}
|
||||
self.__bot: discord.Client = bot
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_ready(self):
|
||||
async def on_ready(self) -> None:
|
||||
for guild in self.__bot.guilds:
|
||||
self.__guilds[guild] = Player(self.__bot, guild)
|
||||
|
||||
@commands.command(name="play", help=config.HELP_PLAY, aliases=['p', 'tocar'])
|
||||
async def play(self, ctx, *args):
|
||||
user_input = " ".join(args)
|
||||
async def play(self, ctx, *args) -> None:
|
||||
track = " ".join(args)
|
||||
requester = ctx.author.name
|
||||
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
await self.__send_embed(ctx, description=config.NO_GUILD, colour_name='red')
|
||||
await self.__send_embed(ctx, config.ERROR_TITLE, config.NO_GUILD, 'red')
|
||||
return
|
||||
|
||||
if is_connected(ctx) == None:
|
||||
result = await player.connect(ctx)
|
||||
if result['success'] == False:
|
||||
await self.__send_embed(ctx, description=result['reason'], colour_name='red')
|
||||
success = await player.connect(ctx)
|
||||
if success == False:
|
||||
await self.__send_embed(ctx, config.ERROR_TITLE, config.NO_CHANNEL, 'red')
|
||||
return
|
||||
|
||||
await player.play(ctx, user_input, requester)
|
||||
await player.play(ctx, track, requester)
|
||||
|
||||
@commands.command(name="queue", help=config.HELP_QUEUE, aliases=['q', 'fila'])
|
||||
async def queue(self, ctx):
|
||||
async def queue(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
@ -43,8 +43,8 @@ class Music(commands.Cog):
|
||||
embed = await player.queue()
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="skip", help=config.HELP_SKIP, aliases=['pular'])
|
||||
async def skip(self, ctx):
|
||||
@commands.command(name="skip", help=config.HELP_SKIP, aliases=['s', 'pular'])
|
||||
async def skip(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
@ -52,7 +52,7 @@ class Music(commands.Cog):
|
||||
await player.skip()
|
||||
|
||||
@commands.command(name='stop', help=config.HELP_STOP, aliases=['parar'])
|
||||
async def stop(self, ctx):
|
||||
async def stop(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
@ -60,37 +60,36 @@ class Music(commands.Cog):
|
||||
await player.stop()
|
||||
|
||||
@commands.command(name='pause', help=config.HELP_PAUSE, aliases=['pausar'])
|
||||
async def pause(self, ctx):
|
||||
async def pause(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
print('No player')
|
||||
return
|
||||
else:
|
||||
success = await player.pause()
|
||||
if success:
|
||||
await self.__send_embed(ctx, description='Song paused', colour_name='blue')
|
||||
await self.__send_embed(ctx, config.SONG_PLAYER, config.SONG_PAUSED, 'blue')
|
||||
|
||||
@commands.command(name='resume', help=config.HELP_RESUME, aliases=['soltar'])
|
||||
async def resume(self, ctx):
|
||||
async def resume(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
else:
|
||||
success = await player.resume()
|
||||
if success:
|
||||
await self.__send_embed(ctx, description='Song Playing', colour_name='blue')
|
||||
await self.__send_embed(ctx, config.SONG_PLAYER, config.SONG_RESUMED, 'blue')
|
||||
|
||||
@commands.command(name='loop', help=config.HELP_LOOP, aliases=['repeat'])
|
||||
async def loop(self, ctx, args: str):
|
||||
@commands.command(name='loop', help=config.HELP_LOOP, aliases=['l', 'repeat'])
|
||||
async def loop(self, ctx, args: str) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
else:
|
||||
result = await player.loop(args)
|
||||
await self.__send_embed(ctx, description=result, colour_name='blue')
|
||||
description = await player.loop(args)
|
||||
await self.__send_embed(ctx, config.SONG_PLAYER, description, 'blue')
|
||||
|
||||
@commands.command(name='clear', help=config.HELP_CLEAR, aliases=['limpar'])
|
||||
async def clear(self, ctx):
|
||||
@commands.command(name='clear', help=config.HELP_CLEAR, aliases=['c', 'limpar'])
|
||||
async def clear(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
@ -98,7 +97,7 @@ class Music(commands.Cog):
|
||||
await player.clear()
|
||||
|
||||
@commands.command(name='np', help=config.HELP_NP, aliases=['playing', 'now'])
|
||||
async def now_playing(self, ctx):
|
||||
async def now_playing(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
@ -108,45 +107,44 @@ class Music(commands.Cog):
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name='shuffle', help=config.HELP_SHUFFLE, aliases=['aleatorio'])
|
||||
async def shuffle(self, ctx):
|
||||
async def shuffle(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
else:
|
||||
result = await player.shuffle()
|
||||
await self.__send_embed(ctx, description=result, colour_name='blue')
|
||||
description = await player.shuffle()
|
||||
await self.__send_embed(ctx, config.SONG_PLAYER, description, 'blue')
|
||||
|
||||
@commands.command(name='move', help=config.HELP_MOVE, aliases=['mover'])
|
||||
async def move(self, ctx, pos1, pos2='1'):
|
||||
@commands.command(name='move', help=config.HELP_MOVE, aliases=['m', 'mover'])
|
||||
async def move(self, ctx, pos1, pos2='1') -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
else:
|
||||
result = await player.move(pos1, pos2)
|
||||
await self.__send_embed(ctx, description=result, colour_name='blue')
|
||||
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'])
|
||||
async def remove(self, ctx, position):
|
||||
"""Remove a song from the queue in the position"""
|
||||
async def remove(self, ctx, position) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player == None:
|
||||
return
|
||||
else:
|
||||
result = await player.remove(position)
|
||||
await self.__send_embed(ctx, description=result, colour_name='blue')
|
||||
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'])
|
||||
async def reset(self, ctx):
|
||||
async def reset(self, ctx) -> None:
|
||||
player = self.__get_player(ctx)
|
||||
if player != None:
|
||||
await player.stop()
|
||||
|
||||
self.__guilds[ctx.guild] = Player(self.__bot, ctx.guild)
|
||||
|
||||
async def __send_embed(self, ctx, title='', description='', colour_name='grey'):
|
||||
async def __send_embed(self, ctx, title='', description='', colour='grey') -> None:
|
||||
try:
|
||||
colour = config.COLOURS[colour_name]
|
||||
except Exception as e:
|
||||
colour = config.COLOURS[colour]
|
||||
except:
|
||||
colour = config.COLOURS['grey']
|
||||
|
||||
embedvc = discord.Embed(
|
||||
@ -156,8 +154,7 @@ class Music(commands.Cog):
|
||||
)
|
||||
await ctx.send(embed=embedvc)
|
||||
|
||||
async def __clean_messages(self, ctx):
|
||||
"""Clear Bot messages if send recently"""
|
||||
async def __clean_messages(self, ctx) -> None:
|
||||
last_messages = await ctx.channel.history(limit=5).flatten()
|
||||
|
||||
for message in last_messages:
|
||||
@ -165,12 +162,12 @@ class Music(commands.Cog):
|
||||
if message.author == self.__bot.user:
|
||||
if len(message.embeds) > 0:
|
||||
embed = message.embeds[0]
|
||||
if embed.title == 'Song Playing Now' or embed.title == 'Song Looping Now':
|
||||
if embed.title in config.SONGS_PLAYING_TITLES:
|
||||
await message.delete()
|
||||
except:
|
||||
continue
|
||||
|
||||
def __get_player(self, ctx):
|
||||
def __get_player(self, ctx) -> Player:
|
||||
try:
|
||||
return self.__guilds[ctx.guild]
|
||||
except:
|
||||
|
||||
@ -36,6 +36,7 @@ class Phrases(commands.Cog):
|
||||
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:
|
||||
@ -51,7 +52,7 @@ class Phrases(commands.Cog):
|
||||
text = f'{phrase} \nBy: {author}'
|
||||
|
||||
return text
|
||||
except Exception as e:
|
||||
except:
|
||||
continue
|
||||
|
||||
|
||||
|
||||
@ -64,7 +64,6 @@ class Downloader():
|
||||
except (ExtractorError, DownloadError) as e:
|
||||
return None
|
||||
else:
|
||||
print('Invalid type of playlist URL')
|
||||
return None
|
||||
|
||||
async def preload(self, songs: list) -> None:
|
||||
|
||||
@ -24,10 +24,6 @@ class IPlaylist(ABC):
|
||||
def next_song(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def prev_song(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_song(self, identifier: str) -> None:
|
||||
pass
|
||||
|
||||
@ -6,6 +6,7 @@ import datetime
|
||||
from vulkan.music.Downloader import Downloader
|
||||
from vulkan.music.Playlist import Playlist
|
||||
from vulkan.music.Searcher import Searcher
|
||||
from vulkan.music.Song import Song
|
||||
from vulkan.music.Types import Provider
|
||||
from vulkan.music.utils import *
|
||||
|
||||
@ -25,41 +26,49 @@ class Player(commands.Cog):
|
||||
self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
||||
'options': '-vn'}
|
||||
|
||||
async def connect(self, ctx):
|
||||
async def connect(self, ctx) -> None:
|
||||
if not ctx.author.voice:
|
||||
return {'success': False, 'reason': config.NO_CHANNEL}
|
||||
return False
|
||||
|
||||
if self.__guild.voice_client == None:
|
||||
await ctx.author.voice.channel.connect(reconnect=True, timeout=None)
|
||||
return {'success': True, 'reason': ''}
|
||||
return True
|
||||
|
||||
def __play_next(self, error, ctx):
|
||||
def __play_next(self, error, ctx) -> None:
|
||||
song = self.__playlist.next_song()
|
||||
if song != None: # If there is not a song for the song
|
||||
|
||||
if song != None:
|
||||
coro = self.__play_music(ctx, song)
|
||||
self.__bot.loop.create_task(coro)
|
||||
else:
|
||||
self.__playing = False
|
||||
|
||||
async def __play_music(self, ctx, song):
|
||||
self.__playing = True
|
||||
async def __play_music(self, ctx, song: Song) -> None:
|
||||
try:
|
||||
source = self.__ensure_source(song)
|
||||
if source == None:
|
||||
self.__play_next(None, ctx)
|
||||
|
||||
player = discord.FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||
self.__guild.voice_client.play(
|
||||
player, after=lambda e: self.__play_next(e, ctx))
|
||||
self.__playing = True
|
||||
|
||||
self.__timer.cancel()
|
||||
self.__timer = Timer(self.__timeout_handler)
|
||||
player = discord.FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||
self.__guild.voice_client.play(
|
||||
player, after=lambda e: self.__play_next(e, ctx))
|
||||
|
||||
await ctx.invoke(self.__bot.get_command('np'))
|
||||
self.__timer.cancel()
|
||||
self.__timer = Timer(self.__timeout_handler)
|
||||
|
||||
songs = self.__playlist.songs_to_preload
|
||||
await self.__down.preload(songs)
|
||||
await ctx.invoke(self.__bot.get_command('np'))
|
||||
|
||||
async def play(self, ctx, track, requester) -> str:
|
||||
songs = self.__playlist.songs_to_preload
|
||||
await self.__down.preload(songs)
|
||||
except:
|
||||
self.__play_next(None, ctx)
|
||||
|
||||
async def play(self, ctx, track=str, requester=str) -> str:
|
||||
try:
|
||||
songs_names, provider = self.__searcher.search(track)
|
||||
if provider == Provider.Unknown:
|
||||
if provider == Provider.Unknown or songs_names == None:
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.INVALID_INPUT,
|
||||
@ -98,67 +107,53 @@ class Player(commands.Cog):
|
||||
return
|
||||
elif not self.__playing:
|
||||
embed = discord.Embed(
|
||||
title=config.SONG_QUEUE_TITLE,
|
||||
title=config.SONG_PLAYER,
|
||||
description=config.SONG_ADDED.format(song.title),
|
||||
colour=config.COLOURS['blue'])
|
||||
await ctx.send(embed=embed)
|
||||
else:
|
||||
embed = self.__format_embed(song.info, config.SONG_ADDED)
|
||||
embed = self.__format_embed(song.info, config.SONG_ADDED_TWO)
|
||||
await ctx.send(embed=embed)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title=config.SONG_QUEUE_TITLE,
|
||||
title=config.SONG_PLAYER,
|
||||
description=config.SONGS_ADDED.format(songs_quant),
|
||||
colour=config.COLOURS['blue'])
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
if not self.__playing:
|
||||
try_another = True
|
||||
|
||||
while try_another: # This will ensure the first song source to be ready
|
||||
first_song = self.__playlist.next_song()
|
||||
if first_song == None:
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.DOWNLOADING_ERROR,
|
||||
colour=config.COLOURS['blue'])
|
||||
await ctx.send(embed=embed)
|
||||
break
|
||||
|
||||
while True:
|
||||
if first_song.source != None: # If song got downloaded
|
||||
try_another = False
|
||||
break
|
||||
|
||||
if first_song.problematic: # If song got any error, try another one
|
||||
break
|
||||
|
||||
if first_song != None:
|
||||
await self.__play_music(ctx, first_song)
|
||||
first_song = self.__playlist.next_song()
|
||||
await self.__play_music(ctx, first_song)
|
||||
|
||||
async def queue(self) -> discord.Embed:
|
||||
if self.__playlist.looping_one:
|
||||
info = self.__playlist.current.info
|
||||
title = 'Song Looping Now'
|
||||
title = config.ONE_SONG_LOOPING
|
||||
return self.__format_embed(info, title)
|
||||
|
||||
songs_preload = self.__playlist.songs_to_preload
|
||||
await self.__down.preload(songs_preload)
|
||||
total_time = format_time(sum([int(song.duration if song.duration else 0)
|
||||
for song in songs_preload])) # Sum the duration
|
||||
total_songs = len(self.__playlist)
|
||||
text = f'Total musics: {total_songs} | Duration: `{total_time}` downloaded \n\n'
|
||||
|
||||
for pos, song in enumerate(songs_preload, start=1):
|
||||
title = song.title if song.title else 'Downloading...'
|
||||
text += f"**`{pos}` - ** {title} - `{format_time(song.duration)}`\n"
|
||||
if len(songs_preload) == 0:
|
||||
title = config.SONG_PLAYER
|
||||
text = config.EMPTY_QUEUE
|
||||
|
||||
title = 'Songs in Queue'
|
||||
if len(songs_preload) > 0:
|
||||
if self.__playlist.looping_all:
|
||||
title = 'Repeating All'
|
||||
else:
|
||||
text = 'There is no musics in queue'
|
||||
if self.__playlist.looping_all:
|
||||
title = config.ALL_SONGS_LOOPING
|
||||
else:
|
||||
title = 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 config.SONG_DOWNLOADING
|
||||
text += f"**`{pos}` - ** {song_name} - `{format_time(song.duration)}`\n"
|
||||
|
||||
embed = discord.Embed(
|
||||
title=title,
|
||||
@ -202,7 +197,7 @@ class Player(commands.Cog):
|
||||
self.__guild.voice_client.resume()
|
||||
return True
|
||||
|
||||
async def loop(self, args: str):
|
||||
async def loop(self, args: str) -> str:
|
||||
args = args.lower()
|
||||
if args == 'one':
|
||||
description = self.__playlist.loop_one()
|
||||
@ -211,7 +206,7 @@ class Player(commands.Cog):
|
||||
elif args == 'off':
|
||||
description = self.__playlist.loop_off()
|
||||
else:
|
||||
description = 'Comando Loop\nOne - Repete a música atual\nAll - Repete as músicas atuais\nOff - Desativa o loop'
|
||||
description = config.HELP_LONG_LOOP
|
||||
|
||||
return description
|
||||
|
||||
@ -220,9 +215,9 @@ class Player(commands.Cog):
|
||||
|
||||
async def now_playing(self) -> discord.Embed:
|
||||
if self.__playlist.looping_one:
|
||||
title = 'Song Looping Now'
|
||||
title = config.ONE_SONG_LOOPING
|
||||
else:
|
||||
title = 'Song Playing Now'
|
||||
title = config.SONG_PLAYING
|
||||
|
||||
current_song = self.__playlist.current
|
||||
embed = self.__format_embed(current_song.info, title)
|
||||
@ -235,9 +230,9 @@ class Player(commands.Cog):
|
||||
songs = self.__playlist.songs_to_preload
|
||||
|
||||
await self.__down.preload(songs)
|
||||
return 'Musics shuffled successfully'
|
||||
return config.SONGS_SHUFFLED
|
||||
except:
|
||||
return 'An error ocurred :/'
|
||||
return config.ERROR_SHUFFLING
|
||||
|
||||
async def move(self, pos1, pos2='1') -> str:
|
||||
try:
|
||||
@ -245,7 +240,7 @@ class Player(commands.Cog):
|
||||
pos2 = int(pos2)
|
||||
|
||||
except:
|
||||
return 'This command require a number'
|
||||
return config.ERROR_NUMBER
|
||||
|
||||
result = self.__playlist.move_songs(pos1, pos2)
|
||||
|
||||
@ -259,12 +254,12 @@ class Player(commands.Cog):
|
||||
position = int(position)
|
||||
|
||||
except:
|
||||
return 'This command require a number'
|
||||
return config.ERROR_NUMBER
|
||||
|
||||
result = self.__playlist.remove_song(position)
|
||||
return result
|
||||
|
||||
def __format_embed(self, info, title='') -> discord.Embed:
|
||||
def __format_embed(self, info=dict, title='') -> discord.Embed:
|
||||
"""Configure the embed to show the song information"""
|
||||
embedvc = discord.Embed(
|
||||
title=title,
|
||||
@ -306,3 +301,11 @@ class Player(commands.Cog):
|
||||
self.__playlist.clear()
|
||||
self.__playlist.loop_off()
|
||||
await self.__guild.voice_client.disconnect()
|
||||
|
||||
def __ensure_source(self, song: Song) -> str:
|
||||
while True:
|
||||
if song.source != None: # If song got downloaded
|
||||
return song.source
|
||||
|
||||
if song.problematic: # If song got any error
|
||||
return None
|
||||
|
||||
@ -41,42 +41,27 @@ class Playlist(IPlaylist):
|
||||
def next_song(self) -> Song:
|
||||
"""Return the next song to play"""
|
||||
if self.__current == None and len(self.__queue) == 0:
|
||||
# If not playing and nothing to play
|
||||
return None
|
||||
|
||||
# If playing
|
||||
played_song = self.__current
|
||||
|
||||
# Check if need to repeat the played song
|
||||
if self.__looping_one: # Insert the current song to play again
|
||||
self.__queue.appendleft(played_song)
|
||||
|
||||
if self.__looping_all: # Insert the current song in the end of queue
|
||||
self.__queue.append(played_song)
|
||||
|
||||
while True: # Try to get the source of next song
|
||||
if len(self.__queue) == 0: # If no more song to play, return None
|
||||
while True:
|
||||
if len(self.__queue) == 0:
|
||||
return None
|
||||
|
||||
# Att the current with the first one
|
||||
self.__current = self.__queue[0]
|
||||
self.__queue.popleft() # Remove the current from queue
|
||||
self.__name_history.append(
|
||||
self.__current.identifier) # Add to name history
|
||||
self.__songs_history.append(self.__current) # Add to song history
|
||||
self.__queue.popleft()
|
||||
self.__name_history.append(self.__current.identifier)
|
||||
self.__songs_history.append(self.__current)
|
||||
|
||||
return self.__current
|
||||
|
||||
def prev_song(self) -> Song:
|
||||
"""Return the source of the last song played
|
||||
|
||||
Return None or the source of the prev song
|
||||
"""
|
||||
if len(self.__songs_history) == 0:
|
||||
return None
|
||||
else:
|
||||
return self.__songs_history[0].source
|
||||
|
||||
def add_song(self, identifier: str, requester: str) -> Song:
|
||||
"""Create a song object, add to queue and return it"""
|
||||
song = Song(identifier=identifier, playlist=self, requester=requester)
|
||||
@ -102,12 +87,13 @@ class Playlist(IPlaylist):
|
||||
Return: Embed descrition to show to user
|
||||
"""
|
||||
if self.__looping_all == True:
|
||||
return 'Vulkan already looping one music, disable loop first'
|
||||
return config.LOOP_ALL_ON
|
||||
|
||||
elif self.__looping_one == True:
|
||||
return "I'm already doing this, you dumb ass"
|
||||
return config.LOOP_ONE_ALREADY_ON
|
||||
else:
|
||||
self.__looping_one = True
|
||||
return 'Repeating the current song'
|
||||
return config.LOOP_ONE_ACTIVATE
|
||||
|
||||
def loop_all(self) -> str:
|
||||
"""Try to start the loop of all songs
|
||||
@ -115,21 +101,23 @@ class Playlist(IPlaylist):
|
||||
Return: Embed descrition to show to user
|
||||
"""
|
||||
if self.__looping_one == True:
|
||||
return 'Vulkan already looping one music, disable loop first'
|
||||
return config.LOOP_ONE_ON
|
||||
|
||||
elif self.__looping_all == True:
|
||||
return "I'm already doing this, you dumb ass"
|
||||
return config.LOOP_ALL_ALREADY_ON
|
||||
|
||||
else:
|
||||
self.__looping_all = True
|
||||
return 'Repeating all songs in queue'
|
||||
return config.LOOP_ALL_ACTIVATE
|
||||
|
||||
def loop_off(self) -> str:
|
||||
"""Disable both types of loop"""
|
||||
if self.__looping_all == False and self.__looping_one == False:
|
||||
return "The loop is already off, you fucking dick head"
|
||||
return config.LOOP_ALREADY_DISABLE
|
||||
|
||||
self.__looping_all = False
|
||||
self.__looping_one = False
|
||||
return 'Loop disable'
|
||||
return config.LOOP_DISABLE
|
||||
|
||||
def destroy_song(self, song_destroy: Song) -> None:
|
||||
"""Destroy a song object from the queue"""
|
||||
@ -150,7 +138,7 @@ class Playlist(IPlaylist):
|
||||
pos2 = len(self.__queue)
|
||||
|
||||
if pos2 not in range(1, len(self.__queue) + 1) or pos1 not in range(1, len(self.__queue) + 1):
|
||||
return 'Numbers must be between 1 and queue length, or -1 for the last song'
|
||||
return config.LENGTH_ERROR
|
||||
|
||||
try:
|
||||
song1 = self.__queue[pos1-1]
|
||||
@ -162,18 +150,17 @@ class Playlist(IPlaylist):
|
||||
song1_name = song1.title if song1.title else song1.identifier
|
||||
song2_name = song2.title if song2.title else song2.identifier
|
||||
|
||||
return f'Song `{song1_name}` in position `{pos1}` moved with `{song2_name}` in position `{pos2}` successfully'
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return 'There was a problem with the moving of songs'
|
||||
return config.SONG_MOVED_SUCCESSFULLY.format(song1_name, pos1, song2_name, pos2)
|
||||
except:
|
||||
return config.ERROR_MOVING
|
||||
|
||||
def remove_song(self, position) -> tuple:
|
||||
def remove_song(self, position) -> str:
|
||||
if position not in range(1, len(self.__queue) + 1) and position != -1:
|
||||
return 'Numbers must be between 1 and queue length, or -1 for the last song'
|
||||
return config.LENGTH_ERROR
|
||||
else:
|
||||
song = self.__queue[position-1]
|
||||
self.__queue.remove(song)
|
||||
|
||||
song_name = song.title if song.title else song.identifier
|
||||
|
||||
return f'Song `{song_name}` removed successfully'
|
||||
return config.SONG_REMOVED_SUCCESSFULLY.format(song_name)
|
||||
|
||||
@ -24,7 +24,7 @@ class SpotifySearch():
|
||||
except:
|
||||
return False
|
||||
|
||||
def search(self, music) -> list:
|
||||
def search(self, music=str) -> list:
|
||||
"""Search and return the title of musics on Spotify"""
|
||||
type = music.split('/')[3].split('?')[0]
|
||||
code = music.split('/')[4].split('?')[0]
|
||||
@ -34,19 +34,20 @@ class SpotifySearch():
|
||||
musics = self.__get_playlist(code)
|
||||
elif type == 'track':
|
||||
musics = self.__get_track(code)
|
||||
elif type == 'artist':
|
||||
musics = self.__get_artist(code)
|
||||
else:
|
||||
return None
|
||||
|
||||
return musics
|
||||
|
||||
def __get_album(self, code) -> list:
|
||||
"""Get the externals urls of a album
|
||||
def __get_album(self, code=str) -> list:
|
||||
"""Convert a album ID to list of songs names
|
||||
|
||||
ARG: Spotify Code of the Album
|
||||
ARG: Spotify Code of the Album
|
||||
"""
|
||||
if self.__connected == True:
|
||||
try:
|
||||
# Load all music objects
|
||||
results = self.__api.album_tracks(code)
|
||||
musics = results['items']
|
||||
|
||||
@ -66,10 +67,10 @@ class SpotifySearch():
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def __get_playlist(self, code) -> list:
|
||||
"""Get the externals urls of a playlist
|
||||
def __get_playlist(self, code=str) -> list:
|
||||
"""Convert a playlist ID to list of songs names
|
||||
|
||||
Arg: Spotify Code of the Playlist
|
||||
Arg: Spotify Code of the Playlist
|
||||
"""
|
||||
try:
|
||||
results = self.__api.playlist_items(code)
|
||||
@ -96,10 +97,10 @@ class SpotifySearch():
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def __get_track(self, code) -> list:
|
||||
"""Convert a external_url track to the title of the music
|
||||
def __get_track(self, code=str) -> list:
|
||||
"""Convert a track ID to the title of the music
|
||||
|
||||
ARG: Spotify Code of the Music
|
||||
ARG: Spotify Code of the Track
|
||||
"""
|
||||
results = self.__api.track(code)
|
||||
name = results['name']
|
||||
@ -109,10 +110,24 @@ class SpotifySearch():
|
||||
|
||||
return [f'{name} {artists}']
|
||||
|
||||
def __get_artist(self, code=str) -> list:
|
||||
"""Convert a external_url track to the title of the music
|
||||
|
||||
ARG: Spotify Code of the Music
|
||||
"""
|
||||
results = self.__api.artist_top_tracks(code, country='BR')
|
||||
|
||||
musics_titles = []
|
||||
for music in results['tracks']:
|
||||
title = self.__extract_title(music)
|
||||
musics_titles.append(title)
|
||||
|
||||
return musics_titles
|
||||
|
||||
def __extract_title(self, music: dict) -> str:
|
||||
"""Receive a spotify music object and return his title
|
||||
|
||||
ARG: music dict returned by Spotify
|
||||
ARG: music dict returned by Spotify
|
||||
"""
|
||||
title = f'{music["name"]} '
|
||||
for artist in music['artists']:
|
||||
|
||||
@ -11,7 +11,7 @@ def is_connected(ctx):
|
||||
return None
|
||||
|
||||
|
||||
def format_time(duration):
|
||||
def format_time(duration) -> str:
|
||||
if not duration:
|
||||
return "00:00"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user