Есть ли способ отправить Быстрые ответы обратно из Fulfillment Webhook?
Я играл с DialogFlow и Fulfillment, но до сих пор я всегда возвращал FulfillmentText из моего webhook обратно в моего бота так:
response = {
fulfillmentText: "Some message!"
};
Есть ли способ вернуть набор опций (быстрые ответы) вместо этого? В основном я хочу вернуть 3 кнопки, по одной для каждого из вариантов a, b и c. Это возможно?
Спасибо!
РЕДАКТИРОВАТЬ:
Мне удалось отправить карту обратно, используя следующий код, но я не могу найти образцы, которые отправляют быстрые ответы, а не карту.
"fulfillmentMessages": [
{
"card": {
"title": "card title",
"subtitle": "card text",
"imageUri": "https://assistant.google.com/static/images/molecule/Molecule-Formation-stop.png",
"buttons": [
{
"text": "button text",
"postback": "https://assistant.google.com/"
}
]
}
}
],
1 ответ
Прошло некоторое время, но этот маленький ярлык сработал для меня на платформе Facebook Messenger, если кто-то все еще ищет его.
const {Suggestion} = require('dialogflow-fulfillment');
agent.add(new Suggestion('Suggestion'));
Вот пример:
fulfillmentMessages: [
{
quickReplies: {
title: 'Hello',
quickReplies: [
'First Reply',
'Second Reply',
],
},
platform: 'FACEBOOK'
},
};
Кроме того, вот трюк:) https://miningbusinessdata.com/how-to-send-any-facebook-messenger-rich-response-from-dialogflow-webhook/
Проверьте сообщения Rich UI из Dialogflow. В зависимости от платформы, которую вы разрабатываете, вы можете показывать быстрые ответы или карточки или другие сообщения Rich UI.
В веб-приложениях и приложениях для мобильных устройств (нативных) вам нужно будет обрабатывать их самостоятельно, передавая флажок того, что вы хотите (кнопка, флажок и т. Д.), И манипулируя текстовым ответом.
ОБНОВИТЬ
При использовании помощника Google вы можете перейти по следующей ссылке https://developers.google.com/actions/assistant/responses
Было бы лучше использовать клиентские библиотеки для разработки Webhooks
Клиент Action-On-Google NodeJS
Dialogflow NodeJS Fulfillment Client
Я сам столкнулся с этой проблемой. Как правило, проблема в том, что создатель card-response.js не предсказал, что кто-то захочет делать быстрые ответы в виде кнопки карты. Замените код в диалоговом потоке выполнения /src/rich-response/card-response.js приведенным ниже кодом. Я просто добавил исключения, поддерживающие отсутствие buttonUrl.
/**
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const {
RichResponse,
PLATFORMS,
SUPPORTED_RICH_MESSAGE_PLATFORMS,
V2_TO_V1_PLATFORM_NAME,
} = require('./rich-response');
/**
* Enum for Dialogflow v1 text message object https://dialogflow.com/docs/reference/agent/message-objects
*/
const v1MessageObjectCard = 1;
/**
* Class representing a card response
* @extends RichResponse
*/
class Card extends RichResponse {
/**
* Constructor for Card object.
*
* @example
*
* @param {string|Object} card response title string or an object representing a card response
*/
constructor(card) {
super();
if (card === undefined || (typeof card === 'object' && !card.title)) {
throw new Error('title string required by Card constructor');
}
if (typeof card === 'string') {
this.title = card;
} else if (typeof card === 'object') {
this.title = card.title;
this.text = card.text;
this.imageUrl = card.imageUrl;
if(card.buttonUrl) {
this.buttonUrl = card.buttonUrl;
}
if(!card.buttonUrl) {
card.buttonUrl = "buffor"
}
if (
(!card.buttonText && card.buttonUrl) ||
(!card.buttonUrl && card.buttonText)
) {
throw new Error('card button requires title or title with link');
}
this.buttonText = card.buttonText;
if (
typeof card.platform !== 'undefined' &&
card.platform !== PLATFORMS.UNSPECIFIED
) {
if (SUPPORTED_RICH_MESSAGE_PLATFORMS.indexOf(card.platform) < 0) {
throw new Error(`Platform '${card.platform}' not supported.`);
} else {
this.platform = card.platform;
}
}
}
}
/**
* Set the title for a Card
*
* @example
* let card = new Card();
* card.setTitle('sample card title')
*
* @param {string} title containing the title content
* @return {Card}
*/
setTitle(title) {
if (typeof title !== 'string') {
throw new Error('setText requires a string of the text');
}
this.title = title;
return this;
}
/**
* Set the text for a Card
*
* @example
* let card = new Card();
* card.setText('sample card body text')
*
* @param {string} text containing the card body text content
* @return {Card}
*/
setText(text) {
if (typeof text !== 'string') {
throw new Error('setText requires a string of the text');
}
this.text = text;
return this;
}
/**
* Set the image for a Card
*
* @example
*
* @param {string} imageUrl
* @return {Card}
*/
setImage(imageUrl) {
if (typeof imageUrl !== 'string') {
throw new Error('setImage requires a string of the image URL');
}
this.imageUrl = imageUrl;
return this;
}
/**
* Set the button for a Card
*
* @example
* let card = new Card();
* card.setButton({
* text: 'button text',
* url: 'https://assistant.google.com/'
* });
*
* @param {Object} button JSON configuration
* @param {Object} options.text button text
* @param {Object} options.url button link URL
* @return {Card}
*/
setButton(button) {
if ((!button.text)) {
throw new Error(
`card button requires button title and url. \
\nUsage: setButton({text: \'button text\', url: \'http://yoururlhere.com\'}`
);
}
this.buttonText = button.text;
if(button.url) {
this.buttonUrl = button.url;
}
return this;
}
/**
* Get the v1 response object for the rich response
* https://dialogflow.com/docs/reference/agent/message-objects
*
* @example
* let richResponse = new RichResponse();
* richResponse.getV1ResponseObject_(PLATFORMS.ACTIONS_ON_GOOGLE)
*
* @param {string} platform desired message object platform
* @return {Object} v1 response object
* @private
*/
getV1ResponseObject_(platform) {
// Check if response is platform specific
if (this.platform && this.platform !== platform) {
// if it is and is not for the specific platform return null
return null;
}
//
let response;
if (platform === PLATFORMS.ACTIONS_ON_GOOGLE) {
// If the platform is Actions on Google use a simple response
response = {
type: 'basic_card',
platform: V2_TO_V1_PLATFORM_NAME[platform],
};
response.title = this.title;
if (!this.text && !this.imageUrl) {
response.formattedText = ' '; // AoG requires text or image in card
}
if (this.text) response.formattedText = this.text;
if (this.imageUrl) {
response.image = {};
response.image.url = this.imageUrl;
response.image.accessibilityText = 'accessibility text';
}
if (this.buttonText) {
response.buttons = [{openUrlAction: {}}];
response.buttons[0].title = this.buttonText;
if(this.buttonUrl) {
response.buttons[0].openUrlAction.url = this.buttonUrl;
}
}
} else {
response = {type: v1MessageObjectCard};
response.title = this.title;
if (this.text) response.subtitle = this.text;
if (this.imageUrl) response.imageUrl = this.imageUrl;
// this is required in the response even if there are no buttons for some reason
if (platform === PLATFORMS.SLACK) response.buttons = [];
if (this.buttonText && this.buttonUrl) {
response.buttons = [];
response.buttons[0] = {};
response.buttons[0].text = this.buttonText;
if(this.buttonUrl) {
response.buttons[0].postback = this.buttonUrl;
}
}
// response is the same for generic responses without the platform attribute
// if the platform is not undefined or the platform is not unspecified
if (SUPPORTED_RICH_MESSAGE_PLATFORMS.indexOf(platform) > -1) {
response.platform = V2_TO_V1_PLATFORM_NAME[platform];
}
}
return response;
}
/**
* Get the v2 response object for the rich response
* https://dialogflow.com/docs/reference/api-v2/rest/v2beta1/projects.agent.intents#Message
*
* @example
* let richResponse = new RichResponse();
* richResponse.getV2ResponseObject_(PLATFORMS.ACTIONS_ON_GOOGLE)
*
* @param {string} platform desired message object platform
* @return {Object} v2 response object
* @private
*/
getV2ResponseObject_(platform) {
// Check if response is platform specific
if (this.platform && this.platform !== platform) {
// if it is and is not for the specific platform return null
return null;
}
let response;
if (platform === PLATFORMS.ACTIONS_ON_GOOGLE) {
// If the platform is Actions on Google use a basic card response
response = {basicCard: {}};
response.basicCard.title = this.title;
response.platform = PLATFORMS.ACTIONS_ON_GOOGLE;
if (this.text) response.basicCard.formattedText = this.text;
if (this.imageUrl) {
response.basicCard.image = {};
response.basicCard.image.imageUri = this.imageUrl;
response.basicCard.image.accessibilityText = 'accessibility text';
}
if (this.buttonText && !this.buttonUrl) {
response.basicCard.buttons = [{
title: this.buttonText
}];
}
if (this.buttonText && this.buttonUrl) {
response.basicCard.buttons = [{
title: this.buttonText,
openUriAction: {
uri: this.buttonUrl,
},
}];
}
} else {
response = {card: {}};
response.card.title = this.title;
if (this.text) response.card.subtitle = this.text;
if (this.imageUrl) response.card.imageUri = this.imageUrl;
if (this.buttonText && !this.buttonUrl) {
response.card.buttons = [];
response.card.buttons[0] = {};
response.card.buttons[0].text = this.buttonText;
}
if (this.buttonText && this.buttonUrl) {
response.card.buttons = [];
response.card.buttons[0] = {};
response.card.buttons[0].text = this.buttonText;
response.card.buttons[0].postback = this.buttonUrl;
}
// response is the same for generic responses without the platform attribute
// if the platform is not undefined or the platform is not unspecified
if (SUPPORTED_RICH_MESSAGE_PLATFORMS.indexOf(platform) > -1) {
response.platform = platform;
}
}
return response;
}
}
module.exports = Card;