Skip to content

[INTPROD-9625] Add support for reaction slack events#112

Merged
david-lyft merged 10 commits intomasterfrom
INTPROD-9625
May 27, 2025
Merged

[INTPROD-9625] Add support for reaction slack events#112
david-lyft merged 10 commits intomasterfrom
INTPROD-9625

Conversation

@david-lyft
Copy link
Contributor

@david-lyft david-lyft commented May 12, 2025

Adds support for reaction slack events.

For now, reaction handlers will only do callbacks if the reaction is on a matching bot slack message.

  • Reaction Event Processing: Added logic to process reaction_added and reaction_removed events in omnibot/processor.py.
  • New Reaction Class: Created a Reaction class omnibot/services/slack/reaction.py to encapsulate reaction event data and provide helper methods.
  • Redis Caching: Utilized Redis to fetch and cache messages and bot information for efficient reaction processing.
  • Bot Configuration: Updated omnibot/services/slack/bot.py to support reaction handlers.
  • Moved common elements to a BaseMessage class for message and reaction
  • Added new reaction match_type that will match against regex of emoji names

@david-lyft david-lyft requested a review from Copilot May 12, 2025 17:55
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for processing Slack reaction events by introducing a new Reaction class and integrating reaction handlers into the bot's event processing.

  • Added a Reaction class to encapsulate reaction event data and helper methods.
  • Integrated reaction handler registration and processing in the bot and event processor.
  • Added new Redis caching functions for fetching messages and bot info to support the reaction functionality.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
omnibot/services/slack/reaction.py New Reaction class with duplicate reaction attribute handling logic.
omnibot/services/slack/bot.py Added reaction handlers registration in bot initialization.
omnibot/services/slack/init.py Added functions for fetching messages and bot info using Redis caching.
omnibot/processor.py Integrated reaction events processing and reaction callbacks.

@david-lyft david-lyft requested a review from colinsl May 12, 2025 17:56
@david-lyft david-lyft requested a review from Copilot May 12, 2025 18:03
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for handling Slack reaction events by introducing a new Reaction class, integrating reaction handlers in the bot configuration, and updating event processing to handle reaction_added and reaction_removed events.

  • Introduces a new Reaction class to encapsulate reaction event data.
  • Registers reaction handlers in the bot configuration.
  • Updates the event processor to process reaction events with appropriate callbacks.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
omnibot/services/slack/reaction.py New Reaction class with logic for parsing reaction events; duplication in reaction attribute assignment noted.
omnibot/services/slack/bot.py Registers and exposes reaction handlers alongside other event handlers.
omnibot/services/slack/init.py Adds helper functions for fetching messages and bot info used in reaction processing.
omnibot/processor.py Extends event processing to handle reaction_added/reaction_removed events and invoke reaction callbacks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if event_type == "message" or event_type == "app_mention" looks like it opens up for duplicates

Comment on lines +79 to +86
# Ignore slackbot as it doesn't get classified as a bot user
elif self.user and self.user == "USLACKBOT":
logger.debug("ignoring reaction from slackbot", extra=self.event_trace)
unsupported = True
if unsupported:
statsd = stats.get_statsd_client()
statsd.incr("event.unsupported")
raise ReactionUnsupportedError()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why raising when you say it's ignoring?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the same way as message.py

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are any of these common with message handler base? just override and call base a possibility then?

),
)
redis_client = omniredis.get_redis_client()
hash_key = f"message:{bot.team.name}:{channel}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is key by channel or message? If it's by channel why prefixed as message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the hash key is by channel, message just indicates the data type, this pattern is used in other slack functions

@david-lyft david-lyft requested a review from Copilot May 22, 2025 17:36
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds support for processing Slack reaction events by introducing a new Reaction class, reworking message parsing into a shared BaseMessage, and leveraging Redis caching for messages and bot info.

  • Introduces Reaction and updates processor.py to handle reaction_added/reaction_removed
  • Refactors Message into a subclass of BaseMessage and removes redundant code
  • Adds Redis-backed get_message and get_bot_info helpers in slack/__init__.py

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
omnibot/services/slack/reaction.py New Reaction class with parsing and unsupported-event checks
omnibot/services/slack/message.py Converted Message to extend BaseMessage, removed old props
omnibot/services/slack/base_message.py New base class for shared event parsing logic
omnibot/services/slack/init.py Added get_message and get_bot_info for Redis caching
omnibot/processor.py Updated dispatcher to route reaction events to new handlers

@david-lyft david-lyft requested a review from colinsl May 22, 2025 17:39
_process_message_message_handlers(message)
except MessageUnsupportedError:
pass
elif event_type == "reaction_added" or event_type == "reaction_removed":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why nest it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wasn't it clearer before with

messages
--> process message
reactions
--> process reactions?

statsd.incr("event.ignored")


def _is_message_from_bot(bot: Bot, channel: str, ts: str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment why this is necessary vs just looking up bot from lookup table of registered handlers

colinsl
colinsl previously approved these changes May 23, 2025
@david-lyft david-lyft requested a review from colinsl May 27, 2025 17:25
Comment on lines +56 to 57
logger.debug("Event is not a message or reaction type.", extra=event_trace)
logger.debug(event)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why double log?

Comment on lines +60 to +107
def _process_message_event(bot, event_info, event_trace, event_type):
"""
Process message or app_mention events.
"""
statsd = stats.get_statsd_client()
try:
with statsd.timer("process_event"):
logger.debug(
f"Processing event: {json.dumps(event_info, indent=2)}",
extra=event_trace,
)
try:
message = Message(bot, event_info, event_trace)
_process_message_message_handlers(message)
except MessageUnsupportedError:
pass
except Exception:
statsd.incr(f"event.process.failed.{event_type}")
logger.exception(
"Could not process message event.",
exc_info=True,
extra=event_trace,
)


def _process_reaction_event(bot, event_info, event_trace, event_type):
"""
Process reaction_added or reaction_removed events.
"""
statsd = stats.get_statsd_client()
try:
with statsd.timer("process_event"):
logger.debug(
f"Processing event: {json.dumps(event_info, indent=2)}",
extra=event_trace,
)
try:
reaction = Reaction(bot, event_info, event_trace)
_process_reaction_message_handlers(reaction)
except ReactionUnsupportedError:
pass
except Exception:
statsd.incr(f"event.process.failed.{event_type}")
logger.exception(
"Could not process reaction event.",
exc_info=True,
extra=event_trace,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe better as a decorator

if not message or "bot_id" not in message:
logger.warning("Failed to retrieve valid message or 'bot_id' is missing")
return False
# There can be multiple bot_ids for the same bot
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any documentation?

Comment on lines +15 to +16
# `bot` is the receiving bot instance handling this reaction event,
# not the user or bot who sent the reaction.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe better as docstring?

Copy link
Contributor

@colinsl colinsl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addl cmmts

@david-lyft david-lyft merged commit 32ad36a into master May 27, 2025
5 checks passed
@david-lyft david-lyft deleted the INTPROD-9625 branch May 27, 2025 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants