diff --git a/disagreement/client.py b/disagreement/client.py index bd15b0b..4ddbaaf 100644 --- a/disagreement/client.py +++ b/disagreement/client.py @@ -1016,6 +1016,26 @@ class Client: self._voice_clients[guild_id] = voice return voice + async def add_reaction(self, channel_id: str, message_id: str, emoji: str) -> None: + """|coro| Add a reaction to a message.""" + + await self.create_reaction(channel_id, message_id, emoji) + + async def remove_reaction( + self, channel_id: str, message_id: str, emoji: str + ) -> None: + """|coro| Remove the bot's reaction from a message.""" + + await self.delete_reaction(channel_id, message_id, emoji) + + async def clear_reactions(self, channel_id: str, message_id: str) -> None: + """|coro| Remove all reactions from a message.""" + + if self._closed: + raise DisagreementException("Client is closed.") + + await self._http.clear_reactions(channel_id, message_id) + async def create_reaction( self, channel_id: str, message_id: str, emoji: str ) -> None: diff --git a/disagreement/http.py b/disagreement/http.py index f350f15..8b3f35a 100644 --- a/disagreement/http.py +++ b/disagreement/http.py @@ -348,6 +348,16 @@ class HTTPClient: f"/channels/{channel_id}/messages/{message_id}/reactions/{encoded}", ) + async def clear_reactions( + self, channel_id: "Snowflake", message_id: "Snowflake" + ) -> None: + """Removes all reactions from a message.""" + + await self.request( + "DELETE", + f"/channels/{channel_id}/messages/{message_id}/reactions", + ) + async def bulk_delete_messages( self, channel_id: "Snowflake", messages: List["Snowflake"] ) -> List["Snowflake"]: diff --git a/disagreement/models.py b/disagreement/models.py index a3e7370..d462ac8 100644 --- a/disagreement/models.py +++ b/disagreement/models.py @@ -202,6 +202,21 @@ class Message: view=view, ) + async def add_reaction(self, emoji: str) -> None: + """|coro| Add a reaction to this message.""" + + await self._client.add_reaction(self.channel_id, self.id, emoji) + + async def remove_reaction(self, emoji: str) -> None: + """|coro| Remove the bot's reaction from this message.""" + + await self._client.remove_reaction(self.channel_id, self.id, emoji) + + async def clear_reactions(self) -> None: + """|coro| Remove all reactions from this message.""" + + await self._client.clear_reactions(self.channel_id, self.id) + async def delete(self, delay: Optional[float] = None) -> None: """|coro| diff --git a/tests/test_http_reactions.py b/tests/test_http_reactions.py index e1c0914..02b43a0 100644 --- a/tests/test_http_reactions.py +++ b/tests/test_http_reactions.py @@ -4,7 +4,7 @@ from unittest.mock import AsyncMock from disagreement.client import Client from disagreement.errors import DisagreementException -from disagreement.models import User, Reaction +from disagreement.models import Message, User, Reaction @pytest.mark.asyncio @@ -14,7 +14,16 @@ async def test_create_reaction_calls_http(): client._http = http client._closed = False - await client.create_reaction("1", "2", "😀") + message_data = { + "id": "2", + "channel_id": "1", + "author": {"id": "3", "username": "u", "discriminator": "0001"}, + "content": "hi", + "timestamp": "t", + } + message = Message(message_data, client_instance=client) + + await message.add_reaction("😀") http.create_reaction.assert_called_once_with("1", "2", "😀") @@ -26,8 +35,17 @@ async def test_create_reaction_closed(): client._http = http client._closed = True + message_data = { + "id": "2", + "channel_id": "1", + "author": {"id": "3", "username": "u", "discriminator": "0001"}, + "content": "hi", + "timestamp": "t", + } + message = Message(message_data, client_instance=client) + with pytest.raises(DisagreementException): - await client.create_reaction("1", "2", "😀") + await message.add_reaction("😀") @pytest.mark.asyncio @@ -37,7 +55,16 @@ async def test_delete_reaction_calls_http(): client._http = http client._closed = False - await client.delete_reaction("1", "2", "😀") + message_data = { + "id": "2", + "channel_id": "1", + "author": {"id": "3", "username": "u", "discriminator": "0001"}, + "content": "hi", + "timestamp": "t", + } + message = Message(message_data, client_instance=client) + + await message.remove_reaction("😀") http.delete_reaction.assert_called_once_with("1", "2", "😀") @@ -69,7 +96,16 @@ async def test_create_reaction_dispatches_event(monkeypatch): client._event_dispatcher.register("MESSAGE_REACTION_ADD", on_add) - await client.create_reaction("1", "2", "😀") + message_data = { + "id": "2", + "channel_id": "1", + "author": {"id": "3", "username": "u", "discriminator": "0001"}, + "content": "hi", + "timestamp": "t", + } + message = Message(message_data, client_instance=client) + + await message.add_reaction("😀") assert isinstance(events.get("add"), Reaction) @@ -86,6 +122,15 @@ async def test_delete_reaction_dispatches_event(monkeypatch): client._event_dispatcher.register("MESSAGE_REACTION_REMOVE", on_remove) - await client.delete_reaction("1", "2", "😀") + message_data = { + "id": "2", + "channel_id": "1", + "author": {"id": "3", "username": "u", "discriminator": "0001"}, + "content": "hi", + "timestamp": "t", + } + message = Message(message_data, client_instance=client) + + await message.remove_reaction("😀") assert isinstance(events.get("remove"), Reaction)