Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(message): include member data in InteractionReference.user #1160

Merged
merged 5 commits into from
Aug 24, 2024
Merged
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
1 change: 1 addition & 0 deletions changelog/1160.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:attr:`InteractionReference.user` can now be a :class:`Member` in guild contexts.
55 changes: 42 additions & 13 deletions disnake/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,24 +704,48 @@ class InteractionReference:

For interaction references created before July 18th, 2022, this will not include group or subcommand names.

user: :class:`User`
The interaction author.
user: Union[:class:`User`, :class:`Member`]
The user or member that triggered the referenced interaction.

.. versionchanged:: 2.10
This is now a :class:`Member` when in a guild, if the message was received via a
gateway event or the member is cached.
"""

__slots__ = ("id", "type", "name", "user", "_state")
__slots__ = ("id", "type", "name", "user")

def __init__(self, *, state: ConnectionState, data: InteractionMessageReferencePayload) -> None:
self._state: ConnectionState = state
def __init__(
self,
*,
state: ConnectionState,
guild: Optional[Guild],
data: InteractionMessageReferencePayload,
) -> None:
self.id: int = int(data["id"])
self.type: InteractionType = try_enum(InteractionType, int(data["type"]))
self.name: str = data["name"]
self.user: User = User(state=state, data=data["user"])

user: Optional[Union[User, Member]] = None
if guild:
if isinstance(guild, Guild): # this can be a placeholder object in interactions
user = guild.get_member(int(data["user"]["id"]))

# If not cached, try data from event.
# This is only available via gateway (message_create/_edit), not HTTP
if not user and (member := data.get("member")):
user = Member(data=member, user_data=data["user"], guild=guild, state=state)

# If still none, deserialize user
if not user:
user = state.store_user(data["user"])

self.user: Union[User, Member] = user

def __repr__(self) -> str:
return f"<InteractionReference id={self.id!r} type={self.type!r} name={self.name!r} user={self.user!r}>"

@property
def author(self) -> User:
def author(self) -> Union[User, Member]:
return self.user


Expand Down Expand Up @@ -1003,12 +1027,6 @@ def __init__(
for d in data.get("components", [])
]

inter_payload = data.get("interaction")
inter = (
None if inter_payload is None else InteractionReference(state=state, data=inter_payload)
)
self.interaction: Optional[InteractionReference] = inter

self.poll: Optional[Poll] = None
if poll_data := data.get("poll"):
self.poll = Poll.from_dict(message=self, data=poll_data)
Expand All @@ -1019,6 +1037,12 @@ def __init__(
except AttributeError:
self.guild = state._get_guild(utils._get_as_snowflake(data, "guild_id"))

self.interaction: Optional[InteractionReference] = (
InteractionReference(state=state, guild=self.guild, data=interaction)
if (interaction := data.get("interaction"))
else None
)

if thread_data := data.get("thread"):
if not self.thread and isinstance(self.guild, Guild):
self.guild._store_thread(thread_data)
Expand Down Expand Up @@ -1236,8 +1260,13 @@ def _handle_components(self, components: List[ComponentPayload]) -> None:
def _rebind_cached_references(self, new_guild: Guild, new_channel: GuildMessageable) -> None:
self.guild = new_guild
self.channel = new_channel

# rebind the members' guilds; the members themselves will potentially be
# updated later in _update_member_references, after re-chunking
if isinstance(self.author, Member):
self.author.guild = new_guild
if self.interaction and isinstance(self.interaction.user, Member):
self.interaction.user.guild = new_guild

@utils.cached_slot_property("_cs_raw_mentions")
def raw_mentions(self) -> List[int]:
Expand Down
6 changes: 6 additions & 0 deletions disnake/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -2258,6 +2258,7 @@ def _update_guild_channel_references(self) -> None:
if new_guild is None:
continue

# TODO: use PartialMessageable instead of Object (3.0)
new_channel = new_guild._resolve_channel(vc.channel.id) or Object(id=vc.channel.id)
if new_channel is not vc.channel:
vc.channel = new_channel # type: ignore
Expand All @@ -2275,6 +2276,11 @@ def _update_member_references(self) -> None:
if new_author is not None and new_author is not msg.author:
msg.author = new_author

if msg.interaction is not None and isinstance(msg.interaction.user, Member):
new_author = msg.guild.get_member(msg.interaction.user.id)
if new_author is not None and new_author is not msg.interaction.user:
msg.interaction.user = new_author

async def chunker(
self,
guild_id: int,
Expand Down
1 change: 1 addition & 0 deletions disnake/types/interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ class InteractionMessageReference(TypedDict):
type: InteractionType
name: str
user: User
member: NotRequired[Member]


class EditApplicationCommand(TypedDict):
Expand Down
Loading