Skip to content

Commit aedc4c2

Browse files
committed
Add interaction metadata to interactions.
1 parent c9e52fe commit aedc4c2

5 files changed

+149
-3
lines changed

hikari/impl/entity_factory.py

+78-3
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,7 @@ def deserialize_application(self, payload: data_binding.JSONObject) -> applicati
643643
oauth2_install_parameters = None
644644
if (oauth2_install_params_payload := integration_payload.get("oauth2_install_params")) is not None:
645645
oauth2_install_parameters = application_models.OAuth2InstallParameters(
646-
scopes=[
647-
application_models.OAuth2Scope(scope) for scope in oauth2_install_params_payload["scopes"]
648-
],
646+
scopes=[application_models.OAuth2Scope(scope) for scope in oauth2_install_params_payload["scopes"]],
649647
permissions=permission_models.Permissions(int(oauth2_install_params_payload["permissions"])),
650648
)
651649

@@ -2590,6 +2588,30 @@ def _deserialize_resolved_option_data(
25902588
attachments=attachments, channels=channels, members=members, messages=messages, roles=roles, users=users
25912589
)
25922590

2591+
def _deserialize_command_message_interaction_metadata(
2592+
self, payload: data_binding.JSONObject
2593+
) -> command_interactions.CommandMessageInteractionMetadata:
2594+
authorizing_integration_owners = {
2595+
application_models.ApplicationIntegrationType(int(integration_type)): snowflakes.Snowflake(
2596+
integration_owner_id
2597+
)
2598+
for integration_type, integration_owner_id in payload["authorizing_integration_owners"].items()
2599+
}
2600+
2601+
return command_interactions.CommandMessageInteractionMetadata(
2602+
interaction_id=payload["id"],
2603+
type=base_interactions.InteractionType(payload["type"]),
2604+
user=self.deserialize_user(payload["user"]),
2605+
authorizing_integration_owners=authorizing_integration_owners,
2606+
original_response_message_id=snowflakes.Snowflake(payload["original_response_message_id"])
2607+
if "original_response_message_id" in payload
2608+
else None,
2609+
target_user=self.deserialize_user(payload["target_user"]) if "target_user" in payload else None,
2610+
target_message_id=snowflakes.Snowflake(payload["target_message_id"])
2611+
if "target_message_id" in payload
2612+
else None,
2613+
)
2614+
25932615
def deserialize_command_interaction(
25942616
self, payload: data_binding.JSONObject
25952617
) -> command_interactions.CommandInteraction:
@@ -2653,6 +2675,9 @@ def deserialize_command_interaction(
26532675
entitlements=entitlements,
26542676
authorizing_integration_owners=authorizing_integration_owners,
26552677
context=application_models.ApplicationContextType(payload["context"]),
2678+
interaction_metadata=self._deserialize_command_message_interaction_metadata(payload["interaction_metadata"])
2679+
if "interaction_metadata" in payload
2680+
else None,
26562681
)
26572682

26582683
def deserialize_autocomplete_interaction(
@@ -2707,6 +2732,27 @@ def deserialize_autocomplete_interaction(
27072732
context=application_models.ApplicationContextType(payload["context"]),
27082733
)
27092734

2735+
def _deserialize_modal_message_interaction_metadata(
2736+
self, payload: data_binding.JSONObject
2737+
) -> modal_interactions.ModalMessageInteractionMetadata:
2738+
authorizing_integration_owners = {
2739+
application_models.ApplicationIntegrationType(int(integration_type)): snowflakes.Snowflake(
2740+
integration_owner_id
2741+
)
2742+
for integration_type, integration_owner_id in payload["authorizing_integration_owners"].items()
2743+
}
2744+
2745+
return modal_interactions.ModalMessageInteractionMetadata(
2746+
interaction_id=payload["id"],
2747+
type=base_interactions.InteractionType(payload["type"]),
2748+
user=self.deserialize_user(payload["user"]),
2749+
authorizing_integration_owners=authorizing_integration_owners,
2750+
original_response_message_id=snowflakes.Snowflake(payload["original_response_message_id"])
2751+
if "original_response_message_id" in payload
2752+
else None,
2753+
triggering_interaction_metadata=NotImplemented, # FIXME: Unsure how to handle this.
2754+
)
2755+
27102756
def deserialize_modal_interaction(self, payload: data_binding.JSONObject) -> modal_interactions.ModalInteraction:
27112757
data_payload = payload["data"]
27122758

@@ -2756,6 +2802,9 @@ def deserialize_modal_interaction(self, payload: data_binding.JSONObject) -> mod
27562802
entitlements=[self.deserialize_entitlement(entitlement) for entitlement in payload.get("entitlements", ())],
27572803
authorizing_integration_owners=authorizing_integration_owners,
27582804
context=application_models.ApplicationContextType(payload["context"]),
2805+
interaction_metadata=self._deserialize_modal_message_interaction_metadata(payload["interaction_metadata"])
2806+
if "interaction_metadata" in payload
2807+
else None,
27592808
)
27602809

27612810
def deserialize_interaction(self, payload: data_binding.JSONObject) -> base_interactions.PartialInteraction:
@@ -2804,6 +2853,27 @@ def serialize_command_option(self, option: commands.CommandOption) -> data_bindi
28042853

28052854
return payload
28062855

2856+
def _deserialize_component_message_interaction_metadata(
2857+
self, payload: data_binding.JSONObject
2858+
) -> component_interactions.ComponentMessageInteractionMetadata:
2859+
authorizing_integration_owners = {
2860+
application_models.ApplicationIntegrationType(int(integration_type)): snowflakes.Snowflake(
2861+
integration_owner_id
2862+
)
2863+
for integration_type, integration_owner_id in payload["authorizing_integration_owners"].items()
2864+
}
2865+
2866+
return component_interactions.ComponentMessageInteractionMetadata(
2867+
interaction_id=payload["id"],
2868+
type=base_interactions.InteractionType(payload["type"]),
2869+
user=self.deserialize_user(payload["user"]),
2870+
authorizing_integration_owners=authorizing_integration_owners,
2871+
original_response_message_id=snowflakes.Snowflake(payload["original_response_message_id"])
2872+
if "original_response_message_id" in payload
2873+
else None,
2874+
interacted_message_id=snowflakes.Snowflake(payload["interacted_message_id"]),
2875+
)
2876+
28072877
def deserialize_component_interaction(
28082878
self, payload: data_binding.JSONObject
28092879
) -> component_interactions.ComponentInteraction:
@@ -2857,6 +2927,11 @@ def deserialize_component_interaction(
28572927
entitlements=[self.deserialize_entitlement(entitlement) for entitlement in payload.get("entitlements", ())],
28582928
authorizing_integration_owners=authorizing_integration_owners,
28592929
context=application_models.ApplicationContextType(payload["context"]),
2930+
interaction_metadata=self._deserialize_component_message_interaction_metadata(
2931+
payload["interaction_metadata"]
2932+
)
2933+
if "interaction_metadata" in payload
2934+
else None,
28602935
)
28612936

28622937
##################

hikari/interactions/base_interactions.py

+23
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,29 @@ def webhook_id(self) -> snowflakes.Snowflake:
234234
return self.application_id
235235

236236

237+
@attrs_extensions.with_copy
238+
@attrs.define(unsafe_hash=True, kw_only=True, weakref_slot=False)
239+
class PartialMessageInteractionMetadata:
240+
"""Metadata about the interaction, including the source of the interaction and relevant server and user IDs."""
241+
242+
interaction_id: snowflakes.Snowflake = attrs.field(hash=True, repr=True)
243+
"""The ID for this message interaction."""
244+
245+
type: typing.Union[InteractionType, int] = attrs.field(eq=False, repr=True)
246+
"""The type of this message interaction."""
247+
248+
user: users.User = attrs.field(eq=False, repr=True)
249+
"""The user who triggered the interaction."""
250+
251+
authorizing_integration_owners: typing.Mapping[applications.ApplicationIntegrationType, snowflakes.Snowflake] = (
252+
attrs.field(eq=False, repr=True)
253+
)
254+
"""A mapping of the [applications.ApplicationIntegrationType] to the related guild or user ID."""
255+
256+
original_response_message_id: typing.Optional[snowflakes.Snowflake] = attrs.field(hash=True, repr=True)
257+
"""The ID of the original response message."""
258+
259+
237260
class PremiumResponseMixin(PartialInteraction):
238261
"""Mixin' class for all interaction types which can be responded to with a premium upsell."""
239262

hikari/interactions/command_interactions.py

+15
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,9 @@ class CommandInteraction(
327327
target_id: typing.Optional[snowflakes.Snowflake] = attrs.field(default=None, eq=False, hash=False, repr=True)
328328
"""The target of the command. Only available if the command is a context menu command."""
329329

330+
interaction_metadata: typing.Optional[CommandMessageInteractionMetadata] = attrs.field(eq=False, repr=True)
331+
"""Sent if the message is sent as a result of an interaction."""
332+
330333
def build_response(self) -> special_endpoints.InteractionMessageBuilder:
331334
"""Get a message response builder for use in the REST server flow.
332335
@@ -441,3 +444,15 @@ async def create_response(self, choices: typing.Sequence[special_endpoints.Autoc
441444
The choices for the autocomplete.
442445
"""
443446
await self.app.rest.create_autocomplete_response(self.id, self.token, choices)
447+
448+
449+
@attrs_extensions.with_copy
450+
@attrs.define(unsafe_hash=True, kw_only=True, weakref_slot=False)
451+
class CommandMessageInteractionMetadata(base_interactions.PartialMessageInteractionMetadata):
452+
"""FIXME: Do docs."""
453+
454+
target_user: typing.Optional[users_.User] = attrs.field(eq=False, hash=False, repr=True)
455+
"""The user the command was run on, present only on user command interactions."""
456+
457+
target_message_id: typing.Optional[snowflakes.Snowflake] = attrs.field(eq=False, hash=False, repr=True)
458+
"""The ID of the message the command was run on, present only on message command interactions."""

hikari/interactions/component_interactions.py

+14
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ class ComponentInteraction(
153153
entitlements: typing.Sequence[monetization.Entitlement] = attrs.field(eq=False, hash=False, repr=True)
154154
"""For monetized apps, any entitlements for the invoking user, represents access to SKUs."""
155155

156+
interaction_metadata: typing.Optional[ComponentMessageInteractionMetadata] = attrs.field(eq=False, repr=True)
157+
"""Sent if the message is sent as a result of an interaction."""
158+
156159
def build_response(self, type_: _ImmediateTypesT, /) -> special_endpoints.InteractionMessageBuilder:
157160
"""Get a message response builder for use in the REST server flow.
158161
@@ -316,3 +319,14 @@ def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
316319
return self.app.cache.get_guild(self.guild_id)
317320

318321
return None
322+
323+
324+
@attrs.define(unsafe_hash=True, kw_only=True, weakref_slot=False)
325+
class ComponentMessageInteractionMetadata(base_interactions.PartialMessageInteractionMetadata):
326+
"""FIXME: Do docs."""
327+
328+
original_response_message_id: typing.Optional[snowflakes.Snowflake] = attrs.field(eq=False, hash=False, repr=True)
329+
"""The ID of the original response message, present only on follow-up messages."""
330+
331+
interacted_message_id: snowflakes.Snowflake = attrs.field(eq=False, hash=False, repr=True)
332+
"""The ID of the message that contained the interactive component"""

hikari/interactions/modal_interactions.py

+19
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323

2424
from __future__ import annotations
2525

26+
from hikari.interactions.command_interactions import CommandMessageInteractionMetadata
27+
from hikari.interactions.component_interactions import ComponentMessageInteractionMetadata
28+
2629
__all__: list[str] = ["ModalResponseTypesT", "ModalInteraction", "ModalInteraction"]
2730

2831
import typing
@@ -127,6 +130,9 @@ class ModalInteraction(
127130
entitlements: typing.Sequence[monetization.Entitlement] = attrs.field(eq=False, hash=False, repr=True)
128131
"""For monetized apps, any entitlements for the invoking user, represents access to SKUs."""
129132

133+
interaction_metadata: typing.Optional[ModalMessageInteractionMetadata] = attrs.field(eq=False, repr=True)
134+
"""Sent if the message is sent as a result of an interaction."""
135+
130136
async def fetch_channel(self) -> channels.TextableChannel:
131137
"""Fetch the guild channel this interaction was triggered in.
132138
@@ -266,3 +272,16 @@ def build_deferred_response(self) -> special_endpoints.InteractionDeferredBuilde
266272
Deferred interaction message response builder object.
267273
"""
268274
return self.app.rest.interaction_deferred_builder(base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE)
275+
276+
277+
@attrs.define(unsafe_hash=True, kw_only=True, weakref_slot=False)
278+
class ModalMessageInteractionMetadata(base_interactions.PartialMessageInteractionMetadata):
279+
"""FIXME: Do docs."""
280+
281+
original_response_message_id: typing.Optional[snowflakes.Snowflake] = attrs.field(eq=False, hash=False, repr=True)
282+
"""The ID of the original response message, present only on follow-up messages."""
283+
284+
triggering_interaction_metadata: typing.Union[
285+
CommandMessageInteractionMetadata, ComponentMessageInteractionMetadata
286+
] = attrs.field(eq=False, hash=False, repr=True) # FIXME: Might have to do some mixin object for this?
287+
"""The metadata for the interaction that was used to open the modal."""

0 commit comments

Comments
 (0)