Dialogflow easy way for authorization - node.js

Does exist an easy way to connect Dialogflow agent to node.js code? When I use this code with the correct projectID taken from the Dialogflow agent's settings page, I have the following error:
Error: Unexpected error while acquiring application default credentials: Could not load the default credentials. Browse to https://developers.google.com/accounts/docs/application-default-credentials for more information.
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
I visited the page, but for what I want I think is quite confused (they quotes other API and a lot of setting), how can I solve this?
I want to take informations from a file and loading all without installing third party APIs.

It is not very well documented, but the easiest way to authenticate is using the JSON file provided on your google cloud platform console.
const sessionClient = new dialogflow.SessionsClient({
keyFilename: '/path/to/google.json'
});
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
This also works for all the other clients. ContextsClients, EntityTypesClient and so on.

I am writing the code, which worked for me. Please follow all the steps provided in Reference link 2 and for coding purpose you can use the snippet provided.
I have also added the sample JSON of Google Cloud Oauth
References:
https://www.npmjs.com/package/dialogflow#samples
https://medium.com/#tzahi/how-to-setup-dialogflow-v2-authentication-programmatically-with-node-js-b37fa4815d89
//Downloaded JSON format
{
"type": "service_account",
"project_id": "mybot",
"private_key_id": "123456asd",
"private_key": "YOURKEY",
"client_email": "yourID#mybot.iam.gserviceaccount.com",
"client_id": "098091234",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/yourID%40mybot.iam.gserviceaccount.com"
}
//------*********************---------------------------
//
const projectId = 'mybot';
//https://dialogflow.com/docs/agents#settings
// generate session id (currently hard coded)
const sessionId = '981dbc33-7c54-5419-2cce-edf90efd2170';
const query = 'hello';
const languageCode = 'en-US';
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
let privateKey = 'YourKey';
// as per goolgle json
let clientEmail = "yourID#mybot.iam.gserviceaccount.com";
let config = {
credentials: {
private_key: privateKey,
client_email: clientEmail
}
}
const sessionClient = new dialogflow.SessionsClient(config);
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});

I have the same issue few months ago, check this, this is how i solve it.
From your JSON that Google Cloud extract this lines.
const dialogflow = require('dialogflow');
const LANGUAGE_CODE = 'en-US'
const projectId = 'projectid';
const sessionId = 'sessionId';
const query = 'text to check';
let privateKey = "private key JSON";
let clientEmail = "email acount from JSON";
let config = {
credentials: {
private_key: privateKey,
client_email: clientEmail
}
};
sessionClient = new dialogflow.SessionsClient(config);
async function sendTextMessageToDialogFlow(textMessage, sessionId) {
// Define session path
const sessionPath = this.sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: textMessage,
languageCode: LANGUAGE_CODE
}
}
}
try {
let responses = await this.sessionClient.detectIntent(request)
console.log('DialogFlow.sendTextMessageToDialogFlow: Detected intent', responses);
return responses
} catch (err) {
console.error('DialogFlow.sendTextMessageToDialogFlow ERROR:', err);
throw err
}
};
sendTextMessageToDialogFlow(query, sessionId)

Since the original question, the documentation for Dialogflow authentication has been improved. You should find all your answers here:
Authentication and access contro

I follow the above solutions with little changes :
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient({
keyFilename: require("path").join('config/google-credential.json')
});
const sessionPath = sessionClient.sessionPath(process.env.DIALOGFLOW_PROJECTID, sessionId);

Related

For some reason when using the dialogflow detectIntent googleapi, I keep getting default fallback intent even though other api's like listIntents work

Has anyone experienced this issue?
I am sure the dialogflow connection works because listing the intents works which is (intentsClient.listIntents(request)) and it gives me back all the intents from my dialogflow es agent. So it looks like the credentials should be fine.
Any help would be highly appreciated,
Thanks
const dialogflow = require('#google-cloud/dialogflow').v2;
const uuid = require('uuid');
const sessionId = uuid.v4();
const sessionClient = new dialogflow.SessionsClient({ keyFilename: '..........' });
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId
);
const query = 'What are the pets rules';
async function detectIntentForQuestion() {
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: 'en-US',
},
},
queryParams: {
sentimentAnalysisRequestConfig: {
analyzeQueryTextSentiment: true,
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(' No intent matched.');
}
if (result.sentimentAnalysisResult) {
console.log('Detected sentiment');
console.log(
` Score: ${result.sentimentAnalysisResult.queryTextSentiment.score}`
);
console.log(
` Magnitude: ${result.sentimentAnalysisResult.queryTextSentiment.magnitude}`
);
} else {
console.log('No sentiment Analysis Found');
}
};
you are setting languageCode: 'en-US' for language. Does your agent support this language? If it is set using a different language (ie. Spanish), then it is expected to give you back only the fallback intent response.
other thing that you can do is checking at https://dialogflow.cloud.google.com/#/agent/<your agent name>/history and in your last interactions, you click on the 3 dots in the agent response and go to Raw interaction log. There you can see the information the agent got from your code, how it was interpreted by the agent and how it answered you back.

Dialogflow CX webhook for fulfilment to reply user using nodejs

I tried using dialogflow-fulfillment library but I guess it is for Dialogflow ES so now I am using
#google-cloud/dialogflow-cx library but I don't know how to use this library for webhook connection to reply to users using fulfilments, there is very little material available for Dialogflow CX.
// use credentials or keyFilename i'm using keyFile
credentials: {
private_key: "-----BEGIN PRIVATE KEY-----==\n-----END PRIVATE KEY-----\n",
client_email:"pro1a3711.iam.gserviceaccount.com",
},
keyFilename: './pr.json'
}
const {SessionsClient} = require('#google-cloud/dialogflow-cx');
const projectId = 'pro1-293711';
const location = 'global';
const agentId = 'da2271f5-0221-4dce-98d3-efa----9dd';
const languageCode = 'en';
const query = ['hello'];
// Imports the Google Cloud Some API library
//console.log(WebhooksClient)
const client = new SessionsClient(config);
//console.log("client",client)
async function detectIntentText() {
const sessionId = Math.random().toString(36).substring(7);
const sessionPath = client.projectLocationAgentSessionPath(
projectId,
location,
agentId,
sessionId
);
console.info(sessionPath);
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
},
languageCode,
},
};
const [response] = await client.detectIntent(request);
console.log(`User Query: ${query}`);
for (const message of response.queryResult.responseMessages) {
if (message.text) {
console.log(`Agent Response: ${message.text.text}`);
}
}
if (response.queryResult.match.intent) {
console.log(
`Matched Intent: ${response.queryResult.match.intent.displayName}`
);
}
console.log(
`Current Page: ${response.queryResult.currentPage.displayName}`
);
}
detectIntentText()```
Note that the dialogflow-fulfillment library only supports Dialogflow ES and the #google-cloud/dialogflow-cx library is only used for node.js applications to access Dialogflow CX API.
As there are no fulfillment libraries available yet for Dialogflow CX, you can refer to the Dialogflow CX webhook request and webhook response for building webhook services for your Dialogflow CX agent.
You can also refer to the sample webhook service code for Dialogflow CX using Node.js and express below:
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post("/webhook", (request, response) => {
let tag = request.body.fulfillmentInfo.tag;
let jsonResponse = {};
if (tag == "welcome tag") {
//fulfillment response to be sent to the agent if the request tag is equal to "welcome tag"
jsonResponse = {
fulfillment_response: {
messages: [
{
text: {
//fulfillment text response to be sent to the agent
text: ["Hi! This is a webhook response"]
}
}
]
}
};
} else {
jsonResponse = {
//fulfillment text response to be sent to the agent if there are no defined responses for the specified tag
fulfillment_response: {
messages: [
{
text: {
////fulfillment text response to be sent to the agent
text: [
`There are no fulfillment responses defined for "${tag}"" tag`
]
}
}
]
}
};
}
response.json(jsonResponse);
});
const listener = app.listen(process.env.PORT, () => {
console.log("Your app is listening on port " + listener.address().port);
});

Error : Dialogflow server in 'us' received request for resources located in 'europe-west2-dialogflow.googleapis.com.'

I want to detect an intent with dialogflow, but my dialogflow agent's region is europe-west2 for some reasons. So to specify a location, I use the version v2beta1 of Dialogflow API like described in the documentation. But it doesn't worked and I have the following error Dialogflow server in 'us' received request for resources located in 'europe-west2-dialogflow.googleapis.com.
Code :
const sessionId = crypto.randomBytes(16).toString("hex");
// Create a new dialogflow session
const sessionClient = new Dialogflow.SessionsClient(this.dialogFlowConfig)
const sessionPath = sessionClient.projectLocationAgentSessionPath(this.projectId, "europe-west2-dialogflow.googleapis.com", sessionId);
// The text query request.
const dfRequest = {
session: sessionPath,
queryInput: {
event: {
name: "Welcome",
languageCode: DialogFlowService.LANGUAGE_CODE
}
}
}
try {
const responses = await sessionClient.detectIntent(dfRequest);
const result = responses[0].queryResult!;
Logger.debug(` Query: ${result.queryText}`);
Logger.debug(` Response: ${result.fulfillmentText}`);
if (result.intent) {
Logger.debug(` Intent: ${result.intent.displayName}`);
} else {
Logger.debug(` No intent matched.`);
}
return result
I had the similar issue, but the below config worked to access dialogflow agent's in region europe-west2
Set the Location as "europe-west2"
Also need to set the
SessionsClient's 'apiEndpoint' as
"europe-west2-dialogflow.googleapis.com"
const sessionClient = new dialogflow.SessionsClient({ apiEndpoint: "europe-west2-dialogflow.googleapis.com" });
const sessionPath = sessionClient.projectLocationAgentSessionPath(
projectId,
"europe-west2",
sessionId
);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
Try to use 'europe-west2' as location. More docs here.

How to connect my G-Suite in nodejs server using Gmail API

I want to get access to my G-Suite account in a nodejs server, using Gmail API.
I understood I should create Service Account and authenticate with its credentials.
I tried many examples and ways but couldn't make it works.
This is the last try I've made.
returns 400 bad request.
code: 400,
errors: [
{
domain: 'global',
reason: 'failedPrecondition',
message: 'Bad Request'
}
]
const {GoogleAuth} = require('google-auth-library');
const credentials = require('./sevice-account-credentials.json');
async function main() {
const clientEmail = credentials.client_email;
const privateKey = credentials.private_key;
if (!clientEmail || !privateKey) {
throw new Error(`
The CLIENT_EMAIL and PRIVATE_KEY environment variables are required for
this sample.
`);
}
const auth = new GoogleAuth({
credentials: {
client_email: clientEmail,
private_key: privateKey,
},
scopes: 'https://mail.google.com/',
});
const client = await auth.getClient();
const projectId = await auth.getProjectId();
const url = `https://www.googleapis.com/gmail/v1/users/my-gsuite#domain.co.il/labels/label_id`;
const res = await client.request({url});
console.log(res.data);
}
main().catch(console.error);
Issue:
You are not impersonating any account in the domain. That's the point of domain-wide delegation: impersonating / acting on behalf of another account.
Solution:
You have to specify which account you want the Service Account to act on behalf of, by providing the property clientOptions when instantiating GoogleAuth:
clientOptions: { subject: "my-gsuite#domain.co.il" }
So it would be like:
const auth = new GoogleAuth({
credentials: {
client_email: clientEmail,
private_key: privateKey,
},
scopes: 'https://mail.google.com/',
clientOptions: { subject: "my-gsuite#domain.co.il" }
});
Reference:
GoogleAuthOptions

Dialogflow Node SDK permission fail (dialogflow.sessions.detectIntent)

I got a problem with Node DialogFlow API integration.
I can not have the necessary permissions to make calls to the API, although I have followed all possible documentation.
Here is my Agent Service Account from Dialogflow admin :
Then the Service Account roles :
The "Client de l'API Dialogflow" role detail, where we can see "dialogflow.sessions.detectIntent" :
And finally, the Node error after downloading the JSON file corresponding to the Service Account :
Am I missing something ?
I tried to generate other JSON files, create other Service Accounts, nothing worked...
The Node script is simple, just pasted from the official tutorial :
const projectId = 'newagent-9e77e '; //https://dialogflow.com/docs/agents#settings
const sessionId = 'quickstart-session-id';
const query = 'bonjour';
const languageCode = 'fr-FR';
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient();
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});
Thanks !
The problem was on space on the "projectId" constant.
Shame on me.

Resources