9090 Intents ,
9191 InteractionType ,
9292 Status ,
93+ MessageFlags ,
9394)
9495from interactions .models .discord .file import UPLOADABLE_TYPE
9596from interactions .models .discord .snowflake import Snowflake , to_snowflake_list
9697from interactions .models .internal .active_voice_state import ActiveVoiceState
97- from interactions .models .internal .application_commands import ContextMenu , ModalCommand , GlobalAutoComplete
98+ from interactions .models .internal .application_commands import (
99+ ContextMenu ,
100+ ModalCommand ,
101+ GlobalAutoComplete ,
102+ CallbackType ,
103+ )
98104from interactions .models .internal .auto_defer import AutoDefer
99105from interactions .models .internal .callback import CallbackObject
100106from interactions .models .internal .command import BaseCommand
113119if TYPE_CHECKING :
114120 from interactions .models import Snowflake_Type , TYPE_ALL_CHANNEL
115121
116-
117122__all__ = ("Client" ,)
118123
119-
120124# see https://discord.com/developers/docs/topics/gateway#list-of-intents
121125_INTENT_EVENTS : dict [BaseEvent , list [Intents ]] = {
122126 # Intents.GUILDS
@@ -227,6 +231,7 @@ class Client(
227231 enforce_interaction_perms: Enforce discord application command permissions, locally
228232 fetch_members: Should the client fetch members from guilds upon startup (this will delay the client being ready)
229233 send_command_tracebacks: Automatically send uncaught tracebacks if a command throws an exception
234+ send_not_ready_messages: Send a message to the user if they try to use a command before the client is ready
230235
231236 auto_defer: AutoDefer: A system to automatically defer commands after a set duration
232237 interaction_context: Type[InteractionContext]: InteractionContext: The object to instantiate for Interaction Context
@@ -282,6 +287,7 @@ def __init__(
282287 modal_context : Type [BaseContext ] = ModalContext ,
283288 owner_ids : Iterable ["Snowflake_Type" ] = (),
284289 send_command_tracebacks : bool = True ,
290+ send_not_ready_messages : bool = False ,
285291 shard_id : int = 0 ,
286292 show_ratelimit_tracebacks : bool = False ,
287293 slash_context : Type [BaseContext ] = SlashContext ,
@@ -319,6 +325,8 @@ def __init__(
319325 """Sync global commands as guild for quicker command updates during debug"""
320326 self .send_command_tracebacks : bool = send_command_tracebacks
321327 """Should the traceback of command errors be sent in reply to the command invocation"""
328+ self .send_not_ready_messages : bool = send_not_ready_messages
329+ """Should the bot send a message when it is not ready yet in response to a command invocation"""
322330 if auto_defer is True :
323331 auto_defer = AutoDefer (enabled = True )
324332 else :
@@ -696,7 +704,7 @@ async def on_command_error(self, event: events.CommandError) -> None:
696704 embeds = Embed (
697705 title = f"Error: { type (event .error ).__name__ } " ,
698706 color = BrandColors .RED ,
699- description = f"```\n { out [:EMBED_MAX_DESC_LENGTH - 8 ]} ```" ,
707+ description = f"```\n { out [:EMBED_MAX_DESC_LENGTH - 8 ]} ```" ,
700708 )
701709 )
702710
@@ -1712,6 +1720,32 @@ async def get_context(self, data: dict) -> InteractionContext:
17121720 self .logger .debug (f"Failed to fetch channel data for { data ['channel_id' ]} " )
17131721 return cls
17141722
1723+ async def handle_pre_ready_response (self , data : dict ) -> None :
1724+ """
1725+ Respond to an interaction that was received before the bot was ready.
1726+
1727+ Args:
1728+ data: The interaction data
1729+
1730+ """
1731+ if data ["type" ] == InteractionType .AUTOCOMPLETE :
1732+ # we do not want to respond to autocompletes as discord will cache the response,
1733+ # so we just ignore them
1734+ return
1735+
1736+ with contextlib .suppress (HTTPException ):
1737+ await self .http .post_initial_response (
1738+ {
1739+ "type" : CallbackType .CHANNEL_MESSAGE_WITH_SOURCE ,
1740+ "data" : {
1741+ "content" : f"{ self .user .display_name } is starting up. Please try again in a few seconds" ,
1742+ "flags" : MessageFlags .EPHEMERAL ,
1743+ },
1744+ },
1745+ token = data ["token" ],
1746+ interaction_id = data ["id" ],
1747+ )
1748+
17151749 async def _run_slash_command (self , command : SlashCommand , ctx : "InteractionContext" ) -> Any :
17161750 """Overrideable method that executes slash commands, can be used to wrap callback execution"""
17171751 return await command (ctx , ** ctx .kwargs )
@@ -1729,6 +1763,8 @@ async def _dispatch_interaction(self, event: RawGatewayEvent) -> None: # noqa:
17291763
17301764 if not self ._startup :
17311765 self .logger .warning ("Received interaction before startup completed, ignoring" )
1766+ if self .send_not_ready_messages :
1767+ await self .handle_pre_ready_response (interaction_data )
17321768 return
17331769
17341770 if interaction_data ["type" ] in (
0 commit comments