From e2ba8b472ab40243fd124aa642cc86bdac4dd669 Mon Sep 17 00:00:00 2001 From: Choco Date: Thu, 20 Nov 2025 23:34:34 +0800 Subject: [PATCH] Refactor message dispatch and playlist view error handling Updated dispatch_message to use discord.utils.MISSING and improved content formatting. Added error handling in PlaylistView for VoicelinkException and refactored on_timeout logic in PlaylistViewManager to avoid duplication. Minor improvements to playlist track rendering. --- voicelink/utils.py | 13 ++++++------- voicelink/views/playlist.py | 33 +++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/voicelink/utils.py b/voicelink/utils.py index cc3a092..7d63192 100644 --- a/voicelink/utils.py +++ b/voicelink/utils.py @@ -30,7 +30,6 @@ from itertools import zip_longest from typing import Dict, Optional, Union from timeit import default_timer as timer from discord.ext import commands -from discord.utils import MISSING from .mongodb import MongoDBHandler from .language import LangHandler @@ -303,7 +302,7 @@ async def dispatch_message( *params, view: Optional[discord.ui.View] = None, file: Optional[discord.File] = None, - delete_after: Optional[float] = MISSING, + delete_after: Optional[float] = discord.utils.MISSING, ephemeral: bool = False, requires_fetch: bool = False ) -> Optional[discord.Message]: @@ -323,12 +322,12 @@ async def dispatch_message( Returns: The sent message object, or None. """ - if content is None: + if not content: content = "No content provided." # Determine the text to send embed = content if isinstance(content, discord.Embed) else None - text = None if embed else content.format(*params) + text = None if embed else str(content).format(*params) if params else str(content) # Determine the sending function send_func = ( @@ -354,13 +353,13 @@ async def dispatch_message( send_kwargs["view"] = view if "delete_after" in send_func.__code__.co_varnames: - if delete_after is MISSING and settings and ctx.channel.id == settings.get("music_request_channel", {}).get("text_channel_id"): + if delete_after is discord.utils.MISSING and settings and ctx.channel.id == settings.get("music_request_channel", {}).get("text_channel_id"): delete_after = 10 - send_kwargs["delete_after"] = delete_after if delete_after != MISSING else None + send_kwargs["delete_after"] = delete_after if delete_after is not discord.utils.MISSING else None if "ephemeral" in send_func.__code__.co_varnames: send_kwargs["ephemeral"] = ephemeral - + # Send the message or embed message = await send_func(**send_kwargs) diff --git a/voicelink/views/playlist.py b/voicelink/views/playlist.py index 068fc8f..a418955 100644 --- a/voicelink/views/playlist.py +++ b/voicelink/views/playlist.py @@ -31,9 +31,10 @@ from typing import Any from .utils import DynamicViewManager, Pagination from .pagination import PaginationView from ..config import Config -from ..utils import format_ms, truncate_string +from ..utils import format_ms, truncate_string, dispatch_message from ..mongodb import MongoDBHandler from ..language import LangHandler +from ..exceptions import VoicelinkException class PlaylistDropdown(discord.ui.Select): def __init__(self, results: list[dict[str, Any]], lang: str) -> None: @@ -108,7 +109,7 @@ class PlaylistView(PaginationView): embed.description += f"\n\n**{texts[5]}:**\n" if tracks: for index, track in enumerate(tracks, start=self.pagination.start_index + 1): - if self.type == "playlist": + if isinstance(track, dict): source_emoji = Config().get_source_config(track['sourceName'], 'emoji') track_info = f"{source_emoji} `{index:>2}.` `[{format_ms(track['length'])}]` [{truncate_string(track['title'])}]({track['uri']})" else: @@ -140,6 +141,10 @@ class PlaylistView(PaginationView): } return super().update_view(extra_states) + async def on_error(self, interaction: discord.Interaction, error: Exception, item: discord.ui.Item) -> None: + if isinstance(error, VoicelinkException): + return await dispatch_message(interaction, content=getattr(error, 'original', error), ephemeral=True) + async def update_message(self, interaction: discord.Interaction) -> None: """Update the view and edit the message with the new embed.""" self.update_view() @@ -199,6 +204,18 @@ class PlaylistViewManager(DynamicViewManager): self.response: discord.Message = None self.add_item(PlaylistDropdown(results, self.lang)) + async def on_timeout(self) -> None: + for view in self._views.values(): + view.stop() + + for child in self.current_view.children: + child.disabled = True + + try: + await self.response.edit(view=self) + except: + pass + def get_width(self, s): width = 0 for char in str(s): @@ -214,18 +231,6 @@ class PlaylistViewManager(DynamicViewManager): padding = width - current_width return s + " " * padding - async def on_timeout(self) -> None: - for view in self._views.values(): - view.stop() - - for child in self.current_view.children: - child.disabled = True - - try: - await self.response.edit(view=self) - except: - pass - def build_embed(self) -> discord.Embed: """ Build the embed for the playlist overview.