diff --git a/discord/abc.py b/discord/abc.py index 511d69ebe..0251bbb4f 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1659,6 +1659,85 @@ class Messageable: await ret.delete(delay=delete_after) return ret + async def greet( + self, + sticker: Union[GuildSticker, StickerItem], + *, + allowed_mentions: AllowedMentions = MISSING, + reference: Union[Message, MessageReference, PartialMessage] = MISSING, + mention_author: bool = MISSING, + ) -> Message: + """|coro| + + Sends a sticker greeting to the destination. + + A sticker greeting is used to begin a new DM or reply to a system message. + + .. versionadded:: 2.0 + + Parameters + ------------ + sticker: Union[:class:`~discord.GuildSticker`, :class:`~discord.StickerItem`] + The sticker to greet with. + allowed_mentions: :class:`~discord.AllowedMentions` + Controls the mentions being processed in this message. If this is + passed, then the object is merged with :attr:`~discord.Client.allowed_mentions`. + The merging behaviour only overrides attributes that have been explicitly passed + to the object, otherwise it uses the attributes set in :attr:`~discord.Client.allowed_mentions`. + If no object is passed at all then the defaults given by :attr:`~discord.Client.allowed_mentions` + are used instead. In the case of greeting, only :attr:`~discord.AllowedMentions.replied_user` is + considered. + reference: Union[:class:`~discord.Message`, :class:`~discord.MessageReference`, :class:`~discord.PartialMessage`] + A reference to the :class:`~discord.Message` to which you are replying, this can be created using + :meth:`~discord.Message.to_reference` or passed directly as a :class:`~discord.Message`. You can control + whether this mentions the author of the referenced message using the :attr:`~discord.AllowedMentions.replied_user` + attribute of ``allowed_mentions`` or by setting ``mention_author``. + mention_author: :class:`bool` + If set, overrides the :attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions``. + + Raises + -------- + ~discord.HTTPException + Sending the message failed. + ~discord.Forbidden + You do not have the proper permissions to send the message, or this is not a valid greet context. + TypeError + The ``reference`` object is not a :class:`~discord.Message`, + :class:`~discord.MessageReference` or :class:`~discord.PartialMessage`. + + Returns + --------- + :class:`~discord.Message` + The sticker greeting that was sent. + """ + channel = await self._get_channel() + state = self._state + previous_allowed_mention = state.allowed_mentions + + if reference: + try: + reference_dict = reference.to_message_reference_dict() + except AttributeError: + raise TypeError('reference parameter must be Message, MessageReference, or PartialMessage') from None + else: + reference_dict = MISSING + + if allowed_mentions: + if previous_allowed_mention: + allowed_mentions = previous_allowed_mention.merge(allowed_mentions) + if mention_author is not MISSING: + if not allowed_mentions: + allowed_mentions = AllowedMentions() + allowed_mentions.replied_user = mention_author + if allowed_mentions and allowed_mentions.replied_user: + # No point sending them + allowed_mentions = MISSING + + data = await state.http.send_greet( + channel.id, sticker.id, message_reference=reference_dict, allowed_mentions=allowed_mentions + ) + return state.create_message(channel=channel, data=data) + def typing(self) -> Typing: """Returns an asynchronous context manager that allows you to send a typing indicator to the destination for an indefinite period of time, or 10 seconds if the context manager diff --git a/discord/http.py b/discord/http.py index 8a9e03272..db8ef0e59 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1051,6 +1051,22 @@ class HTTPClient: else: return self.request(r, json=params.payload) + def send_greet( + self, + channel_id: Snowflake, + sticker_id: Snowflake, + *, + allowed_mentions: Optional[AllowedMentions] = None, + message_reference: Optional[message.MessageReference] = None, + ) -> Response[message.Message]: + payload: Dict[str, Any] = {'sticker_ids': [sticker_id]} + if allowed_mentions: + payload['allowed_mentions'] = allowed_mentions.to_dict() + if message_reference: + payload['message_reference'] = message_reference + + return self.request(Route('POST', '/channels/{channel_id}/greet', channel_id=channel_id), json=payload) + def send_typing(self, channel_id: Snowflake) -> Response[None]: return self.request(Route('POST', '/channels/{channel_id}/typing', channel_id=channel_id)) diff --git a/discord/message.py b/discord/message.py index 25f439318..3567a2593 100644 --- a/discord/message.py +++ b/discord/message.py @@ -99,6 +99,7 @@ if TYPE_CHECKING: from .components import ActionRow, ActionRowChildComponentType from .state import ConnectionState from .mentions import AllowedMentions + from .sticker import GuildSticker from .user import User from .role import Role @@ -1155,6 +1156,28 @@ class PartialMessage(Hashable): """ return await self.channel.send(content, reference=self, **kwargs) + async def greet(self, sticker: Union[GuildSticker, StickerItem], **kwargs: Any) -> Message: + """|coro| + + A shortcut method to :meth:`.abc.Messageable.greet` to reply to the + :class:`.Message` with a sticker greeting. + + .. versionadded:: 2.0 + + Raises + -------- + ~discord.HTTPException + Sending the message failed. + ~discord.Forbidden + You do not have the proper permissions to send the message, or this is not a valid greet context. + + Returns + --------- + :class:`.Message` + The sticker greeting that was sent. + """ + return await self.channel.greet(sticker, reference=self, **kwargs) + def to_reference(self, *, fail_if_not_exists: bool = True) -> MessageReference: """Creates a :class:`~discord.MessageReference` from the current message.