Skip to content

Commit 4a661d9

Browse files
authored
feat: send not ready messages if requested (#1389)
1 parent a061f72 commit 4a661d9

File tree

1 file changed

+40
-4
lines changed

1 file changed

+40
-4
lines changed

interactions/client/client.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,17 @@
9090
Intents,
9191
InteractionType,
9292
Status,
93+
MessageFlags,
9394
)
9495
from interactions.models.discord.file import UPLOADABLE_TYPE
9596
from interactions.models.discord.snowflake import Snowflake, to_snowflake_list
9697
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+
)
98104
from interactions.models.internal.auto_defer import AutoDefer
99105
from interactions.models.internal.callback import CallbackObject
100106
from interactions.models.internal.command import BaseCommand
@@ -113,10 +119,8 @@
113119
if 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

Comments
 (0)