diff --git a/docs/api.rst b/docs/api.rst index 4db9953..0f7b268 100755 --- a/docs/api.rst +++ b/docs/api.rst @@ -78,6 +78,9 @@ Message .. autoclass:: Message :members: +.. autoclass:: MessageReply + :members: + Messageable ~~~~~~~~~~~~ diff --git a/revolt/__init__.py b/revolt/__init__.py index 8b572f6..49d560d 100755 --- a/revolt/__init__.py +++ b/revolt/__init__.py @@ -9,7 +9,7 @@ from .enums import (AssetType, ChannelType, PresenceType, RelationshipType, from .errors import HTTPError, RevoltError, ServerError from .file import File from .member import Member -from .message import Message +from .message import Message, MessageReply from .messageable import Messageable from .permissions import ChannelPermissions, ServerPermissions from .role import Role diff --git a/revolt/ext/commands/context.py b/revolt/ext/commands/context.py index ce04c29..91269de 100755 --- a/revolt/ext/commands/context.py +++ b/revolt/ext/commands/context.py @@ -66,5 +66,5 @@ class Context: return await command.invoke(self, *self.args, **self.kwargs) @copy_doc(revolt.Messageable.send) - async def send(self, content: Optional[str] = None, *, embeds: Optional[list[revolt.Embed]] = None, embed: Optional[revolt.Embed] = None, attachments: Optional[list[revolt.File]] = None) -> revolt.Message: - return await self.message.channel.send(content, embeds=embeds, embed=embed, attachments=attachments) + async def send(self, content: Optional[str] = None, *, embeds: Optional[list[revolt.Embed]] = None, embed: Optional[revolt.Embed] = None, attachments: Optional[list[revolt.File]] = None, replies: Optional[list[revolt.MessageReply]] = None, reply: Optional[revolt.MessageReply] = None) -> revolt.Message: + return await self.message.channel.send(content, embeds=embeds, embed=embed, attachments=attachments, replies=replies, reply=reply) diff --git a/revolt/http.py b/revolt/http.py index 1dd807e..14e5a35 100755 --- a/revolt/http.py +++ b/revolt/http.py @@ -24,7 +24,7 @@ if TYPE_CHECKING: from .types import Channel, DMChannel from .types import Embed as EmbedPayload from .types import GetServerMembers, Member - from .types import Message as MessagePayload + from .types import Message as MessagePayload, MessageReplyPayload from .types import (MessageWithUserData, Role, Server, ServerBans, ServerInvite, TextChannel) from .types import User as UserPayload @@ -104,7 +104,7 @@ class HttpClient: else: return response - async def send_message(self, channel: str, content: Optional[str], embeds: Optional[list[EmbedPayload]], attachments: Optional[list[File]]) -> MessagePayload: + async def send_message(self, channel: str, content: Optional[str], embeds: Optional[list[EmbedPayload]], attachments: Optional[list[File]], replies: Optional[list[MessageReplyPayload]]) -> MessagePayload: json: dict[str, Any] = {} if content: @@ -121,6 +121,9 @@ class HttpClient: attachment_ids.append(data["id"]) json["attachments"] = attachment_ids + + if replies: + json["replies"] = replies return await self.request("POST", f"/channels/{channel}/messages", json=json) diff --git a/revolt/message.py b/revolt/message.py index 5ea184b..1964bd1 100755 --- a/revolt/message.py +++ b/revolt/message.py @@ -1,7 +1,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, NamedTuple, Optional from .asset import Asset from .channel import Messageable @@ -9,10 +9,13 @@ from .embed import Embed if TYPE_CHECKING: from .state import State - from .types import Message as MessagePayload + from .types import Message as MessagePayload, MessageReplyPayload -__all__ = ("Message",) +__all__ = ( + "Message", + "MessageReply", +) class Message: """Represents a message @@ -108,3 +111,19 @@ class Message: async def delete(self) -> None: """Deletes the message. The bot can only delete its own messages and messages it has permission to delete """ await self.state.http.delete_message(self.channel.id, self.id) + +class MessageReply(NamedTuple): + """A namedtuple which represents a reply to a message. + + Parameters + ----------- + message: :class:`Message` + The message being replied to. + mention: :class:`bool` + Whether the reply should mention the author of the message. Defaults to false. + """ + message: Message + mention: bool = False + + def to_dict(self) -> MessageReplyPayload: + return { "id": self.message.id, "mention": self.mention } diff --git a/revolt/messageable.py b/revolt/messageable.py index 79cc9bb..d1b7a65 100755 --- a/revolt/messageable.py +++ b/revolt/messageable.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Optional if TYPE_CHECKING: from .embed import Embed from .file import File - from .message import Message + from .message import Message, MessageReply from .state import State @@ -24,7 +24,7 @@ class Messageable: __slots__ = () - async def send(self, content: Optional[str] = None, *, embeds: Optional[list[Embed]] = None, embed: Optional[Embed] = None, attachments: Optional[list[File]] = None) -> Message: + async def send(self, content: Optional[str] = None, *, embeds: Optional[list[Embed]] = None, embed: Optional[Embed] = None, attachments: Optional[list[File]] = None, replies: Optional[list[MessageReply]] = None, reply: Optional[MessageReply] = None) -> Message: """Sends a message in a channel, you must send at least one of either `content`, `embeds` or `attachments` Parameters @@ -35,6 +35,8 @@ class Messageable: The attachments of the message embeds: Optional[list[:class:`Embed`]] The embeds of the message + replies: Optional[list[:class:`MessageReply`]] + The list of messages to reply to. Returns -------- @@ -44,7 +46,11 @@ class Messageable: if embed: embeds = [embed] - embed_payload = [embed.to_dict() for embed in embeds] if embeds else None + if reply: + replies = [reply] - message = await self.state.http.send_message(self.id, content, embed_payload, attachments) + embed_payload = [embed.to_dict() for embed in embeds] if embeds else None + reply_payload = [reply.to_dict() for reply in replies] if replies else None + + message = await self.state.http.send_message(self.id, content, embed_payload, attachments, reply_payload) return self.state.add_message(message) diff --git a/revolt/types/message.py b/revolt/types/message.py index ff25690..6c3dd30 100755 --- a/revolt/types/message.py +++ b/revolt/types/message.py @@ -7,7 +7,10 @@ if TYPE_CHECKING: from .file import File -__all__ = ("Message",) +__all__ = ( + "Message", + "MessageReplyPayload", + ) class UserAddContent(TypedDict): id: str @@ -54,3 +57,7 @@ class Message(_OptionalMessage): channel: str author: str content: Union[str, UserAddContent, UserRemoveContent, UserJoinedContent, UserLeftContent, UserKickedContent, UserBannedContent, ChannelRenameContent, ChannelDescriptionChangeContent, ChannelIconChangeContent] + +class MessageReplyPayload(TypedDict): + id: str + mention: bool