Как совершать асинхронные звонки из внешних сервисов на действия в гугле?

Я пытаюсь подключить Google Home к внешнему чат-боту с помощью actionssdk. У меня есть API, который принимает пользовательские входные данные и отправляет их в мой чат-бот с помощью webhook, но мой чат-бот отвечает асинхронно, вызывая другую конечную точку моего API, и я не могу показать ответ в действиях в Google или Google Home.

Я создаю 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 Home. Но мне нужен объект conv, чтобы показать ответ в Google Home, или действия в 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);
        }
    }
}); 

С этого момента мой бот не отправляет ответ, а звонит /webhook Конечная точка моего API с ответом. Но в этой функции у меня нет объекта de conv, и я не могу отправить ответ в Google. Я не знаю, как получить доступ к этому объекту. Может быть, есть URI для подключения к моему проекту в действиях на Google из моего API.

1 ответ

Решение

Как правило, действия в Google работают в режиме запрос-ответ. Пользователь что-то говорит Действию, и Действие отвечает ответом. Этот ответ должен прийти в течение 5 секунд. Если вы считаете, что вызов /webhook может происходить так быстро, и вы доставите сообщение пользователю только после того, как он что-то скажет, вы можете /webhook сохранить ответ в очереди для пользователя, и ваш обработчик Intent будет в цикл, который проверяет эту очередь на наличие сообщений для ответа - если в течение 5 секунд есть сообщение, вы отвечаете им, если нет, вам нужно ответить до истечения 5 секунд.

Если вы не можете гарантировать, что это будет сделано в течение 5 секунд, однако, есть несколько обходных путей, которые могут быть полезны в зависимости от ваших потребностей.

Во-первых, вы можете использовать уведомления. В этом случае вы отправите сообщение от пользователя, а затем закроете диалог. Когда ваш /webhook endpiont запущен, вы должны найти пользователя и отправить уведомление его помощнику. К сожалению, это немного громоздко, не приводит к очень интерактивной системе чата, а уведомления на интеллектуальных колонках также не поддерживаются.

Вы также можете использовать Media Response, чтобы настроить периодический опрос новых сообщений. По этой схеме ваш пользователь отправит свое сообщение. В своем ответе на них вы включили бы Media Response для некоторого звука, который воспроизводится, скажем, в течение 15 секунд. Когда аудио закончится, ваше Действие будет вызвано снова, и вы можете проверить, были ли какие-либо сообщения поставлены в очередь для доставки пользователю. Если это так, вы ретранслируете эти сообщения, после чего получаете усиление Media Response. В противном случае просто отправьте медиа-ответ. Ваш вызов /webhook должен был бы поместить сообщения в очередь для доставки пользователю. Это сложнее, особенно в масштабе, но можно сделать более интерактивным. Это также более общий случай попытки обработать его в цикле за 5 секунд.

Другие вопросы по тегам