Update a bot message after responding to a slack dialog

Viewed 1534

I'm having some issues to update an interactive message after responding to a slack dialog. I'm using botkit on a node.js server.

Here is my workflow:

  1. User trigger an interactive message via a slash command
  2. User click a button on that message
  3. A dialog pops up, user fill the form and validate
  4. Something is done on the server side
  5. The first message should update

Now, here is the logic I'm using:

  1. User trigger an interactive message via a slash command

Nothing fancy, I use:

controller.on('slash_command', function (bot, message)

Then I parse the command, and send the appropriate message, with the appropriate attachments (buttons)

  1. User click a button on that message

Same, I use the event sent by botkit:

controller.on('interactive_message_callback', function (bot, message)

Then I create a dialog:

var dialog = bot.createDialog(
                        'Which book?',
                        JSON.stringify(callback),
                        'Ok'
                    )

Here I'm doing something really (really) dirty, and should not be done. But that's the only way I found to update the initial message after the dialog is filled. The callback_id actually contains an object, with the response_urlof the initial message (and something to identify the form).

  1. A dialog pops up, user fill the form and validate
  2. Something is done on the server side

Here, I use once more the event provided by botkit:

controller.on('dialog_submission', function (bot, message)

then I parse the message.submission.callback_id and detect the response_url. With this, I can create an object I call originalMessage.

  1. The first message should update

At the moment I use :

bot.replyInteractive(originalMessage, 'DONE, everything is saved.');

with originalMessagecontaining the response_url of the first message. It does work. The first message is being replaced by the new one.

But I'm really not happy with that solution, and was wondering if I was missing something somewhere. I've seen couple apps having that type of workflow, so there must be a way.

Thank you for your help :)

2 Answers

I wrote to Slack to ask about this situation and got a great suggestion from Mark P:

Use the state dialog field to pass the original response_url to the dialog. Then when you receive the dialog data, you can use state instead of response_url.

I just tried it and it worked great. No need to store any state on your own server.

I don't know how that would work exactly with Node and botkit, since that's not what I use.

To flesh this out a bit more:

  1. Someone clicks a button and Slack POSTs about that interaction to your configured "Request URL".
  2. From Slack's payload, get the "response_url" value.
  3. When you call dialog.open in the Slack API, pass along this response_url as the "state" value.
  4. When the dialog is submitted, Slack again POSTs to your "Request URL".
  5. From Slack's payload, get the "state" value and use it as a response_url.
  6. Profit!

This only works if you hold the original message object somewhere on your server for future reference.

So on creating the interactive dialog store it somewhere and add a reference. I use uuids.

    let newId = uuid();
    messageStore[newId] = message;
    var dialog = bot.createDialog(
        'My Dialog',
        'idPrefix_' + newId,
        'Submit'
    ).addText('Sample Input', 'input', '');
    bot.replyWithDialog(message, dialog.asObject());

Then once you get your interactive dialog response back disassemble the prefix and the uuid and get your original message object back from the servers memory. Then use ´replayInteractive` there.

controller.on('dialog_submission', function handler(bot, message) {
    if (message.callback_id.indexOf('idPrefix') === 0) {
       let id = message.callback_id.substr('idPrefix_'.length);
       bot.dialogOk();
       let originalMessage = messageStore[id];
       bot.replyInteractive(originalMessage, {
            text: 'replacing the original message with this.'
       });
    }
});

Be careful that you do not create a memory leak here. You have to find a way to clean up your messageStore over time.

Related