mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b39e1f0216 | ||
|
|
37f5773c8e | ||
|
|
0d606361da | ||
|
|
173b6a7b43 | ||
|
|
5b4c5b49f1 | ||
|
|
ea5245cf95 | ||
|
|
5063c45e87 | ||
|
|
c41a6a6c8a | ||
|
|
615fd580bc | ||
|
|
9b38ba4434 | ||
|
|
bbddcb555b | ||
|
|
3b1a7d5364 | ||
|
|
37acd1a61b | ||
|
|
ccad2de97c | ||
|
|
a1881cd46b | ||
|
|
bb8d514525 | ||
|
|
ef2d7bb8fa | ||
|
|
13bc51fae7 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
assets/
|
||||
__pycache__
|
||||
.env
|
||||
.cache
|
||||
|
||||
91
README.md
91
README.md
@@ -1,12 +1,53 @@
|
||||
# **Vulkan**
|
||||
|
||||
A multi-purpose Discord bot, including music, written in Python and supports Youtube and Spotify sources for playing. Vulkan was designed so that everyone could fork this project and use it, including a 24/7 host on Heroku.
|
||||
A Music Discord bot, written in Python, that supports Youtube and Spotify sources for playing. Vulkan was designed so that anyone can fork this project, follow the instructions and use it in their own way, Vulkan can also be configured in Heroku to work 24/7.
|
||||
|
||||
|
||||
Vulkan is also able to get data from Warframe and send it to users, get random phrases and handle random operations to help users decide what to do.
|
||||
# **Music**
|
||||
- Play musics from Youtube and Spotify Playlists
|
||||
- Control loop of one or all musics
|
||||
- Allow moving and removing musics in the queue
|
||||
- Play musics in queue randomly
|
||||
- Store played songs and allow bidirectional flow
|
||||
|
||||
### Commands
|
||||
```!play [title, spotify_url, youtube_url]``` - Start playing song
|
||||
|
||||
```!resume``` - Resume the song player
|
||||
|
||||
```!pause``` - Pause the song player
|
||||
|
||||
```!skip``` - Skip the currently playing song
|
||||
|
||||
```!prev``` - Return to play the previous song
|
||||
|
||||
```!stop``` - Stop the playing of musics
|
||||
|
||||
```!queue``` - Show the musics list in queue
|
||||
|
||||
```!history``` - Show the played songs list
|
||||
|
||||
```!loop [one, all, off]``` - Control the loop of songs
|
||||
|
||||
```!shuffle``` - Shuffle the songs in queue
|
||||
|
||||
```!remove [x]``` - Remove the song in position x
|
||||
|
||||
```!move [x, y]``` - Change the musics in position x and y in Queue
|
||||
|
||||
```!np``` - Show information of the currently song
|
||||
|
||||
```!clear``` - Clear the songs in queue, doesn't stop the player
|
||||
|
||||
```!reset``` - Reset the player, recommended if any error happen
|
||||
|
||||
```!invite``` - Send the URL to invite Vulkan to your server
|
||||
|
||||
```!help [command]``` - Show more info about the command selected
|
||||
|
||||
|
||||
## **Prerequisites:**
|
||||
|
||||
# **Usage:**
|
||||
|
||||
### **API Keys**
|
||||
* Your Discord Application - [Discord](https://discord.com/developers)
|
||||
@@ -26,17 +67,11 @@ pip install -r requirements.txt
|
||||
*FFMPEG must be configured in the PATH for Windows users. Check this [YoutubeVideo](https://www.youtube.com/watch?v=r1AtmY-RMyQ&t=114s&ab_channel=TroubleChute).*
|
||||
|
||||
### **.Env File Example**
|
||||
This is an example of how your .env file (located in root) should look like, those API url could be the same.
|
||||
This is an example of how your .env file (located in root) should look like.
|
||||
```
|
||||
CETUS_API=https://api.warframestat.us/pc/cetusCycle
|
||||
CAMBION_API=https://api.warframestat.us/pc/cambionCycle
|
||||
FISSURES_API=https://api.warframestat.us/pc/fissures
|
||||
PHRASES_API='http://api.forismatic.com/api/1.0/?method=getQuote&key=457653&format=json&lang=en'
|
||||
|
||||
BOT_TOKEN=Your_Own_Bot_Token
|
||||
SPOTIFY_ID=Your_Own_Spotify_ID
|
||||
SPOTIFY_SECRET=Your_Own_Spotify_Secret
|
||||
SECRET_MESSAGE=Your_Own_Secret_Message
|
||||
|
||||
```
|
||||
|
||||
@@ -57,40 +92,6 @@ To run your Bot in Heroku 24/7, you will need the Procfile located in root, then
|
||||
- https://github.com/xrisk/heroku-opus.git
|
||||
|
||||
|
||||
# **Music**
|
||||
- Play musics from Youtube and Spotify Playlists
|
||||
- Controll loop of one or all musics
|
||||
- Allow realocating musics in the queue
|
||||
- Play musics in queue randomly
|
||||
|
||||
### Commands
|
||||
```!play [title, spotify_url, youtube_url]``` - Start playing song in Discord
|
||||
|
||||
```!resume``` - Resume the song player
|
||||
|
||||
```!pause``` - Pause the song player
|
||||
|
||||
```!move [x, y]``` - Change the musics in position x and y in Queue
|
||||
|
||||
```!skip``` - Skip the currently playing song
|
||||
|
||||
```!stop``` - Stop the playing of musics
|
||||
|
||||
```!queue``` - Show the musics list in queue
|
||||
|
||||
```!shuffle``` - Shuffle the songs in queue
|
||||
|
||||
```!remove [x]``` - Remove the song in position x
|
||||
|
||||
```!reset``` - Reset the player, recommended if any error happen
|
||||
|
||||
```!loop [one, all, off]``` - Control the loop of songs
|
||||
|
||||
```!np``` - Show information of the currently song
|
||||
|
||||
```!clear``` - Clear the songs in queue, doesn't stop the player
|
||||
|
||||
|
||||
## License
|
||||
- This program is free software: you can redistribute it and/or modify it under the terms of the [MIT License](https://github.com/RafaelSolVargas/Vulkan/blob/master/LICENSE).
|
||||
|
||||
@@ -100,4 +101,4 @@ To run your Bot in Heroku 24/7, you will need the Procfile located in root, then
|
||||
|
||||
|
||||
## Acknowledgment
|
||||
- See the DingoLingo [project](https://github.com/Raptor123471/DingoLingo) from Raptor123471, it helped me a lot building Vulkan
|
||||
- See the DingoLingo [project](https://github.com/Raptor123471/DingoLingo) from Raptor123471, it helped me a lot to build Vulkan.
|
||||
|
||||
@@ -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,47 +11,62 @@ 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 = 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_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_HELP = 'This command :)'
|
||||
|
||||
SONGS_ADDED = 'You added {} songs to the queue'
|
||||
SONG_ADDED = 'You added the song {} to the queue'
|
||||
SONG_QUEUE_TITLE = 'Songs 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'
|
||||
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 :/'
|
||||
HISTORY_TITLE = '🎧 Played Songs'
|
||||
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'
|
||||
|
||||
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'
|
||||
LOOP_ON = f'❌ This command cannot be invoked with any loop activated. Use {BOT_PREFIX}loop off to disable loop'
|
||||
|
||||
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 = 'This guild are not connected to Vulkan'
|
||||
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,
|
||||
|
||||
43
config/help.py
Normal file
43
config/help.py
Normal file
@@ -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.'
|
||||
@@ -1,5 +1,5 @@
|
||||
discord.py
|
||||
discord.py==1.7.3
|
||||
discord.py[voice]
|
||||
yt_dlp
|
||||
spotipy
|
||||
python-decouple
|
||||
python-decouple==3.5
|
||||
spotipy==2.19.0
|
||||
yt-dlp==2021.12.1
|
||||
|
||||
@@ -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', 'drop']
|
||||
'MUSIC': ['resume', 'pause', 'loop', 'stop',
|
||||
'skip', 'play', 'queue', 'clear',
|
||||
'np', 'shuffle', 'move', 'remove',
|
||||
'reset', 'prev', 'history'],
|
||||
'RANDOM': ['choose', 'cara', 'random']
|
||||
|
||||
}
|
||||
|
||||
@commands.Cog.listener()
|
||||
@@ -27,44 +29,93 @@ 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')
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.ERROR_MISSING_ARGUMENTS,
|
||||
colour=config.COLOURS['red']
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
elif isinstance(error, CommandNotFound):
|
||||
await ctx.channel.send(f'O comando não existe')
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.COMMAND_NOT_FOUND,
|
||||
colour=config.COLOURS['red']
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
else:
|
||||
await ctx.channel.send(f'Teve um erro aí bicho')
|
||||
raise error
|
||||
print(error)
|
||||
embed = discord.Embed(
|
||||
title=config.ERROR_TITLE,
|
||||
description=config.UNKNOWN_ERROR,
|
||||
colour=config.COLOURS['red']
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="help", alisases=['ajuda'], help=config.HELP_HELP)
|
||||
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(
|
||||
colour=config.COLOURS['grey'],
|
||||
title=f'Comandos do {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):
|
||||
|
||||
@@ -2,40 +2,56 @@ 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 *
|
||||
|
||||
|
||||
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:
|
||||
"""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'])
|
||||
async def play(self, ctx, *args):
|
||||
user_input = " ".join(args)
|
||||
@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
|
||||
|
||||
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.IMPOSSIBLE_MOVE, 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):
|
||||
@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:
|
||||
return
|
||||
@@ -43,62 +59,84 @@ 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=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:
|
||||
return
|
||||
else:
|
||||
await player.skip()
|
||||
await player.skip(ctx)
|
||||
|
||||
@commands.command(name='stop', help=config.HELP_STOP, aliases=['parar'])
|
||||
async def stop(self, ctx):
|
||||
@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:
|
||||
return
|
||||
else:
|
||||
await player.stop()
|
||||
|
||||
@commands.command(name='pause', help=config.HELP_PAUSE, aliases=['pausar'])
|
||||
async def pause(self, ctx):
|
||||
@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:
|
||||
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):
|
||||
@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:
|
||||
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='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:
|
||||
return
|
||||
|
||||
if is_connected(ctx) == None:
|
||||
success = await player.connect(ctx)
|
||||
if success == False:
|
||||
await self.__send_embed(ctx, config.IMPOSSIBLE_MOVE, config.NO_CHANNEL, 'red')
|
||||
return
|
||||
|
||||
await player.play_prev(ctx)
|
||||
|
||||
@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:
|
||||
return
|
||||
else:
|
||||
result = await player.loop(args)
|
||||
await self.__send_embed(ctx, description=result, colour_name='blue')
|
||||
embed = player.history()
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name='clear', help=config.HELP_CLEAR, aliases=['limpar'])
|
||||
async def clear(self, ctx):
|
||||
@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:
|
||||
return
|
||||
else:
|
||||
description = await player.loop(args)
|
||||
await self.__send_embed(ctx, config.SONG_PLAYER, description, 'blue')
|
||||
|
||||
@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:
|
||||
return
|
||||
else:
|
||||
await player.clear()
|
||||
|
||||
@commands.command(name='np', help=config.HELP_NP, aliases=['playing', 'now'])
|
||||
async def now_playing(self, ctx):
|
||||
@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:
|
||||
return
|
||||
@@ -107,46 +145,45 @@ class Music(commands.Cog):
|
||||
await self.__clean_messages(ctx)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name='shuffle', help=config.HELP_SHUFFLE, aliases=['aleatorio'])
|
||||
async def shuffle(self, ctx):
|
||||
@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:
|
||||
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=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:
|
||||
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"""
|
||||
@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:
|
||||
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):
|
||||
@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:
|
||||
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 +193,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 +201,14 @@ 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':
|
||||
await message.delete()
|
||||
if len(embed.fields) > 0:
|
||||
if embed.fields[0].name == 'Uploader:':
|
||||
await message.delete()
|
||||
|
||||
except:
|
||||
continue
|
||||
|
||||
def __get_player(self, ctx):
|
||||
def __get_player(self, ctx) -> Player:
|
||||
try:
|
||||
return self.__guilds[ctx.guild]
|
||||
except:
|
||||
|
||||
@@ -1,59 +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 '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 Exception as e:
|
||||
continue
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Phrases(bot))
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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))
|
||||
@@ -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 *
|
||||
|
||||
@@ -21,45 +22,60 @@ 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):
|
||||
async def connect(self, ctx) -> bool:
|
||||
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) -> None:
|
||||
if self.__force_stop: # If it's forced to stop player
|
||||
self.__force_stop = False
|
||||
return
|
||||
|
||||
def __play_next(self, error, ctx):
|
||||
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 +114,81 @@ 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
|
||||
first_song = self.__playlist.next_song()
|
||||
await self.__play_music(ctx, first_song)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
while True:
|
||||
if first_song.source != None: # If song got downloaded
|
||||
try_another = False
|
||||
break
|
||||
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
|
||||
|
||||
if first_song.problematic: # If song got any error, try another one
|
||||
break
|
||||
|
||||
if first_song != None:
|
||||
await self.__play_music(ctx, first_song)
|
||||
await self.__play_music(ctx, 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,
|
||||
@@ -168,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
|
||||
@@ -202,8 +259,11 @@ 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 self.__playlist.current == None:
|
||||
return config.PLAYER_NOT_PLAYING
|
||||
|
||||
if args == 'one':
|
||||
description = self.__playlist.loop_one()
|
||||
elif args == 'all':
|
||||
@@ -211,7 +271,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 = help.HELP_LONG_LOOP
|
||||
|
||||
return description
|
||||
|
||||
@@ -219,10 +279,18 @@ 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 = '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,17 +303,20 @@ 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:
|
||||
if not self.__playing:
|
||||
return config.PLAYER_NOT_PLAYING
|
||||
|
||||
try:
|
||||
pos1 = int(pos1)
|
||||
pos2 = int(pos2)
|
||||
|
||||
except:
|
||||
return 'This command require a number'
|
||||
return config.ERROR_NUMBER
|
||||
|
||||
result = self.__playlist.move_songs(pos1, pos2)
|
||||
|
||||
@@ -255,16 +326,19 @@ 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)
|
||||
|
||||
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 +380,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
|
||||
|
||||
@@ -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,43 +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:
|
||||
# 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)
|
||||
# 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: # Try to get the source of next song
|
||||
if len(self.__queue) == 0: # If no more song to play, return None
|
||||
return None
|
||||
elif self.__looping_one: # Insert the current song to play again
|
||||
self.__queue.appendleft(played_song)
|
||||
|
||||
# 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
|
||||
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:
|
||||
"""Return the source of the last song played
|
||||
|
||||
Return None or the source of the prev song
|
||||
"""
|
||||
"""If playing return it to queue and return the previous song to play"""
|
||||
if len(self.__songs_history) == 0:
|
||||
return None
|
||||
else:
|
||||
return self.__songs_history[0].source
|
||||
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"""
|
||||
@@ -94,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
|
||||
@@ -102,12 +107,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 +121,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 +158,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 +170,26 @@ 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)
|
||||
|
||||
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
|
||||
|
||||
@@ -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']:
|
||||
|
||||
@@ -6,12 +6,16 @@ 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
|
||||
|
||||
|
||||
def format_time(duration):
|
||||
def format_time(duration) -> str:
|
||||
if not duration:
|
||||
return "00:00"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user