From 7a5afefb00fcbc1b5d6524dc8b6ad27af5b51593 Mon Sep 17 00:00:00 2001 From: CMDR furrycat Date: Sat, 20 Mar 2021 17:36:11 +0100 Subject: [PATCH] Added handle_reaction(). --- app.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ bot.py | 3 +++ plugins/__init__.py | 15 +++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/app.py b/app.py index bd225d4..2f3dd09 100644 --- a/app.py +++ b/app.py @@ -373,6 +373,59 @@ async def on_message(message): if not result: await process_module(message, command, raw) +async def on_reaction(reaction, event_type, emoji = None): + message = None + channel = bot.get_channel(reaction.channel_id) + if not channel: + user = bot.get_user(reaction.user_id) + if not user: + log.error("Can't get channel with ID {}. Maybe it is a DMChannel...".format(reaction.channel_id)) + return + message = await user.fetch_message(reaction.message_id) + if message: + channel = message.channel + try: + if not message: + message = await channel.fetch_message(reaction.message_id) + if message.author.id != client.user.id: + return + except discord.NotFound: + log.error('No message with ID {} found in channel {}!'.format(reaction.message_id, channel)) + return + except discord.Forbidden: + log.error("We don't have access to message with ID {} in channel {}!".format(reaction.message_id, channel)) + return + except: + log.error('Failed to retrieve message with ID {} from channel {}!'.format(reaction.message_id, channel)) + return + + server = bot.get_server(reaction.guild_id) if reaction.guild_id is not None else None + if server: + member = server.get_member(reaction.user_id) + else: + member = None + + if not emoji and event_type in ['REACTION_ADD', 'REACTION_REMOVE']: + emoji = reaction.emoji + + await plugins.handle_reaction(reaction, message = message, member = member, channel = channel, server = server, event_type = event_type, emoji = emoji) + +@client.event +async def on_raw_reaction_add(reaction): + await on_reaction(reaction, 'REACTION_ADD') + +@client.event +async def on_raw_reaction_remove(reaction): + await on_reaction(reaction, 'REACTION_REMOVE') + +@client.event +async def on_raw_reaction_clear(reaction): + await on_reaction(reaction, 'REACTION_CLEAR') + +@client.event +async def on_raw_reaction_clear_emoji(reaction): + await on_reaction(reaction, event_type = 'REACTION_CLEAR_EMOJI', emoji = reaction.emoji) + @client.event async def on_member_join(member): await plugins.on_member_join(member) diff --git a/bot.py b/bot.py index 3028146..995e01f 100644 --- a/bot.py +++ b/bot.py @@ -179,6 +179,9 @@ def get_server(id): def get_channel(id): return client.get_channel(snowflake(id)) +def get_user(id): + return client.get_user(snowflake(id)) + def get_message_servers(message, allow_private = False): servers = [] if is_private(message.channel): diff --git a/plugins/__init__.py b/plugins/__init__.py index 4cd28c1..02f12e2 100644 --- a/plugins/__init__.py +++ b/plugins/__init__.py @@ -5,6 +5,8 @@ import logging import os from enum import Enum +import bot + log = logging.getLogger('plugins') class PluginCommand(Enum): @@ -21,6 +23,7 @@ class Plugins(object): 'on_typing', 'handle_command', 'handle_help', + 'handle_reaction', 'eddn_message', 'non_command_message', 'not_our_message' @@ -170,6 +173,18 @@ class Plugins(object): log.debug('Plugin {} handled command {}.'.format(name, command)) continue + async def handle_reaction(self, reaction, message, member, channel, server, event_type, emoji): + handled = [] + args = [reaction] + for name in self.method_cache('handle_reaction'): + asyncio.ensure_future(self.call_coroutine(name, 'handle_reaction', reaction, message, member, channel, server, event_type, emoji)) + handled.append(name) + emoji_name = emoji.name if emoji else 'unknown' + if handled: + log.info('{} "{}" on message {} in channel {} delegated to plugins: {}'.format(event_type, emoji_name, message.id, channel if bot.is_private(channel) else channel.name, ', '.join(handled))) + else: + log.info('Unhandled {} "{}" on message {} in channel {}.'.format(event_type, emoji_name, message.id, channel if bot.is_private(channel) else channel.name)) + async def non_command_message(self, message): for name in self.method_cache('non_command_message'): asyncio.ensure_future(self.call_coroutine(name, 'non_command_message', message)) -- 2.7.4