From 2794f1a6d0c25726883bf99d803ec56694ab5af6 Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Tue, 16 Aug 2022 18:19:17 -0400 Subject: [PATCH] Upgrading views manager in messages timeout --- Handlers/QueueHandler.py | 2 +- Messages/MessagesManager.py | 19 +++++++++++++++++-- Messages/Responses/EmbedCogResponse.py | 2 +- Parallelism/ProcessExecutor.py | 2 +- .../{EmptyButton.py => CallbackButton.py} | 2 +- UI/Buttons/HandlerButton.py | 2 +- UI/Buttons/PlaylistDropdown.py | 10 ++++++---- UI/Views/AbstractView.py | 4 ++++ UI/Views/BasicView.py | 19 ++++++++++++++++--- 9 files changed, 48 insertions(+), 14 deletions(-) rename UI/Buttons/{EmptyButton.py => CallbackButton.py} (96%) diff --git a/Handlers/QueueHandler.py b/Handlers/QueueHandler.py index 5215f87..fea2f2a 100644 --- a/Handlers/QueueHandler.py +++ b/Handlers/QueueHandler.py @@ -11,7 +11,7 @@ from Music.Song import Song from Music.Playlist import Playlist from typing import List, Union from discord import Button, Interaction -from UI.Buttons.EmptyButton import CallbackButton +from UI.Buttons.CallbackButton import CallbackButton from UI.Buttons.PlaylistDropdown import PlaylistDropdown from Config.Emojis import VEmojis diff --git a/Messages/MessagesManager.py b/Messages/MessagesManager.py index 585852a..58140b0 100644 --- a/Messages/MessagesManager.py +++ b/Messages/MessagesManager.py @@ -1,6 +1,7 @@ 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 @@ -9,8 +10,10 @@ class MessagesManager(Singleton): 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]]] = {} + # Will, for each message, store the AbstractView that controls it + self.__messagesViews: Dict[Message, AbstractView] = {} - def addMessage(self, guildID: int, category: MessagesCategory, message: Message) -> None: + def addMessage(self, guildID: int, category: MessagesCategory, message: Message, view: AbstractView = None) -> None: if message is None: return @@ -22,9 +25,11 @@ class MessagesManager(Singleton): self.__guildsMessages[guildID][category] = [] sendedMessages = self.__guildsMessages[guildID][category] + if view is not None and isinstance(view, AbstractView): + self.__messagesViews[message] = view sendedMessages.append(message) - async def addMessageAndClearPrevious(self, guildID: int, category: MessagesCategory, message: Message) -> None: + async def addMessageAndClearPrevious(self, guildID: int, category: MessagesCategory, message: Message, view: AbstractView = None) -> None: if message is None: return @@ -44,6 +49,10 @@ class MessagesManager(Singleton): # Create a new list with only the new message self.__guildsMessages[guildID][category] = [message] + # Store the view of this message + if view is not None and isinstance(view, AbstractView): + self.__messagesViews[message] = view + async def clearMessagesOfCategory(self, guildID: int, category: MessagesCategory) -> None: sendedMessages = self.__guildsMessages[guildID][category] @@ -59,6 +68,12 @@ class MessagesManager(Singleton): async def __deleteMessage(self, message: Message) -> None: try: + # If there is a view for this message delete the key + if message in self.__messagesViews.keys(): + messageView = self.__messagesViews.pop(message) + messageView.stopView() + del messageView + await message.delete() except Exception as e: print(f'[ERROR DELETING MESSAGE] -> {e}') diff --git a/Messages/Responses/EmbedCogResponse.py b/Messages/Responses/EmbedCogResponse.py index 3e3fac9..058d1d0 100644 --- a/Messages/Responses/EmbedCogResponse.py +++ b/Messages/Responses/EmbedCogResponse.py @@ -19,6 +19,6 @@ class EmbedCommandResponse(AbstractCommandResponse): if 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) + await self.manager.addMessageAndClearPrevious(self.context.guild.id, self.category, message, self.response.view) else: self.manager.addMessage(self.context.guild.id, self.category, message) diff --git a/Parallelism/ProcessExecutor.py b/Parallelism/ProcessExecutor.py index 1509e18..ba6ab1e 100644 --- a/Parallelism/ProcessExecutor.py +++ b/Parallelism/ProcessExecutor.py @@ -43,7 +43,7 @@ class ProcessCommandsExecutor: view = self.__getPlayerView(channel) # Send Message and add to the MessagesManager message = await channel.send(embed=embed, view=view) - await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, MessagesCategory.NOW_PLAYING, message) + await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, MessagesCategory.NOW_PLAYING, message, view) # Set in the view the message witch contains the view view.set_message(message=message) diff --git a/UI/Buttons/EmptyButton.py b/UI/Buttons/CallbackButton.py similarity index 96% rename from UI/Buttons/EmptyButton.py rename to UI/Buttons/CallbackButton.py index 0fe9e9b..e112938 100644 --- a/UI/Buttons/EmptyButton.py +++ b/UI/Buttons/CallbackButton.py @@ -39,7 +39,7 @@ class CallbackButton(Button): # Clear the last sended message in this category and add the new one if message: - await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, self.__category, message) + await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, self.__category, message, response.view) def set_view(self, view: View): self.__view = view diff --git a/UI/Buttons/HandlerButton.py b/UI/Buttons/HandlerButton.py index 2bac59d..316e954 100644 --- a/UI/Buttons/HandlerButton.py +++ b/UI/Buttons/HandlerButton.py @@ -41,7 +41,7 @@ class HandlerButton(Button): # Clear the last category sended message and add the new one if message: - await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, self.__category, message) + await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, self.__category, message, response.view) def set_view(self, view: View): self.__view = view diff --git a/UI/Buttons/PlaylistDropdown.py b/UI/Buttons/PlaylistDropdown.py index 209a125..b8ad7a4 100644 --- a/UI/Buttons/PlaylistDropdown.py +++ b/UI/Buttons/PlaylistDropdown.py @@ -19,15 +19,17 @@ class PlaylistDropdown(Select, AbstractItem): songs = list(playlist.getSongs()) values = [str(x) for x in range(1, len(songs) + 1)] - # Get the title of each of the 20 first songs, library doesn't accept more - songsNames = [song.title[:80] for song in songs[:20]] + # Get the title of each of the 20 first songs, the pycord library doesn't accept more + songsNames: List[str] = [] + for x in range(20): + songsNames.append(f'{x + 1} - {songs[x].title[:80]}') selectOptions: List[SelectOption] = [] for x in range(len(songsNames)): selectOptions.append(SelectOption(label=songsNames[x], value=values[x])) - super().__init__(placeholder="Select one music to play now, may be overdue", + super().__init__(placeholder="Select one music to play now, may be outdated", min_values=1, max_values=1, options=selectOptions) self.__playlist = playlist @@ -55,7 +57,7 @@ class PlaylistDropdown(Select, AbstractItem): # Clear the last sended message in this category and add the new one if message: - await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, self.__category, message) + await self.__messagesManager.addMessageAndClearPrevious(self.__guildID, self.__category, message, response.view) # Extreme ugly way to wait for the player process to actually retrieve the next song await asyncio.sleep(2) diff --git a/UI/Views/AbstractView.py b/UI/Views/AbstractView.py index 7fe5668..71948f5 100644 --- a/UI/Views/AbstractView.py +++ b/UI/Views/AbstractView.py @@ -8,3 +8,7 @@ class AbstractView(ABC): def set_message(self, message) -> None: pass + + @abstractmethod + def stopView(self) -> None: + pass diff --git a/UI/Views/BasicView.py b/UI/Views/BasicView.py index ca57cd7..46f04ed 100644 --- a/UI/Views/BasicView.py +++ b/UI/Views/BasicView.py @@ -16,18 +16,25 @@ class BasicView(View, AbstractView): super().__init__(timeout=timeout) self.__bot = bot self.__message: Message = None + self.__working = True for button in buttons: # Set the buttons to have a instance of the view that contains them button.set_view(self) self.add_item(button) + def stopView(self): + self.__working = False + async def on_timeout(self) -> None: # Disable all itens and, if has the message, edit it try: + if not self.__working: + return + self.disable_all_items() if self.__message is not None and isinstance(self.__message, Message): - await self.__message.edit(view=self) + await self.__message.edit(f"{emojis.MUSIC} - The buttons in this message have been disabled due timeout", view=self) except Exception as e: print(f'[ERROR EDITING MESSAGE] -> {e}') @@ -35,5 +42,11 @@ class BasicView(View, AbstractView): self.__message = message async def update(self): - if self.__message is not None: - await self.__message.edit(view=self) + try: + if not self.__working: + return + + if self.__message is not None: + await self.__message.edit(view=self) + except Exception as e: + print(f'[ERROR UPDATING MESSAGE] -> {e}')