I create a chat bot using dialogflow and actions on google library. In the back-end code I have created function including if else. I added new suggestions in the "else if". That are not display in the actions on google simulator.Another suggestions are working. Only that time it is not displayed. Please give me some instructions for fixed that.
this is my code:
'use strict';
const functions = require('firebase-functions');
const {
dialogflow,
Suggestions,
Carousel,
Image,
Table,
List,
} = require('actions-on-google');
const app = dialogflow({debug: true});
// Constants for list and carousel selection
const Order_Food = 'order food';
const Extra_Product = 'extra product';
const Spa_Reservation = 'spa reservation';
const Restaurant_Booking = 'restaurant booking';
app.intent('user.provide_room_number', (conv) => {
conv.ask('Great! I can help you with the following. Please select
from the options below.');
//conv.ask(new Suggestions('Order Food', 'Extra Product',
'Restaurant', 'Spa'));
// Create a carousel
conv.ask(new Carousel({
items: {
// Add the first item to the carousel
[Order_Food]: {
synonyms: [
'order food',
'food',
],
title: 'Food',
description: 'Can order some food',
image: new Image({
url: 'http://www.restauranteelpalacete.com/wp-content/uploads/2018/01/Online-Food-Ordering.jpg',
alt: 'Food',
}),
},
// Add third item to the carousel
[Spa_Reservation]: {
synonyms: [
'spa',
'spa reservation',
],
title: 'Spa Reservation',
description: 'Can put the reservation on the spa.',
image: new Image({
url: 'https://res.klook.com/images/fl_lossy.progressive,q_65/c_fill,w_1295,h_720,f_auto/w_80,x_15,y_15,g_south_west,l_klook_water/activities/kykzulvt1t71kwhnmkik/OasisSpa.jpg',
alt: 'Spa',
}),
},
// Add fourth item to the carousel
[Restaurant_Booking]: {
synonyms: [
'restaurant',
'restaurant booking',
],
title: 'Restaurant',
description: 'Can put the reservation on the Restaurant.',
image: new Image({
url: 'https://cdn-image.foodandwine.com/sites/default/files/1501607996/opentable-scenic-restaurants-marine-room-FT-BLOG0818.jpg',
alt: 'Restaurant',
}),
},
},
}));
});
app.intent('actions_intent_OPTION-handler', (conv, params, option) => {
// Get the user's selection
// Compare the user's selections to each of the item's keys
if (!option) {
conv.ask('You did not select any item from the list or carousel');
} else if (option === 'order food') {
conv.ask(new SimpleResponse({speech:"Absolutely, have you decided what you like or you could go through the in room dinning menu. \n Do you need order Food.?",text:"Absolutely, have you decided what you like or you could go through the in room dinning menu. Do you need order Food.?"}));
conv.ask(new Suggestions(["Ok", "Done", "Thanks"]));
} else if (option === 'spa reservation') {
conv.ask(new Suggestions('Yes I need Spa.'));
conv.ask(`We have an excellent Spa that offer exquisite treatment packages. You can select one of the options. We have quite a few free slots today. Do you need information about that.`);
} else if (option === 'restaurant booking') {
conv.ask(`We have some dining options for you today. Do you want more information. `);
conv.ask(new Suggestions('I need restaurant.'));
} else {
conv.ask('You selected an unknown item from the list, or carousel');
}
});
You should design your conversation bot more efficiently.In second elseif condition, after a suggestion no further conversation should happen in an intent.Suggestion are for triggering intent. For your case best scenario would be to create a follow up intent.
Suggestion is not appearing in conversation because, in every rich response at least one simple response should be present. Try below code. Hope this helps you.
conv.ask(new SimpleResponse({speech:"Absolutely, have you decided what you like or you could go through the in room dinning menu. \n Do you need order Food.?",text:"Absolutely, have you decided what you like or you could go through the in room dinning menu. Do you need order Food.?"}));
conv.ask(new Suggestions(["Ok", "Done", "Thanks"]));
Related
I am writing tickets to the system. Reports come to a special channel. There is an "accept" button, it works, but when more than one report arrives, if you click on the "accept" button, then all reports will be accepted
2 reports IMAGE
i clicked one IMAGE
client.on('interactionCreate', async interaction => {
if(interaction.isButton()) {
if (interaction.customId.includes(`acceptB`)) {
myacceptB.edit({embeds:[editEmbRep]})
interaction
let channelx = interaction.guild.channels.cache.get(myreportChannel)
if(channelx){
channelx.permissionOverwrites.edit(interaction.user.id,{ VIEW_CHANNEL: true,SEND_MESSAGES: true,ATTACH_FILES: true,READ_MESSAGE_HISTORY:true })}
Might need to use a unique idButton each time, but I don't know how to check that
This code should only edit the message that the button clicked is attached to. There is no need for unique ID’s for each button when you edit the message the interaction is attached to.
client.on('interactionCreate', async interaction => {
if(interaction.isButton()) {
if (interaction.customId === `acceptB`) {
const editEmbRep = new MessageEmbed()
.setTitle('New Embed')
interaction.message.edit({
content: 'updated text', // to change the text
embeds: [editEmbRep], // to change the embed
components: [] // if you want to remove the button
})
// Not sure what you are trying to do with this part so I didn’t do anything with it.
let channelx = interaction.guild.channels.cache.get(myreportChannel)
if (channelx) {
channelx.permissionOverwrites.edit(
interaction.user.id,
{
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
ATTACH_FILES: true,
READ_MESSAGE_HISTORY:true
}
)
}
}
}
})
When I try to create a carousel dynamically in dialogflow it appears vertically and with two items per row.
This is for a Google assistant application, the actions on Google documentation say that the carousel scrolls horizontally, but I can't make it happen.
for (let i = 0; i < data_JSON.length; i++) {
let name;
let imageurl;
let venue;
name = datosJSON[i].nombre_evento
imageurl = datosJSON[i].nombre_imagen;
venue = name;
items[i] = {
optionInfo: {
key: (i + 1).toString(),
synonyms: name,
},
description: "Imagen "+i,
title: name,
url: imageurl,
image: new Image({
url: imageurl,
alt: venue
}),
}
}
var carrusel = new Carousel({
title: 'Search Items ',
items: items
});
conv.ask(carrusel);
});
I expect in Google assistant only one row which I can scroll horizontally, but I have multiple rows with 2 items per row.
Carousel displays horizontally on smart displays, but uses the 2xN grid on phones.
I have to add multiple buttons on Card or Basic card. Is it possible ?
In dialog flow documentation, its mentioned there is one element buttons which takes array of element. Based on this I have added buttons like:
agent.add(new BasicCard({
title: body.hits.hits[i]._source.name,
formattedText: '',
image: {
url: body.hits.hits[i]._source.images ? body.hits.hits[i]._source.images[0].src : '',
accessibilityText: 'Logo',
},
buttons: [{
title: "Buy",
openUrlAction: {
url: body.hits.hits[i]._source.buy,
}
},{
title: "Add to Cart",
openUrlAction: {
url: body.hits.hits[i]._source.aad_to_card,
}
}
],
}));
But its throws error as below:
throw new Error(`Unknown response type: "${JSON.stringify(response)}"`);
Some places its mentioned buttons takes only one element. So what's the point of making it array ?
A BasicCard can only have one button. That is the current rule. I can't give a good reason on why it is in an array even if it only accepts one element.
I've created a simple Google Assistant interface using DialogFlow with several Carousels that I want to be able to chain together. Whenever I touch a carousel option though, it always goes to the first Intent that has the actions_intent_OPTION event specified. I can get to all of my screens using voice commands, but I'm not sure how to process the touch commands to send the user to right Intent.
Current code in webhook:
const party = 'party';
const cocktail = 'cocktail';
const SELECTED_ITEM_RESPONSES = {
[party]: 'You selected party',
[cocktail]: 'You selected cocktail',
};
function carousel(agent) {
//agent.add(`Item selected`);
app.intent('actions.intent.OPTION', (conv, params, option) => {
let response = 'You did not select any item from the list or carousel';
if (option && SELECTED_ITEM_RESPONSES.hasOwnProperty(option)) {
response = SELECTED_ITEM_RESPONSES[option];
} else {
response = 'You selected an unknown item from the list or carousel';
}
conv.ask(response);
});
}
If I leave the agent.add() line in, then I get "Item selected"... but if I try to use the app.intent code, it says I'm just getting an empty speech response.
I was trying to create 1 intent called CarouselHandler to process all the menu selections. I used the sample code to call the carousel() function when that intent gets hit by the event.
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('CarouselHandler', carousel);
agent.handleRequest(intentMap);
You have several questions in here about using options. Let's try to clear a few things up.
Can I get a different Intent triggered for each option?
No. The way options are reported to Dialogflow is that all options will trigger the same Intent. You're responsible for looking at the option string sent and calling another function if you wish.
As you've noted, you need to create an Intent with the Event actions_intent_OPTION.
Your code to handle this might look something like this, although there are other ways to handle it:
app.intent('list.reply.click', (conv, params, option) => {
// Get the user's selection
// Compare the user's selections to each of the item's keys
if (!option) {
conv.ask('You did not select any item from the list or carousel');
} else if (option === 'OPTION_1') {
handleOption1( conv );
} else if (option === 'OPTION_2') {
handleOption2Or3( conv );
} else if (option === 'OPTION_3') {
handleOption2Or3( conv );
} else {
conv.ask('You selected an unknown item from the list, or carousel');
}
});
Can I get a different Intent triggered for each carousel?
Yes. To do this, when you send the carousel you will set an OutgoingContext and delete any other OutgoingContexts you created for a carousel (set their lifespan to 0). Then you will create an Intent that has this Context as an IncomingContext.
The code to send a carousel might look something like this if you're using the actions-on-google library
conv.ask("Here is menu 2");
conv.ask(new List({
title: "Menu 2",
items: {
"OPTION_1": {
title: "Option 1",
description: "Description 1"
},
"OPTION_2": {
title: "Option 2",
description: "Description 2"
},
"OPTION_3": {
title: "Option 3",
description: "Description 3"
},
}
});
conv.contexts.set("menu_2",99);
conv.contexts.delete("menu_1");
conv.contexts.delete("menu_3");
// Don't forget to add suggestions, too
If you're using the dialogflow-fulfillment library, it would be similar, although there are a few differences:
let conv = agent.conv();
conv.ask("Here is menu 2");
conv.ask(new List({
title: "Menu 2",
items: {
"OPTION_1": {
title: "Option 1",
description: "Description 1"
},
"OPTION_2": {
title: "Option 2",
description: "Description 2"
},
"OPTION_3": {
title: "Option 3",
description: "Description 3"
},
}
});
agent.add(conv);
agent.setContext({name:"menu_1", lifespan:0});
agent.setContext({name:"menu_2", lifespan:99});
agent.setContext({name:"menu_3", lifespan:0});
If you were using multivocal, the response configuration might look something like this:
{
Template: {
Text: "Here is menu 2",
Option: {
Type: "carousel",
Title: "Menu 2",
Items: [
{
Title: "Option 1",
Body: "Description 1"
},
{
Title: "Option 2",
Body: "Description 2"
},
{
Title: "Option 3",
Body: "Description 3"
}
]
}
},
Context: [
{
name: "menu_1",
lifetime: 0
},
{
name: "menu_2",
lifetime: 99
},
{
name: "menu_3",
lifetime: 0
}
]
}
The Intent that would capture this option suggestion might look something like this:
Your code to handle this would be similar as above, except using the different Intent name.
If there are overlapping options between the handlers, they could call the same function that actually does the work (again, as illustrated above).
How can I handle voice and option responses the same way?
AoG, in some cases, will use the voice response to trigger the option. This is what the aliases are for. But even beyond this, if you have Intents that catch phrases from the user and an Intent that works with the Options, all you need to do is have the fulfillment code call the same function.
Why doesn't the code work?
The line
app.intent('actions.intent.OPTION', (conv, params, option) => {
Probably doesn't do what you think it does. Unless this is the name for the Intent in Dialogflow, the string actions.intent.OPTION won't be seen in your handler. It is also how you register an Intent handler with the actions-on-google library.
It also looks like you're mixing the dialogflow-fulfillment library way of registering Intent handlers with the actions-on-google library way of registering Intent handlers through your carousel() function. Don't do this. (This may also be part of the cause about why replies aren't getting back correctly.)
we're testing out CB and part of our requirements is sending messages to Slack.
This tutorial works great, but it'd be helpful if we could specify the source of the build, so we don't have to click in to the message to see what repo/trigger failed/succeeded.
Is there a variable we can pass to the cloud function in the tutorial? I couldn't find helpful documentation.
Ideally, it would be great if CB had an integration/slack GUI that made these options configurable but c'est la vie.
You can add source information to the slack message by adding a new item to the fields list within the createSlackMessage function. You need to make sure title and value are strings.
// createSlackMessage create a message from a build object.
const createSlackMessage = (build) => {
let message = {
text: `Build \`${build.id}\``,
mrkdwn: true,
attachments: [
{
title: 'Build logs',
title_link: build.logUrl,
fields: [{
title: 'Status',
value: build.status
},{
title: 'Source',
value: JSON.stringify(build.source, null, 2)
}]
}
]
};
return message
}
You can find more information on build object here.