Get UserId GoogleActions - actions-on-google

I am trying to get the userId in Firebase for my Google user but, apparently it's undefined
dialogflowFirebaseFulfillment
ReferenceError: userId is not defined
at IncomingMessage.resp.on (/user_code/index.js:73:17)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
This is my code
const REQUEST_PERMISSION_ACTION = 'request_permission';
const userUID = app.getUser().userId;
const userName = app.getUserName().displayName;
console.log(userUID, 'USERRRRRRID');
What can I do to get the userId?

This is bigger part of my code
function processV1Request (request, response) {
let action = request.body.result.action; // https://dialogflow.com/docs/actions-and-parameters
let parameters = request.body.result.parameters; // https://dialogflow.com/docs/actions-and-parameters
let inputContexts = request.body.result.contexts; // https://dialogflow.com/docs/contexts
let requestSource = (request.body.originalRequest) ? request.body.originalRequest.source : undefined;
const googleAssistantRequest = 'google'; // Constant to identify Google Assistant requests
const app = new DialogflowApp({request: request, response: response});
// Create handlers for Dialogflow actions as well as a 'default' handler
const actionHandlers = {
// The default welcome intent has been matched, welcome the user (https://dialogflow.com/docs/events#default_welcome_intent)
'input.welcome': () => {
sendGoogleResponse(' Bonjour, Que puis je faire pour vous ?');
},
'input.what': () => {
const http = require('http');
const https = require('https');
https.get('https://bnpparibas-api.openbankproject.com/obp/v3.0.0/my/banks/bnpparibas.07.fr/accounts/cbf874f8-9eb1-4fdf-899c-54b8c5e7c2c8/account', (resp) => {
let data = '';
const app = new ActionsSdkApp({request: request, response: response});
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});

You have to ask the assistant to guide the user to grant permission for your app to get this information.
Take a look here

Related

Dialogflow to Firestore using Inline Fulfillment - Get original user input from a certain parameter

Is there a way to get the original input from a certain parameter?
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
process.env.DEBUG = 'dialogflow:debug';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
function getData(agent) {
let age = agent.parameters.age;
let location = agent.parameters.location;
let opinion = agent.parameters.opinion;
db.collection("users").add({
age: age,
location: location,
opinion: opinion
});
}
let intentMap = new Map();
intentMap.set('getData', getData);
agent.handleRequest(intentMap);
});
e.g. The user inputs "I love this thing!"
This is the data that was stored in Firestore.
Notice that only the word "love" was stored in the opinion line since my #opinion entity has only the word love. This is the getData intent.
This is what I'm trying to achieve.

Webhook call failed. Error: DEADLINE_EXCEEDED. though the request latency took 4991ms

here's my fulfillment code in the inline editor :
NOTE: requests are reaching my api server with 200 OK code but says deadline exceeded in the dialogflow platform. I hope you find with me a solution the faster you can`
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));
let number = request.body.queryResult.parameters['number'];
var url = 'https://7400546e4d1e.ngrok.io/api/reclamations'+'/'+ number ;
getDescription(url).then(response => {
var bot_response = "description:"+response.data.description ;
agent.add(bot_response);
console.log(bot_response);
response.json({ 'fulfillmentText': bot_response });
}).catch (error => {
console.log("Something is wrong !! ");
console.log(error);
agent.add(bot_response);
});
function getDescription(url) {
const axios = require('axios');
return axios.get(url,{timeout:10000});
}
});
Try defining the function getDescription as an async function (ie. async function getDescription(url){...}).
This is because when you call getDescription(url).then(response => {...}), the .then() implies that it is asynchronous, which it is.

Unable to read from firestore collection

i have a firestore collection called Users and trying to write a document in the collection through fulfillment. I am getting the user's name and his location through dialogflow agent and trying to insert it into the collection. But the document is not getting inserted.
1)Getting data from agent:
name= agent.parameters.name;
location=agent.parameters.location;
2) Writing to the firestore collection Users
db.collection("Users").doc("101").set({
name: name,
location:location});
The function got executed but the document is not inserted into the firestore collection. what am i missing?
'use strict';
const functions = require('firebase-functions');
const { WebhookClient } = require('dialogflow-fulfillment');
const { Card, Suggestion } = require('dialogflow-fulfillment');
const admin = require('firebase-admin');
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));
var name='';
var location='';
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
function getUserDetails(agent)
{
name= agent.parameters.name;
location=agent.parameters.location;
console.log("buyer name is " + name);
db.collection("Users").doc("101").set({
name: name,
location:location});
agent.add(`User has been inserted`);
}
intentMap.set('Buy Car', getUserDetails);
agent.handleRequest(intentMap);
})
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {WebhookClient} = require('dialogflow-fulfillment');
process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) =>
{const agent = new WebhookClient({request,response});
function saveName(agent){
const nameParam = agent.parameters.name;
const name = nameParam;
agent.add(`thank you, ` + name + `!`);
return db.collection('test').add({name: name}).then((snapshot) => {(console.log('success'));
});
}
let intentMap = new Map();
intentMap.set('Get_Name', saveName);
agent.handleRequest(intentMap);
});
It isn't clear what is going wrong, but at least in part that is because you're not checking what the error might be from doing the write to the collection/doc.
This is compounded by your reply "User has been inserted" is sent without you actually confirming that the user document has been set. There isn't even any guarantee that it has been sent by the time the function completes, because you're not treating the document write as asynchronous.
The normal way to do this is to return the Promise that set() returns, so handleRequest() will wait for the handler to finish before it sends the reply. You should also set the reply in a then() portion of the Promise and catch any errors in a catch() block.
A function like this is more correct, and may log what the error is:
function getUserDetails(agent)
{
name= agent.parameters.name;
location=agent.parameters.location;
console.log("buyer name is " + name);
return db.collection("Users").doc("101").set({
name: name,
location: location
})
.then( () => {
agent.add(`User has been inserted`);
})
.catch( err => {
console.log( err );
agent.add('Something went wrong');
});
}

When I launch an event, this call to the intent but not show in the client app

I have this event:
Image of the intent
And I have this code in the Fullfillment:
function LanzarEvento(session) {
//var user = firebase.auth().currentUser;
const uuid = require('uuid');
const sessionId = uuid.v1();//user.uid;
// Imports the Dialogflow library
const dialogflow = require('dialogflow');
// Instantiates a sessison client
const sessionClient = new dialogflow.SessionsClient();
// The path to identify the agent that owns the created intent.
const sessionPath = session;//sessionClient.sessionPath(projectId, sessionId);
console.log('sessionPath -> ' + sessionPath);
let responseToUser = {
'fulfillmentText': 'Voy a buscar los mejores alojamientos, dame unos segundos.'
};
sendResponse(responseToUser);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
event: {
name: 'PruebaEvento',
parameters: jsonToStructProto({user_name: 'Andres',name: 'Andres'}),
languageCode: languageCode,
},
},
};
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
logQueryResult(sessionClient, responses[0].queryResult);
})
.catch(err => {
console.error('ERROR:', err);
});
}
And this is the conversation in the Training section of Dialogflow:
Trainning capture
How you can see, the event was returning "Hola Andres", but this never appears in the Facebook Messenger or in the Slack.
Please, I need your help. Can you help me?
Thanks in advance,
Andrés Gilabert

API Gateway Custom Authorizer for Federated Identity

I created a custom authorizer for API Gateway so that i can pass the Facebook token and it will authenticate it using Cognito's Federated identity.
My problem is that the fb token seems to expire so I keep getting 403 errors. I am wondering if my approach is correct. Should I pass the Facebook token as part of the request header to API gateway on every REST API call or so I pass AWS identity id instead. Any feedback is appreciated. Thank you.
var AWS = require('aws-sdk');
var cognitoidentity = new AWS.CognitoIdentity();
exports.handler = (event, context, callback) => {
var params = {
IdentityPoolId: 'us-west-2:xxxxxxxxxxxxxxxxx’, /* required */
AccountId: ‘xxxxxxxxxxxxxxxxx,
Logins: {
'graph.facebook.com': event.authorizationToken //Token given by Facebook
}
};
console.log(event.methodArn);
cognitoidentity.getId(params, function(err, data) {
if (err) {
console.log(err);
callback(null, generatePolicy('user', 'Deny', event.methodArn));
}
else{
console.log("success");
callback(null, generatePolicy('user', 'Allow', event.methodArn));
}
});
};
var generatePolicy = function(principalId, effect, resource) {
var authResponse = {};
authResponse.principalId = principalId;
if (effect && resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17'; // default version
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = 'execute-api:Invoke'; // default action
statementOne.Effect = effect;
statementOne.Resource = resource;
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
return authResponse;
}