简体   繁体   English

如何从外部服务向Google上的操作进行异步调用?

[英]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. 我正在尝试使用actionsdk将Google Home连接到外部聊天机器人。 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. 我有一个API,它接受用户输入并将其通过webhook发送到我的聊天机器人,但是我的聊天机器人做出响应,并以异步方式调用我的API的另一个端点,并且我无法在Google或Google Home上的操作中显示响应。

I create an actionssdkApp. 我创建一个actionsdkApp。

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

My API has 2 endpoints. 我的API有2个端点。 One of them is for actions on google to send user inputs to my chatbot: 其中之一是在Google上执行的操作,用于将用户输入发送到我的聊天机器人:

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. TextFound函数使用webhook将用户输入发送到我的聊天机器人,但是请求未收到响应。 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. 这是我要将答案发送到Google Home的地方。 But I need the conv object to show the answer in google Home, or actions on google, or any other device. 但是我需要conv对象才能在google主页中显示答案,或者在google或任何其他设备上显示操作。

Edit: 编辑:

My textFound function: 我的textFound函数:

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: 从这里,我的api通过messageToBot函数将用户输入发送给我的机器人:

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. 从现在开始,我的机器人不再发送响应,而是使用答案调用我的api的/webhook端点。 But in this function I haven't de conv object and I can't send the answer to google. 但是在此功能中,我没有转换对象,也无法将答案发送给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. 也许有一个uri可以通过我的api在谷歌上与我的项目建立联系。

Typically, Actions on Google works in a request-response way. 通常,Google上的操作以请求-响应的方式工作。 The user says something to the Action, and the Action replies with a response. 用户对操作说了些什么,然后该操作以响应进行回复。 That reply needs to come within about 5 seconds. 该回复大约需要5秒钟。 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. 如果您认为对/ webhook的调用可以很快到达,并且仅在用户说了几句话后才向用户发送消息,则可以让/ webhook将响应保存在该用户的队列中,并使Intent处理程序位于一个循环,检查此队列中是否有要答复的消息-如果在5秒钟内有消息,则用它答复,否则,则需要在5秒钟之前答复。

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. 但是,如果您不能保证将在5秒钟内完成操作,则有两种变通办法可能会根据您的需要而有用。

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. 触发/ webhook endpiont时,您将找到用户并将通知发送给其助手。 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. 在对他们的答复中,您将包括一些音频播放的媒体响应,例如,播放时间为15秒。 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. 您对/ webhook的调用必须将消息放入队列中才能传递给用户。 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. 尝试在5秒内循环处理它也是一种更普遍的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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