Adding support to slash commands

This commit is contained in:
Rafael Vargas 2022-09-22 16:20:05 -03:00
parent ef66bf8bcb
commit 3b198cf78a
18 changed files with 422 additions and 40 deletions

View File

@ -396,6 +396,11 @@ class VEmbeds:
)
return embed
def PLAYLIST_CLEAR(self) -> Embed:
return Embed(
description=self.__messages.PLAYLIST_CLEAR
)
def CARA_COROA(self, result: str) -> Embed:
embed = Embed(
title='Cara Coroa',

View File

@ -21,8 +21,8 @@ class Helper(Singleton):
Off - Disable loop."""
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_QUEUE = f'Show the first {config.MAX_PRELOAD_SONGS} 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 = f'Show the first {config.MAX_SONGS_IN_PAGE} songs in queue.'
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_LONG = 'If playing, pauses the song player.\n\nArguments: None'
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_HISTORY = f'Show the history of 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_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.'
@ -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_CARA = '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.'

View File

@ -31,6 +31,7 @@ class Messages(Singleton):
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.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_EMPTY = f'{self.__emojis.QUEUE} There is no musics in history'

View File

@ -45,7 +45,12 @@ class MusicCog(Cog):
try:
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:
cogResponser1 = EmbedCommandResponse(response, MessagesCategory.PLAYER)
cogResponser2 = EmoteCommandResponse(response, MessagesCategory.PLAYER)

271
DiscordCogs/SlashCog.py Normal file
View 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))

View File

@ -23,7 +23,8 @@ class ClearHandler(AbstractHandler):
if acquired:
playlist.clear()
processLock.release()
return HandlerResponse(self.ctx)
embed = self.embeds.PLAYLIST_CLEAR()
return HandlerResponse(self.ctx, embed)
else:
processManager.resetProcess(self.guild, self.ctx)
embed = self.embeds.PLAYER_RESTARTED()

View File

@ -21,8 +21,7 @@ class PlayHandler(AbstractHandler):
self.__searcher = Searcher()
self.__down = Downloader()
async def run(self, args: str) -> HandlerResponse:
track = " ".join(args)
async def run(self, track: str) -> HandlerResponse:
requester = self.ctx.author.name
if not self.__isUserConnected():

View File

@ -47,11 +47,11 @@ class QueueHandler(AbstractHandler):
return HandlerResponse(self.ctx, embed)
songsPages = playlist.getSongsPages()
if pageNumber < 0 or pageNumber >= len(songsPages):
embed = self.embeds.INVALID_INDEX()
error = InvalidIndex()
processLock.release() # Release the Lock
return HandlerResponse(self.ctx, embed, error)
# Truncate the pageNumber to the closest value
if pageNumber < 0:
pageNumber = 0
elif pageNumber >= len(songsPages):
pageNumber = len(songsPages) - 1
# Select the page in queue to be printed
songs = songsPages[pageNumber]

View File

@ -1,10 +1,10 @@
from typing import Union
from discord.ext.commands import Context
from Handlers.AbstractHandler import AbstractHandler
from Handlers.HandlerResponse import HandlerResponse
from Config.Exceptions import BadCommandUsage, VulkanError, ErrorRemoving, InvalidInput, NumberRequired
from Music.Playlist import Playlist
from Music.VulkanBot import VulkanBot
from Parallelism.ProcessInfo import ProcessInfo
from typing import Union
from discord import Interaction
@ -16,15 +16,14 @@ class RemoveHandler(AbstractHandler):
async def run(self, position: str) -> HandlerResponse:
# Get the current process of the guild
processManager = self.config.getProcessManager()
processInfo = processManager.getRunningPlayerInfo(self.guild)
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
if not processInfo:
# Clear the playlist
embed = self.embeds.NOT_PLAYING()
error = BadCommandUsage()
return HandlerResponse(self.ctx, embed, error)
playlist = processInfo.getPlaylist()
if playlist.getCurrentSong() is None:
if playlist is None:
embed = self.embeds.NOT_PLAYING()
error = BadCommandUsage()
return HandlerResponse(self.ctx, embed, error)

View 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()

View File

@ -1,19 +1,20 @@
from typing import Dict, List
from discord import Message
from Config.Singleton import Singleton
from UI.Views.AbstractView import AbstractView
from Messages.MessagesCategory import MessagesCategory
from Messages.DiscordMessages import VAbstractMessage
import traceback
class MessagesManager(Singleton):
def __init__(self) -> None:
if not super().created:
# 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
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:
return
@ -29,7 +30,7 @@ class MessagesManager(Singleton):
self.__messagesViews[message] = view
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:
return
@ -66,7 +67,7 @@ class MessagesManager(Singleton):
for message in categoriesMessages[category]:
self.__deleteMessage(message)
async def __deleteMessage(self, message: Message) -> None:
async def __deleteMessage(self, message: VAbstractMessage) -> None:
try:
# If there is a view for this message delete the key
if message in self.__messagesViews.keys():
@ -75,6 +76,5 @@ class MessagesManager(Singleton):
del messageView
await message.delete()
except Exception as e:
print(f'[ERROR DELETING MESSAGE] -> {e}')
pass
except Exception:
print(f'[ERROR DELETING MESSAGE] -> {traceback.format_exc()}')

View File

@ -1,6 +1,7 @@
from Messages.Responses.AbstractCogResponse import AbstractCommandResponse
from Handlers.HandlerResponse import HandlerResponse
from Messages.MessagesCategory import MessagesCategory
from Messages.DiscordMessages import VAbstractMessage, VDefaultMessage
class EmbedCommandResponse(AbstractCommandResponse):
@ -9,16 +10,20 @@ class EmbedCommandResponse(AbstractCommandResponse):
async def run(self, deleteLast: bool = True) -> None:
message = None
# If the response has both embed and view to be sended
if self.response.embed and self.response.view:
message = await self.context.send(embed=self.response.embed, view=self.response.view)
# Set the view to contain the sended message
self.response.view.set_message(message)
# Or just a embed
elif self.response.embed:
message = await self.context.send(embed=self.response.embed)
if message:
vMessage: VAbstractMessage = VDefaultMessage(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, message, self.response.view)
await self.manager.addMessageAndClearPrevious(self.context.guild.id, self.category, vMessage, self.response.view)
else:
self.manager.addMessage(self.context.guild.id, self.category, message)
self.manager.addMessage(self.context.guild.id, self.category, vMessage)

View File

@ -11,6 +11,10 @@ class EmoteCommandResponse(AbstractCommandResponse):
self.__emojis = VEmojis()
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:
await self.message.add_reaction(self.__emojis.SUCCESS)
else:

View 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)

View File

@ -8,13 +8,18 @@ from Config.Embeds import VEmbeds
class VulkanBot(Bot):
def __init__(self, *args, **kwargs):
def __init__(self, listingSlash: bool = False, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__listingSlash = listingSlash
self.__configs = VConfigs()
self.__messages = Messages()
self.__embeds = VEmbeds()
self.remove_command("help")
@property
def listingSlash(self) -> bool:
return self.__listingSlash
def startBot(self) -> None:
"""Blocking function that will start the bot"""
if self.__configs.BOT_TOKEN == '':

View File

@ -23,13 +23,18 @@ class VulkanInitializer:
def __create_bot(self, willListen: bool) -> VulkanBot:
if willListen:
prefix = self.__config.BOT_PREFIX
bot = VulkanBot(listingSlash=True,
command_prefix=prefix,
pm_help=True,
case_insensitive=True,
intents=self.__intents)
else:
prefix = ''.join(choices(string.ascii_uppercase + string.digits, k=4))
bot = VulkanBot(command_prefix=prefix,
pm_help=True,
case_insensitive=True,
intents=self.__intents)
bot = VulkanBot(listingSlash=False,
command_prefix=prefix,
pm_help=True,
case_insensitive=True,
intents=self.__intents)
return bot
def __add_cogs(self, bot: Bot) -> None:

View File

@ -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 in multiple discord server at the same time.
- 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.
- Manage the loop of one or all playing musics.
- Manage the order and remove musics from the queue.

View File

@ -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.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()
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):
super().__init__(timeout=timeout)
@ -42,6 +45,7 @@ class BasicView(View, AbstractView):
self.__message = message
async def update(self):
"""Edit the message sending the view again"""
try:
if not self.__working:
return