mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Adding support to slash commands
This commit is contained in:
parent
ef66bf8bcb
commit
3b198cf78a
@ -396,6 +396,11 @@ class VEmbeds:
|
|||||||
)
|
)
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
|
def PLAYLIST_CLEAR(self) -> Embed:
|
||||||
|
return Embed(
|
||||||
|
description=self.__messages.PLAYLIST_CLEAR
|
||||||
|
)
|
||||||
|
|
||||||
def CARA_COROA(self, result: str) -> Embed:
|
def CARA_COROA(self, result: str) -> Embed:
|
||||||
embed = Embed(
|
embed = Embed(
|
||||||
title='Cara Coroa',
|
title='Cara Coroa',
|
||||||
|
|||||||
@ -21,8 +21,8 @@ class Helper(Singleton):
|
|||||||
Off - Disable loop."""
|
Off - Disable loop."""
|
||||||
self.HELP_NP = 'Show the info of the current song.'
|
self.HELP_NP = 'Show the info of the current song.'
|
||||||
self.HELP_NP_LONG = 'Show the information of the song being played.\n\nRequire: A song being played.\nArguments: None.'
|
self.HELP_NP_LONG = 'Show the information of the song being played.\n\nRequire: A song being played.\nArguments: None.'
|
||||||
self.HELP_QUEUE = f'Show the first {config.MAX_PRELOAD_SONGS} songs in queue.'
|
self.HELP_QUEUE = f'Show the first {config.MAX_SONGS_IN_PAGE} songs in queue.'
|
||||||
self.HELP_QUEUE_LONG = f'Show the first {config.MAX_PRELOAD_SONGS} song in the queue.\n\nArguments: None.'
|
self.HELP_QUEUE_LONG = f'Show the first {config.MAX_SONGS_IN_PAGE} song in the queue.\n\nArguments: None.'
|
||||||
self.HELP_PAUSE = 'Pauses the song player.'
|
self.HELP_PAUSE = 'Pauses the song player.'
|
||||||
self.HELP_PAUSE_LONG = 'If playing, pauses the song player.\n\nArguments: None'
|
self.HELP_PAUSE_LONG = 'If playing, pauses the song player.\n\nArguments: None'
|
||||||
self.HELP_PREV = 'Play the previous song.'
|
self.HELP_PREV = 'Play the previous song.'
|
||||||
@ -33,7 +33,7 @@ class Helper(Singleton):
|
|||||||
self.HELP_PLAY_LONG = 'Play a song in discord. \n\nRequire: You to be connected to a voice channel.\nArguments: Youtube, Spotify or Deezer song/playlist link or the title of the song to be searched in Youtube.'
|
self.HELP_PLAY_LONG = 'Play a song in discord. \n\nRequire: You to be connected to a voice channel.\nArguments: Youtube, Spotify or Deezer song/playlist link or the title of the song to be searched in Youtube.'
|
||||||
self.HELP_HISTORY = f'Show the history of played songs.'
|
self.HELP_HISTORY = f'Show the history of played songs.'
|
||||||
self.HELP_HISTORY_LONG = f'Show the last {config.MAX_SONGS_HISTORY} played songs'
|
self.HELP_HISTORY_LONG = f'Show the last {config.MAX_SONGS_HISTORY} played songs'
|
||||||
self.HELP_MOVE = 'Moves a song from position x to y in queue.'
|
self.HELP_MOVE = 'Moves a song from position pos1 to pos2 in queue.'
|
||||||
self.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.'
|
self.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.'
|
||||||
self.HELP_REMOVE = 'Remove a song in position x.'
|
self.HELP_REMOVE = 'Remove a song in position x.'
|
||||||
self.HELP_REMOVE_LONG = 'Remove a song from queue in the position passed.\n\nRequire: Position to be a valid number.\nArguments: 1º self.Number => Position in queue of the song.'
|
self.HELP_REMOVE_LONG = 'Remove a song from queue in the position passed.\n\nRequire: Position to be a valid number.\nArguments: 1º self.Number => Position in queue of the song.'
|
||||||
@ -49,3 +49,6 @@ class Helper(Singleton):
|
|||||||
self.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.'
|
self.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.'
|
||||||
self.HELP_CARA = 'Return cara or coroa.'
|
self.HELP_CARA = 'Return cara or coroa.'
|
||||||
self.HELP_CARA_LONG = 'Return cara or coroa.'
|
self.HELP_CARA_LONG = 'Return cara or coroa.'
|
||||||
|
|
||||||
|
self.SLASH_QUEUE_DESCRIPTION = f'Number of queue page, there is only {config.MAX_SONGS_IN_PAGE} musics by page'
|
||||||
|
self.SLASH_MOVE_HELP = 'Moves a song from position pos1 to pos2 in queue.'
|
||||||
|
|||||||
@ -31,6 +31,7 @@ class Messages(Singleton):
|
|||||||
self.STOPPING = f'{self.__emojis.STOP} Player Stopped'
|
self.STOPPING = f'{self.__emojis.STOP} Player Stopped'
|
||||||
self.EMPTY_QUEUE = f'{self.__emojis.QUEUE} Song queue is empty, use {configs.BOT_PREFIX}play to add new songs'
|
self.EMPTY_QUEUE = f'{self.__emojis.QUEUE} Song queue is empty, use {configs.BOT_PREFIX}play to add new songs'
|
||||||
self.SONG_DOWNLOADING = f'{self.__emojis.DOWNLOADING} Downloading...'
|
self.SONG_DOWNLOADING = f'{self.__emojis.DOWNLOADING} Downloading...'
|
||||||
|
self.PLAYLIST_CLEAR = f'{self.__emojis.MUSIC} Playlist is now empty'
|
||||||
|
|
||||||
self.HISTORY_TITLE = f'{self.__emojis.MUSIC} Played Songs'
|
self.HISTORY_TITLE = f'{self.__emojis.MUSIC} Played Songs'
|
||||||
self.HISTORY_EMPTY = f'{self.__emojis.QUEUE} There is no musics in history'
|
self.HISTORY_EMPTY = f'{self.__emojis.QUEUE} There is no musics in history'
|
||||||
|
|||||||
@ -45,7 +45,12 @@ class MusicCog(Cog):
|
|||||||
try:
|
try:
|
||||||
controller = PlayHandler(ctx, self.__bot)
|
controller = PlayHandler(ctx, self.__bot)
|
||||||
|
|
||||||
response = await controller.run(args)
|
if len(args) > 1:
|
||||||
|
track = " ".join(args)
|
||||||
|
else:
|
||||||
|
track = args
|
||||||
|
|
||||||
|
response = await controller.run(track)
|
||||||
if response is not None:
|
if response is not None:
|
||||||
cogResponser1 = EmbedCommandResponse(response, MessagesCategory.PLAYER)
|
cogResponser1 = EmbedCommandResponse(response, MessagesCategory.PLAYER)
|
||||||
cogResponser2 = EmoteCommandResponse(response, MessagesCategory.PLAYER)
|
cogResponser2 = EmoteCommandResponse(response, MessagesCategory.PLAYER)
|
||||||
|
|||||||
271
DiscordCogs/SlashCog.py
Normal file
271
DiscordCogs/SlashCog.py
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
from discord.ext.commands import slash_command, Cog
|
||||||
|
from discord import Option, ApplicationContext, OptionChoice
|
||||||
|
from Handlers.ClearHandler import ClearHandler
|
||||||
|
from Handlers.MoveHandler import MoveHandler
|
||||||
|
from Handlers.NowPlayingHandler import NowPlayingHandler
|
||||||
|
from Handlers.PlayHandler import PlayHandler
|
||||||
|
from Handlers.PrevHandler import PrevHandler
|
||||||
|
from Handlers.RemoveHandler import RemoveHandler
|
||||||
|
from Handlers.ResetHandler import ResetHandler
|
||||||
|
from Handlers.ShuffleHandler import ShuffleHandler
|
||||||
|
from Handlers.SkipHandler import SkipHandler
|
||||||
|
from Handlers.PauseHandler import PauseHandler
|
||||||
|
from Handlers.StopHandler import StopHandler
|
||||||
|
from Handlers.ResumeHandler import ResumeHandler
|
||||||
|
from Handlers.HistoryHandler import HistoryHandler
|
||||||
|
from Handlers.QueueHandler import QueueHandler
|
||||||
|
from Handlers.LoopHandler import LoopHandler
|
||||||
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
|
from Messages.Responses.SlashEmbedResponse import SlashEmbedResponse
|
||||||
|
from Music.VulkanBot import VulkanBot
|
||||||
|
from Config.Embeds import VEmbeds
|
||||||
|
from Config.Helper import Helper
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
helper = Helper()
|
||||||
|
|
||||||
|
|
||||||
|
class SlashCommands(Cog):
|
||||||
|
"""
|
||||||
|
Class to listen to Music commands
|
||||||
|
It'll listen for commands from discord, when triggered will create a specific Handler for the command
|
||||||
|
Execute the handler and then create a specific View to be showed in Discord
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, bot: VulkanBot) -> None:
|
||||||
|
self.__bot: VulkanBot = bot
|
||||||
|
self.__embeds = VEmbeds()
|
||||||
|
|
||||||
|
@slash_command(name="play", description=helper.HELP_PLAY)
|
||||||
|
async def play(self, ctx: ApplicationContext,
|
||||||
|
music: Option(str, "The music name or URL", required=True)) -> None:
|
||||||
|
# Due to the utilization of multiprocessing module in this Project, we have multiple instances of the Bot, and by using this flag
|
||||||
|
# we can control witch bot instance will listen to the commands that Discord send to our application
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = PlayHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run(music)
|
||||||
|
if response is not None:
|
||||||
|
cogResponser1 = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser1.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name="queue", description=helper.HELP_QUEUE)
|
||||||
|
async def queue(self, ctx: ApplicationContext,
|
||||||
|
page_number: Option(int, helper.SLASH_QUEUE_DESCRIPTION, min_value=1, default=1)) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = QueueHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
# Change index 1 to 0
|
||||||
|
page_number -= 1
|
||||||
|
response = await controller.run(page_number)
|
||||||
|
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.QUEUE)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name="skip", description=helper.HELP_SKIP)
|
||||||
|
async def skip(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = SkipHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='stop', description=helper.HELP_STOP)
|
||||||
|
async def stop(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = StopHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='pause', description=helper.HELP_PAUSE)
|
||||||
|
async def pause(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = PauseHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='resume', description=helper.HELP_RESUME)
|
||||||
|
async def resume(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = ResumeHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='previous', description=helper.HELP_PREV)
|
||||||
|
async def previous(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = PrevHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
if response is not None:
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='history', description=helper.HELP_HISTORY)
|
||||||
|
async def history(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = HistoryHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.HISTORY)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='loop', description=helper.HELP_LOOP)
|
||||||
|
async def loop(self, ctx: ApplicationContext,
|
||||||
|
loop_type: Option(str, choices=[
|
||||||
|
OptionChoice(name='off', value='off'),
|
||||||
|
OptionChoice(name='one', value='one'),
|
||||||
|
OptionChoice(name='all', value='all')
|
||||||
|
])) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = LoopHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run(loop_type)
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.LOOP)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='clear', description=helper.HELP_CLEAR)
|
||||||
|
async def clear(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = ClearHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='now_playing', description=helper.HELP_NP)
|
||||||
|
async def now_playing(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = NowPlayingHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.NOW_PLAYING)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='shuffle_songs', description=helper.HELP_SHUFFLE)
|
||||||
|
async def shuffle(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = ShuffleHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='move_song', description=helper.SLASH_MOVE_HELP)
|
||||||
|
async def move(self, ctx: ApplicationContext,
|
||||||
|
from_pos: Option(int, "The position of song to move", min_value=1),
|
||||||
|
to_pos: Option(int, "The position to put the song, default 1", min_value=1, default=1)) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
if from_pos == 0:
|
||||||
|
from_pos = 1
|
||||||
|
|
||||||
|
controller = MoveHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run(from_pos, to_pos)
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.MANAGING_QUEUE)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='remove', description=helper.HELP_REMOVE)
|
||||||
|
async def remove(self, ctx: ApplicationContext,
|
||||||
|
position: Option(int, "The song position to remove", min_value=1)) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = RemoveHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run(position)
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.MANAGING_QUEUE)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='reset', description=helper.HELP_RESET)
|
||||||
|
async def reset(self, ctx: ApplicationContext) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
controller = ResetHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run()
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(SlashCommands(bot))
|
||||||
@ -23,7 +23,8 @@ class ClearHandler(AbstractHandler):
|
|||||||
if acquired:
|
if acquired:
|
||||||
playlist.clear()
|
playlist.clear()
|
||||||
processLock.release()
|
processLock.release()
|
||||||
return HandlerResponse(self.ctx)
|
embed = self.embeds.PLAYLIST_CLEAR()
|
||||||
|
return HandlerResponse(self.ctx, embed)
|
||||||
else:
|
else:
|
||||||
processManager.resetProcess(self.guild, self.ctx)
|
processManager.resetProcess(self.guild, self.ctx)
|
||||||
embed = self.embeds.PLAYER_RESTARTED()
|
embed = self.embeds.PLAYER_RESTARTED()
|
||||||
|
|||||||
@ -21,8 +21,7 @@ class PlayHandler(AbstractHandler):
|
|||||||
self.__searcher = Searcher()
|
self.__searcher = Searcher()
|
||||||
self.__down = Downloader()
|
self.__down = Downloader()
|
||||||
|
|
||||||
async def run(self, args: str) -> HandlerResponse:
|
async def run(self, track: str) -> HandlerResponse:
|
||||||
track = " ".join(args)
|
|
||||||
requester = self.ctx.author.name
|
requester = self.ctx.author.name
|
||||||
|
|
||||||
if not self.__isUserConnected():
|
if not self.__isUserConnected():
|
||||||
|
|||||||
@ -47,11 +47,11 @@ class QueueHandler(AbstractHandler):
|
|||||||
return HandlerResponse(self.ctx, embed)
|
return HandlerResponse(self.ctx, embed)
|
||||||
|
|
||||||
songsPages = playlist.getSongsPages()
|
songsPages = playlist.getSongsPages()
|
||||||
if pageNumber < 0 or pageNumber >= len(songsPages):
|
# Truncate the pageNumber to the closest value
|
||||||
embed = self.embeds.INVALID_INDEX()
|
if pageNumber < 0:
|
||||||
error = InvalidIndex()
|
pageNumber = 0
|
||||||
processLock.release() # Release the Lock
|
elif pageNumber >= len(songsPages):
|
||||||
return HandlerResponse(self.ctx, embed, error)
|
pageNumber = len(songsPages) - 1
|
||||||
|
|
||||||
# Select the page in queue to be printed
|
# Select the page in queue to be printed
|
||||||
songs = songsPages[pageNumber]
|
songs = songsPages[pageNumber]
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
from typing import Union
|
|
||||||
from discord.ext.commands import Context
|
from discord.ext.commands import Context
|
||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Config.Exceptions import BadCommandUsage, VulkanError, ErrorRemoving, InvalidInput, NumberRequired
|
from Config.Exceptions import BadCommandUsage, VulkanError, ErrorRemoving, InvalidInput, NumberRequired
|
||||||
from Music.Playlist import Playlist
|
from Music.Playlist import Playlist
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
|
from Parallelism.ProcessInfo import ProcessInfo
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
|
|
||||||
@ -16,15 +16,14 @@ class RemoveHandler(AbstractHandler):
|
|||||||
async def run(self, position: str) -> HandlerResponse:
|
async def run(self, position: str) -> HandlerResponse:
|
||||||
# Get the current process of the guild
|
# Get the current process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager = self.config.getProcessManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if not processInfo:
|
if not processInfo:
|
||||||
# Clear the playlist
|
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
error = BadCommandUsage()
|
error = BadCommandUsage()
|
||||||
return HandlerResponse(self.ctx, embed, error)
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|
||||||
playlist = processInfo.getPlaylist()
|
playlist = processInfo.getPlaylist()
|
||||||
if playlist.getCurrentSong() is None:
|
if playlist is None:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
error = BadCommandUsage()
|
error = BadCommandUsage()
|
||||||
return HandlerResponse(self.ctx, embed, error)
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|||||||
39
Messages/DiscordMessages.py
Normal file
39
Messages/DiscordMessages.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
from discord import Message, WebhookMessage
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class VAbstractMessage(ABC):
|
||||||
|
"""
|
||||||
|
Abstract class to allow create a pattern when dealing with multiple Discord
|
||||||
|
messages types, such as Interaction Messages and the standard discord messages
|
||||||
|
that contains two different ways of deletion
|
||||||
|
"""
|
||||||
|
@abstractmethod
|
||||||
|
async def delete(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class VWebHookMessage(VAbstractMessage):
|
||||||
|
"""
|
||||||
|
Holds a WebhookMessage instance
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, message: WebhookMessage) -> None:
|
||||||
|
self.__message = message
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
async def delete(self):
|
||||||
|
await self.__message.delete()
|
||||||
|
|
||||||
|
|
||||||
|
class VDefaultMessage(VAbstractMessage):
|
||||||
|
"""
|
||||||
|
Holds a Message instance, the basic Discord message type
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, message: Message) -> None:
|
||||||
|
self.__message = message
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
async def delete(self):
|
||||||
|
await self.__message.delete()
|
||||||
@ -1,19 +1,20 @@
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
from discord import Message
|
|
||||||
from Config.Singleton import Singleton
|
from Config.Singleton import Singleton
|
||||||
from UI.Views.AbstractView import AbstractView
|
from UI.Views.AbstractView import AbstractView
|
||||||
from Messages.MessagesCategory import MessagesCategory
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
|
from Messages.DiscordMessages import VAbstractMessage
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
class MessagesManager(Singleton):
|
class MessagesManager(Singleton):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
if not super().created:
|
if not super().created:
|
||||||
# For each guild, and for each category, there will be a list of messages
|
# For each guild, and for each category, there will be a list of messages
|
||||||
self.__guildsMessages: Dict[int, Dict[MessagesCategory, List[Message]]] = {}
|
self.__guildsMessages: Dict[int, Dict[MessagesCategory, List[VAbstractMessage]]] = {}
|
||||||
# Will, for each message, store the AbstractView that controls it
|
# Will, for each message, store the AbstractView that controls it
|
||||||
self.__messagesViews: Dict[Message, AbstractView] = {}
|
self.__messagesViews: Dict[VAbstractMessage, AbstractView] = {}
|
||||||
|
|
||||||
def addMessage(self, guildID: int, category: MessagesCategory, message: Message, view: AbstractView = None) -> None:
|
def addMessage(self, guildID: int, category: MessagesCategory, message: VAbstractMessage, view: AbstractView = None) -> None:
|
||||||
if message is None:
|
if message is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ class MessagesManager(Singleton):
|
|||||||
self.__messagesViews[message] = view
|
self.__messagesViews[message] = view
|
||||||
sendedMessages.append(message)
|
sendedMessages.append(message)
|
||||||
|
|
||||||
async def addMessageAndClearPrevious(self, guildID: int, category: MessagesCategory, message: Message, view: AbstractView = None) -> None:
|
async def addMessageAndClearPrevious(self, guildID: int, category: MessagesCategory, message: VAbstractMessage, view: AbstractView = None) -> None:
|
||||||
if message is None:
|
if message is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ class MessagesManager(Singleton):
|
|||||||
for message in categoriesMessages[category]:
|
for message in categoriesMessages[category]:
|
||||||
self.__deleteMessage(message)
|
self.__deleteMessage(message)
|
||||||
|
|
||||||
async def __deleteMessage(self, message: Message) -> None:
|
async def __deleteMessage(self, message: VAbstractMessage) -> None:
|
||||||
try:
|
try:
|
||||||
# If there is a view for this message delete the key
|
# If there is a view for this message delete the key
|
||||||
if message in self.__messagesViews.keys():
|
if message in self.__messagesViews.keys():
|
||||||
@ -75,6 +76,5 @@ class MessagesManager(Singleton):
|
|||||||
del messageView
|
del messageView
|
||||||
|
|
||||||
await message.delete()
|
await message.delete()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
print(f'[ERROR DELETING MESSAGE] -> {e}')
|
print(f'[ERROR DELETING MESSAGE] -> {traceback.format_exc()}')
|
||||||
pass
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from Messages.Responses.AbstractCogResponse import AbstractCommandResponse
|
from Messages.Responses.AbstractCogResponse import AbstractCommandResponse
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Messages.MessagesCategory import MessagesCategory
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
|
from Messages.DiscordMessages import VAbstractMessage, VDefaultMessage
|
||||||
|
|
||||||
|
|
||||||
class EmbedCommandResponse(AbstractCommandResponse):
|
class EmbedCommandResponse(AbstractCommandResponse):
|
||||||
@ -9,16 +10,20 @@ class EmbedCommandResponse(AbstractCommandResponse):
|
|||||||
|
|
||||||
async def run(self, deleteLast: bool = True) -> None:
|
async def run(self, deleteLast: bool = True) -> None:
|
||||||
message = None
|
message = None
|
||||||
|
# If the response has both embed and view to be sended
|
||||||
if self.response.embed and self.response.view:
|
if self.response.embed and self.response.view:
|
||||||
message = await self.context.send(embed=self.response.embed, view=self.response.view)
|
message = await self.context.send(embed=self.response.embed, view=self.response.view)
|
||||||
# Set the view to contain the sended message
|
# Set the view to contain the sended message
|
||||||
self.response.view.set_message(message)
|
self.response.view.set_message(message)
|
||||||
|
|
||||||
|
# Or just a embed
|
||||||
elif self.response.embed:
|
elif self.response.embed:
|
||||||
message = await self.context.send(embed=self.response.embed)
|
message = await self.context.send(embed=self.response.embed)
|
||||||
|
|
||||||
if message:
|
if message:
|
||||||
|
vMessage: VAbstractMessage = VDefaultMessage(message)
|
||||||
# Only delete the previous message if this is not error and not forbidden by method caller
|
# Only delete the previous message if this is not error and not forbidden by method caller
|
||||||
if deleteLast and self.response.success:
|
if deleteLast and self.response.success:
|
||||||
await self.manager.addMessageAndClearPrevious(self.context.guild.id, self.category, message, self.response.view)
|
await self.manager.addMessageAndClearPrevious(self.context.guild.id, self.category, vMessage, self.response.view)
|
||||||
else:
|
else:
|
||||||
self.manager.addMessage(self.context.guild.id, self.category, message)
|
self.manager.addMessage(self.context.guild.id, self.category, vMessage)
|
||||||
|
|||||||
@ -11,6 +11,10 @@ class EmoteCommandResponse(AbstractCommandResponse):
|
|||||||
self.__emojis = VEmojis()
|
self.__emojis = VEmojis()
|
||||||
|
|
||||||
async def run(self, deleteLast: bool = True) -> None:
|
async def run(self, deleteLast: bool = True) -> None:
|
||||||
|
# Now with Discord Interactions some commands are triggered without message
|
||||||
|
if (self.message is None):
|
||||||
|
return None
|
||||||
|
|
||||||
if self.response.success:
|
if self.response.success:
|
||||||
await self.message.add_reaction(self.__emojis.SUCCESS)
|
await self.message.add_reaction(self.__emojis.SUCCESS)
|
||||||
else:
|
else:
|
||||||
|
|||||||
35
Messages/Responses/SlashEmbedResponse.py
Normal file
35
Messages/Responses/SlashEmbedResponse.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from Messages.Responses.AbstractCogResponse import AbstractCommandResponse
|
||||||
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
|
from Messages.DiscordMessages import VAbstractMessage, VWebHookMessage
|
||||||
|
from discord import ApplicationContext
|
||||||
|
|
||||||
|
|
||||||
|
class SlashEmbedResponse(AbstractCommandResponse):
|
||||||
|
def __init__(self, response: HandlerResponse, ctx: ApplicationContext, category: MessagesCategory) -> None:
|
||||||
|
self.__ctx = ctx
|
||||||
|
super().__init__(response, category)
|
||||||
|
|
||||||
|
async def run(self, deleteLast: bool = True) -> None:
|
||||||
|
message = None
|
||||||
|
# If the response has both embed and view to send
|
||||||
|
if self.response.embed and self.response.view:
|
||||||
|
# Respond the Slash command and set the view to contain the sended message
|
||||||
|
message = await self.__ctx.send_followup(embed=self.response.embed, view=self.response.view)
|
||||||
|
self.response.view.set_message(message)
|
||||||
|
|
||||||
|
# If the response only has the embed then send the embed
|
||||||
|
elif self.response.embed:
|
||||||
|
message = await self.__ctx.send_followup(embed=self.response.embed)
|
||||||
|
else:
|
||||||
|
message = await self.__ctx.send_followup('Ok!')
|
||||||
|
|
||||||
|
# If any message was sended
|
||||||
|
if message:
|
||||||
|
# Convert the Discord message type to an Vulkan type
|
||||||
|
vMessage: VAbstractMessage = VWebHookMessage(message)
|
||||||
|
# Only delete the previous message if this is not error and not forbidden by method caller
|
||||||
|
if deleteLast and self.response.success:
|
||||||
|
await self.manager.addMessageAndClearPrevious(self.context.guild.id, self.category, vMessage, self.response.view)
|
||||||
|
else:
|
||||||
|
self.manager.addMessage(self.context.guild.id, self.category, vMessage)
|
||||||
@ -8,13 +8,18 @@ from Config.Embeds import VEmbeds
|
|||||||
|
|
||||||
|
|
||||||
class VulkanBot(Bot):
|
class VulkanBot(Bot):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, listingSlash: bool = False, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
self.__listingSlash = listingSlash
|
||||||
self.__configs = VConfigs()
|
self.__configs = VConfigs()
|
||||||
self.__messages = Messages()
|
self.__messages = Messages()
|
||||||
self.__embeds = VEmbeds()
|
self.__embeds = VEmbeds()
|
||||||
self.remove_command("help")
|
self.remove_command("help")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def listingSlash(self) -> bool:
|
||||||
|
return self.__listingSlash
|
||||||
|
|
||||||
def startBot(self) -> None:
|
def startBot(self) -> None:
|
||||||
"""Blocking function that will start the bot"""
|
"""Blocking function that will start the bot"""
|
||||||
if self.__configs.BOT_TOKEN == '':
|
if self.__configs.BOT_TOKEN == '':
|
||||||
|
|||||||
@ -23,10 +23,15 @@ class VulkanInitializer:
|
|||||||
def __create_bot(self, willListen: bool) -> VulkanBot:
|
def __create_bot(self, willListen: bool) -> VulkanBot:
|
||||||
if willListen:
|
if willListen:
|
||||||
prefix = self.__config.BOT_PREFIX
|
prefix = self.__config.BOT_PREFIX
|
||||||
|
bot = VulkanBot(listingSlash=True,
|
||||||
|
command_prefix=prefix,
|
||||||
|
pm_help=True,
|
||||||
|
case_insensitive=True,
|
||||||
|
intents=self.__intents)
|
||||||
else:
|
else:
|
||||||
prefix = ''.join(choices(string.ascii_uppercase + string.digits, k=4))
|
prefix = ''.join(choices(string.ascii_uppercase + string.digits, k=4))
|
||||||
|
bot = VulkanBot(listingSlash=False,
|
||||||
bot = VulkanBot(command_prefix=prefix,
|
command_prefix=prefix,
|
||||||
pm_help=True,
|
pm_help=True,
|
||||||
case_insensitive=True,
|
case_insensitive=True,
|
||||||
intents=self.__intents)
|
intents=self.__intents)
|
||||||
|
|||||||
@ -15,7 +15,8 @@ Vulkan uses multiprocessing and asynchronous Python modules to maximize Music Pl
|
|||||||
- Play musics from Youtube, Spotify and Deezer links (Albums, Artists, Playlists and Tracks).
|
- Play musics from Youtube, Spotify and Deezer links (Albums, Artists, Playlists and Tracks).
|
||||||
- Play musics in multiple discord server at the same time.
|
- Play musics in multiple discord server at the same time.
|
||||||
- The player contains buttons to shortcut some commands.
|
- The player contains buttons to shortcut some commands.
|
||||||
- Search for all musics in Queue using buttons
|
- Support for the new Discord Slash commands.
|
||||||
|
- Search for all musics in Queue using buttons.
|
||||||
- Shortcut the playing of one song using dropdown menu.
|
- Shortcut the playing of one song using dropdown menu.
|
||||||
- Manage the loop of one or all playing musics.
|
- Manage the loop of one or all playing musics.
|
||||||
- Manage the order and remove musics from the queue.
|
- Manage the order and remove musics from the queue.
|
||||||
|
|||||||
@ -1,16 +1,19 @@
|
|||||||
from typing import List
|
|
||||||
from discord import Message
|
|
||||||
from discord.ui import View
|
|
||||||
from Config.Emojis import VEmojis
|
|
||||||
from Music.VulkanBot import VulkanBot
|
|
||||||
from UI.Views.AbstractView import AbstractView
|
from UI.Views.AbstractView import AbstractView
|
||||||
from UI.Buttons.AbstractItem import AbstractItem
|
from UI.Buttons.AbstractItem import AbstractItem
|
||||||
|
from Music.VulkanBot import VulkanBot
|
||||||
|
from Config.Emojis import VEmojis
|
||||||
|
from discord import Message
|
||||||
|
from discord.ui import View
|
||||||
|
from typing import List
|
||||||
|
|
||||||
emojis = VEmojis()
|
emojis = VEmojis()
|
||||||
|
|
||||||
|
|
||||||
class BasicView(View, AbstractView):
|
class BasicView(View, AbstractView):
|
||||||
"""View that receives buttons to hold, in timeout disable buttons"""
|
"""
|
||||||
|
View class that inherits from the Discord View Class, managing a list of Buttons
|
||||||
|
and the message that holds this View.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, bot: VulkanBot, buttons: List[AbstractItem], timeout: float = 6000):
|
def __init__(self, bot: VulkanBot, buttons: List[AbstractItem], timeout: float = 6000):
|
||||||
super().__init__(timeout=timeout)
|
super().__init__(timeout=timeout)
|
||||||
@ -42,6 +45,7 @@ class BasicView(View, AbstractView):
|
|||||||
self.__message = message
|
self.__message = message
|
||||||
|
|
||||||
async def update(self):
|
async def update(self):
|
||||||
|
"""Edit the message sending the view again"""
|
||||||
try:
|
try:
|
||||||
if not self.__working:
|
if not self.__working:
|
||||||
return
|
return
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user