Smooch: How to do postback dependent state transition?

后端 未结 3 949
挽巷
挽巷 2021-01-20 19:42

I am trying to transition the script from one state to another based on Smooch postback payloads; but getting error code H12.

Consider the example https://github.com

相关标签:
3条回答
  • 2021-01-20 19:49

    Postbacks won't automatically transition your conversation from one state to the next, you have to write that logic yourself. Luckily the smooch-bot-example you're using already has a postback handler defined here:

    https://github.com/smooch/smooch-bot-example/blob/30d2fc6/heroku/index.js#L115

    So whatever transition logic you want should go in there. You can do this by creating a stateMachine and calling receiveMessage() on it the same way handleMessages() already works. For example:

    const stateMachine = new StateMachine({
        script,
        bot: createBot(req.body.appUser)
    });
    
    stateMachine.receiveMessage({
        text: 'whatever your script expects'
    })
    

    Alternatively, you could have your handlePostback implementation call stateMachine.setState(state) and stateMachine.prompt(state) independently, if you wanted to have your postbacks behave differently from regular text responses.

    0 讨论(0)
  • 2021-01-20 19:55

    I got the same issue with the [object Object] instead of a string. This is because the state you get or set with a function is contained in an object, not a string... I fixed it with this code inside index.js, replacing the existing handlePostback function in the smooch-bot-example GitHub repo:

    function handlePostback(req, res) {
    
    const stateMachine = new StateMachine({
        script,
        bot: createBot(req.body.appUser)
    });
    
    const postback = req.body.postbacks[0];
    if (!postback || !postback.action) {
        res.end();
    };
    
    const smoochPayload = postback.action.payload;
    
    // Change conversation state according to postback clicked
    switch (smoochPayload) {
        case "POSTBACK-PAYLOAD":
            Promise.all([
                stateMachine.bot.releaseLock(),
                stateMachine.setState(smoochPayload), // set new state
                stateMachine.prompt(smoochPayload) // call state prompt() if any
            ]);
            res.end();
        break;
    
        default:
            stateMachine.bot.say("POSTBACK ISN'T RECOGNIZED") // for testing purposes
                .then(() => res.end());
    };
    }
    

    Then inside script.js all you need to do is define states corresponding to the exact postback payloads. If you have multiple postbacks that should take the user to other states, just add them to the case list like so :

    case "POSTBACK-PAYLOAD-1":
    case "POSTBACK-PAYLOAD-2":
    case "POSTBACK-PAYLOAD-3":
    case "POSTBACK-PAYLOAD-4":
    Promise.all([
            stateMachine.bot.releaseLock(),
            stateMachine.setState(smoochPayload), // set new state
            stateMachine.prompt(smoochPayload) // call state prompt() if any
        ]);
        res.end();
    break;
    

    Note that you should not write break; at the end of each case if the outcome you want is the same (here : setting the state and prompting the corresponding message).

    If you want to handle other postbacks differently, you can add cases after the break; statement and do other stuff instead.

    Hope this helps!

    0 讨论(0)
  • 2021-01-20 20:14

    If you want to advance the conversation based on a postback you'll have to first output the buttons from the bot's prompt (so you can handle the button click in the receive), modify the handlePostback function in index.js, then handle the user's "reply" in your receive method - try this - modify script.js like so:

    start: {
        prompt: (bot) => bot.say(`Hi! I'm Smooch Bot! Continue? %[Yes](postback:askName) %[No](postback:bye)`),
        receive: (bot, message) => {
    
          switch(message.text) {
            case 'Yes':
              return bot.say(`Ok, great!`)
                .then(() => 'hi')
              break;
            case 'No':
              return bot.say(`Ok, no prob!`)
                .then(() => 'bye')
              break;
            default:
              return bot.say(`hmm...`)
                .then(() => 'processing')
              break;          
          }
        }
    },
    
    hi: {
        prompt: (bot) => bot.say('Pleasure meeting you'),
        receive: () => 'processing'
    },
    
    bye: {
        prompt: (bot) => bot.say('Pleasure meeting you'),
        receive: () => 'processing'
    },
    

    Then modify the handlePostback function in index.js so that it treats a postback like a regular message:

    function handlePostback(req, res) {
    
        const postback = req.body.postbacks[0];
    
        if (!postback || !postback.action)
            res.end();
    
        const stateMachine = new StateMachine({
            script,
            bot: createBot(req.body.appUser)
        });
    
        const msg = postback;
    
        // if you want the payload instead just do msg.action.paylod
        msg.text = msg.action.text;
    
        stateMachine.receiveMessage(msg)
          .then(() => res.end())
          .catch((err) => {
            console.error('SmoochBot error:', err);
            res.end();
          });
    }
    

    Now when a user clicks your button it will be pushed to the stateMachine and handled like a reply.

    0 讨论(0)
提交回复
热议问题