How to trigger an sending email to human using Dialogflow ES Fulfillment - dialogflow-es

I am using the fulfillment and nodemailer in my editor and would like to send an email to my personal email address. When I try to integrate to Dialogflow Messenger Beta version, my chatbot will not understand the response.
My output:
User: "I would like to send an email to the support service."
Bot: "Sorry. I do not understand your question."
Correct output:
User: "I would like to send an email to the support service."
Bot: "What is your name?"
User: "Henry"
Bot: "What is your email?"
User: "henry65#gmail.com"
Bot: "Thanks Henry. We will get back to you as soon as possible."
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 nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'james641#gmail.com',
pass: 'test#1567'
}
});
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 sendEmailHandler(agent){
const { email, name } = agent.parameters;
const question = agent.parameters.question;
const mailOptions = {
from: "James", // sender address
to: email, // list of receivers
subject: "Email from Chatbot", // Subject line
html: "<p>Name:</p> " + name + "<p>Email:</p>" + email + "<p>Questions:</p>" + question
};
transporter.sendMail(mailOptions, function (err, info) {
if(err)
{
console.log(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('Default Fallback Intent', fallback);
intentMap.set('sendEmail_intent', sendEmailHandler);
// intentMap.set('your intent name here', yourFunctionHandler);
// intentMap.set('your intent name here', googleAssistantHandler);
agent.handleRequest(intentMap);
});
I'm still new to Dialogflow so I'm not that savvy with the webhooks and fulfillments. Please help me.

One approach to achieving your use case is to activate the Default fallback intent and enable the Fulfilment of that intent. However, you must ensure that you collect the email address at the fallback intent.
On Dialogflow webhook is triggered by the default fallback, which provides the question
and sessionID, which is then saved in a database.
Then fallback method requests an email address.
Lastly, the user provides an email and intent fires another webhook, which updates the
original record with the email address and sends the request to the inbox.
To avoid this hassle, you can integrate Dialoglfow with any third-party platform, such as Kommunicate, and send email notifications directly from the dashboard. When the default fallback intent gets triggered or when a human agent is assigned to a conversation, an email will be automatically sent.
PS: I work for Kommunicate.

Related

I am new to node js, am trying to implement "Account Signin" in Dialogflow But, I am getting this error "The agent returned an empty TTS"

const app = dialogflow({
clientId: MY_CLIENT_ID,
});
app.intent('Start Signin', (conv) => {
conv.ask(new SignIn('To get your account details'));
});
app.intent('Get Signin', (conv, params, signin) => {
if (signin.status === 'OK') {
const payload = conv.user.profile.payload;
conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`);
} else {
conv.ask(`I won't be able to save your data, but what do you want to do next?`);
}
});
Above is the code,
Also, I did create the intents as the name in the intents tab and fulfillment tab. I did enable the account link for the project with which I am working with and am using only google-sign and got client id. And created an event actions_intent_SIGN_IN in 'Get Signin' intent but still facing the same problem

Dialogflow Detect Intent Fulfillment

Hi i have created a dialogflow nodejs backend which detects intents using the client library for nodejs.
const sessionPath = this.sessionClient.sessionPath(this.configService.get('dialogFlowProjectId'), sessionId);
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: "en-US"
}
}
};
// Send request and log result
Logger.log(request);
const responses = await this.sessionClient.detectIntent(request);
this works fine but I also want to trigger a fulfillment for certain intents.
I have setup a webhook url - this works fine when you use the chat in the dialogflow console. But when I use the method that I have created to send the request to dialogflow the webhook doesn't get called and goes to fallback intent. I'm calling the same intent through the dialogflow console chat and through my own API.
How can I trigger the webhook call when I use the client library API?
First, remember that you don't "call an Intent", either through the test console or through the API. What you can do is send query text that should be matched by an Intent.
If you have set the Intent so that it should call the Fulfillment webhook, then this should happen no matter the source, as long as the Intent itself is triggered.
That the Fallback Intent is getting triggered instead suggests that something about the query text isn't matching the Intent you think it should be matching. I would check to make sure the text you're sending in query should match the training phrases for the Intent in question, that you have no Input Contexts, and that your agent is set for the "en-US" language code.
For routing multiple intents through a webhook you're going to want to have a handler.js file with an express router in it...
const def = require('./intents/default')
const compression = require('compression')
const serverless = require('serverless-http')
const bodyParser = require('body-parser')
const { WebhookClient } = require('dialogflow-fulfillment')
const express = require('express')
const app = express()
// register middleware
app.use(bodyParser.json({ strict: false }))
app.use(function (err, req, res, next) {
res.status(500)
res.send(err)
})
app.use(compression())
app.post('/', async function (req, res) {
// Instantiate agent
const agent = new WebhookClient({ request: req, response: res })
const intentMap = new Map()
intentMap.set('Default Welcome Intent', def.defaultWelcome)
await agent.handleRequest(intentMap)
})
module.exports.server = serverless(app)
As you can see, this handler.js is using serverless-http and express.
Your intent.js function could look something like this ...
module.exports.defaultWelcome = async function DefaultWelcome (agent) {
const responses = [
'Hi! How are you doing?',
'Hello! How can I help you?',
'Good day! What can I do for you today?',
'Hello, welcoming to the Dining Bot. Would you like to know what\'s being served? Example: \'What\'s for lunch at cronkhite?\'',
'Greetings from Dining Bot, what can I do for you?(Hint, you can ask things like: \'What\'s for breakfast at Annenberg etc..\' or \'What time is breakfast at Anennberg?\')',
'greetings',
'hey',
'long time no see',
'hello',
"lovely day isn't it"
]
const index = Math.floor((Math.random() * responses.length) + 1)
console.log(responses[index].text)
agent.add(responses[index].text)
}
This gives you the bare bones for routing multiple request through your webhook. Hope this helps.

DialogFlow context is always empty in google assistant

I've made a simple chatbot on dialogflow by referencing the dialogflow documentation which is based on Dialogflow's fulfillment library. The bot works good on integration with Google Assistant.
However when I started using context (getting and setting context) in the node.js code, the bot doesn't work on google assistant.
This line agent.context.get('iotcontext'); is null in google assistant but works good in dialogflow test console.
Following is my code:
'use strict';
var https = require ('https');
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?`);
}
function myIntentHandler(agent) {
console.log("Function myIntentHandler Run");
const codeContext=agent.context.get("iotcontext");
agent.add("Date spoken by user: "+codeContext.parameters["date.original"]);
}
// 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('your intent name here', yourFunctionHandler);
intentMap.set('IoTIntent', myIntentHandler);
agent.handleRequest(intentMap);
});

Malformed response error : empty speech response while making my agent

I was making dialogflow app that links the user to each links regarding to the number that user says.
I got google codelab's fulfillment code and edited it to make it.
But when I try to use Card and other things to create clickable url links, "MalformedResponse: Failed to parse Dialogflow response into AppResponse because of empty speech response" happens.
I'm using Dialogflow InlineEditor for this.
Tried to app.buildRichResponse but that also fails
This is my node.js code.
'use strict';
// Import the Dialogflow module from the Actions on Google client library.
const {dialogflow} = require('actions-on-google');
// Import the firebase-functions package for deployment.
const functions = require('firebase-functions');
// Instantiate the Dialogflow client.
const app = dialogflow({debug: true});
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
// Handle the Dialogflow intent named 'favorite color'.
// The intent collects a parameter named 'color'.
app.intent('getJobs', (conv, {number}) => {
const jobNum = number;
// Respond with the user's lucky number and end the conversation.
if (number == 1) {
conv.ask(new Card({
title: `Title: this is a card title`,
imageUrl: 'https://dialogflow.com/images/api_home_laptop.svg',
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://docs.dialogflow.com/'
}));
} else if (number == 2) {
conv.close('camera on');
} else {
conv.close('unknown number');
}
});
//Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
I think problem is, you use only rich response when number is 1 and this may cause "MalformedResponse: Failed to parse Dialogflow response into AppResponse because of empty speech response" error since there is nothing assistant can response with voice. You can't use rich response without simple response.
Also you are trying to use both actions-on-google and dialogflow-fulfillmentlibraries. This can cause the problem as well. You can try:
function getJobs(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/'
})
);
intentMap.set('getJobs', getJobs);
or
const { dialogflow, BasicCard, Image, Button } = require('actions-on-google');
app.intent('getJobs', (conv, {number}) => {
conv.ask('This is simple response...',new BasicCard({
text: `This is a basic card.`
subtitle: 'This is a subtitle',
title: 'Title: this is a title',
buttons: new Button({
title: 'This is a button',
url: 'https://assistant.google.com/',
}),
image: new Image({
url: 'https://example.com/image.png',
alt: 'Image alternate text',
}),
display: 'CROPPED',
}));
});

Possibility to send context data to dialogflow without webhook being called from Dialogflow, but from server itself

Currently I have a webhook which is being called from Dialogflow (fulfillment) and checks which intent is currently applicable. (I do everything via JSON) once I know which Intent, I send back (via the webhook) a JSON response. I was wondering if it is possible to initiate a JSON object and send it to Dialogflow. (I want to send context without letting the user type first and Dialogflow receiving a fallback) (NodeJS Server -> Dialogflow) Currently the only way I can do it is (Dialogflow -> NodeJS Server (JSON object with contex) -> Dialogflow)
CURRENT:
var dialog_flow = {
// Create context using Google dialogflow
createContext: async function(projectId, sessionId, contextId, parameters, lifespanCount){
console.log("params to be sent: ", parameters);
//Instantiates client to create the actual context before sending
const contextsClient = new dialogflow.ContextsClient({
keyFilename: './dialogflow_credentials.json'
});
const sessionPath = contextsClient.sessionPath(projectId, sessionId);
const contextPath = contextsClient.contextPath(
projectId,
sessionId,
contextId
);
const createContextRequest = {
parent: sessionPath,
context: {
name: contextPath,
lifespanCount: lifespanCount,
parameters: parameters
},
};
const response = await contextsClient.createContext(createContextRequest);
console.log(`Created ${response[0].name}`);
}
};
PARAMETERS:
let testobj = {
firstname: 'test name',
lastname: 'itworks!!',
dd: 'fgfgf',
ff: 'fgfg'
}
You can call directly Dialogflow from Node.js, without the need of receiving a webhook. For that you will need to use the dialogflow package.
const sessionClient = new dialogflow.SessionsClient();
const session = sessionClient.sessionPath(projectId, sessionId);
const request = {
session,
queryInput: {
text: {
text: 'Some text'
}
},
queryParams: {
contexts: [context] // here you send the data
}
};
sessionClient.detectIntent(request)
.then(console.log)
.catch(console.error);
In order to send a context, with data, you will need to use dialogflow.ContextsClient
I give a detailed explanation about that in these other questions:
set input or output context dialogflow nodejs v2
Dialogflow pass parameters through NodeJS
And in order to authenticate the client you can check:
Dialogflow easy way for authorization
UPDATE: 2 weeks ago, Dialogflow, removed the structjson.js sample from the repository, but in favor of an npm package to handle the encoding/decoding of the protobuf struct: pb-util

Resources