如何从外部服务异步调用 google 上的操作?

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

我正在尝试使用 actionssdk 将 Google 主页连接到外部聊天机器人。我有一个 API 接受用户输入并使用 webhook 将它们发送到我的聊天机器人,但我的聊天机器人做出响应以异步方式调用我的 API 的另一个端点,我无法显示响应在 Google 或 Google 主页上的操作中。

我创建了一个actionssdkApp。

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

我的 API 有 2 个端点。其中之一是针对 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 函数使用 webhook 将用户输入发送到我的聊天机器人,但请求没有收到响应。我的聊天机器人用文本答案调用另一个端点:

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);
});

这里是我要将答案发送到 Google 主页的地方。但我需要 conv 对象在 google 主页中显示答案,或在 google 或任何其他设备上显示操作。

编辑:

我的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");
        }
    });

从这里我的 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);
        }
    }
}); 

从现在开始,我的机器人不会发送响应,而是会调用 api 的 /webhook 端点并提供答案。但是在这个函数中我没有 de conv 对象,我不能将答案发送到 google。我不知道如何访问这个对象。也许有一个 uri 可以连接到我的 google 上的项目,来自我的 api。

通常,Google 上的操作以请求-响应方式工作。用户对 Action 说了些什么,Action 回复了一个响应。该回复需要在大约 5 秒内到达。如果您认为对 /webhook 的调用可以那么快,并且您只会在用户说些什么后向用户发送消息,您可以让 /webhook 将响应保存在用户的队列中,并让您的 Intent 处理程序在一个循环,检查此队列中是否有任何要回复的消息 - 如果 5 秒内有消息,你就回复它,如果没有,你需要在 5 秒结束之前回复。

如果您不能保证它会在 5 秒内完成,但是,根据您的需要,有一些可能有用的解决方法。

首先是您可以使用 notifications。在这种情况下,您将发送来自用户的消息,然后关闭对话。当你的 /webhook endpiont 被触发时,你会找到用户并将通知发送给他们的助手。不幸的是,这有点笨重,不会导致非常互动的聊天系统,并且智能扬声器也不支持通知。

您还可以考虑使用 Media Response 来设置一种方法,以便您定期轮询新消息。在此方案下,您的用户将发送他们的消息。在您对他们的回复中,您会为某些播放了 15 秒的音频添加媒体响应。当音频结束时,您的 Action 将再次被调用,您可以检查是否有任何消息排队等待发送给用户。如果是这样,您将转发这些消息,然后是媒体响应增益。否则,只需发送媒体响应。您对 /webhook 的调用必须将消息放入队列中以传递给用户。这更复杂,尤其是在规模上,但可以使其更具交互性。这也是一个更一般的情况,试图在 5 秒内循环处理它。