Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Interactive Mode over Websockets #94

Open
blairhoddinott opened this issue Jan 1, 2023 · 2 comments
Open

Support for Interactive Mode over Websockets #94

blairhoddinott opened this issue Jan 1, 2023 · 2 comments

Comments

@blairhoddinott
Copy link

Greetings,

I've been looking through the documentation, and the code itself. Unless I'm missing something, I do not see support for interactive messages over websocket (likely missing everywhere, but I'm only focused on websocket backend). Is this functionality there and I'm missing it? Or is this on the roadmap to be included?

Also, if there were any hints on doing this manually as a workaround, it would be much appreciated.

Happy New Year!

@blairhoddinott
Copy link
Author

blairhoddinott commented Jan 1, 2023

Update:

So I have modified the backend to make this work. If anyone else comes across this, here is how I got it to go:

  1. Modify the slackv3.py with the following:
def _generic_wrapper(self, event_data):
        """Calls the event handler based on the event type"""
        log.debug("Received event: {}".format(str(event_data)))
        if event_data['type'] == "block_actions" or \
           event_data['type'] == "interactive_message":
            return self._interactive_message_event_handler(event_data)
        try:
            event = event_data["event"]
            event_type = event["type"]
...

I put in the lookup to catch the block_actions or Interactive_message type before it gets sent off to the generic handler. Sent it to the new custom function:

def _interactive_message_event_handler(self, event):
        """
        Event handler for the 'interactive' event, used in attachments / buttons.
        """
        log.debug(f"event: {event}")
        msg = Message(
            frm=SlackPerson(self.slack_web, event['user']['id'], event['channel']['id']),
            to=self.bot_identifier,
            extras={
                'actions': event["actions"],
                'url': event['response_url'],
                'trigger_id': event.get('trigger_id', None),
                'callback_id': event.get('callback_id', None),
                'ts': event.get('message_ts', None),
                'slack_event': event
            }
        )

        flow, _ = self.flow_executor.check_inflight_flow_triggered(msg.extras['callback_id'], msg.frm)
        if flow:
            log.debug("Reattach context from flow %s to the message", flow._root.name)
            msg.ctx = flow.ctx

        self.callback_message(msg)

This code was lifted from this SUPER helpful post:
#40 (comment)

  1. Modify my plugin as follows:
def callback_message(self, msg):
        log.debug("Callback initiated...")
        callback = msg.extras.get('callback_id', None)
        log.debug(f"callback: {callback}")
        if (
            callback and callback in dir(self) and
            callable(getattr(self, callback))
        ):
            self.log.info(f'Calling function {callback}')
            return getattr(self, callback)(msg)

Which, when hit will now call a function that has the same name as the callback. In my case, I tested with this:

@botcmd
    def approval_request(self, msg, args=None) -> None:
        log.debug(f"msg: {msg.extras.get('callback_id', None)}")
        if msg.extras.get('callback_id', None) == 'approval_request':
            answer = msg.extras.get('actions')[0]['value']
            ts = msg.extras.get('ts', None)
            log.debug(f"channel: {msg.extras.get('slack_event')['channel']['id']}")

            ...
            <logic to modify original slack message>
            ...

            if ts:
                SLACK.chat_update(
                    channel=msg.extras.get('slack_event')['channel']['id'],
                    text=answer.capitalize(),
                    blocks=blocks,
                    attachments=attachments,
                    ts=ts
                )

Which in turn updated the original message. This works for me, so for future noobies like myself who stumble across this, it was not super straight forward.

I know the above is a dirty(ish) hack to make it go, so would love to see this implemented "correctly" by someone smarter in the future.

Cheers!

@lingfish
Copy link

so would love to see this implemented "correctly" by someone smarter in the future.

Agreed, and not have to maintain forks.

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

No branches or pull requests

2 participants