Add support for clearing a specific reaction.

Closes #2440
This commit is contained in:
Rapptz
2020-01-17 19:48:46 -05:00
parent 7b2c01c48a
commit 87f9dcff9c
6 changed files with 152 additions and 6 deletions

View File

@ -402,6 +402,11 @@ class HTTPClient:
return self.request(r)
def clear_single_reaction(self, channel_id, message_id, emoji):
r = Route('DELETE', '/channels/{channel_id}/messages/{message_id}/reactions/{emoji}',
channel_id=channel_id, message_id=message_id, emoji=emoji)
return self.request(r)
def get_message(self, channel_id, message_id):
r = Route('GET', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id, message_id=message_id)
return self.request(r)
@ -425,7 +430,7 @@ class HTTPClient:
return self.request(Route('GET', '/channels/{channel_id}/messages', channel_id=channel_id), params=params)
def publish_message(self, channel_id, message_id):
return self.request(Route('POST', '/channels/{channel_id}/messages/{message_id}/crosspost',
return self.request(Route('POST', '/channels/{channel_id}/messages/{message_id}/crosspost',
channel_id=channel_id, message_id=message_id))
def pin_message(self, channel_id, message_id):

View File

@ -371,6 +371,18 @@ class Message:
return reaction
def _clear_emoji(self, emoji):
to_check = str(emoji)
for index, reaction in enumerate(self.reactions):
if str(reaction.emoji) == to_check:
break
else:
# didn't find anything so just return
return
del self.reactions[index]
return reaction
def _update(self, data):
handlers = self._HANDLERS
for key, value in data.items():
@ -945,6 +957,37 @@ class Message:
else:
await self._state.http.remove_reaction(self.channel.id, self.id, emoji, member.id)
async def clear_reaction(self, emoji):
"""|coro|
Clears a specific reaction from the message.
The emoji may be a unicode emoji or a custom guild :class:`Emoji`.
You need the :attr:`~Permissions.manage_messages` permission to use this.
.. versionadded:: 1.3
Parameters
-----------
emoji: Union[:class:`Emoji`, :class:`Reaction`, :class:`PartialEmoji`, :class:`str`]
The emoji to clear.
Raises
--------
HTTPException
Clearing the reaction failed.
Forbidden
You do not have the proper permissions to clear the reaction.
NotFound
The emoji you specified was not found.
InvalidArgument
The emoji parameter is invalid.
"""
emoji = self._emoji_reaction(emoji)
await self._state.http.clear_single_reaction(self.channel.id, self.id, emoji)
@staticmethod
def _emoji_reaction(emoji):
if isinstance(emoji, Reaction):

View File

@ -177,3 +177,32 @@ class RawReactionClearEvent(_RawReprMixin):
self.guild_id = int(data['guild_id'])
except KeyError:
self.guild_id = None
class RawReactionClearEmojiEvent(_RawReprMixin):
"""Represents the payload for a :func:`on_raw_reaction_clear_emoji` event.
.. versionadded:: 1.3.0
Attributes
-----------
message_id: :class:`int`
The message ID that got its reactions cleared.
channel_id: :class:`int`
The channel ID where the reactions got cleared.
guild_id: Optional[:class:`int`]
The guild ID where the reactions got cleared.
emoji: :class:`PartialEmoji`
The custom or unicode emoji being removed.
"""
__slots__ = ('message_id', 'channel_id', 'guild_id', 'emoji')
def __init__(self, data, emoji):
self.emoji = emoji
self.message_id = int(data['message_id'])
self.channel_id = int(data['channel_id'])
try:
self.guild_id = int(data['guild_id'])
except KeyError:
self.guild_id = None

View File

@ -121,6 +121,28 @@ class Reaction:
await self.message.remove_reaction(self.emoji, user)
async def clear(self):
"""|coro|
Clears this reaction from the message.
You need the :attr:`~Permissions.manage_messages` permission to use this.
.. versionadded:: 1.3
Raises
--------
HTTPException
Clearing the reaction failed.
Forbidden
You do not have the proper permissions to clear the reaction.
NotFound
The emoji you specified was not found.
InvalidArgument
The emoji parameter is invalid.
"""
await self.message.clear_reaction(self.emoji)
def users(self, limit=None, after=None):
"""Returns an :class:`AsyncIterator` representing the users that have reacted to the message.

View File

@ -509,6 +509,23 @@ class ConnectionState:
if user:
self.dispatch('reaction_remove', reaction, user)
def parse_message_reaction_remove_emoji(self, data):
emoji = data['emoji']
emoji_id = utils._get_as_snowflake(emoji, 'id')
emoji = PartialEmoji.with_state(self, animated=emoji.get('animated', False), id=emoji_id, name=emoji['name'])
raw = RawReactionClearEmojiEvent(data, emoji)
self.dispatch('raw_reaction_clear_emoji', raw)
message = self._get_message(raw.message_id)
if message is not None:
try:
reaction = message._clear_emoji(emoji)
except (AttributeError, ValueError): # eventual consistency lol
pass
else:
if reaction:
self.dispatch('reaction_clear_emoji', reaction)
def parse_presence_update(self, data):
guild_id = utils._get_as_snowflake(data, 'guild_id')
guild = self._get_guild(guild_id)