Dialogflow API - DetectIntent is not responding and ends up being time out - dialogflow-es

I'm working on communicating with Dialogflow API.
`
const dialogflow = require('#google-cloud/dialogflow-cx');
const uuid = require('uuid');
const config = require('./devkey');
const projectId = 'test';
const location = 'northamerica-northeast1';
const agentId = 'test';
const sessionId = uuid.v4();
async function runIntent(text) {
const sessionClient = new dialogflow.SessionsClient({
apiEndpoint: 'northamerica-northeast1-dialogflow.googleapis.com',
credentials: {
private_key: config.private_key,
client_email: config.client_email
}
});
const sessionPath = sessionClient.projectLocationAgentSessionPath(
projectId,
location,
agentId,
sessionId
);
console.log('sessionPath: ', sessionPath, 'sessionId: ', sessionId);
const intentRequest = {
session: sessionPath,
queryInput: {
text: {
text: text
},
languageCode: 'en'
}
}
try {
const [response] = await sessionClient.detectIntent(intentRequest);
console.log('response: ', response);
console.log('resonse.text: ', response.queryResult.responseMessages[0].text.text[0]);
return response.queryResult.responseMessages[0].text.text[0];
} catch (err) {
console.log('error: ', err);
return err;
}
}
`
My question is regarding detectIntent method.
Usually it is working fine, however, sometimes it's not responding at all and ends up getting time out error.
Not sure what to do for this.
Any recommendation would be appreciated.
Thanks,
`
GoogleError: Total timeout of API google.cloud.dialogflow.cx.v3.Sessions exceeded 220000 milliseconds before any response was received.
at repeat (C:\google-dialogflow\poc-dialogflow2\backend\node_modules\google-gax\build\src\normalCalls\retries.js:66:31)
at Timeout._onTimeout (C:\google-dialogflow\poc-dialogflow2\backend\node_modules\google-gax\build\src\normalCalls\retries.js:101:25)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7) {
code: 4
}
`
Normally the detectIntent method is working, but sometimes it's responding at all, and only throws time out error at the end.
No idea what goes wrong.

Related

Firebase 401 Error https://fcm.googleapis.com/fcm/send works with admin().messaging().send() but does not work with admin().messaing().sendTopic()

I have created my backend in nodejs like shown below. When calling code example 1, code executes without problem. Example 1 calls admin().messaging().send() and works; however, when calling code example 2 (sending topic message) there is 401 error (like shown below)
An error occurred when trying to authenticate to the FCM servers.
Make sure the credential used to authenticate this SDK has the proper permissions.
See https://firebase.google.com/docs/admin/setup for setup instructions.
PROJECT_NOT_PERMITTED
Error 401
Is there authorization setting when sending topic message? What needs to be done to resolve issue with 401 Error? Thank you
Example 1
// Load the AWS SDK for Node.js
var AWS = require("aws-sdk");
// Set the region
AWS.config.update({ region: "ap-northeast-2" });
var admin = require("firebase-admin");
var serviceAccount = require("../firebadeCredentialInformation.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
module.exports.handler = async (event) => {
console.log(event);
var body = JSON.parse(event.body);
console.log(body);
var topic;
var topicPayload;
try {
//body, title, data, token
const message = {
data: {
type: "VOTE",
senderName: body.senderName,
question: body.question,
questionRangeKey: body.questionRangeKey,
senderToken: body.senderToken,
gender: body.gender,
schoolGrade: body.schoolGrade,
schoolName: body.schoolName,
},
token: body.token,
};
//? Make sure the message is sent
//TODO REMOVE BELOW AWAIT TO IMPROVE SPEED
var result = await admin.messaging().send(message);
console.log(result);
return {
statusCode: 200,
body: JSON.stringify(
{
message: "Sucessfully sent response",
input: event,
},
null,
2
),
};
} catch (e) {
console.log("Error", e);
return {
statusCode: 500,
body: JSON.stringify(
{
message: e,
input: event,
},
null,
2
),
};
}
};
Example 2
// Load the AWS SDK for Node.js
var AWS = require("aws-sdk");
// Set the region
AWS.config.update({ region: "ap-northeast-2" });
var admin = require("firebase-admin");
var serviceAccount = require("../firebadeCredentialInformation.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
module.exports.handler = async (event) => {
console.log(event);
var body = JSON.parse(event.body);
console.log(body);
var topic;
var topicPayload;
try {
//body, title, data, token
const message = {
data: {
type: "VOTE",
senderName: body.senderName,
question: body.question,
questionRangeKey: body.questionRangeKey,
senderToken: body.senderToken,
gender: body.gender,
schoolGrade: body.schoolGrade,
schoolName: body.schoolName,
},
token: body.token,
};
//? Make sure the message is sent
//TODO REMOVE BELOW AWAIT TO IMPROVE SPEED
var result = await admin.messaging().send(message);
console.log(result);
if (body.schoolId != "") {
//* Ff not missing school id
const topicPayload = {
data: {
type: "TOPIC",
senderName: body.senderName,
question: body.question,
questionRangeKey: body.questionRangeKey,
senderToken: body.senderToken,
gender: body.gender,
schoolGrade: body.schoolGrade,
schoolName: body.schoolName,
},
};
const schoolId = body.schoolId;
const topic = "/topics/" + schoolId;
console.log(topic);
//? Make sure the message is sent
//TODO REMOVE BELOW AWAIT TO IMPROVE SPEED
// Send a message to devices subscribed to the provided topic.
var topicResult = await admin
.messaging()
.sendToTopic(topic, topicPayload);
console.log(topicResult);
}
return {
statusCode: 200,
body: JSON.stringify(
{
message: "Sucessfully sent response",
input: event,
},
null,
2
),
};
} catch (e) {
console.log("Error", e);
return {
statusCode: 500,
body: JSON.stringify(
{
message: e,
input: event,
},
null,
2
),
};
}
};
Have figured out the issue for those who are stuck as well. Instead of using admin().message.sendTopic(). I have used the command below which is also same as sending a topic message, which worked.
//* if not missing school id
const schoolId = body.schoolId;
const topic = "/topics/" + schoolId;
const topicPayload = {
data: {
type: "TOPIC",
senderName: body.senderName,
},
topic: topic,
};
console.log(topic);
// Send a message to devices subscribed to the provided topic.
var topicResult = await admin.messaging().send(topicPayload);

createClickwrap returns 404 Not Found

When I call createClickwrap method, I got 404 error Not Found. If I run this method through Quickstart generated demo project, I don't get this error. However, if I run it through my project I get the error. If I debug the demo app and my app, the functions parameters are the same.
This is the code in my app:
docusign controller:
const docuSignService = require('./docusign_esign_service');
const demoDocumentsPath = path.resolve(__dirname, '../demo_documents');
const { createClickwrap } = require('./createClickWrap');
async getDocusignRecieptService() {
const authResponse = await docuSignService.authenticate();
if (authResponse) {
const docTermsPdf = 'Term_Of_Service.pdf';
const docFile = path.resolve(demoDocumentsPath, docTermsPdf);
const { basePath, accessToken, apiAccountId } = authResponse;
const { clickwrapId } = await createClickwrap({ docFile, basePath, accessToken, accountId: apiAccountId });
const res = await activateClickwrap({ clickwrapId, basePath, accessToken, accountId: apiAccountId });
console.log({ res });
}
}
docuSignService.js
const SCOPES = ['signature', 'impersonation', 'openid', 'click.manage', 'click.send'];
const fs = require('fs');
const docusign = require('docusign-esign');
class DocusingService {
async authenticate() {
const jwtLifeSec = 10 * 60, // requested lifetime for the JWT is 10 min
dsApi = new docusign.ApiClient();
dsApi.setOAuthBasePath(process.env.dsOauthServer.replace('https://', '')); // it should be domain only.
let rsaKey = fs.readFileSync(process.env.privateKeyLocation);
try {
const results = await dsApi.requestJWTUserToken(
process.env.dsJWTClientId,
process.env.impersonatedUserGuid,
SCOPES,
rsaKey,
jwtLifeSec
);
const accessToken = results.body.access_token;
// get user info
const userInfoResults = await dsApi.getUserInfo(accessToken);
// use the default account
let userInfo = userInfoResults.accounts.find((account) => account.isDefault === 'true');
return {
accessToken: results.body.access_token,
apiAccountId: userInfo.accountId,
basePath: `${userInfo.baseUri}/restapi`
};
} catch (e) {
let body = e.response && e.response.body;
// Determine the source of the error
if (body) {
// The user needs to grant consent
if (body.error && body.error === 'consent_required') {
if (this.getConsent()) {
return this.authenticate();
}
} else {
// Consent has been granted. Show status code for DocuSign API error
this._debug_log(`\nAPI problem: Status code ${e.response.status}, message body:
${JSON.stringify(body, null, 4)}\n\n`);
}
}
}
}
getConsent() {
var urlScopes = SCOPES.join('+');
// Construct consent URL
var redirectUri = 'https://developers.docusign.com/platform/auth/consent';
var consentUrl =
`${process.env.dsOauthServer}/oauth/auth?response_type=code&` +
`scope=${urlScopes}&client_id=${process.env.dsJWTClientId}&` +
`redirect_uri=${redirectUri}`;
throw new Error(`Open the following URL in your browser to grant consent to the application: ${consentUrl}`);
}
getArgs(apiAccountId, accessToken, basePath, signerEmail, signerName, id, agreementData, redirect_uri) {
const envelopeArgs = {
signerEmail: signerEmail,
signerName: signerName,
status: 'sent',
signerClientId: id,
dsReturnUrl: redirect_uri,
agreement: agreementData
};
const args = {
accessToken: accessToken,
basePath: basePath,
accountId: apiAccountId,
envelopeArgs: envelopeArgs
};
return args;
}
}
module.exports = new DocusingService();
createClickWrap.js
const createClickwrap = async ({ docFile, clickwrapName = 'clickwrapName', basePath, accessToken, accountId }) => {
// Step 3. Construct the request Body
// Create display settings model
const displaySettings = docusignClick.DisplaySettings.constructFromObject({
consentButtonText: 'I Agree',
displayName: 'Terms of Service',
downloadable: true,
format: 'modal',
hasAccept: true,
mustRead: true,
requireAccept: true,
documentDisplay: 'document'
});
// Create document model
// Read and encode file. Put encoded value to Document entity.
// The reads could raise an exception if the file is not available!
const documentPdfExample = fs.readFileSync(docFile);
const encodedExampleDocument = Buffer.from(documentPdfExample).toString('base64');
const document = docusignClick.Document.constructFromObject({
documentBase64: encodedExampleDocument,
documentName: 'Terms of Service',
fileExtension: 'pdf',
order: 0
});
// Create clickwrapRequest model
const clickwrapRequest = docusignClick.ClickwrapRequest.constructFromObject({
displaySettings,
documents: [document],
name: clickwrapName,
requireReacceptance: true
});
// Step 4. Call the Click API
const dsApiClient = new docusignClick.ApiClient();
dsApiClient.setBasePath(basePath);
dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + accessToken);
const accountApi = new docusignClick.AccountsApi(dsApiClient);
// Create a clickwrap
let result = null;
try {
result = await accountApi.createClickwrap(accountId, {
clickwrapRequest
});
} catch (e) {
debugger;
console.log(e);
}
debugger;
console.log(`Clickwrap was created. ClickwrapId ${result.clickwrapId}`);
return result;
};
module.exports = { createClickwrap };
Parameters look like this in the demo app and it works:
and these are the parameters in my app:
The first parameter accountId is the same. Why I am getting this issue in my app if function gets the same parameters?
"Error: Not Found
at Request.callback (/Users/and/test/node_modules/docusign-click/node_modules/superagent/lib/node/index.js:696:15)
at IncomingMessage.<anonymous> (/Users/and/test/node_modules/docusign-click/node_modules/superagent/lib/node/index.js:906:18)
at IncomingMessage.emit (node:events:539:35)
at IncomingMessage.emit (node:domain:475:12)
at endReadableNT (node:internal/streams/readable:1345:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)"
Thanks to pointing out in the comments, when I changed basePath ${userInfo.baseUri}/restapi to ${userInfo.baseUri}/clickapi, it works now.

How to make dialogflow session

I want to set different session for different users in dialogflow.
https://www.npmjs.com/package/dialogflow
I referred to the following site for this, but the program is not returning any output.
const dialogflow = require('dialogflow');
const uuid = require('uuid');
/**
* Send a query to the dialogflow agent, and return the query result.
* #param {string} projectId The project to be used
*/
async function runSample(projectId = 'your-project-id') {
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: 'hello',
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// 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.`);
}
}
const functions = require('firebase-functions');
const dialogflow = require('dialogflow');
const cors = require('cors')({origin: true});
const admin = require('firebase-admin');
admin.initializeApp();
// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions
exports.connectChat = functions.https.onRequest((req, response) => {
cors(req, response, () => {
const projectId = '******';
const query = req.query.text;
const session= req.query.session;
const languageCode = 'en-US';
var result="";
let privateKey = "-----BEGIN PRIVATE KEY-----******\n-----END PRIVATE KEY-----\n";
// as per goolgle json
let clientEmail = "*****#.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, session);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
result = responses[0].queryResult;
response.send(result);
return null;
})
.catch(err => {
console.error('ERROR:', err);
response.send('ERROR');
return null;
});
});
});
projectId,clientEmail,privateKey are get from JSON file downloaded from https://console.cloud.google.com/iam-admin
create your session id (req.query.session) from client side in javascript

Auth error:TypeError: URL is not a constructor

I am getting this error while deploying in AWS:
"Auth error:TypeError: URL is not a constructor" "DF ERROR:14
UNAVAILABLE: Getting metadata from plugin failed with error: URL is
not a constructor"
Although locally it is working fine.
Not getting any response after it calls to Dialogflow.
My code is :
// Instantiate a DialogFlow client.
var dialogflow = require('dialogflow');
var sessionClient = new dialogflow.SessionsClient({
credentials: {
private_key: config.dialogflow.privateKey,
client_email: config.dialogflow.clientEmail
}
}
);
// Define session path
var sessionPath = sessionClient.sessionPath(config.dialogflow.projectId, req.sessionID);
// The text query request.
var request = {
session: sessionPath,
queryInput: {},
};
if (chatBotEvent.text.text){
request.queryInput.text = {
text:chatBotEvent.text.text,
languageCode: chatBotEvent.text.languageCode
};
}
if (chatBotEvent.event.name){
var dialogflowService = new DialogflowService();
request.queryInput.event = {
name:chatBotEvent.event.name,
parameters:dialogflowService.jsonToStructProto(chatBotEvent.event.parameters),//event.parameters,
languageCode: chatBotEvent.event.languageCode,
};
}
// Send request and log result
return sessionClient
.detectIntent(request)
.then(function(responses){
var incidentData = $this.analyseResponse(responses[0].queryResult);
if (incidentData){
responses[0].queryResult.incident = incidentData;
}
return responses[0].queryResult;
})
.catch(function(err){
console.error('ERROR:', err);
});

how to call a event in the dialogflow v2 :nodejs

I'm using dialogflow v2 using npm. I just want call a welcome event in dialogflow. How can I do it in the nodejs. I'm pretty new to it.
This is my code
const projectId = "xxxxxx";
const LANGUAGE_CODE = 'en-US';
const sessionId = req.body.sessionId;
var query = req.body.query;
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId,sessionId);
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: LANGUAGE_CODE,
},
},
};
sessionClient.detectIntent(request).then(response => {
console.log('intent detected');
const result = response[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if(result.fulfillmentText) {
console.log(result.fulfillmentText);
return res.json({reply: result.fulfillmentText})
}
// if(result.intent) {
// console.log(` Intent: ${result.intent.displayName}`)
// }
else {
console.log('no intent found');
}
}).catch(err => {
console.log('error '+err);
})
As I open the chat page I just want to throw a welcome message. In order to do that, i read that i have to call the event. How can I do that? I have taken the reference from here
The Request body should be like this:
let eventName='WELCOME'; //name of the event
let request = {
session: sessionPath,
queryInput: {
event: {
name: eventName,
languageCode: 'en-US'
},
},
};
checkout- https://github.com/googleapis/nodejs-dialogflow/blob/master/samples/detect.js#L96
let me know if you find any difficulties :)
I would suggest using actions-on-google as it is much easier to build nodejs backend for dialogflow link : actions on google
And for sample project refer Number genie project
Hope this would help you.

Resources