Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions changelog/1225.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Implement new :attr:`Message.type`: :attr:`MessageType.purchase_notifcation`.
- New types :class:`PurchaseNotificationInfo`, :class:`GuildProductInfo`.
- New :attr:`Message.purchase_information` attribute.
- New enum :class:`PurchaseType`.
6 changes: 6 additions & 0 deletions disnake/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"OnboardingPromptType",
"SKUType",
"EntitlementType",
"PurchaseType",
)


Expand Down Expand Up @@ -260,6 +261,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 PartyType(Enum):
Expand Down Expand Up @@ -1364,6 +1366,10 @@ class EntitlementType(Enum):
application_subscription = 8


class PurchaseType(Enum):
guild_product = 0


T = TypeVar("T")


Expand Down
64 changes: 63 additions & 1 deletion disnake/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@
from .components import ActionRow, MessageComponent, _component_factory
from .embeds import Embed
from .emoji import Emoji
from .enums import ChannelType, InteractionType, MessageType, try_enum, try_enum_to_int
from .enums import (
ChannelType,
InteractionType,
MessageType,
PurchaseType,
try_enum,
try_enum_to_int,
)
from .errors import HTTPException
from .file import File
from .flags import AttachmentFlags, MessageFlags
Expand Down Expand Up @@ -64,10 +71,12 @@
from .types.member import Member as MemberPayload, UserWithMember as UserWithMemberPayload
from .types.message import (
Attachment as AttachmentPayload,
GuildProductPurchase as GuildProductPayload,
Message as MessagePayload,
MessageActivity as MessageActivityPayload,
MessageApplication as MessageApplicationPayload,
MessageReference as MessageReferencePayload,
PurchaseNotification as PurchaseNotificationPayload,
Reaction as ReactionPayload,
RoleSubscriptionData as RoleSubscriptionDataPayload,
)
Expand All @@ -86,6 +95,8 @@
"InteractionReference",
"DeletedReferencedMessage",
"RoleSubscriptionData",
"GuildProductInfo",
"PurchaseNotificationInfo",
)


Expand Down Expand Up @@ -748,6 +759,42 @@ def __init__(self, data: RoleSubscriptionDataPayload) -> None:
self.is_renewal: bool = data["is_renewal"]


class GuildProductInfo:
"""Represents the information about the guild product purchased by a user in a message
of type :attr:`MessageType.purchase_notification`.

.. versionadded:: 2.10

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

__slots__ = ("listing_id", "product_name")

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


class PurchaseNotificationInfo:
"""Represents the information about a purchase made by a user in a message of type
:attr:`MessageType.purchase_notification`.

.. versionadded:: 2.10
"""

__slots__ = ("type", "guild_product")

def __init__(self, data: PurchaseNotificationPayload) -> None:
self.type: PurchaseType = try_enum(PurchaseType, data["type"])
guild_product_info = data.get("guild_product_purchase")
self.guild_product: Optional[GuildProductInfo] = (GuildProductInfo(guild_product_info) if guild_product_info is not None else None)


def flatten_handlers(cls):
prefix = len("_handle_")
handlers = [
Expand Down Expand Up @@ -894,6 +941,11 @@ class Message(Hashable):

.. versionadded:: 2.0

purchase_notification: Optional[:class:`PurchaseNotification`]
The purchase a user made if this message is of type :attr:`MessageType.purchase_notification`.

.. versionadded:: 2.10

guild: Optional[:class:`Guild`]
The guild that the message belongs to, if applicable.
"""
Expand Down Expand Up @@ -930,6 +982,7 @@ class Message(Hashable):
"activity",
"stickers",
"components",
"purchase_notification",
"guild",
"_edited_timestamp",
"_role_subscription_data",
Expand Down Expand Up @@ -986,6 +1039,9 @@ def __init__(
for d in data.get("components", [])
]

purchase_notif = data.get("purchase_notification")
self.purchase_notification: Optional[PurchaseNotificationInfo] = PurchaseNotificationInfo(purchase_notif) if purchase_notif is not None else None

inter_payload = data.get("interaction")
inter = (
None if inter_payload is None else InteractionReference(state=state, data=inter_payload)
Expand Down Expand Up @@ -1538,6 +1594,12 @@ def system_content(self) -> Optional[str]:
if self.type is MessageType.guild_incident_report_false_alarm:
return f"{self.author.name} resolved an Activity Alert."

if self.type is MessageType.purchase_notification and self.purchase_notification is not None:
if self.purchase_notification.guild_product is not None:
return f"{self.author.name} has purchased {self.purchase_notification.guild_product.product_name}!"

# TODO: maybe more purcahse notification types will be added?

# in the event of an unknown or unsupported message type, we return nothing
return None

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


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


PurchaseType = Literal[0]


class PurchaseNotification(TypedDict):
type: PurchaseType
guild_product_purchase: NotRequired[GuildProductPurchase]


# fmt: off
MessageType = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 36, 37, 38, 39]
# fmt: on
Expand Down Expand Up @@ -114,6 +127,7 @@ class Message(TypedDict):
sticker_items: NotRequired[List[StickerItem]]
position: NotRequired[int]
role_subscription_data: NotRequired[RoleSubscriptionData]
purchase_notification: NotRequired[PurchaseNotification]

# specific to MESSAGE_CREATE/MESSAGE_UPDATE events
guild_id: NotRequired[Snowflake]
Expand Down
29 changes: 29 additions & 0 deletions docs/api/messages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ RoleSubscriptionData
.. autoclass:: RoleSubscriptionData
:members:

GuildProductInfo
~~~~~~~~~~~~~~~~

.. attributetable:: GuildProductInfo

.. autoclass:: GuildProductInfo
:members:

PurchaseNotificationInfo
~~~~~~~~~~~~~~~~~~~~~~~~

.. attributetable:: PurchaseNotificationInfo

.. autoclass:: PurchaseNotificationInfo
:members:

RawTypingEvent
~~~~~~~~~~~~~~

Expand Down Expand Up @@ -183,6 +199,14 @@ Enumerations
MessageType
~~~~~~~~~~~

.. class:: PurchaseType

Specifies the type of purchase for :class:`PurchaseNotificationInfo`.

.. attribute:: guild_product

The purchase is of a product from a guild.

.. class:: MessageType

Specifies the type of :class:`Message`. This is used to denote if a message
Expand Down Expand Up @@ -367,6 +391,11 @@ MessageType

The system message denoting that a raid report was a false alarm.

.. versionadded:: 2.10
.. attribute:: purchase_notification

The system message denoting that a user has purchased a product.

.. versionadded:: 2.10

Events
Expand Down