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

Add support for messages with type purchase_notification #9906

Merged
merged 11 commits into from
Oct 10, 2024
1 change: 1 addition & 0 deletions discord/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class MessageType(Enum):
guild_incident_alert_mode_disabled = 37
guild_incident_report_raid = 38
guild_incident_report_false_alarm = 39
purchase_notification = 44


class SpeakingState(Enum):
Expand Down
75 changes: 75 additions & 0 deletions discord/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
RoleSubscriptionData as RoleSubscriptionDataPayload,
MessageInteractionMetadata as MessageInteractionMetadataPayload,
CallMessage as CallMessagePayload,
PurchaseNotificationResponse as PurchaseNotificationResponsePayload,
GuildProductPurchase as GuildProductPurchasePayload,
)

from .types.interactions import MessageInteraction as MessageInteractionPayload
Expand Down Expand Up @@ -114,6 +116,8 @@
'RoleSubscriptionInfo',
'MessageInteractionMetadata',
'CallMessage',
'GuildProductPurchase',
'PurchaseNotification',
)


Expand Down Expand Up @@ -890,6 +894,59 @@ def __init__(self, data: RoleSubscriptionDataPayload) -> None:
self.is_renewal: bool = data['is_renewal']


class GuildProductPurchase:
"""Represents a message's guild product that the user has purchased.

.. versionadded:: 2.5

Attributes
-----------
listing_id: :class:`int`
The ID of the listing that the user has purchased.
product_name: :class:`str`
The name of the product that the user has purchased.
"""

Soheab marked this conversation as resolved.
Show resolved Hide resolved
__slots__ = ('listing_id', 'product_name')

def __init__(self, data: GuildProductPurchasePayload) -> None:
self.listing_id: int = int(data['listing_id'])
self.product_name: str = data['product_name']

def __hash__(self) -> int:
return self.listing_id >> 22
Soheab marked this conversation as resolved.
Show resolved Hide resolved

def __eq__(self, other: object) -> bool:
return isinstance(other, GuildProductPurchase) and other.listing_id == self.listing_id

def __ne__(self, other: object) -> bool:
return not self.__eq__(other)


class PurchaseNotification:
"""Represents a message's purchase notification data.

This is currently only attached to messages of type :attr:`MessageType.purchase_notification`.

.. versionadded:: 2.5

Attributes
-----------
guild_product_purchase: Optional[:class:`GuildProductPurchase`]
The guild product purchase that prompted the message.
"""

Soheab marked this conversation as resolved.
Show resolved Hide resolved
__slots__ = ('_type', 'guild_product_purchase')

def __init__(self, data: PurchaseNotificationResponsePayload) -> None:
self._type: int = data['type']

self.guild_product_purchase: Optional[GuildProductPurchase] = None
guild_product_purchase = data.get('guild_product_purchase')
if guild_product_purchase is not None:
Soheab marked this conversation as resolved.
Show resolved Hide resolved
self.guild_product_purchase = GuildProductPurchase(guild_product_purchase)


class PartialMessage(Hashable):
"""Represents a partial message to aid with working messages when only
a message and channel ID are present.
Expand Down Expand Up @@ -1820,6 +1877,10 @@ class Message(PartialMessage, Hashable):
call: Optional[:class:`CallMessage`]
The call associated with this message.

.. versionadded:: 2.5
purchase_notification: Optional[:class:`PurchaseNotification`]
The data of the purchase notification that prompted this :attr:`MessageType.purchase_notification` message.

.. versionadded:: 2.5
"""

Expand Down Expand Up @@ -1858,6 +1919,7 @@ class Message(PartialMessage, Hashable):
'interaction_metadata',
'poll',
'call',
'purchase_notification',
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -1983,6 +2045,14 @@ def __init__(
else:
self.role_subscription = RoleSubscriptionInfo(role_subscription)

self.purchase_notification: Optional[PurchaseNotification] = None
try:
purchase_notification = data['purchase_notification']
except KeyError:
pass
else:
self.purchase_notification = PurchaseNotification(purchase_notification)

for handler in ('author', 'member', 'mentions', 'mention_roles', 'components', 'call'):
try:
getattr(self, f'_handle_{handler}')(data[handler])
Expand Down Expand Up @@ -2496,6 +2566,11 @@ def system_content(self) -> str:
else:
return '{0.author.name} started a call.'.format(self)

if self.type is MessageType.purchase_notification and self.purchase_notification is not None:
guild_product_purchase = self.purchase_notification.guild_product_purchase
if guild_product_purchase is not None:
Soheab marked this conversation as resolved.
Show resolved Hide resolved
return f'{self.author.name} has purchased {guild_product_purchase.product_name}!'

# Fallback for unknown message types
return ''

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


PurchaseNotificationResponseType = Literal[0]
Soheab marked this conversation as resolved.
Show resolved Hide resolved


class GuildProductPurchase(TypedDict):
listing_id: Snowflake
product_name: str


class PurchaseNotificationResponse(TypedDict):
type: PurchaseNotificationResponseType
guild_product_purchase: Optional[GuildProductPurchase]


class CallMessage(TypedDict):
participants: SnowflakeList
ended_timestamp: NotRequired[Optional[str]]
Expand Down Expand Up @@ -156,6 +169,7 @@ class CallMessage(TypedDict):
37,
38,
39,
44,
]


Expand Down Expand Up @@ -193,6 +207,7 @@ class Message(PartialMessage):
role_subscription_data: NotRequired[RoleSubscriptionData]
thread: NotRequired[Thread]
call: NotRequired[CallMessage]
purchase_notification: NotRequired[PurchaseNotificationResponse]


AllowedMentionType = Literal['roles', 'users', 'everyone']
Expand Down
22 changes: 22 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1881,6 +1881,12 @@ of :class:`enum.Enum`.

.. versionadded:: 2.4

.. attribute:: purchase_notification

The system message sent when a purchase is made in the guild.

.. versionadded:: 2.5

.. class:: UserFlags

Represents Discord User flags.
Expand Down Expand Up @@ -5418,6 +5424,22 @@ RoleSubscriptionInfo
.. autoclass:: RoleSubscriptionInfo
:members:

PurchaseNotification
~~~~~~~~~~~~~~~~~~~~~

.. attributetable:: PurchaseNotification

.. autoclass:: PurchaseNotification()
:members:

GuildProductPurchase
+++++++++++++++++++++

.. attributetable:: GuildProductPurchase

.. autoclass:: GuildProductPurchase()
:members:

Intents
~~~~~~~~~~

Expand Down
Loading