Agent unable to print all results received from Axion library request in Dialogflow - node.js

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:

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

nodejs unit test PubSub.publish not sending data

I'm having issues doing a unit test with the following environment:
"pubsub-js": "^1.9.2",
"#types/chai": "^4.2.14",
"#types/mocha": "^8.2.0",
"chai": "^4.2.0",
"firebase-functions-test": "^0.2.3",
"mocha": "^8.2.1",
"ts-node": "^9.1.1",
"ts-sinon": "^2.0.1",
When publish a message to my pubsub the data received by it is always: Message { data: undefined, attributes: {}, _json: undefined } and I can't figure out why.
There is some code to describe my scenario:
pubsub-myFunc.ts
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1")
console.log(message)
/**
* Received message from topic
*/
const myMessage = Buffer.from(message.data, "base64").toString("utf-8")
pubsub-myFunc.spec.ts
import * as functions from 'firebase-functions';
import * as PubSub from 'pubsub-js';
import * as tsSinon from 'ts-sinon';
import { pubsubMyFunc } from './pubsub-myFuncr';
import * as sendEmail from './send-mail';
describe("PubSub tests", () => {
beforeEach(() => {
process.env.GCLOUD_PROJECT = "my env"
})
it("Should call sendNotificationMessage", function (done) {
// this.timeout(60000)
const today = new Date()
const data = {
dateCreated: today,
expireDate: today.getDate() + 30,
objId: "id",
objParentId: "parentId",
}
const spy = tsSinon.default.spy(sendEmail, "sendNotificationMessage")
const dataBuffer = Buffer.from(JSON.stringify(data))
const pubsubMessage = new functions.pubsub.Message(dataBuffer)
PubSub.subscribe("on-myTopic", pubsubMyFunc)
console.log("publish")
PubSub.publish("on-myTopic", pubsubMessage)
setTimeout(() => {
// check if spy was called
tsSinon.default.assert.calledOnce(spy)
done()
}, 15000)
})
})
I have tried to pass directly the dataBuffer but without any luck as well, the outputs of my console logs are:
publish
version 1
Message { data: undefined, attributes: {}, _json: undefined }
Is there any reason for my Message.data to be undefined?
I'm not sure if pubsub-js's subscribe function is compatible with the output of firebase-functions' onPublish method.
You could use firebase's emulators to run your functions locally and test them by sending messages like you would normally instead of going through pubsub-js.
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1");
console.log(message);
/**
* Received message from topic
*/
const myMessage = message.json;
...
Make sure pubsubMyFunc is being exported at firebase functions entry point.
Install and configure firebase emulators, make sure PUBSUB_EMULATOR_HOST env var is set to localhost:$PORT where $PORT is set to the port you have configured for pub sub emulator, located in firebase.json under emulators.pubsub.port.
Once that's all setup, you can send a message to pubsub by:
import {PubSub} from "#google-cloud/pubsub";
cont getTopic = () => {
const topic = new PubSub().topic("on-myTopic");
topic.exists().then(([exists]) => exists
? topic
: topic.create().then(([newTopic]) => newTopic)
);
};
describe("PubSub tests", () => {
let topic;
beforeEach(async() => {
process.env.GCLOUD_PROJECT = "my env"
topic = await getTopic();
});
it("should test something", async() => {
await topic.publishJSON(const data = {
dateCreated: today,
expireDate: today.getDate() + 30,
objId: "id",
objParentId: "parentId",
});
// rest of your code here.
});
});
This will work on the process of hack
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1");

Dialogflow #vitalets/google-translate-api Translation not working

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.

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