How to use ngrok in the boilerplate code of actions on google? - node.js

I would like to use the "boilerplate"-structure (see github), use firebase for productive code, but ngrok during development. How can I combine it?
https://github.com/actions-on-google/dialogflow-webhook-boilerplate-nodejs/blob/master/functions/index.js
'use strict';
const {dialogflow} = require('actions-on-google');
const functions = require('firebase-functions');
const app = dialogflow({debug: true});
app.intent('Default Welcome Intent', (conv) => {
conv.close('Hello, World!');
// Complete your fulfillment logic and
// send a response when the function is done executing
});
exports.yourAction = functions.https.onRequest(app);

Related

How to set my flag variable 0 everytime my page gets refreshed in DialogFlow?

I want to set my flag variable 0 everytime a new user comes to my website or an existing user refreshes the webpage. Where should I declare this flag variable in my code?
This is my index.js :
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const admin=require('firebase-admin');
admin.initializeApp();
console.log(`1`);
var flag=0;
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
console.log(`2`);
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log(`3`);
function welcome(agent) {
console.log(`4`);
var query=request.body.queryResult.queryText;
query=query.toLowerCase();
console.log(query);
console.log(flag);
agent.add(`Welcome user`);
}
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
agent.handleRequest(intentMap);
});
I am not able to figure this out as firebase console shows no logs when I refresh my page i.e., I want a function similar to 'onload' in DialogFlow fulfillment.

agent.add() sometimes not able to give results in dialogflow

I am using Dialogflow to build a chatbot and I am using Axios to make some posts and get requests, but sometimes agent.add() inside that HTTP call doesn't work.
I am attaching the sample code.
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
// Using some external libraries
//axios for using third party api hosted as http.
const axios = require('axios');
// xml2js for parsing xml output in response
const xml2js = require('xml2js');
const json = require('json');
// Accessing firebase admin
const admin = require('firebase-admin');
function name(agent){
return axios.post('http://some-api,
{"name": "Kyle"}).then((result) => {
console.log('Store datato api');
agent.add('What is your email id'); // Sometimes its working and sometimes its not
//return Promise.resolve(agent); // I tried this as well but the same issue.
});
}
What could be appropiate changes, as I was going through all other questions on Stackoverflow, I tried returning pomise as well, but didn't work.
It looks like you've structured your Promise incorrectly. This is the format I use to return responses that require Promises:
function name(agent) {
const promise = new Promise(resolve => {
// logic goes here
resolve(agent.add(output));
});
return promise;
}
If this doesn't work, check other points it may be failing at - are you sure your webhook isn't failing in the POST request?

Dialogflow Node.js Client - save data on data side, but don't return response

I'm using DialogFlow with the official Google Node.js library. I want to use a webhook to save input data to a database, but not return a response.
However, currently I'm just waiting for the function to timeout which is slow, and writes an error to the logs Error: No responses defined for platform: FACEBOOK
I've checked the documentation hoping for a way to send a 200 status or similar, but haven't found anything. https://dialogflow.com/docs/reference/fulfillment-library/webhook-client
Is it possible to do what I'd like to do? It seems like a fairly standard requirement.
UPDATE: My code is simple, but below
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
const firebase = require('firebase-admin');
firebase.initializeApp();
const session_split = agent.session.split('/');
const session = session_split[blf_session_split.length - 1];
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((req, res) => {
const agent = new WebhookClient({
request: req,
response: res
});
agent.handleRequest(savedata);
function input(agent) {
return firebase.database().ref('/tests/' + session).update({
"input": agent.action
});
}
});

Can I just use Dialogfow's default fulfillment webhook code as a starting place on Azure?

I am developing a webhook in Node.js for my Fullfillment piece in Google's Dialogflow. I will host the webhook on Azure.
My question is can I just take/use the default webhook/fullfillment code that's in Dialogflow and copy it / host it on Azure and use it as a starting place? What about the segment of code "exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response)?
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
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?`);
}
agent.add(`Thank you...`);
return admin.database().ref('AgeInfo').once("value").then((snapshot) => {
var averageAge = snapshot.child("RunningAverage").val();
agent.add(`Our recorded average age is ` + averageAge);
});
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('AskAge', handleAge);
// intentMap.set('your intent name here', yourFunctionHandler);
// intentMap.set('your intent name here', googleAssistantHandler);
agent.handleRequest(intentMap);
});
If you are using an express-like service on Azure, you shouldn't have too many problems. There are two things you'll need to do
Setup the body-parser middleware for your express app which will convert the JSON text body into an object and store it in request.body.
Replace the exports.dialogflowFirebaseFulfillment = functions.https.onRequest( portion with the express routing for a POST request to "/dialogflowFirebaseFulfillment" (or pick a different name, as I did below - you just need to change the URL for your webhook).
I haven't tested, but it might look something like this:
var expressApp = express();
var bodyParser = require('body-parser');
expressApp.use( bodyParser.json() );
expressApp.post( '/dialogflowFulfillment', (request, response) => {
// Continue with the rest of the code here that was inside the
// onRequest handler

Matching Express Routes to Google Assistant intents

I have an Express app that I am trying to integrate with Google Assistant.
I've installed https://www.npmjs.com/package/actions-on-google and have followed https://codelabs.developers.google.com/codelabs/actions-1/#0 which deploys functions to Firebase - however I would like to run them from a self-hosted Express server.
In my app.js I have set up as follows:
const {
dialogflow,
Image,
} = require('actions-on-google')
// Create an app instance
const gapp = dialogflow();
});
However I am unsure how to create the route that I add in Dialogflow console as the webhook - do I use the format below?
app.post('/webhook', function(req, res){
gapp.intent('favorite color', (conv, {color}) => {
const luckyNumber = color.length;
// Respond with the user's lucky number and end the conversation.
conv.close('Your lucky number is ' + luckyNumber);
});
});
If so do all of my intents then go within this route?
EDIT
Updated in response to answer:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const {
dialogflow,
Image,
} = require('actions-on-google')
// Create a google app instance
const gapp = dialogflow()
// Register handlers for Dialogflow intents
gapp.intent('Default Welcome Intent', conv => {
conv.ask('Hi, how is it going?')
conv.ask(`Here's a picture of a cat`)
conv.ask(new Image({
url: 'https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/imgs/160204193356-01-cat-500.jpg',
alt: 'A cat',
}))
})
// Intent in Dialogflow called `Goodbye`
gapp.intent('Goodbye', conv => {
conv.close('See you later!')
})
gapp.intent('Default Fallback Intent', conv => {
conv.ask(`I didn't understand. Can you tell me something else?`)
})
app.post('/ga/webhook', gapp)
You can define all of your gapp intents at the start of your Express server, then you can pass in your gapp object into the webhook that you define:
const express = require('express')
const bodyParser = require('body-parser')
// ... gapp code here
const expressApp = express().use(bodyParser.json())
expressApp.post('/webhook', gapp)
expressApp.listen(3000)

Resources