Skip to content
Merged

5.5.0 #1415

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions interactions/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ def get_guild_websocket(self, id: "Snowflake_Type") -> GatewayClient:
def _sanity_check(self) -> None:
"""Checks for possible and common errors in the bot's configuration."""
self.logger.debug("Running client sanity checks...")

contexts = {
self.interaction_context: InteractionContext,
self.component_context: ComponentContext,
Expand Down Expand Up @@ -911,6 +912,11 @@ async def login(self, token: str | None = None) -> None:
# so im gathering commands here
self._gather_callbacks()

if any(v for v in constants.CLIENT_FEATURE_FLAGS.values()):
# list all enabled flags
enabled_flags = [k for k, v in constants.CLIENT_FEATURE_FLAGS.items() if v]
self.logger.info(f"Enabled feature flags: {', '.join(enabled_flags)}")

self.logger.debug("Attempting to login")
me = await self.http.login(self.token)
self._user = ClientUser.from_dict(me, self)
Expand Down Expand Up @@ -1105,7 +1111,7 @@ async def wait_for_component(
dict,
]
] = None,
check: Optional[Callable] = None,
check: Absent[Optional[Union[Callable[..., bool], Callable[..., Awaitable[bool]]]]] = None,
timeout: Optional[float] = None,
) -> "events.Component":
"""
Expand Down Expand Up @@ -1136,22 +1142,26 @@ async def wait_for_component(
if custom_ids and not all(isinstance(x, str) for x in custom_ids):
custom_ids = [str(i) for i in custom_ids]

def _check(event: events.Component) -> bool:
async def _check(event: events.Component) -> bool:
ctx: ComponentContext = event.ctx
# if custom_ids is empty or there is a match
wanted_message = not message_ids or ctx.message.id in (
[message_ids] if isinstance(message_ids, int) else message_ids
)
wanted_component = not custom_ids or ctx.custom_id in custom_ids
if wanted_message and wanted_component:
if asyncio.iscoroutinefunction(check):
return bool(check is None or await check(event))
return bool(check is None or check(event))
return False

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

def command(self, *args, **kwargs) -> Callable:
"""A decorator that registers a command. Aliases `interactions.slash_command`"""
raise NotImplementedError # TODO: implement
raise NotImplementedError(
"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/"
)

def listen(self, event_name: Absent[str] = MISSING) -> Callable[[AsyncCallable], Listener]:
"""
Expand Down
17 changes: 17 additions & 0 deletions interactions/client/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
T TypeVar: A type variable used for generic typing.
Absent Union[T, Missing]: A type hint for a value that may be MISSING.

CLIENT_FEATURE_FLAGS dict: A dict of feature flags that can be enabled or disabled for the client.
has_feature_flag Callable[[str], bool]: A function that returns whether a feature flag is enabled.

"""
import inspect
import logging
Expand Down Expand Up @@ -78,6 +81,8 @@
"LIB_PATH",
"RECOVERABLE_WEBSOCKET_CLOSE_CODES",
"NON_RESUMABLE_WEBSOCKET_CLOSE_CODES",
"CLIENT_FEATURE_FLAGS",
"has_client_feature",
)

_ver_info = sys.version_info
Expand Down Expand Up @@ -195,6 +200,18 @@ class MentionPrefix(Sentinel):
},
)

CLIENT_FEATURE_FLAGS = {
"FOLLOWUP_INTERACTIONS_FOR_IMAGES": False, # Experimental fix to bypass Discord's broken image proxy
}


def has_client_feature(feature: str) -> bool:
"""Checks if a feature is enabled for the client."""
if feature.upper() not in CLIENT_FEATURE_FLAGS:
get_logger().warning(f"Unknown feature {feature!r} - Known features: {list(CLIENT_FEATURE_FLAGS)}")
return False
return CLIENT_FEATURE_FLAGS[feature.upper()]


GUILD_WELCOME_MESSAGES = (
"{0} joined the party.",
Expand Down
21 changes: 18 additions & 3 deletions interactions/models/internal/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import discord_typings
from aiohttp import FormData

from interactions.client import const
from interactions.client.const import get_logger, MISSING
from interactions.models.discord.components import BaseComponent
from interactions.models.discord.file import UPLOADABLE_TYPE
Expand Down Expand Up @@ -401,6 +403,14 @@ async def defer(self, *, ephemeral: bool = False) -> None:
async def _send_http_request(
self, message_payload: dict, files: typing.Iterable["UPLOADABLE_TYPE"] | None = None
) -> dict:
if const.has_client_feature("FOLLOWUP_INTERACTIONS_FOR_IMAGES") and not self.deferred:
# experimental bypass for discords broken image proxy
if embeds := message_payload.get("embeds", {}):
if any(e.get("image") for e in embeds) or any(e.get("thumbnail") for e in embeds):
if MessageFlags.EPHEMERAL in message_payload.get("flags", MessageFlags.NONE):
self.ephemeral = True
await self.defer(ephemeral=self.ephemeral)

if self.responded:
message_data = await self.client.http.post_followup(
message_payload, self.client.app.id, self.token, files=files
Expand All @@ -409,9 +419,14 @@ async def _send_http_request(
if isinstance(message_payload, FormData) and not self.deferred:
await self.defer(ephemeral=self.ephemeral)
if self.deferred:
message_data = await self.client.http.edit_interaction_message(
message_payload, self.client.app.id, self.token, files=files
)
if const.has_client_feature("FOLLOWUP_INTERACTIONS_FOR_IMAGES"):
message_data = await self.client.http.post_followup(
message_payload, self.client.app.id, self.token, files=files
)
else:
message_data = await self.client.http.edit_interaction_message(
message_payload, self.client.app.id, self.token, files=files
)
else:
payload = {
"type": CallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "interactions.py"
version = "5.4.0"
version = "5.5.0"
description = "Easy, simple, scalable and modular: a Python API wrapper for interactions."
authors = [
"LordOfPolls <[email protected]>",
Expand Down