From 534b5b398074fdfe5f752f2281e9dc8102efff1a Mon Sep 17 00:00:00 2001 From: Slipstream Date: Tue, 10 Jun 2025 17:33:54 -0600 Subject: [PATCH] Refactors interaction response handling for flexibility Simplifies modal response creation by accepting both structured data objects and raw dictionaries, reducing unnecessary type casting and import dependencies. Improves text input decorator by auto-generating custom IDs from function names when not explicitly provided. Enhances example code by properly utilizing parsed Guild objects instead of raw data and fixes modal component registration. --- disagreement/interactions.py | 32 +++++++++++++++++--------------- disagreement/ui/modal.py | 2 +- examples/basic_bot.py | 7 ++++--- examples/modal_send.py | 1 + 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/disagreement/interactions.py b/disagreement/interactions.py index 9e42de8..4dc7337 100644 --- a/disagreement/interactions.py +++ b/disagreement/interactions.py @@ -395,17 +395,14 @@ class Interaction: async def respond_modal(self, modal: "Modal") -> None: """|coro| Send a modal in response to this interaction.""" - - from typing import Any, cast - - payload = { - "type": InteractionCallbackType.MODAL.value, - "data": modal.to_dict(), - } + payload = InteractionResponsePayload( + type=InteractionCallbackType.MODAL, + data=modal.to_dict(), + ) await self._client._http.create_interaction_response( interaction_id=self.id, interaction_token=self.token, - payload=cast(Any, payload), + payload=payload, ) async def edit( @@ -489,7 +486,7 @@ class InteractionResponse: """Sends a modal response.""" payload = InteractionResponsePayload( type=InteractionCallbackType.MODAL, - data=InteractionCallbackData(modal.to_dict()), + data=modal.to_dict(), ) await self._interaction._client._http.create_interaction_response( self._interaction.id, @@ -506,11 +503,13 @@ class InteractionCallbackData: self.tts: Optional[bool] = data.get("tts") self.content: Optional[str] = data.get("content") self.embeds: Optional[List[Embed]] = ( - [Embed(e) for e in data.get("embeds", [])] if data.get("embeds") else None + [Embed(e) for e in data.get("embeds", [])] + if data.get("embeds") + else None ) self.allowed_mentions: Optional[AllowedMentions] = ( AllowedMentions(data["allowed_mentions"]) - if data.get("allowed_mentions") + if "allowed_mentions" in data else None ) self.flags: Optional[int] = data.get("flags") # MessageFlags enum could be used @@ -557,15 +556,18 @@ class InteractionResponsePayload: def __init__( self, type: InteractionCallbackType, - data: Optional[InteractionCallbackData] = None, + data: Optional[Union[InteractionCallbackData, Dict[str, Any]]] = None, ): - self.type: InteractionCallbackType = type - self.data: Optional[InteractionCallbackData] = data + self.type = type + self.data = data def to_dict(self) -> Dict[str, Any]: payload: Dict[str, Any] = {"type": self.type.value} if self.data: - payload["data"] = self.data.to_dict() + if isinstance(self.data, dict): + payload["data"] = self.data + else: + payload["data"] = self.data.to_dict() return payload def __repr__(self) -> str: diff --git a/disagreement/ui/modal.py b/disagreement/ui/modal.py index 80271cc..0d4ef76 100644 --- a/disagreement/ui/modal.py +++ b/disagreement/ui/modal.py @@ -74,7 +74,7 @@ def text_input( item = TextInput( label=label, - custom_id=custom_id, + custom_id=custom_id or func.__name__, style=style, placeholder=placeholder, required=required, diff --git a/examples/basic_bot.py b/examples/basic_bot.py index 4028d46..e4518ee 100644 --- a/examples/basic_bot.py +++ b/examples/basic_bot.py @@ -28,6 +28,7 @@ if os.path.join(os.getcwd(), "examples") == os.path.dirname(os.path.abspath(__fi try: import disagreement + from disagreement.models import Guild from disagreement.ext import commands # Import the new commands extension except ImportError: print( @@ -190,9 +191,9 @@ async def on_message(message: disagreement.Message): @client.on_event( "GUILD_CREATE" ) # Example of listening to a specific event by its Discord name -async def on_guild_available(guild_data: dict): # Receives raw data for now - # In a real scenario, guild_data would be parsed into a Guild model - print(f"Guild available: {guild_data.get('name')} (ID: {guild_data.get('id')})") +async def on_guild_available(guild: Guild): + # The event now passes a Guild object directly + print(f"Guild available: {guild.name} (ID: {guild.id})") # --- Main Execution --- diff --git a/examples/modal_send.py b/examples/modal_send.py index b6b007e..0b15489 100644 --- a/examples/modal_send.py +++ b/examples/modal_send.py @@ -26,6 +26,7 @@ class NameModal(ui.Modal): def __init__(self): super().__init__(title="Your Name", custom_id="name_modal") self.name = ui.TextInput(label="Name", custom_id="name") + self.add_item(self.name) @slash_command(name="namemodal", description="Shows a modal")