I came to know that context expires in 15 minutes but is there any way to solve it manually i.e by storing the previous conversation in dB so can we handle that session expiring issue or else the whole conversation(output context) under that session ID will get clear and need to start from the first.
exports.fulfillmenttext = functions.https.onRequest((req,res) =>{
const answer1 = req.body.Text;
console.log("Text said by the user",answer1);
const uid = answer1.substring(0,28);
console.log("uid1 is",uid);
const answer = answer1.substring(28);
console.log("answer is",answer);
const sessionId = uid;
var count,questvalue;
runSample();
async function runSample(projectId = 'xxxxxxx') {
const languageCode = 'en-US';
const credentials = {
client_email: 'xxxxxxxxxx',
private_key: 'xxxxxxxxx'
};
//Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient({
projectId,
credentials,
});
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: answer,
languageCode,
},
},
};
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
let action = result.action;
console.log("action is"+action);
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
const question = result.fulfillmentText;
console.log("question is",question);
const actionHandlers = {
'early': () => {
console.log('earlyaction1', action);
let name1 = JSON.stringify(result.parameters.fields.Name.stringValue);
name1 = name1.toString().replace(/"/g,"");
var data1 = {
Name: name1
};
var setDoc1 = admin.firestore().collection('User').doc(uid).collection("Popop").doc(uid).collection('Answers').doc('Earlyyears').update(data1);
},
'family': () => {
console.log('familyaction1', action);
let mname1 = JSON.stringify(result.parameters.fields.M_Name.stringValue);
let mname_string = mname1.toString().replace(/"/g,"");
var data20 = {
MName: mname_string
};
var setDoc20 = admin.firestore().collection('User').doc(uid).collection("Popop").doc(uid).collection('Answers').doc('Family').update(data20);
}
};
if (action === 'early') {
console.log('1');
actionHandlers[action]();
}
else if (action === 'family') {
console.log('2');
actionHandlers[action]();
}
res.status(200).send({"question":result.fulfillmentText,"action":action});
} else {
console.log(` No intent matched.`);
res.status(400).send({"action":"empty"});
}
}
});
I stumbled upon this problem as well. My solution was to save the userID and save the contexts to Firestore.
UPDATE:
This is how I stored Dialogflow's contexts in Firestore:
function saveContexts(userId, contexts) {
let UID = userId;
//get all contexts + parameters
if (contexts === undefined) {
console.log("contexts are undefined! returning");
return false;
}
db.collection("user-contexts-prod").doc(UID).set({
dateCreated: new Date(),
contexts: JSON.stringify(contexts)
})
.then(function () {
console.log("success!");
return true;
})
.catch(function (error) {
console.log("error writing document..", error);
return false;
});
}
Retrieving user contexts:
async function getContexts(userId) {
let UID = userId;
let docRef = db.collection("user-contexts-prod").doc(UID);
return docRef.get()
.then(res => {
if (res.exists) {
let contexts = JSON.parse(res.data().contexts);
console.log("<><> parsed contexts <><>: ");
console.log(contexts);
return contexts;
} else {
console.log(" UID DOES NOT EXIST!");
return false;
}
})
}
You can set the contexts again by looping over them and using the contextClient to create new contexts. Or use this method to loop through the contexts and find the one you need:
contexts.forEach(function(context) {
if (context.name === 'projects/{DIALOGFLOWPROJECTID}/agent/sessions/' + senderId + '/contexts/{CONTEXTNAME}') {
sessionData = context.parameters;
// all data that you saved in CONTEXTNAME is now available in the sessionData variable
}
});
Original answer:
Whenever a user started talking that didn't have any active contexts I check if I had the userID stored in my Database. If this user existed in my DB I retrieved the user information with all his data like this:
knownUser = await db.isKnownUser(senderId);
if (knownUser) {
//knownUser
console.log("Known user");
let userData = db.getUserDataById(senderId)
//initialize contexts with data you need
payload = returningUser_useSameData();
messenger.send(payload, senderId);
dashbot.logBotMessage(payload.toString, sessionId, intentName);
break;
} else {
//newUser
console.log("new user");
createContext('await_fillInTogether', '', sessionPath, sessionId, 1);
createContext('session', '', sessionPath, sessionId, 500);
payload = fillInTogetherNewUser();
messenger.send(payload, senderId);
dashbot.logBotMessage(payload.toString, sessionId, intentName);
break;
}
Related
I am trying to connect with the api hubstaff to which I have set up my authentication using auth0 and express as my backend. To know about the info about the logged in user I need to send the token object via the API.
By some research I have gotten to this point:
const {
Issuer,
TokenSet
} = require('openid-client');
const fs = require('fs');
const jose = require('jose');
// constants
const ISSUER_EXPIRE_DURATION = 7 * 24 * 60 * 60; // 1 week
const ACCESS_TOKEN_EXPIRATION_FUZZ = 30; // 30 seconds
const ISSUER_DISCOVERY_URL = 'https://account.hubstaff.com';
// API URl with trailing slash
const API_BASE_URL = 'https://api.hubstaff.com/';
let state = {
api_base_url: API_BASE_URL,
issuer_url: ISSUER_DISCOVERY_URL,
issuer: {}, // The issuer discovered configuration
issuer_expires_at: 0,
token: {},
};
let client;
function loadState() {
return fs.readFileSync('./configState.json', 'utf8');
}
function saveState() {
fs.writeFileSync('./configState.json', JSON.stringify(state, null, 2), 'utf8');
console.log('State saved');
}
function unixTimeNow() {
return Date.now() / 1000;
}
async function checkToken() {
//console.log('state.token.access_token', state.token.access_token);
if (!state.token.access_token || state.token.expires_at < (unixTimeNow() + ACCESS_TOKEN_EXPIRATION_FUZZ)) {
// console.log('Refresh token');
state.token = await client ? .refresh(state.token);
// console.log('Token refreshed');
saveState();
}
}
async function initialize() {
console.log('API Hubstaff API');
let data = loadState();
data = JSON.parse(data);
if (data.issuer) {
state.issuer = new Issuer(data.issuer);
state.issuer_expires_at = data.issuer_expires_at;
}
if (data.token) {
state.token = new TokenSet(data.token);
}
if (data.issuer_url) {
state.issuer_url = data.issuer_url;
}
if (data.api_base_url) {
state.api_base_url = data.api_base_url;
}
if (!state.issuer_expires_at || state.issuer_expires_at < unixTimeNow()) {
console.log('Discovering');
state.issuer = await Issuer.discover(state.issuer_url);
state.issuer_expires_at = unixTimeNow() + ISSUER_EXPIRE_DURATION;
console.log(state.issuer);
}
client = new state.issuer.Client({
// For personal access token we can use PAT/PAT.
// This is only needed because the library requires a client_id where as the API endpoint does not require it
client_id: 'Z',
client_secret: 'J',
});
saveState();
console.log('API Hubstaff initialized');
}
async function request(url, options) {
await checkToken();
let fullUrl = state.api_base_url + url;
return client ? .requestResource(fullUrl, state.token, options);
}
function tokenDetails() {
let ret = {};
if (state.token.access_token) {
ret.access_token = jose.JWT.decode(state.token.access_token);
}
if (state.token.refresh_token) {
ret.refresh_token = jose.JWT.decode(state.token.refresh_token);
}
return ret;
}
module.exports = {
initialize,
checkToken,
request,
tokenDetails
};
// COntroller
const { response } = require('express')
const api = require('../util/hubstaffConnect.util');
const testConnected = require('../util/testhubstaff.util');
const usersGet = async (req, res = response) => {
await api.initialize();
const response = await api.request('v2/organizations',{
method: 'GET',
json: true,
});
console.log('response', response);
if(response != null){
const body = JSON.parse(response);
res.json({
organizations: body.organizations || []
});
}
};
Although when I go to the address localhost:8080/oauth/api/organizations I ran into an error:
I do realise this is regarding missing tokens which won't let me get the user's information.
I got a Microsoft bot framework chatbot deployed on Azure and I´m using Tedious to save my conversations, thing is, bot it's being used on a web and many persons can open it to interact simultaneosly, but when I save a conversation from an user, it saves all the other interactions that have been made by other users at the same time, I need that each user has it's own conversation saved separately even if they are interacting with the chatbot at the same time...
Here's my code, maybe I'm missing something:
Bot.js
//SQL Connection
var Connection = require('tedious').Connection;
var config = {
server: 'myserver',
authentication: {
type: 'default',
options: {
userName: 'myuser',
password: 'mypass'
}
},
options: {
encrypt: true,
database: 'mydatabase'
}
};
const connection = new Connection(config);
connection.on('connect', function(err) {
console.log("Connected");
});
var Request = require('tedious').Request
var TYPES = require('tedious').TYPES;
// Function to save the conversation and bot ids
function executeConversationStatement(bot, cid, ulg ) {
request = new Request("INSERT INTO table (bot_id, conversationID, conversation_date, userlogged) VALUES (#bot, #cid, CURRENT_TIMESTAMP, #ulg); SELECT ##IDENTITY AS ID",function(err) {
if (err) {
console.log(err);}
});
request.addParameter('bot', TYPES.Int, bot);
request.addParameter('cid', TYPES.NVarChar, cid);
request.addParameter('ulg', TYPES.NVarChar, ulg);
request.on('row', function(columns) {
insertedcid = columns[0].value; // This is the id I pass later
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log("Conversation id of inserted item is " + column.value);
}
});
});
connection.execSql(request);
}
// Here on members added I save the conversation id generated by the framework
class BOT extends ActivityHandler {
constructor(conversationState,userState,telemetryClient) {
super();
this.conversationState = conversationState;
this.userState = userState;
this.dialogState = conversationState.createProperty("dialogState");
this.previousIntent = this.conversationState.createProperty("previousIntent");
this.conversationData = this.conversationState.createProperty('conservationData');
const qnaMaker = new QnAMaker({
knowledgeBaseId: process.env.QnAKnowledgebaseId,
endpointKey: process.env.QnAEndpointKey,
host: process.env.QnAEndpointHostName
});
this.qnaMaker = qnaMaker;
this.onMessage(async (context, next) => {
await this.dispatchToIntentAsync(context);
await next();
});
this.onDialog(async (context, next) => {
await this.conversationState.saveChanges(context, false);
await this.userState.saveChanges(context, false);
await next();
});
this.onMembersAdded(async (context, next) => {
const { channelId, membersAdded } = context.activity;
actid = context._activity.id;
if (channelId === 'directline' || channelId === 'webchat') {
for (let member of membersAdded) {
if (member.id === context.activity.recipient.id) {
await context.sendActivity("Hi, I´m a chatbot to guide You");
try{
var saveqna = new executeConversationStatement(context._activity.id , 'Invitado');
}
catch{
console.log('Not saved');
}
}
}
}
await next();
});
}
//Finally, here I save the interaction:
async dispatchToIntentAsync(context) {
var result = await this.qnaMaker.getAnswers(context);
// Statement to save interaction with the insertedcid obtained above
var saveqnaint = new executeInteractionStatement(insertedcid, context._activity.text, result);
}
No matter if I use thet generated Id or the databse pk, I always keep the same identifier when multiple users are chatting, how can I got a separately Id for each session ?
I am planning to get AI prediction result using service account and deploy a cloud function to a Firebase project. When trying to get prediction result
https://ml.googleapis.com/v1/projects/projectid/models/category:predict?
using accesstoken JWT and the result is
{ StatusCodeError: 403 - {"error":{"code":403,"message":"Access to model denied.","status":"PERMISSION_DENIED"}}
It is confirmed that the service account I'm using has been added to the ML project.
Any idea how to get the ML result in Firebase function using service account? or other method?
Here is the code (I am still newbie to NodeJS)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const admin = require('firebase-admin');
const request = require("request");
const requestProm = require("request-promise");
const functions = require('firebase-functions');
const { GoogleAuth } = require('google-auth-library');
admin.initializeApp();
var reportFld, reportNarTr, reportTitTr;
var input, input2, input3;
var result, predictedHaz, predictedSig, predictedRep, setDoc
var getAccessTokenId
getAccessTokenId = async function main() {
const auth = new GoogleAuth({
scopes: 'https://www.googleapis.com/auth/cloud-platform'
});
const client = await auth.getClient();
const projectId = await auth.getProjectId();
const accessTokenId = await auth.getAccessToken();
return accessTokenId
}
exports.newReport = functions.firestore
.document('/users/{usersId}')
.onCreate((change, context) => {
const db = admin.firestore();
const interDoc = db.collection('users').doc(context.params.usersId);
interDoc.get().then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
var getPrediction
getPrediction = async function main2() {
reportFld = doc.data();
reportNarTr = JSON.stringify(reportFld.narrative);
reportTitTr = JSON.stringify(reportFld.title);
reportNumTr = context.params.usersId;
input = {
instances: [
[reportNumTr, reportTitTr, reportNarTr]
]
};
var accessToken = await getAccessTokenId();
var endpointhazCat = 'https://ml.googleapis.com/v1/projects/projectid/models/hazcat:predict?access_token=' + accessToken;
var endpointsigCat = 'https://ml.googleapis.com/v1/projects/projectid/models/sig:predict?access_token=' + accessToken;
var endpointrepCat = 'https://ml.googleapis.com/v1/projects/projectid/models/type:predict?access_token=' + accessToken;
var options1 = {
method: 'POST',
uri: endpointhazCat,
body: input,
json: true // Automatically stringifies the body to JSON
};
var options2 = {
method: 'POST',
uri: endpointsigCat,
body: input,
json: true // Automatically stringifies the body to JSON
};
var options3 = {
method: 'POST',
uri: endpointrepCat,
body: input,
json: true // Automatically stringifies the body to JSON
};
requestProm.post(options1)
.then(function (response) {
result = response['predictions'];
switch (parseInt(result)) {
case 0:
predictedHaz = 'A';
break;
case 1:
predictedHaz = 'B';
break;
case 2:
predictedHaz = 'C';
break;
case 3:
predictedHaz = 'D';
break;
case 4:
predictedHaz = 'E';
break;
case 5:
predictedHaz = 'F';
break;
case 6:
predictedHaz = 'G';
break;
default:
predictedHaz = 'error';
}
const predictedHazData = {
HazardCategory: predictedHaz,
};
setDoc = db.collection('users').doc(context.params.usersId).update(predictedHazData);
console.log(response);
return true
})
.catch(function (err) {
console.log('Failed', err)
});
requestProm.post(options2)
.then(function (response) {
result = response['predictions'];
if (parseInt(result) > -4) {
predictedSig = 'Sig';
} else predictedSig = 'Insig'
const predictedSigData = {
SignifanceCategory: predictedSig,
};
setDoc = db.collection('users').doc(context.params.usersId).update(predictedSigData);
console.log(response);
return true
})
.catch(function (err) {
console.log('Failed', err)
});
requestProm.post(options3)
.then(function (response) {
result = response['predictions'];
if (parseInt(result) === 1) {
predictedRep = 'Inc';
} else predictedRep = 'Haz'
const predictedRepData = {
ReportCategory: predictedRep,
};
setDoc = db.collection('users').doc(context.params.usersId).update(predictedRepData);
console.log(response);
return true
})
.catch(function (err) {
console.log('Failed', err)
});
return true
}
getPrediction().catch(console.error);
} return null
})
.catch(err => {
console.log('Error getting document', err);
});
return true;
});
Added some details:
These are the service account permissions:
ml.jobs.cancel
ml.jobs.create
ml.jobs.get
ml.jobs.getIamPolicy
ml.jobs.list
ml.jobs.update
ml.locations.get
ml.locations.list
ml.models.create
ml.models.delete
ml.models.get
ml.models.getIamPolicy
ml.models.list
ml.models.predict
ml.models.update
ml.operations.cancel
ml.operations.get
ml.operations.list
ml.projects.getConfig
ml.studies.create
ml.studies.delete
ml.studies.get
ml.studies.getIamPolicy
ml.studies.list
ml.trials.create
ml.trials.delete
ml.trials.get
ml.trials.list
ml.trials.update
ml.versions.create
ml.versions.delete
ml.versions.get
ml.versions.list
ml.versions.predict
ml.versions.update
resourcemanager.projects.get
I have tried to use other node library 'googleapis' on debug console :
google.auth.getApplicationDefault((err, authClient, projectId) => {
if (err) {
console.log('Authentication failed because of ', err);
res.status(401).send('Authentication failed');
} else {
// create the full model name which includes the project ID
const modelName = 'projects/ml-project-id/models/hazcat';
const mlRequestJson = {
'auth': authClient,
'name': modelName,
'resource': { instances: [['RepNum', 'RepTit', 'RepNar']]
}
}
ml.projects.predict(mlRequestJson, (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result.data.predictions[0]);
}
});
}
});
and the result is:
3
and deployed to firebase:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const admin = require('firebase-admin');
const request = require("request");
const requestProm = require("request-promise");
const functions = require('firebase-functions');
const { GoogleAuth } = require('google-auth-library');
const { google } = require('googleapis');
const ml = google.ml('v1');
admin.initializeApp();
var reportFld, reportNarTr, reportTitTr, reportNumTr, reportTitStr, reportNarStr;
var input, input2, input3;
var result, predictedHaz, predictedSig, predictedRep, setDoc
exports.predictReport = functions.firestore
.document('/users/{usersId}')
.onCreate((change, context) => {
const db = admin.firestore();
const interDoc = db.collection('users').doc(context.params.usersId);
interDoc.get().then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
reportFld = doc.data();
reportNarTr = JSON.stringify(reportFld.narrative);
reportTitTr = JSON.stringify(reportFld.title);
reportNumTr = context.params.usersId;
input = {
instances: [
[reportNumTr, reportTitTr, reportNarTr]
]
};
var result1, result2, result3
google.auth.getApplicationDefault((err, authClient, projectId) => {
if (err) {
console.log('Authentication failed because of ', err);
res.status(401).send('Authentication failed');
} else {
const modelName = 'projects/ml-project-id/models/hazcat';
const modelName2 = 'projects/ml-project-id/models/sig';
const modelName3 = 'projects/ml-project-id/models/type';
const mlRequestJson1 = {
'auth': authClient,
'name': modelName,
'resource': input
}
const mlRequestJson2 = {
'auth': authClient,
'name': modelName2,
'resource': input
}
const mlRequestJson3 = {
'auth': authClient,
'name': modelName3,
'resource': input
}
var result1, result2, result3
ml.projects.predict(mlRequestJson1, (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result.data.predictions[0]);
result1 = result.data.predictions[0];
switch (parseInt(result1)) {
case 0:
predictedHaz = 'A';
break;
case 1:
predictedHaz = 'B';
break;
case 2:
predictedHaz = 'C';
break;
case 3:
predictedHaz = 'D';
break;
case 4:
predictedHaz = 'E';
break;
case 5:
predictedHaz = 'F';
break;
case 6:
predictedHaz = 'G';
break;
default:
predictedHaz = 'error';
}
const predictedHazData = {
HazardCategory: predictedHaz,
};
setDoc = db.collection('users').doc(context.params.usersId).update(predictedHazData);
}
}); // endof predict1
ml.projects.predict(mlRequestJson2, (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result.data.predictions[0]);
result2 = result.data.predictions[0];
if (parseInt(result2) > -4) {
predictedSig = 'Sig';
} else predictedSig = 'Insig'
const predictedSigData = {
SignifanceCategory: predictedSig,
};
setDoc = db.collection('users').doc(context.params.usersId).update(predictedSigData);
}
});// endof predict2
ml.projects.predict(mlRequestJson3, (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result.data.predictions[0]);
result3 = result.data.predictions[0];
if (parseInt(result3) === 1) {
predictedRep = 'Inc';
} else predictedRep = 'Haz'
const predictedRepData = {
ReportCategory: predictedRep,
};
setDoc = db.collection('users').doc(context.params.usersId).update(predictedRepData);
}
});// endof predict3
}//endof else getappdefault
});//endof getappdefault
} return true
})//endof getdocument
.catch(err => {
console.log('Error getting document', err);
});
return true;
});//endof onCreate
and the result is
Authentication failed because of Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
at AuthPlus.getApplicationDefaultAsync (/srv/node_modules/googleapis-common/node_modules/google-auth-library/build/src/auth/googleauth.js:156:23)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
Added details (update 2)
I have used keyfile pointing to service account json file.
getAccessTokenId = async function main() {
const auth = new GoogleAuth({
keyFile: 'projectid.json',
scopes: 'https://www.googleapis.com/auth/cloud-platform'
});
const client = await auth.getClient();
const projectId = await auth.getProjectId();
const accessTokenId = await auth.getAccessToken();
return accessTokenId
}
got access token like this
ya29.c.xxxx
and the permission denied
Failed { StatusCodeError: 403 - {"error":{"code":403,"message":"Access to model denied.","status":"PERMISSION_DENIED"}}
Added details (update 3)
I'm using my personal credentials to enter the ML model works inside cloud function
getAccessTokenId = async function main() {
const auth = new GoogleAuth({
keyFile: 'application_default_credentials.json',
scopes: 'https://www.googleapis.com/auth/cloud-platform'
});
const client = await auth.getClient();
const projectId = await auth.getProjectId();
const accessTokenId = await auth.getAccessToken();
return accessTokenId
}
Get the result
{ predictions: [ 3 ] }
I also have added Service Account Token Creator role on the service account but still not work using service account to access ML Model
iam.serviceAccountKeys.create
iam.serviceAccountKeys.delete
iam.serviceAccountKeys.get
iam.serviceAccountKeys.list
But curious why it doesnt have these
iam.serviceAccounts.getAccessToken
iam.serviceAccounts.signBlob
iam.serviceAccounts.signJwt
iam.serviceAccounts.implicitDelegation
iam.serviceAccounts.getOpenIdToken
I have two functions in Firebase. The first one is ok:
exports.sendPush = functions.database.ref('/itemADividir/{itemId}').onCreate((snapshot, context) =>{
const oque = snapshot.val();
const quem = oque.userOrigem;
const itemADV = oque.itemAdividir;
const quanto = oque.itemValor;
return pegaTokenUser(oque.userDestino).then(userTk =>{
let payload ={
notification: {
title: 'Solicitação - Notificação InfSocial',
body: `${quem} quer compartilhar ${itemADV} no valor de ${quanto} com vc`,
sound: 'default',
badge: '1'
}
};
console.log(`${quem} quer compartilhar ${itemADV} no valor de ${quanto} com vc`)
console.log(`token ${userTk}`)
return admin.messaging().sendToDevice(userTk, payload)
})
})
The second is returning undefined in userRecusado:
exports.itemRecusado = functions.database.ref('/ItemDividirNegado/{itemId}').onCreate((snapshot, context) => {
const itemId = context.params.itemId;
const oRecusado = snapshot.val();
const userRecusado = oRecusado.userOrigem;
console.log(`item ${itemId} recusado ${userRecusado}`)
return pegaTokenUser(userRecusado).then(userTk =>{
let payload ={
notification: {
title: 'Solicitação - Notificação InfSocial',
body: `${oRecusado.userDestino} recusou compartilhar ${oRecusado.itemADV} com vc`,
sound: 'default',
badge: '1'
}
};
console.log(`${oRecusado.userDestino} recusou compartilhar ${oRecusado.itemADV} com vc`)
console.log(`token ${userTk}`)
return admin.messaging().sendToDevice(userTk, payload)
})
})
Here is the function to get the token from users:
function pegaTokenUser(userGet){
let userGet2 = userGet.replace ('.','')
let dbRef = admin.database().ref('/UserTokens');
let defer = new Promise((resolve, reject) => {
dbRef.once('value', (snap) => {
let data = snap.val();
let userTk;
for (var user in data) {
if(data[user].user === userGet2){
userTk = (data[user].token);
}
}
resolve (userTk)
},(err) => {
reject(err);
});
});
return defer
}
Does anyone know why this is happening? This two functions do the same thing, but the second one does not get the property of the created record.
The full file:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
exports.sendPush = functions.database.ref('/itemADividir/{itemId}').onCreate((snapshot, context) =>{
const oque = snapshot.val();
const quem = oque.userOrigem;
const itemADV = oque.itemAdividir;
const quanto = oque.itemValor;
return pegaTokenUser(oque.userDestino).then(userTk =>{
let payload ={
notification: {
title: 'Solicitação - Notificação InfSocial',
body: `${quem} quer compartilhar ${itemADV} no valor de ${quanto} com vc`,
sound: 'default',
badge: '1'
}
};
console.log(`${quem} quer compartilhar ${itemADV} no valor de ${quanto} com vc`)
console.log(`token ${userTk}`)
return admin.messaging().sendToDevice(userTk, payload)
})
})
exports.itemRecusado = functions.database.ref('/ItemDividirNegado/{itemId}').onCreate((snapshot, context) => {
const itemId = context.params.itemId;
const oRecusado = snapshot.val();
const userRecusado = oRecusado.userOrigem;
console.log(`item ${itemId} recusado ${userRecusado}`)
// the output
//itemRecusado
//item 1586992687992 recusado **undefined**
return pegaTokenUser(userRecusado).then(userTk =>{
let payload ={
notification: {
title: 'Solicitação - Notificação InfSocial',
body: `${oRecusado.userDestino} recusou compartilhar ${oRecusado.itemADV} com vc`,
sound: 'default',
badge: '1'
}
};
console.log(`${oRecusado.userDestino} recusou compartilhar ${oRecusado.itemADV} com vc`)
console.log(`token ${userTk}`)
return admin.messaging().sendToDevice(userTk, payload)
})
})
function pegaTokenUser(userGet){
let userGet2 = userGet.replace ('.','')
let dbRef = admin.database().ref('/UserTokens');
let defer = new Promise((resolve, reject) => {
dbRef.once('value', (snap) => {
let data = snap.val();
let userTk;
for (var user in data) {
if(data[user].user === userGet2){
userTk = (data[user].token);
}
}
resolve (userTk)
},(err) => {
reject(err);
});
});
return defer
}
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});
exports.TrocaEmoki = functions.database.ref('/Chat/{pathStr}/{tStamp}').onCreate((snapshot, context) =>{
const pathStr = context.params.pathStr;
const tStamp = context.params.tStamp;
console.log(`Nova mensagem ${tStamp} na mesa ${pathStr}`)
const mensagem = snapshot.val()
const text = addEmoji(mensagem.text)
return snapshot.ref.update({text})
})
function addEmoji(text) {
//return text.replace(/\bpizza\b/g, '🍕')
var regex1 = /pizza/,
regex2 = /hotdog/,
regex3 = /vinho/,
regex4 = /hamburguer/,
regex5 = /taco/,
regex6 = /fritas/,
regex7 = /sushi/,
regex8 = /churrasco/,
regex9 = /pipoca/,
regex10 = /peixe/,
regex11 = /cerveja/,
regex12 = /sorvete/,
alimento = text;
switch(true){
case regex1.test(alimento) :
return text.replace(/\bpizza\b/g, '🍕');
break;
case regex2.test(alimento):
return text.replace(/\bhotdog\b/g, '🌭');
break;
case regex3.test(alimento):
return text.replace(/\bvinho\b/g, '🍷');
break;
case regex4.test(alimento):
return text.replace(/\bhamburguer\b/g, '🍔');
break;
case regex5.test(alimento):
return text.replace(/\btaco\b/g, '🌮');
break;
case regex6.test(alimento):
return text.replace(/\bfritas\b/g, '🍟');
break;
case regex7.test(alimento):
return text.replace(/\bsushi\b/g, '🍣');
break;
case regex8.test(alimento):
return text.replace(/\bchurrasco\b/g, '🍖');
break;
case regex9.test(alimento):
return text.replace(/\bpipoca\b/g, '🍿');
break;
case regex10.test(alimento):
return text.replace(/\bpeixe\b/g, '🐟');
break;
case regex11.test(alimento):
return text.replace(/\bcerveja\b/g, '🍺');
break;
case regex12.test(alimento):
return text.replace(/\bsorvete\b/g, '🍨');
break;
default:
return text;
}
}
I found the problem. My code was inserting values one by one in Realtime database (name, than id, than item, than value...).
I did the same that was doing in the first case (make an object with values and than update the database with this object) and than update the database. That's it.
I am attempting to retrieve the boolean child (notificationsOn) of an object stored as a Firestore document to see if the rest of a function should be executed.
The overall function works to completion without this portion, but adding the portion from let threadDoc to the if statement presents a "threadDoc.get is not a function" error. I think my syntax is wrong but I don't know how, as a similar function works in a later part of the function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendDMNotification =functions.firestore.document('/dm_threads/{thread_id}/messages/{message_id}').onCreate((snapshot, context) => {
const newMessage = snapshot.data();
const senderName = newMessage.authorName;
const senderID = newMessage.authorUID;
const messageText = newMessage.message;
const recipientID = newMessage.recipientUID;
var notificationsOn = null;
let deviceTokenQuery = admin.firestore().collection(`/users/${recipientID}/device_tokens/`);
var idsToBeSorted = [senderID, recipientID];
idsToBeSorted.sort();
var threadID = idsToBeSorted[0] + idsToBeSorted[1];
console.log(recipientID);
console.log(threadID);
let threadDoc = admin.firestore().document(`users/${recipientID}/threads/${threadID}/`);
return threadDoc.get().then(doc => {
let notificationsOn = doc.data.notificationsOn;
console.log(notificationsOn);
if (notificationsOn !== false){
return deviceTokenQuery.get().then(querySnapshot => {
let tokenShapshot = querySnapshot.docs;
const notificationPromises = tokenShapshot.map(doc => {
let token_id = doc.data().tokenID;
const payload = {
data: {
title: senderName,
body: messageText,
senderID: senderID,
senderName: senderName
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response => {
console.log("Notification sent: ", response);
})
.catch(error => {
console.log("Error sending message: ", error);
});
});
return Promise.all(notificationPromises);
});
}
return;
});
});
admin.firestore().document() was supposed to be admin.firestore().collection(...).doc(...)
This fixed my problem
I think you meant to say admin.firestore() instead of functions.firestore.