Dialogflow #vitalets/google-translate-api Translation not working - node.js

I am using firebase and my translation doesn't working :(
I am not getting any response from it but other functions are working fine
here is my index.js
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const translate = require('#vitalets/google-translate-api');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
function addTwoNo(agent) {
const sno = agent.parameters['sno'];
const fno = agent.parameters['fno'];
var sum = sno + fno ;
agent.add(`Sum is `+sum)
}
function tratext(agent) {
const text = agent.parameters['text'];
const lto = agent.parameters['lang-to'];
const lfrom = agent.parameters['lang-from'];
const ltoLen = lto.length > 0;
const lfromLen = lfrom.length > 0;
if(ltoLen){
translate(agent.text, {to: lto}).then(res => {
agent.add(res.text);
}).catch(err => {
console.error(err);
});
} else {
translate(agent.text, {to: 'en'}).then(res => {
agent.add(res.text);
}).catch(err => {
console.error(err);
});
}
translate(agent, {to: 'en'}).then(res => {
console.log(res.text);
//=> I speak English
console.log(res.from.language.iso);
//=> nl
}).catch(err => {
console.error(err);
});
}
// // Uncomment and edit to make your own intent handler
// // uncomment `intentMap.set('your intent name here', yourFunctionHandler);`
// // below to get this function to be run when a Dialogflow intent is matched
// function yourFunctionHandler(agent) {
// agent.add(`This message is from Dialogflow's Cloud Functions for Firebase editor!`);
// agent.add(new Card({
// title: `Title: this is a card title`,
// imageUrl: 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png',
// text: `This is the body text of a card. You can even use line\n breaks and emoji! 💁`,
// buttonText: 'This is a button',
// buttonUrl: 'https://assistant.google.com/'
// })
// );
// agent.add(new Suggestion(`Quick Reply`));
// agent.add(new Suggestion(`Suggestion`));
// agent.setContext({ name: 'weather', lifespan: 2, parameters: { city: 'Rome' }});
// }
// // Uncomment and edit to make your own Google Assistant intent handler
// // uncomment `intentMap.set('your intent name here', googleAssistantHandler);`
// // below to get this function to be run when a Dialogflow intent is matched
// function googleAssistantHandler(agent) {
// let conv = agent.conv(); // Get Actions on Google library conv instance
// conv.ask('Hello from the Actions on Google client library!') // Use Actions on Google library
// agent.add(conv); // Add Actions on Google library responses to your agent's response
// }
// // See https://github.com/dialogflow/fulfillment-actions-library-nodejs
// // for a complete Dialogflow fulfillment library Actions on Google client library v2 integration sample
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('addTwoNo', addTwoNo);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('tratext',tratext)
// intentMap.set('your intent name here', yourFunctionHandler);
// intentMap.set('your intent name here', googleAssistantHandler);
agent.handleRequest(intentMap);
});
and here is my package.json
{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "10"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "^0.5.0",
"#vitalets/google-translate-api": "^4.0.0"
}
}
I am using pay to go firebase
i tested using addTwoNo function and it is working but translate doesn't
I hope I get some help

It seems that, under your tratext function(agent), you are translating the "agent" instead of the "agent.text". You could try as following:
translate(agent.text, {to: 'en'}).then(res => {
console.log(res.text);
//=> I speak English
console.log(res.from.language.iso);
//=> nl
}).catch(err => {
console.error(err);
});
Also, in order to discard any issue with the translate api authentication, you could debug the translate api by translating a dummy text. I suggest you to try using this code snippet and verify the logs generated:
translate("Hola mundo", {to: 'en'}).then(res => {
console.log(res);
}).catch(err => {
console.error(err);
});
Finally, I found a github repository where a user shared a code snippet for translating text using the dialogflow fulfillment under NodeJS, that you may use for reference.

Related

Webhook stopped working. Has there been a deprication or requirements change?

I'm revisiting a Dialogflow Essentials app set up a few years ago that suddenly stopped working at the webhook calls. The URLs that respond to the webhooks are still functioning perfectly. Has there been a change in webhook requirements or a Google deprication that might account for this?
The "help" and "goodbye" functions internal to the app are still working, but when a webhook call is executed we get a reply that the app "isn't responding right now. Please try again soon." and the app leaves the conversation.
The relevant code is NodeJS version 8 (which should still be functional, though depricated) and is applied using the Inline Editor within Dialogflow. Here are the functions:
function get_keywords(agent) {
const keywords = agent.parameters.keywords;
const site_id = agent.parameters.site_id;
return axios.get(`https://www.FutureOfNews.com/AdEverywhere/SI/PR/AN/GA_API/StorySummary_API.cfm?SiteID=${site_id}&Keywords=${keywords}`)
.then((result) => {
console.log(result.data);
if (response.statusCode != 200) {
agent.add(`Error. Could not connect to news server.`);
} else {
if (result.data.storyFound.length < 1) {
agent.add(result.data.speech);
} else {
if (result.data.storyPhotoURL.length > 1) {
agent.add(result.data.speech);
agent.add(new Card({
title: result.data.storyHeadline,
imageUrl: result.data.storyPhotoURL,
buttonText: 'Full Story',
buttonUrl: result.data.storyURL,
imageDisplayOptions: "WHITE"
}));
} else {
agent.add(result.data.speech);
agent.add(new Card({
title: result.data.storyHeadline,
buttonText: 'Full Story',
buttonUrl: result.data.storyURL,
imageDisplayOptions: "WHITE"
}));
}
}
}
});
}
function get_rss_feed_id(agent) {
const rss_feed_id = agent.parameters.rss_feed_id;
const site_id = agent.parameters.site_id;
return axios.get(`https://www.FutureOfNews.com/AdEverywhere/SI/PR/AN/GA_API/NewsHeadlines_API.cfm?SiteID=${site_id}&RSSFeedID=${rss_feed_id}`)
.then((result) => {
agent.add(result.data.speech);
});
}
Here are versions of the URLs called by the webhooks (with real/live parameter values):
Headlines Group
Specific news item
I'm not seeing any activity in logs relating to these calls, and I see no billing/credit-card issues.
Any thoughts on why this is suddenly failing would be greatly appreciated!
I cannot create a NodeJS 8 environment since it is already deprecated. Instead, I tested your code in NodeJS 10 and it works fine for me.
For testing, I used an intent that is triggered with "Test" and I hard coded values for keywords,site_id,rss_feed_id. And it returned the expected result from the code.
Code used for testing:
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card} = require('dialogflow-fulfillment');
const axios = require('axios');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
function yourFunctionHandler(agent) {
const keywords = 'investigation';
const site_id = 15;
return axios.get(`https://www.FutureOfNews.com/AdEverywhere/SI/PR/AN/GA_API/StorySummary_API.cfm?SiteID=${site_id}&Keywords=${keywords}`)
.then((result) => {
console.log(result.data);
if (response.statusCode != 200) {
agent.add(`Error. Could not connect to news server.`);
} else {
if (result.data.storyFound.length < 1) {
agent.add(result.data.speech);
} else {
if (result.data.storyPhotoURL.length > 1) {
agent.add(result.data.speech);
agent.add(new Card({
title: result.data.storyHeadline,
imageUrl: result.data.storyPhotoURL,
buttonText: 'Full Story',
buttonUrl: result.data.storyURL,
imageDisplayOptions: "WHITE"
}));
} else {
agent.add(result.data.speech);
agent.add(new Card({
title: result.data.storyHeadline,
buttonText: 'Full Story',
buttonUrl: result.data.storyURL,
imageDisplayOptions: "WHITE"
}));
}
}
}
});
}
function get_rss_feed_id(agent) {
const rss_feed_id = 1;
const site_id = 15;
return axios.get(`https://www.FutureOfNews.com/AdEverywhere/SI/PR/AN/GA_API/NewsHeadlines_API.cfm?SiteID=${site_id}&RSSFeedID=${rss_feed_id}`)
.then((result) => {
agent.add(result.data.speech);
});
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('test intent', yourFunctionHandler);
//intentMap.set('test intent', get_rss_feed_id);
agent.handleRequest(intentMap);
});
Package.json:
{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "10"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"firebase-functions": "^2.0.2",
"firebase-admin": "^5.13.1",
"googleapis": "^27.0.0",
"actions-on-google": "2.2.0",
"dialogflow-fulfillment": "0.6.1",
"axios": "0.21.1"
}
}
Test using get_keywords():
Test using get_rss_feed_id():
What I could suggest is to upgrade to NodeJS 10 to ensure that the function is on a supported version of Node.js. See migration guide.

Scope of Response of API after function call in node.js

Post API format
{
"first_name": "sakshi",
"last_name":"agrawal",
"username":"sakshiagrawallllllll",
"is_active":"1"
}
Response from POST API
If the user is already registered, then this will be the format of response.
{
"code": 404,
"message": "User Already In Database"
}
If user is not registered, then this will be response.
{
"code": 200,
"message": {
"first_name": "sakshi",
"last_name": "agrawal",
"username": "sakshiagrawallllllll",
"is_active": "1",
"updated_at": "2021-08-31T06:37:24.536000Z",
"created_at": "2021-08-31T06:37:24.536000Z",
"_id": "612dce240e357825b00182d2"
},
"count": "",
"data": ""
}
index.js Code
'use strict';
// Import the Dialogflow module from the Actions on Google client library.
const { dialogflow } = require('actions-on-google');
const functions = require('firebase-functions');
// Instantiate the Dialogflow client.
const app = dialogflow({ debug: true });
const axios = require('axios');
global.username='';
global.firstname='';
global.lastname='';
global.sessionId=0;
global.flag=0;
global.code=[];
global.sid=[];
global.ques=[];
global.response='';
global.res='';
global.data='';
global.rs = '';
global.resp=[];
global.reply = '';
app.intent('Default Welcome Intent', (conv) => {
conv.add("Welcome to Smart Evaluation world’s largest database of evaluations and interview questions. Are you a registered user ?");
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function welcome(agent) {
const sessionVars = {
'userLang': 'en', // possibilites handled - 'en', 'hi'
'words': [],
'questions': [],
'currentIndexPosition': 0,
'score': 0,
};
const sessionContext = { 'name': KEY_SESSION, 'lifespanCount': 100000, 'parameters': sessionVars };
agent.setContext(sessionContext);
let sessionId = agent.session;
conv.add(sessionId);
sessionId=0;
}
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
agent.handleRequest(intentMap);
});
});
app.intent('Non-Registered User', (conv) => {
console.log(JSON.stringify(conv));
var userreply = conv.body.queryResult.queryText;
if (userreply == "no")
{
conv.ask("In order to register you I will ask you a series of questions, please give honest feedback. Let’s begin. What is your first name? ");
flag=0;
}
else if (userreply == "yes")
{
conv.ask("Welcome back, let’s get you authorized. What is your first name?");
}
});
app.intent('LastNameIntent', (conv) => {
firstname = conv.parameters.any;
conv.ask("What is your last name?" );
});
app.intent('UserNameIntent', (conv) => {
lastname = conv.parameters.any;
conv.ask("What is your user name?" );
});
app.intent('SecurityQuestionIntent', (conv) => {
var reply;
username = conv.parameters.any;
conv.ask("Thank you" + firstname + lastname + username);
if(flag == 0)
{
async function makePostRequest() {
var payload = {
"first_name": firstname,
"last_name": lastname,
"username": username,
"is_active": "1"
};
console.log(payload);
let res = await axios.post('API', payload, {
headers: { 'Content-Type' : 'application/json'}
})
/*(error) => {
console.log(error);
});*/
console.log("Response of data code is" + res.data.code);
reply = res.data.code;
console.log("Reply is " + reply);
return reply;
}
reply = makePostRequest();
console.log("Reply after method is" + reply);
conv.ask(reply);
}
});
// Set the DialogflowApp object to handle theif() HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
package.json
{
"name": "dialogflowFirebaseFulfillments",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "10"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillments",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillments",
"logs": "firebase functions:log"
},
"dependencies": {
"actions-on-google": "^2.4.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "^0.6.0",
"axios": "0.18.0",
"aws-sdk": "2.696.0",
"multivocal": "0.15.2",
"express-session": "1.17.1"
}
}
As I'm trying to access "reply" variable outside the function, I'm getting [object Promise] while that is being printed well if tried to print inside the function.
How can I access the variable "reply" outside the function. Can someone please help me?
This is a matter of async function. It returns promise object (refrence):
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
As makePostRequest is async function there is a need to use some asynchornous construction, like than or await, to get the results.
I think the easiest should be to correct reply assignment and flowing lines to :
EDIT:
return statment added to aviod Error: No rersponse has been sent
return makePostRequest().then(reply => {
console.log("Reply after method is" + reply);
conv.ask(reply);
})

Agent unable to print all results received from Axion library request in Dialogflow

I'm trying to print all results received from the following request (this code not working):
function searchForProducts(agent) {
// category_name = 'Cooking' for example
const category_name = agent.parameters.category_name;
return new Promise((resolve, reject) => {
axios.get(`https://sheetdb.io/api/v1/qvlk728a5p23g/search?Categories=*${category_name}*&Status=1`).then(function (res) {
let Categories = res.data[0];
if (Categories) {
for(var i=0;i<res.data.length;i++){
agent.add(`https://alaswadtrading.com/index.php?route=product/product&product_id=${Categories.ProductID}\n\n${Categories.Name}`);
}
} else {
agent.add(`No items found in the selected category (${category_name})`);
}
resolve();
});
});
}
The problem I'm facing is the agent can only print on result through the following code (this record working but return only one URL):
function searchForProducts(agent) {
const category_name = agent.parameters.category_name;
return new Promise((resolve, reject) => {
axios.get(`https://sheetdb.io/api/v1/qvlk728a5p23g/search?Categories=*${category_name}*&Status=1`).then(function (res) {
let Categories = res.data[0];
if (Categories) {
agent.add(`https://alaswadtrading.com/index.php?route=product/product&product_id=${Categories.ProductID}\n\n${Categories.Name}`);
} else {
agent.add(`No items found in the selected category (${category_name})`);
}
resolve();
});
});
}
What I'm doing wrong?
============ After Applying Proposed Solution ================
Hello, since yesterday I'm testing but with no luck to get the exact problem. Here what I did:
I created new Intent which will trigger your code once "Test" received.
I have test the code using different ways, and here the result:
Category_Name = “Cooking”:
- Dialogflow Agent Test: Worked (https://imgur.com/sov6Th5).
- Web Agent Test: Not Worked (https://imgur.com/15qxgdR).
- Dialogflow Web Messenger: Worked (https://imgur.com/5ajzd2j).
- Twilio: Not Worked (https://imgur.com/fsrYtDG) and error message was (https://imgur.com/jP6TRbZ).
But, when I changed the Category_Name = “Small%20Appliances”:
- Dialogflow Agent Test: Worked (https://imgur.com/undefined).
- Web Agent Test: Worked (https://imgur.com/undefined).
- Dialogflow Web Messenger: Worked (https://imgur.com/rCn8ksT).
- Twilio: Worked (https://imgur.com/kfXGqTf).
Here a link for web test (I will keep Category_name=’Cooking’) so you can see the result:
https://bot.dialogflow.com/004077c2-d426-472c-89f0-4997e2955d59
What do you think?
Using your code above I was able to loop through agent.add() and got the results. I used test as user input that matches intent "test intent".
Here is a snippet of the 29 similar outputs of your code provided:
Here is the full code:
index.js
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const axios = require('axios');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
function yourFunctionHandler(agent) {
const category_name = 'Cooking';
return new Promise((resolve, reject) => {
axios.get(`https://sheetdb.io/api/v1/qvlk728a5p23g/search?Categories=*${category_name}*&Status=1`).then(function (res) {
console.log(res.data);
let Categories = res.data[0];
if (Categories) {
for(var i=0;i<res.data.length;i++){
agent.add(`https://alaswadtrading.com/index.php?route=product/product&product_id=${Categories.ProductID}\n\n${Categories.Name}`);
}
} else {
agent.add(`No items found in the selected category (${category_name})`);
}
resolve();
});
});
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('test intent', yourFunctionHandler);
agent.handleRequest(intentMap);
});
package.json
{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "10"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"firebase-functions": "^2.0.2",
"firebase-admin": "^5.13.1",
"googleapis": "^27.0.0",
"actions-on-google": "2.2.0",
"dialogflow-fulfillment": "0.6.1",
"axios": "0.21.1"
}
}
Just a suggestion, since your objective is to show all products under a certain "category" you might want to loop through the whole res.data. In this example I just used category_name = 'Cooking' and printed all products that is under the specified category.
function yourFunctionHandler(agent) {
const category_name = 'Cooking';
return new Promise((resolve, reject) => {
axios.get(`https://sheetdb.io/api/v1/qvlk728a5p23g/search?Categories=*${category_name}*&Status=1`).then(function (res) {
let Categories = res.data;
if (Categories) {
for (const product of Categories ){
agent.add(`https://alaswadtrading.com/index.php?route=product/product&product_id=${product.ProductID}\n\n${product.Name}`);
}
} else {
agent.add(`No items found in the selected category (${category_name})`);
}
resolve();
});
});
}
This will result to:

First alexa skill

I am trying to develop my first Alexa skill using Node.js, and every time I try to test it I get "There was a problem with the requested skill's response".
I am trying create a random restaurant generator. Pretty simple its an array of restaurants, a random index is selected, and Alexa says the restaurant. I don't know where I went wrong I have uploaded my .json and .js files if anyone can help i'd really appreciate it.
index.js:
const Alexa = require('alexa-sdk');
const APP_ID = 'amzn1.ask.skill.9350e65b-fb41-48ce-9930-98b5156eb63c';
const handlers = {
'LaunchRequest': function () {
this.emit('randomRestaurantGeneratorIntent');
},
'randomRestaurantGeneratorIntent': function () {
var randomResturant;
var foodArray = ['IHOP', 'Dennys', 'burger king'];
randomResturant = foodArray[Math.floor(Math.random() * foodArray.length)];
this.response.speak(randomResturant);
this.emit(':responseReady');
},
'AMAZON.HelpIntent': function () {
const say = 'You can say what did I learn, or, you can say exit... How can I help you?';
this.response.speak(say).listen(say);
this.emit(':responseReady');
},
'AMAZON.CancelIntent': function () {
this.response.speak('Bye!');
this.emit(':responseReady');
},
'AMAZON.StopIntent': function () {
this.response.speak('Bye!');
this.emit(':responseReady');
}
};
exports.handler = function (event, context, callback) {
const alexa = Alexa.handler(event, context, callback);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
randomResturantGeneratorIntent.JSON:
{
"interactionModel": {
"languageModel": {
"invocationName": "random restaurant generator",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "randomRestaurantGeneratorIntent",
"slots": [],
"samples": [
"Launch Random Restaurant Generator "
]
}
],
"types": []
}
}
}
Thank you
Try this way to render responses.
var speechOutput = 'Your response here';
var reprompt = "How can I help?";
this.response.speak(speechOutput);
this.response.listen(reprompt);
this.emit(":responseReady");
Try this function in inline editor for your first skill. and try to test with open random restaurant generator,
/**
* Called when the user launches the skill without specifying what they want.
*/
function onLaunch(launchRequest, session, callback) {
console.log(`onLaunch requestId=${launchRequest.requestId}, sessionId=${session.sessionId}`);
// Dispatch to your skill's launch.
getWelcomeResponse(callback);
}
function buildResponse(sessionAttributes, speechletResponse) {
return {
version: '1.0',
sessionAttributes,
response: speechletResponse,
};
}
function getWelcomeResponse(callback) {
// If we wanted to initialize the session to have some attributes we could add those here.
const sessionAttributes = {};
const cardTitle = 'Welcome';
const speechOutput = 'Welcome to Your First Alexa Skill';
// If the user either does not reply to the welcome message or says something that is not
// understood, they will be prompted again with this text.
const repromptText = 'Please tell me What do you want to know?';
const shouldEndSession = false;
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
return {
outputSpeech: {
type: 'PlainText',
text: output,
},
//For testing purpose only
// card: {
// type: 'Simple',
// title: `SessionSpeechlet - ${title}`,
// content: `SessionSpeechlet - ${output}`,
// },
reprompt: {
outputSpeech: {
type: 'PlainText',
text: repromptText,
},
},
shouldEndSession,
};
}
exports.handler = (event, context, callback) => {
try {
console.log(`event.session.application.applicationId=${event.session.application.applicationId}`);
if (event.request.type === 'LaunchRequest') {
onLaunch(event.request,
event.session,
(sessionAttributes, speechletResponse) => {
callback(null, buildResponse(sessionAttributes, speechletResponse));
});
}
}
catch (err) {
callback(err);
}
};
I’ve been using lambda for two years and it’s terrible to debug and deploy for me until I started to use aws cloud9.
I suggest that you use aws cloud9 which is a cloud IDE for writing, running and debugging code. You could run the lambda function as local environment.
Check their website to get more information. It’s time consuming, but totally worth it, especially if you want to develop an Alexa skill.
Most of the times you get that error for 2 things:
You don't have the trigger "Alexa Skill Kit" in your lambda function. If you don't have it, you can add one in the designer tab of the configuration of the lambda function.
You don't have the neccesary modules in your lambda function. You can add them locally with "npm install ask-sdk-core" and then upload the folder.
Use this way:
var speechOutput = 'Your response here';
var reprompt = "How can I help?";
this.response.speak(speechOutput);
this.response.listen(reprompt);
this.emit(":responseReady");

Cannot read property 'parameters' of undefined while passing Context - Actions on Google

Currently I am trying to develop an action.
I am trying to achieve to reuse an intent. Concretely said, it means that the Assistant shall give me the first three items of a list and if I ask for more, then it should give me the next three items of the list.
I implemented the logic, which is locally working but sadly I always got the first three items from the list. Therefore i tried using a context, where I want to pass the index as a parameter and here i am running into the problem. The cloud function logs always gives me:
Cannot read property 'parameters' of undefined.
I am using dialog v2 api and the actions on Google sdk. Following link provides an example how to implement the context and I don't see a big difference there. https://developers.google.com/actions/reference/nodejsv2/overview
The code written for it looks like this:
app.intent('Default Welcome Intent', conv => {
conv.ask('Welcome.')
const lifespan = 100;
const parameters = {
index: 0,
};
conv.contexts.set('movieCtx', lifespan, parameters);
});
app.intent('New Cinema Movies Intent', async conv => {
let movieCtx = conv.contexts.get('movieCtx');
let index = movieCtx.parameters[index]
let movieRepository = new MovieRepository();
movieRepository.index = index;
await movieRepository.fetchNextTitle(3).then(function(titles) {
movieCtx.parameters[index] = movieRepository.index;
conv.ask('The 3 movies are:' + titles.join(', '))
return true;
}).catch(function(err) {
console.log(err);
return false;
});
})
My dependencies:
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"actions-on-google": "^2.5.0",
"firebase-admin": "~6.0.0",
"firebase-functions": "^2.0.3",
"pg": "^7.7.1"
},
"devDependencies": {
"eslint": "^4.12.0",
"eslint-plugin-promise": "^3.6.0"
},
"private": true
}
Update:
I also tried to change the following lines but also that couldn't help me:
const parameters = {
movieIndex: 0,
};
let index = movieCtx.parameters['movieIndex']
The line
let index = movieCtx.parameters[index]
Should probably be
let index = movieCtx.parameters['index']
(You don't have index defined previous to that, so it is trying to get the reference of undefined, which isn't valid.)
I was able to find the answer!
const {dialogflow} = require('actions-on-google');
const functions = require('firebase-functions');
const MovieRepository = require('./PostgreSQL/MovieRepository');
let movieRepository = new MovieRepository();
const app = dialogflow({debug: true});
const AppContexts = {
NUMBER: 'number',
}
app.intent('Default Welcome Intent', (conv) => {
const lifespan = 10;
const parameters = {
movieIndex: 0,
};
conv.contexts.set(AppContexts.NUMBER, lifespan, parameters);
conv.ask('Welcome!')
});
app.intent('New Cinema Movies Intent', async (conv) => {
const movieCtx = conv.contexts.get(AppContexts.NUMBER);
await movieRepository.fetchNextTitle(3).then(function(titles) {
movieCtx.parameters.movieIndex = movieRepository.index;
conv.ask('The 3 movie titles are: ' + titles.join(', '));
return true;
}).catch(function(err) {
console.log(err);
return false;
});
})
app.intent('Default Fallback Intent', conv => {
conv.ask('Sorry. Can you repeat?')
})
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
As you can see you have to create the AppContext above the intents. Somhow weird but important is that you apply
NUMBER: 'number'
to the context, otherwise you get an undefined context again. And to access your parameters you just need to append your the value of your parameter like this:
movieCtx.parameters.movieIndex

Resources