Go to specific node depending on button pressed in carousel

Hi,
I’m creating a new bot using botpress.
I tried to make a conditional statement based on a carousel. So, when the user presses “Button1” flow must go to “Node1”. When the user presses “Button2” flow goes to “Node2” and so on.
There are three types of actions in carousel: “open URL”, “say something” and “postback”. I assume, only “postback” suits my case, but I don’t understand how to use it properly.
Could you please show me how to switch nodes depending on button pressed in carousel?

P.S.: I’m using botpress v12.1.3

1 Like

I tried to create hook and set variable, but it didn’t work. Variable is set, but when I get it in the next node it appears empty.

async function action(bp: typeof sdk, event: sdk.IO.IncomingEvent){
/** Your code starts below */

async function setVariableHook() {

    const text = event.payload.payload;
    if (event.type === "payload" && text && text.length && text.includes("=")) {
      const parts = text.split("=");
      let varPath = parts[0].trim();
      if (varPath.startsWith("__") && varPath.endsWith("__")) {
        varPath = varPath.slice(2, varPath.length - 2);
      }
      const varValue = parts[1].trim();

      const varPathParts = varPath.split(".");
      const varType = varPathParts[0];
      const varName = varPathParts[1];

      if (varType === 'bot') {
        const original = await bp.kvs.get(event.botId, 'global');
        await bp.kvs.set(event.botId, 'global', {
          ...original,
          [varName]: varValue
        });
      } else if (varValue === 'null' || varValue === '' || typeof varValue === 'undefined') {
        delete event.state[varType][varName];
      } else {
        event.state[varType][varName] = varValue;
      }
    }
  }

  return setVariableHook()
/** Your code ends here */
}

Hey @titusjaka !

To switch nodes depending on the button pressed in your Carousel, I suggest you use a hook.

Overwrite the after_incoming_middleware/00_dialog_engine.js file with the following contents:

if (event.payload.type === 'postback' && event.payload.payload === 'button1') {
  event.state.temp.clickedButton = 'button1'
}

if (event.payload.type === 'postback' && event.payload.payload === 'button2') {
  event.state.temp.clickedButton = 'button2'
}

Make sure your Carousel will send a postback with value “button1” or “button2”, depending on which button is clicked.

You can then use Transitions on your Carousel Node to transition to another node, based on the value of event.state.temp.clickedButton:

13%20AM

I have included a sample bot here, feel free to import it in your Botpress instance to play around: https://drive.google.com/file/d/1jaT5JWDR4JoZ-D7LO_G0wGFjZdgnzlbZ/view?usp=sharing

Hope this helps!

Hi @spgin,
Thanks a lot for your response.

I have already tried this tactic and failed. Did you try your suggestion? Did it work for you?

I created the following hook data/global/hooks/after_incoming_middleware/setVar.js:

async function setVarHook() {
    if (event.type === "postback") {
      const text = event.payload.payload;
      if (event.payload.type === 'postback' && text && text.length && text.includes("clickedButton: ")) {
        bp.logger.info("DEBUG. Get postback with payload: ", event.payload.payload);
        const varValue = text.split(": ")[1].trim();
        bp.logger.info("DEBUG. Extracted variable value: ", varValue);
        event.state.temp.clickedButton = varValue;
        bp.logger.info("DEBUG. Set variable to temp storge: ", event.state.temp.clickedButton);
      }
    }
  }

  return setVarHook();

I see it works and sets variable in logs:

2019-09-20 18:41:15infoDEBUG. Get postback with payload: clickedButton: card1_button1
2019-09-20 18:41:15infoDEBUG. Extracted variable value: card1_button1
2019-09-20 18:41:15infoDEBUG. Set variable to temp storge: card1_button1
2019-09-20 18:41:30warnJust received a postback event: [object Object]. 
                       To handle these kind of events. you need to create a hook that will process them.
                       Please refer to the documentation here: https://botpress.io/docs/build/code/#hooks
2019-09-20 18:41:30infoDEBUG. Get postback with payload: clickedButton: card2_button1
2019-09-20 18:41:30infoDEBUG. Extracted variable value: card2_button1
2019-09-20 18:41:30infoDEBUG. Set variable to temp storge: card2_button1

But then nothing happens and the following variable is not available in the same node neither in the next one.

I have recorded screencast to demonstrate it: https://youtu.be/L3qZxy2n_C8

I studied the official manual and there is the following article https://botpress.io/docs/main/code#after-incoming-middleware . It says, only bp and event objects are available in after-incoming-middleware hooks. I assume it’s the main reason why the variable is not saved properly.

Is there any workaround for this issue?

Can you export your bot so I can try it locally? That would help me see what’s going on.

Sure,
Here is the exported tarball: https://drive.google.com/open?id=1fbAJ5uIRLvnhVfQ87fr7Mcb7oQXkeOCB
And here is the hook

//path to file <BOTPRESS_ROOT>/data/global/hooks/after_incoming_middleware/setVar.js
async function setVarHook() {
    if (event.type === "postback") {
      const text = event.payload.payload;
      if (event.payload.type === 'postback' && text && text.length && text.includes("clickedButton: ")) {
        bp.logger.info("DEBUG. Get postback with payload: ", event.payload.payload);
        const varValue = text.split(": ")[1].trim();
        bp.logger.info("DEBUG. Extracted variable value: ", varValue);
        event.state.temp.clickedButton = varValue;
        bp.logger.info("DEBUG. Set variable to temp storge: ", event.state.temp.clickedButton);
      }
    }
  }

  return setVarHook();

Thank you for help!

To be honest, I’m totally confused.

I tried to use KVS storage for saving global variables. I understand it’s a bad idea but anyway it didn’t work.

I modified my hook this way:

async function action(bp: typeof sdk, event: sdk.IO.IncomingEvent) {
  /** Your code starts below */

  async function setVarHook() {
    if (event.type === "postback") {
      const text = event.payload.payload;
      if (event.payload.type === 'postback' && text && text.length && text.includes("clickedButton: ")) {
        // save to KVS without path provided
        bp.kvs.set(event.botId, "shark", "very sharp teeth")
        let b = bp.kvs.get(event.botId, "shark");
        bp.logger.info("Shark: ", b);

        // save to KVS with path provided
        bp.kvs.set(event.botId, "shark", "very sharp teeth", "temp.teeth")
        let c = bp.kvs.get(event.botId, "shark", "temp.teeth");
        bp.logger.info("Shark: ", c);
      }
    }
  }

  return setVarHook();
  /** Your code ends here */
}

And this is what I see in logs:

14:00:17.083 Hooks Shark: Promise [Object] {
  _bitField: 67108864,
  _fulfillmentHandler0: undefined,
  _rejectionHandler0:
   Promise [Object] {
     _bitField: 0,
     _fulfillmentHandler0: undefined,
     _rejectionHandler0: undefined,
     _promise0: undefined,
     _receiver0: undefined },
  _promise0: undefined,
  _receiver0: undefined }
14:00:17.085 Hooks Shark: Promise [Object] {
  _bitField: 67108864,
  _fulfillmentHandler0: undefined,
  _rejectionHandler0:
   Promise [Object] {
     _bitField: 0,
     _fulfillmentHandler0: undefined,
     _rejectionHandler0: undefined,
     _promise0: undefined,
     _receiver0: undefined },
  _promise0: undefined,
  _receiver0: undefined }

It looks like botpress either don’t save to storage or don’t extract variable from it.

Hey @titusjaka ! I just tried the chatbot you sent as a tarball. I got it to work:

Just make sure you overwrite the **after_incoming_middleware/channel-web/00_dialog_engine.js** hook:

1 Like

@spgin ,

Thank you very much for help, I found the reason why it didn’t work in a separate file. This was because of the following code:

const messageTypesToDiscard = ['request_start_conversation', 'say_something', 'postback'];

if (messageTypesToDiscard.includes(event.type)) {
  event.setFlag(bp.IO.WellKnownFlags.SKIP_DIALOG_ENGINE, true);

  if (event.type === 'postback') {
    bp.logger.warn(`Just received a postback event: ${event.payload}.
    To handle these kind of events. you need to create a hook that will process them.
    Please refer to the documentation here: https://botpress.io/docs/build/code/#hooks`);
  }
}

I commented it and the bot started working :slight_smile:

1 Like

If you use Messenger there are some different variables. You can try this > `function hook(bp: typeof sdk, event: sdk.IO.IncomingEvent) {

/** Your code starts below */

console.log(event)
console.log(‘payloaddddd’, event.type)
if (event.type === ‘callback’ && event.payload.text === ‘button1’) {
event.state.temp.clickedButton = ‘button1’
}

if (event.type === ‘callback’ && event.payload.text === ‘button2’) {
event.state.temp.clickedButton = ‘button2’
}

/** Your code ends here */
}
`

1 Like