简体   繁体   中英

How to make asynchronous calls from external services to actions on google?

I'm trying to connect Google Home to an external chatbot with actionssdk. I have an API that take user inputs and send them to my chatbot with webhook, but my chatbot make a response calling another endpoint of my API in an async way, and I can't show the response in actions on Google or Google Home.

I create an actionssdkApp.

const {
  actionssdk,
  SimpleResponse,
  Image,
} = require('actions-on-google');
var app = actionssdk();
var express_app = express();

My API has 2 endpoints. One of them is for actions on google to send user inputs to my chatbot:

app.intent('actions.intent.MAIN', conv => {
  console.log('entra en main');
  conv.ask('Hi, how is it going?');
});

app.intent('actions.intent.TEXT', (conv, input) => {
  var userId = conv.body.user.userId;
  console.log(userId);

  if(userId && input){
    textFound(conv, input, userId);
  }else{
    textnotFound(conv);
  }
});

TextFound function send user inputs to my chatbot with webhook, but the request doesn't receive the response. My chatbot call another endpoint with the text answer:

express_app.post('/webhook', bodyParser.json(), (req, res)=>{
  console.log("Webhook");
  const userId = req.body.userId;
  if (!userId) {
    return res.status(400).send('Missing User ID');
  }
  console.log(req.body);
  res.sendStatus(200);
});

And here is where I want to send the answer to Google Home. But I need the conv object to show the answer in google Home, or actions on google, or any other device.

Edit:

My textFound function:

webhook.messageToBot(metadata.channelUrl, metadata.channelSecretKey, userId, input, function(err){
        if(err){
            console.log('Error in sending message');
            conv.ask("Error in sending message");
        }else{
            conv.ask("some text");
        }
    });

From here my api send user inputs to my bot through messageToBot function:

request.post({
    uri: channelUrl,
    headers: headers,
    body: body,
    timeout: 60000,
    followAllRedirects: true,
    followOriginalHttpMethod: true,
    callback: function(err, res, body) {
        if (err) {                    
            console.log('err: '+err);
            callback(err);
        } else {
            console.log('Message sent');
            callback(null);
        }
    }
}); 

From now on, my bot doesn't send a response but makes a call to /webhook endpoint of my api with the answer. But in this function I haven't de conv object and I can't send the answer to google. I don't know how to access to this object. Maybe there is an uri to connect with my project in actions on google from my api.

Typically, Actions on Google works in a request-response way. The user says something to the Action, and the Action replies with a response. That reply needs to come within about 5 seconds. If you think the call to /webhook can come that quickly, and you will only deliver a message to the user after they say something, you can have /webhook save the response in a queue for the user, and have your Intent handler be in a loop that checks this queue for any messages to reply with - if there is a message within 5 seconds, you reply with it, if not, you need to reply before the 5 seconds are up.

If you can't guarantee it will be done within 5 seconds, however, there are a couple of workarounds that might be useful depending on your needs.

The first is that you might be able to use notifications . In this scenario, you would send the message from the user and then close the conversation. When your /webhook endpiont is triggered, you would locate the user and send the notification to their Assistant. Unfortunately, this is a bit bulky, doesn't lead to a very interactive chat system, and notifications also aren't supported on smart speakers.

You can also look into using a Media Response to set up a way for you to poll for new messages periodically. Under this scheme, your user would send their message. In your reply to them, you would include a Media Response for some audio that plays for, say, 15 seconds. When the audio finishes, your Action will be called again and you can check to see if any messages have been queued up to be delivered to the user. If so, you relay those messages, followed by a Media Response gain. Otherwise, just send a Media Response. Your call to /webhook would have to put messages in a queue to be delivered to the user. This is more complex, especially to scale, but can be made more interactive. It is also a more general case of trying to handle it in a loop inside 5 seconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM