Search code examples
typescriptbotframeworkslack-api

Unable to render bot framework prompt in slack using interactive messages


I am trying to use Slack's interactive messages to post a slack block kit JSON for a section and buttons. However i am getting an error that says Invalid ChannelData

I tried posting the block JSON through the slack api tester and it works but not through the code I wrote. I wrote some custom code to override the prompt function in bot framework specifically for the slack channel.

Overrided prompt

   public async prompt(stepContext: WaterfallStepContext, dialogId: string, options: PromptOptions): Promise<DialogTurnResult> {

        let promptText: string = '';
        if (isString(options.prompt)) {
            promptText = options.prompt;
        } else if (isActivity(options.prompt)) {
            promptText = options.prompt.text;
        }
        this.logger.log(`prompt: ${promptText}`);

        const choices = options.choices.map((choice) => {
            let text = '';
            this.logger.log(`choice: ${choice}`);
            if (isString(choice)) {
                text = choice;
            } else if (isChoice(choice)) {
                text = choice.value;
            }
            // return { name: text, type: 'button', text: text, value: text };
            return {
                type: 'button',
                text: {
                    type: "plain_text",
                    text: text
                },
                value: text
            };
        });

        const channelData = {
            text: '',
            blocks: [
                {
                    type: "section",
                    text:
                        {
                            type: "mrkdwn",
                            text: "Are you using a Mac or PC?"
                        }
                },
                {
                    type: "actions",
                    elements: choices
                }]
        };
        this.logger.log(`channelData: ${JSON.stringify(channelData)}`);

        return await stepContext.prompt('ChoicePrompt', { type: ActivityTypes.Message, channelData: channelData });
    }

helper functions:

function isString(str: any): str is string {
    return typeof str === 'string';
}

function isActivity(obj: any): obj is Activity {
    return obj && obj.text !== undefined;
}

function isChoice(obj: any): obj is Choice {
    return obj && obj.value !== undefined;
}

Called with:

const channel = getChannel(step.context);
        return await channel.prompt(step, 'ChoicePrompt', {
            choices: buttons,
            prompt: this.generateAssetInfoMessage(deviceType),
            retryPrompt: `Sorry, I didn't understand. Please choose one of the following:`,
        });

I expect to see a message with the two buttons but i'm getting an error saying [onTurnError]: Error: Invalid ChannelData Here is the channel data stringifyied

{"text":"","blocks":[{"type":"section","text":{"type":"mrkdwn","text":"Are you using a Mac or PC?"}},{"type":"actions","elements":[{"type":"button","text":{"type":"plain_text","text":"I'm using a Mac"},"value":"I'm using a Mac"},{"type":"button","text":{"type":"plain_text","text":"I'm using Windows"},"value":"I'm using Windows"}]}]}

Solution

  • Unfortunately, you aren't doing anything wrong. We just don't support that, yet.

    I've submitted a Design Change Request so that we can map the payload from channelData to the appropriate Slack API. It's nothing you can do, locally, either, since this relies on the private/secure part of the API.

    Note, however, that once this is implemented, you'll likely add it to your message's channelData like this:

    "channelData": {
       "text": "Now back in stock! :tada:",
       "blocks": [
            [...]
       ]
    

    Edit: You could do this locally, but it would be difficult as you couldn't do it directly with the Bot Framework. You'd have to use Slack's Conversation API inside of your bot. It's possible and you'd have all of the data you'd need except you'd need a new auth token.