Skip to content

Commit d65ac77

Browse files
authored
5.5.0
5.5.0
2 parents 64d2f2e + d8855fe commit d65ac77

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

interactions/client/client.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ def get_guild_websocket(self, id: "Snowflake_Type") -> GatewayClient:
544544
def _sanity_check(self) -> None:
545545
"""Checks for possible and common errors in the bot's configuration."""
546546
self.logger.debug("Running client sanity checks...")
547+
547548
contexts = {
548549
self.interaction_context: InteractionContext,
549550
self.component_context: ComponentContext,
@@ -911,6 +912,11 @@ async def login(self, token: str | None = None) -> None:
911912
# so im gathering commands here
912913
self._gather_callbacks()
913914

915+
if any(v for v in constants.CLIENT_FEATURE_FLAGS.values()):
916+
# list all enabled flags
917+
enabled_flags = [k for k, v in constants.CLIENT_FEATURE_FLAGS.items() if v]
918+
self.logger.info(f"Enabled feature flags: {', '.join(enabled_flags)}")
919+
914920
self.logger.debug("Attempting to login")
915921
me = await self.http.login(self.token)
916922
self._user = ClientUser.from_dict(me, self)
@@ -1105,7 +1111,7 @@ async def wait_for_component(
11051111
dict,
11061112
]
11071113
] = None,
1108-
check: Optional[Callable] = None,
1114+
check: Absent[Optional[Union[Callable[..., bool], Callable[..., Awaitable[bool]]]]] = None,
11091115
timeout: Optional[float] = None,
11101116
) -> "events.Component":
11111117
"""
@@ -1136,22 +1142,26 @@ async def wait_for_component(
11361142
if custom_ids and not all(isinstance(x, str) for x in custom_ids):
11371143
custom_ids = [str(i) for i in custom_ids]
11381144

1139-
def _check(event: events.Component) -> bool:
1145+
async def _check(event: events.Component) -> bool:
11401146
ctx: ComponentContext = event.ctx
11411147
# if custom_ids is empty or there is a match
11421148
wanted_message = not message_ids or ctx.message.id in (
11431149
[message_ids] if isinstance(message_ids, int) else message_ids
11441150
)
11451151
wanted_component = not custom_ids or ctx.custom_id in custom_ids
11461152
if wanted_message and wanted_component:
1153+
if asyncio.iscoroutinefunction(check):
1154+
return bool(check is None or await check(event))
11471155
return bool(check is None or check(event))
11481156
return False
11491157

11501158
return await self.wait_for("component", checks=_check, timeout=timeout)
11511159

11521160
def command(self, *args, **kwargs) -> Callable:
11531161
"""A decorator that registers a command. Aliases `interactions.slash_command`"""
1154-
raise NotImplementedError # TODO: implement
1162+
raise NotImplementedError(
1163+
"Use interactions.slash_command instead. Please consult the v4 -> v5 migration guide https://interactions-py.github.io/interactions.py/Guides/98%20Migration%20from%204.X/"
1164+
)
11551165

11561166
def listen(self, event_name: Absent[str] = MISSING) -> Callable[[AsyncCallable], Listener]:
11571167
"""

interactions/client/const.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
T TypeVar: A type variable used for generic typing.
3333
Absent Union[T, Missing]: A type hint for a value that may be MISSING.
3434
35+
CLIENT_FEATURE_FLAGS dict: A dict of feature flags that can be enabled or disabled for the client.
36+
has_feature_flag Callable[[str], bool]: A function that returns whether a feature flag is enabled.
37+
3538
"""
3639
import inspect
3740
import logging
@@ -78,6 +81,8 @@
7881
"LIB_PATH",
7982
"RECOVERABLE_WEBSOCKET_CLOSE_CODES",
8083
"NON_RESUMABLE_WEBSOCKET_CLOSE_CODES",
84+
"CLIENT_FEATURE_FLAGS",
85+
"has_client_feature",
8186
)
8287

8388
_ver_info = sys.version_info
@@ -195,6 +200,18 @@ class MentionPrefix(Sentinel):
195200
},
196201
)
197202

203+
CLIENT_FEATURE_FLAGS = {
204+
"FOLLOWUP_INTERACTIONS_FOR_IMAGES": False, # Experimental fix to bypass Discord's broken image proxy
205+
}
206+
207+
208+
def has_client_feature(feature: str) -> bool:
209+
"""Checks if a feature is enabled for the client."""
210+
if feature.upper() not in CLIENT_FEATURE_FLAGS:
211+
get_logger().warning(f"Unknown feature {feature!r} - Known features: {list(CLIENT_FEATURE_FLAGS)}")
212+
return False
213+
return CLIENT_FEATURE_FLAGS[feature.upper()]
214+
198215

199216
GUILD_WELCOME_MESSAGES = (
200217
"{0} joined the party.",

interactions/models/internal/context.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import discord_typings
88
from aiohttp import FormData
9+
10+
from interactions.client import const
911
from interactions.client.const import get_logger, MISSING
1012
from interactions.models.discord.components import BaseComponent
1113
from interactions.models.discord.file import UPLOADABLE_TYPE
@@ -401,6 +403,14 @@ async def defer(self, *, ephemeral: bool = False) -> None:
401403
async def _send_http_request(
402404
self, message_payload: dict, files: typing.Iterable["UPLOADABLE_TYPE"] | None = None
403405
) -> dict:
406+
if const.has_client_feature("FOLLOWUP_INTERACTIONS_FOR_IMAGES") and not self.deferred:
407+
# experimental bypass for discords broken image proxy
408+
if embeds := message_payload.get("embeds", {}):
409+
if any(e.get("image") for e in embeds) or any(e.get("thumbnail") for e in embeds):
410+
if MessageFlags.EPHEMERAL in message_payload.get("flags", MessageFlags.NONE):
411+
self.ephemeral = True
412+
await self.defer(ephemeral=self.ephemeral)
413+
404414
if self.responded:
405415
message_data = await self.client.http.post_followup(
406416
message_payload, self.client.app.id, self.token, files=files
@@ -409,9 +419,14 @@ async def _send_http_request(
409419
if isinstance(message_payload, FormData) and not self.deferred:
410420
await self.defer(ephemeral=self.ephemeral)
411421
if self.deferred:
412-
message_data = await self.client.http.edit_interaction_message(
413-
message_payload, self.client.app.id, self.token, files=files
414-
)
422+
if const.has_client_feature("FOLLOWUP_INTERACTIONS_FOR_IMAGES"):
423+
message_data = await self.client.http.post_followup(
424+
message_payload, self.client.app.id, self.token, files=files
425+
)
426+
else:
427+
message_data = await self.client.http.edit_interaction_message(
428+
message_payload, self.client.app.id, self.token, files=files
429+
)
415430
else:
416431
payload = {
417432
"type": CallbackType.CHANNEL_MESSAGE_WITH_SOURCE,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "interactions.py"
3-
version = "5.4.0"
3+
version = "5.5.0"
44
description = "Easy, simple, scalable and modular: a Python API wrapper for interactions."
55
authors = [
66
"LordOfPolls <[email protected]>",

0 commit comments

Comments
 (0)