Skip to content
59 changes: 58 additions & 1 deletion discord/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
MessageActivity as MessageActivityPayload,
RoleSubscriptionData as RoleSubscriptionDataPayload,
MessageInteractionMetadata as MessageInteractionMetadataPayload,
MessageCall as MessageCallPayload,
)

from .types.interactions import MessageInteraction as MessageInteractionPayload
Expand Down Expand Up @@ -112,6 +113,7 @@
'MessageApplication',
'RoleSubscriptionInfo',
'MessageInteractionMetadata',
'MessageCall',
)


Expand Down Expand Up @@ -804,6 +806,49 @@ def cover(self) -> Optional[Asset]:
return None


class MessageCall:
"""Represents a message's call data in a private channel from a :class:`~discord.Message`.

.. versionadded:: 2.5

Attributes
-----------
ended_timestamp: Optional[:class:`datetime.datetime`]
The timestamp the call has ended.
participants: List[Optional[:class:`User`]]
A list of users that participated in the call.
"""

__slots__ = ('_message', 'ended_timestamp', 'participants')

def __repr__(self) -> str:
return f'<MessageCall participants={self.participants!r}>'

def __init__(self, *, state: ConnectionState, message: Message, data: MessageCallPayload):
self._message: Message = message
self.ended_timestamp: Optional[datetime.datetime] = utils.parse_time(data.get('ended_timestamp'))
self.participants: List[Optional[User]] = []

for user_id in data['participants']:
user_id = int(user_id)
if user_id == self._message.author.id:
self.participants.append(self._message.author) # type: ignore # can't be a Member here
else:
self.participants.append(state.get_user(user_id))

@property
def duration(self) -> datetime.timedelta:
""":class:`datetime.timedelta`: The duration the call has lasted or is already ongoing."""
if self.ended_timestamp is None:
return utils.utcnow() - self._message.created_at
else:
return self.ended_timestamp - self._message.created_at

def is_ended(self) -> bool:
""":class:`bool`: Whether the call is ended or not."""
return self.ended_timestamp is not None


class RoleSubscriptionInfo:
"""Represents a message's role subscription information.

Expand Down Expand Up @@ -1762,6 +1807,10 @@ class Message(PartialMessage, Hashable):
The poll attached to this message.

.. versionadded:: 2.4
call: Optional[:class:`MessageCall`]
The call associated with this message.

.. versionadded:: 2.5
"""

__slots__ = (
Expand Down Expand Up @@ -1798,6 +1847,7 @@ class Message(PartialMessage, Hashable):
'position',
'interaction_metadata',
'poll',
'call',
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -1925,7 +1975,7 @@ def __init__(
else:
self.role_subscription = RoleSubscriptionInfo(role_subscription)

for handler in ('author', 'member', 'mentions', 'mention_roles', 'components'):
for handler in ('author', 'member', 'mentions', 'mention_roles', 'components', 'call'):
try:
getattr(self, f'_handle_{handler}')(data[handler])
except KeyError:
Expand Down Expand Up @@ -2111,6 +2161,13 @@ def _handle_interaction(self, data: MessageInteractionPayload):
def _handle_interaction_metadata(self, data: MessageInteractionMetadataPayload):
self.interaction_metadata = MessageInteractionMetadata(state=self._state, guild=self.guild, data=data)

def _handle_call(self, data: MessageCallPayload):
self.call: Optional[MessageCall]
if data is not None:
self.call = MessageCall(state=self._state, message=self, data=data)
else:
self.call = None

def _rebind_cached_references(
self,
new_guild: Guild,
Expand Down
6 changes: 6 additions & 0 deletions discord/types/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ class RoleSubscriptionData(TypedDict):
is_renewal: bool


class MessageCall(TypedDict):
participants: SnowflakeList
ended_timestamp: NotRequired[Optional[str]]


MessageType = Literal[
0,
1,
Expand Down Expand Up @@ -187,6 +192,7 @@ class Message(PartialMessage):
position: NotRequired[int]
role_subscription_data: NotRequired[RoleSubscriptionData]
thread: NotRequired[Thread]
call: NotRequired[MessageCall]


AllowedMentionType = Literal['roles', 'users', 'everyone']
Expand Down
8 changes: 8 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5406,6 +5406,14 @@ PollMedia
.. autoclass:: PollMedia
:members:

MessageCall
~~~~~~~~~~~~~~~~~~~

.. attributetable:: MessageCall

.. autoclass:: MessageCall()
:members:


Exceptions
------------
Expand Down