how to reply message from web demo on dialogflow via webhook - node.js

I'm currently trying to add chatbot to my website.
I'm integrating web demo on the agent used for our lIne bot.
which some responses are handled by lambda webhook.
what I'm asking is can we send responses to web demo using lambda?
if can, then how do I send them?
there suppose to be some id right? and do we use HTTP post request to send them?
I couldn't find an example.
and for some intent which has more than one response handled by dialogflow it can only send one of them.
why is that? and what should I do so that I can send all of them via dialogflow?

Yes, it can be achieved and you can refer to give NodeJs code for that,
const express = require("express");
const bodyParser = require("body-parser");
const apiai = require("apiai");
const request = require("request");
const app = express();
app.use(bodyParser.json());
app.set("port", process.env.PORT || 5000);
app.post("/", (req, res) => {
//console.log(req.body)
const action = req.body.result.action;
if (!req.body || !req.body.result || !req.body.result.parameters) {
return res.status(400).send("Bad Request");
}
console.log("--------------------------------");
console.log("Action =>", action);
console.log("--------------------------------");
switch (action) {
case "price.search":
const webhookReply = `Sorry NO book found in store.`;
res.status(200).json({
source: "webhook",
speech: webhookReply,
displayText: webhookReply
});
break;
default:
break;
}
});
app.listen(app.get("port"), function() {
console.log("* Webhook service is listening on port:" + app.get("port"));
});
For every intent, there will be an action of that we have to define in dialogFlow.
So when the user enters any query your webhook will get triggered it will
go in the switch case to find the particular action and form that case you can send back the replay to your bot.

Related

Send Grid API in Node.js

I am trying to get the contact list and check if the email recipient opened the email or not.
I found this code and tried but got 401.
import config from "#server/config"
sgClient.setApiKey(config.sendgridKey)
const headers = {
"on-behalf-of": "my account user name" // I put my account user name here
}
const request = {
url: `/v3/subusers`,
method: "GET"
} as any
const list = await sgClient
.request(request)
.then()
.catch((err) => {
console.log("list", err.response.body)
})
What do I need to put for the header 'on-behalf-of'? What does the subuser's user name?
And is there any example to get the 'email opened' event?
I am using Node.js.
Thank you!
Twilio SendGrid developer evangelist here.
The API you are trying to use there is the subuser API, not the contacts API. The subuser API is for managing subusers, which are accounts you can apply credit to and send emails from. Subusers are only available on Pro or Premier email accounts or Advanced Marketing Campaign accounts.
However, even if you were to use the Contacts API to get a list of your contacts, that's not the way to see if they have opened an email.
You should instead register for the Event Webhook. With the Event Webhook, SendGrid will send you webhook requests about events that occur as SendGrid processes your emails. These events include "processed", "delivered", "opened", and "clicked" and there are more in the documentation.
To handle the Event Webhook you need to create yourself an endpoint that can receive incoming HTTP requests. Here is an example from the documentation using Express.
const express = require('express');
const app = express();
app.use(express.json());
app.configure(function(){
app.set('port', process.env.PORT || 3000);
});
app.post('/event', function (req, res) {
const events = req.body;
events.forEach(function (event) {
// Here, you now have each event and can process them how you like
processEvent(event);
});
});
var server = app.listen(app.get('port'), function() {
console.log('Listening on port %d', server.address().port);
});

No response from my webhook on Dialogflow

This is the code I have in my server:
const express = require('express');
const bodyParser = require('body-parser');
const appExpress = express().use(bodyParser.json());
const {
dialogflow,
Image,
} = require('actions-on-google')
const app = dialogflow()
appExpress.post('/hook', express.json() ,(req, res) => {
app.intent('MyIntent', conv => {
conv.ask('Hi, how is it going?')
});
});
appExpress.listen(3333, ()=>console.log("Server is live at port 3333"));
When I run this, it returns no errors (I see the message "server is live..") and also when I send a message to my bot with the intent "MyIntent" I get no error, but also no response..
If I look at the Diagnostic Info, under the Fulfillment Status there is this error:
Webhook call failed. Error: DEADLINE_EXCEEDED.
What am I doing wrong?
I don't know how that google library is supposed to work, but generally when using express, you most close the HTTP request by sending a response, there are several examples here
https://expressjs.com/en/guide/routing.html
You could try adding this after convo.ask
res.sendStatus(200);

Twilio Gather params Digits undefined

I'm going through this tutorial to collect digit input: https://www.twilio.com/docs/voice/tutorials/how-to-gather-user-input-via-keypad-node-js
The request.body is undefined so I can't seem to find the input. When I try request.params it is empty though in my Twilio dash board I can see the params are in the Post request from my gather action.
const fs = require('fs');
const botSpeak = require('./bot_speak/scripts.json');
const VoiceResponse = require('twilio').twiml.VoiceResponse;
const app = express();
// Returns TwiML which prompts the caller to record a message
app.post('/welcome', (request, response) => {
// Use the Twilio Node.js SDK to build an XML response
const twiml = new VoiceResponse();
//read scipts from .json
const gather = twiml.gather({
numDigits: 1,
action: '/gather'
});
gather.say(botSpeak.hello + botSpeak.continue);
//if no response
twiml.say(botSpeak.bye);
// Render the response as XML in reply to the webhook request
response.type('text/xml');
response.send(twiml.toString());
});
app.post('/gather', (request, response) => {
// Use the Twilio Node.js SDK to build an XML response
const twiml = new VoiceResponse();
// If the user entered digits, process their request
console.log(request.body);
if (request.body.Digits) {
switch (request.body.Digits) {
case '1':
twiml.say('You selected sales. Good for you!');
break;
case '2':
twiml.say('You need support. We will help!');
break;
default:
twiml.say("Sorry, I don't understand that choice.").pause();
twiml.redirect('/welcome');
break;
}
} else {
// If no input was sent, redirect to the /voice route
twiml.redirect('/welcome');
}
// Render the response as XML in reply to the webhook request
response.type('text/xml');
response.send(twiml.toString());
});
// Create an HTTP server and listen for requests on port 3000
app.listen(3000);
console.log('Server serving on port 3000');
You need body-parser middleware. Try adding this.
// Body Parser Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
https://expressjs.com/en/4x/api.html#express-json-middleware

How to send email using Angular and Node server?

I am able to send emails with nodejs using nodemailer but my project is in angular 6. I don't know how to integrate that nodejs code into my angular.I just want it for my website contact us forum. Thank you in advance.
You'd need to create a way of allowing your Angular code to talk to your Node.js code, typically you'd use a REST API using Http or Express.
For example, using Express:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = 8081;
app.use(bodyParser.json());
// Allow callers to send an email message
app.post('/send_email', function(req, res){
console.log('send_email body: ', req.body);
sendEmail(req.body);
res.status(201).json({status: 'success' });
});
app.listen(port);
function sendEmail(emailObj) {
// Send the mail
}
In Angular you can use the HttpClient module to call this, for example:
// Replace the url root as necessary
this.httpClient.post("http://127.0.0.1:8081/send_email",
{
"email": "user1#example.com",
"message": "Test message"
})
.subscribe(
data => {
console.log("POST Request is successful ", data);
},
error => {
console.log("Error", error);
}
);
It's worth noting that you will need to provide some authorization mechanism in the REST endpoint (e.g. POST send_email), since you don't want any old client sending mails.

actions-on-google api.ai doesn't send body in POST request with nodejs and express

I'm trying to run the sillyNameMaker example from actions-on-google with api.ai, on my computer.
I set up a nodejs server with express, and a ngrok tunneling. When I try to send a request with my agent on api.ai, my server receives the POST request, but the body appears to be empty. Is there anything i didn't set up properly?
Here is my index.js file:
'use strict';
var express = require('express')
var app = express()
const ApiAiAssistant = require('actions-on-google').ApiAiAssistant;
function sillyNameMaker(req, res) {
const assistant = new ApiAiAssistant({request: req, response: res});
// Create functions to handle requests here
const WELCOME_INTENT = 'input.welcome'; // the action name from the API.AI intent
const NUMBER_INTENT = 'input.number'; // the action name from the API.AI intent
const NUMBER_ARGUMENT = 'input.mynum'; // the action name from the API.AI intent
function welcomeIntent (assistant) {
assistant.ask('Welcome to action snippets! Say a number.');
}
function numberIntent (assistant) {
let number = assistant.getArgument(NUMBER_ARGUMENT);
assistant.tell('You said ' + number);
}
let actionMap = new Map();
actionMap.set(WELCOME_INTENT, welcomeIntent);
actionMap.set(NUMBER_INTENT, numberIntent);
assistant.handleRequest(actionMap);
function responseHandler (assistant) {
console.log("okok")
// intent contains the name of the intent you defined in the Actions area of API.AI
let intent = assistant.getIntent();
switch (intent) {
case WELCOME_INTENT:
assistant.ask('Welcome! Say a number.');
break;
case NUMBER_INTENT:
let number = assistant.getArgument(NUMBER_ARGUMENT);
assistant.tell('You said ' + number);
break;
}
}
// you can add the function name instead of an action map
assistant.handleRequest(responseHandler);
}
app.post('/google', function (req, res) {
console.log(req.body);
sillyNameMaker(req, res);
})
app.get('/', function (req, res) {
res.send("Server is up and running.")
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
And the error I got:
TypeError: Cannot read property 'originalRequest' of undefined
at new ApiAiAssistant (/Users/clementjoudet/Desktop/Dev/google-home/node_modules/actions-on-google/api-ai-assistant.js:67:19)
at sillyNameMaker (/Users/clementjoudet/Desktop/Dev/google-home/main.js:8:21)
I'm trying to print req.body but it is undefined... Thanks in advance for your help.
Both you and the actions-on-google package are making an assumption about how you're using Express. By default, Express does not populate the req.body attribute (see the reference for req.body). Instead it relies on additional middleware such as body-parser to do so.
You should be able to add body parser to your project with
npm install body-parser
and then use it to parse the request body into JSON (which API.AI sends and actions-on-google uses) with some additional lines right after you define app to attach it to Express:
var bodyParser = require('body-parser');
app.use(bodyParser.json());

Resources