90
90
Intents ,
91
91
InteractionType ,
92
92
Status ,
93
+ MessageFlags ,
93
94
)
94
95
from interactions .models .discord .file import UPLOADABLE_TYPE
95
96
from interactions .models .discord .snowflake import Snowflake , to_snowflake_list
96
97
from 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
+ )
98
104
from interactions .models .internal .auto_defer import AutoDefer
99
105
from interactions .models .internal .callback import CallbackObject
100
106
from interactions .models .internal .command import BaseCommand
113
119
if TYPE_CHECKING :
114
120
from interactions .models import Snowflake_Type , TYPE_ALL_CHANNEL
115
121
116
-
117
122
__all__ = ("Client" ,)
118
123
119
-
120
124
# see https://discord.com/developers/docs/topics/gateway#list-of-intents
121
125
_INTENT_EVENTS : dict [BaseEvent , list [Intents ]] = {
122
126
# Intents.GUILDS
@@ -227,6 +231,7 @@ class Client(
227
231
enforce_interaction_perms: Enforce discord application command permissions, locally
228
232
fetch_members: Should the client fetch members from guilds upon startup (this will delay the client being ready)
229
233
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
230
235
231
236
auto_defer: AutoDefer: A system to automatically defer commands after a set duration
232
237
interaction_context: Type[InteractionContext]: InteractionContext: The object to instantiate for Interaction Context
@@ -282,6 +287,7 @@ def __init__(
282
287
modal_context : Type [BaseContext ] = ModalContext ,
283
288
owner_ids : Iterable ["Snowflake_Type" ] = (),
284
289
send_command_tracebacks : bool = True ,
290
+ send_not_ready_messages : bool = False ,
285
291
shard_id : int = 0 ,
286
292
show_ratelimit_tracebacks : bool = False ,
287
293
slash_context : Type [BaseContext ] = SlashContext ,
@@ -319,6 +325,8 @@ def __init__(
319
325
"""Sync global commands as guild for quicker command updates during debug"""
320
326
self .send_command_tracebacks : bool = send_command_tracebacks
321
327
"""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"""
322
330
if auto_defer is True :
323
331
auto_defer = AutoDefer (enabled = True )
324
332
else :
@@ -696,7 +704,7 @@ async def on_command_error(self, event: events.CommandError) -> None:
696
704
embeds = Embed (
697
705
title = f"Error: { type (event .error ).__name__ } " ,
698
706
color = BrandColors .RED ,
699
- description = f"```\n { out [:EMBED_MAX_DESC_LENGTH - 8 ]} ```" ,
707
+ description = f"```\n { out [:EMBED_MAX_DESC_LENGTH - 8 ]} ```" ,
700
708
)
701
709
)
702
710
@@ -1712,6 +1720,32 @@ async def get_context(self, data: dict) -> InteractionContext:
1712
1720
self .logger .debug (f"Failed to fetch channel data for { data ['channel_id' ]} " )
1713
1721
return cls
1714
1722
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
+
1715
1749
async def _run_slash_command (self , command : SlashCommand , ctx : "InteractionContext" ) -> Any :
1716
1750
"""Overrideable method that executes slash commands, can be used to wrap callback execution"""
1717
1751
return await command (ctx , ** ctx .kwargs )
@@ -1729,6 +1763,8 @@ async def _dispatch_interaction(self, event: RawGatewayEvent) -> None: # noqa:
1729
1763
1730
1764
if not self ._startup :
1731
1765
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 )
1732
1768
return
1733
1769
1734
1770
if interaction_data ["type" ] in (
0 commit comments