I'm trying to get started with SendGrid and a Firestore database, using Firebase functions. I've gone through tutorials and set up according to the latest notation, (snap, context) instead of (event). I can't figure out what's wrong with this script:
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
//admin.initializeApp(functions.config().firebase);
const SENDGRID_API_KEY = my-api-key-is-here;
const sendgridemail = require('#sendgrid/mail');
sendgridemail.setApiKey(SENDGRID_API_KEY);
exports.confEmail = functions.firestore
.document('clients/{clientId}/projects/{projectId}/form-data/{docId}') //any write to this node will trigger email
.onCreate((snap, context) => {
const clientId = context.params.clientId;
const projectId = context.params.projectId;
const docId = context.params.docId;
const fsdb = admin.firestore();
return fsdb.collection('clients/'+clientId+'/projects/'+projectId+'/form-data').doc(docId)
.get()
.then(doc => {
const docData = doc.data()
const msgbody = {
to: docData.EMAIL,
from: 'xxxxx#gmail.com',
subject: 'Form Submission Confirmation',
templateId: 'd-07bf6a2b89084951a30ceddcd9c8915f',
substitutionWrappers: ['{{', '}}'],
substitutions: {
formdata: "Message Body\n<br>"+docData.CONF_MSG
}
};
return confEmail.send(msgbody)
})
.then(() => console.log('confimration mail sent success') )
.catch(err => console.log(err) )
});
The error message generated in the Firebase console is mysterious, and I'm not even sure how to interpret it.
ReferenceError: confEmail is not defined
at fsdb.collection.doc.get.then.doc (/user_code/index.js:48:13)
at process._tickDomainCallback (internal/process/next_tick.js:135:7
)
My best guess just that my 'confEmail' function is not defined because there's an error in it, but I can't figure out what. Or does it mean something else?
It looks like most of the tutorial scripts are over-complicating things. and a simpler script like this seems to work.
const sendgrid = require('#sendgrid/mail');
sendgrid.setApiKey(SENDGRID_API_KEY);
exports.confEmail = functions.firestore
.document('clients/{clientId}/projects/{projectId}/form-data/{docId}') //any write to this node will trigger email
.onCreate((snap, context) => {
const docData = snap.data();
const msgbody = {
to: docData.EMAIL,
from: 'xxxxxxx#gmail.com',
subject: 'Form Submission Confirmation',
templateId: 'd-07bf6a2b89084951a30ceddcd9c8915f',
substitutionWrappers: ['{{', '}}'],
substitutions: {
formdata: docData.CONF_MSG
}
};
return sendgrid.send(msgbody)
});
Related
I am using Firebase functions for Firestore database. I am trying to update a field based on the new tweet being added.
Here is my Firebase Function on production:
const admin = require('firebase-admin')
admin.initializeApp()
const db = admin.firestore()
const functions = require("firebase-functions");
functions.logger.log("START OF FUNCTION");
exports.myFunction = functions.firestore
.document('timelines/{userId}/tweets/{tweetId}')
.onCreate((change, context) => {
const userId = context.params.userId
const tweetId = context.params.tweetId
functions.logger.log(context.params.userId);
functions.logger.log(context.params.tweetId);
db.doc(`/timelines/${userId}/tweets/${tweetId}`).update({likeCount: 200})
})
I am triggering it through an iPhone app. I am logged in to my account and I add a new Tweet. The Firebase function does get called but userId and tweetId are undefined. I am not sure why they are undefined. Any ideas?
Without knowing your client-side logic it's difficult to know if there are other issues. I would suggest adding some error handling to narrow down the cause. You could also try pulling it from the data response instead of context (assuming the schema matches).
Also note using 'snap' instead of 'change' as change is generally reserved for 'onWrite' and 'onUpdate' hooks.
exports.myFunction = functions.firestore
.document('timelines/{userId}/tweets/{tweetId}')
.onCreate(async (snap, context) => {
try {
const { userId, tweetId } = snap.data();
functions.logger.log(userId);
functions.logger.log(tweetId);
return await db.doc(`/timelines/${userId}/tweets/${tweetId}`).update({ likeCount: 200 });
}
catch (error) {
functions.logger.log(error);
}
});
I have this cloud function in my index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
const db = admin.firestore();
const fcm = admin.messaging();
console.log("osakosak");
export const sendToDevice = functions.firestore
.document('orders/{orderId}')
.onCreate(async snapshot => {
console.log("osakosak2");
const order = snapshot.data();
const querySnapshot = await db
.collection('users')
.doc(order.ustaID)
.collection('tokens')
.get();
const tokens = querySnapshot.docs.map(snap => snap.id);
const payload: admin.messaging.MessagingPayload = {
notification: {
title: 'New Order!',
body: `you sold a ${order.day} for ${order.time}`,
click_action: 'FLUTTER_NOTIFICATION_CLICK'
}
};
return fcm.sendToDevice(tokens, payload);
});
However, when the document gets added a notification isn't sent. Nor is anything printed. I have deployed the function.
You need to check your function error logs in your firebase functions. Go to your function named sendToDevice and click show daily logs. Also be sure that collection and document names are correct. I had the same issue and I solved them by checking logs and correcting the collection/document names in function.
I have been reading around but cannot find the answer
I tried my firebase and it's not storing any data.
Here's the related inline editor
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
function angerEmotionCapture(agent) {
let angryTo = agent.parameters.angryDirectedTo;
agent.add(`love your ${angryTo},dude`);
return db.collection('directedTo').add({directedTo: angryTo});
}
Here's my firebase database
Any help will be greatly appreciated, thanks!
Please have a look into the following sample code showing how to connect Firebase's Firestore database to Dialogflow fulfillment hosting on Firebase functions:
'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 writeToDb (agent) {
// Get parameter from Dialogflow with the string to add to the database
const databaseEntry = agent.parameters.databaseEntry;
// Get the database collection 'dialogflow' and document 'agent' and store
// the document {entry: "<value of database entry>"} in the 'agent' document
const dialogflowAgentRef = db.collection('dialogflow').doc('agent');
return db.runTransaction(t => {
t.set(dialogflowAgentRef, {entry: databaseEntry});
return Promise.resolve('Write complete');
}).then(doc => {
agent.add(`Wrote "${databaseEntry}" to the Firestore database.`);
}).catch(err => {
console.log(`Error writing to Firestore: ${err}`);
agent.add(`Failed to write "${databaseEntry}" to the Firestore database.`);
});
}
// Map from Dialogflow intent names to functions to be run when the intent is matched
let intentMap = new Map();
intentMap.set('WriteToFirestore', writeToDb);
agent.handleRequest(intentMap);
});
Have a look into the Dialogflow's Firestore GitHub example
I'm having issues in retrieving a token saved in realtime database using cloud function's admin.database(). There is only one token to read from the child.
Firebase Database structure
Here's my code in Index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.database
.ref('/Logs/{LogsID}')
.onWrite( (change, context) => {
const notificationSnapshot = change.after.val();
const status = notificationSnapshot.Status;
const time = notificationSnapshot.Time;
const payload = {
notification: {
title : status,
body : time
}
}
console.info(notificationSnapshot);
const pushToken = admin.database().ref('/Tokens').once('child_added').then( (data) => {
const tokenSnapshot = data.val();
const finaltoken = tokenSnapshot.token;
console.info(finaltoken);
})
// Need help down here.
admin.messaging().sendToDevice(finaltoken, payload)
.then( () => {
console.log('Notification sent');
})
.catch( () =>{
console.log('Notification failed');
})
return null;
});
finalToken shows the correct token in log as expected. Log Showing the token
But I'm getting error while I'm passing the same token to admin.messaging(). Console is logging 'Notification sent' but not receiving a notification.
ReferenceError: finaltoken is not defined
at exports.sendNotification.functions.database.ref.onWrite (/user_code/index.js:43:36)
at cloudFunctionNewSignature (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:105:23)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:135:20)
at /var/tmp/worker/worker.js:827:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
It works when I directly pass the token like,
var finalToken = 'ephrj1........kndji'
so the admin.messaging() works, only passing the token is not working.
I'm new to Cloud Functions and javascript, so any help is much appreciated.
Final token is being retrieved in callback / async function.
That means that when you add it to .sendToDevice() the token is undefined because the async function has not retrieved the token from the database... yet.
const pushToken = admin.database().ref('/Tokens').once('child_added').then( (data) => {
const tokenSnapshot = data.val();
const finaltoken = tokenSnapshot.token;
console.info(finaltoken);
admin.messaging().sendToDevice(finaltoken, payload)
.then( () => {
console.log('Notification sent');
})
.catch( () =>{
console.log('Notification failed');
})
// I moved admin.messaging above this bracket
})
// It used to be here
return null;
Try putting the admin.messaging code within the code block of (data) => {}
By doing this we ensure that whenever we call sendToDevice() the token is defined.
I am facing an issue with my firestore cloud functions. I am trying to set up a trigger to send a notification when a new document is added.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
/*exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello ninjas!");
});*/
// Function to be called when new event occurs
const createNotification = notification => {
return admin
.firestore()
.collection("notifications")
.add(notification)
.then(doc => console.log("Notification added", doc));
};
//Trigger when new project is created
exports.projectCreated = functions.firestore
.document("project/{projectId}")
.onCreate(doc => {
const project = doc.data();
const notification = {
content: "Added a new project",
time: admin.firestore.FieldValue.serverTimestamp()
};
return createNotification(notification);
});
On the client side when I add a new project I am able to see the console message that notification is added but when I check the logs in the Cloud function I cannot see any logs. Am I missing anything here?
Replace
.onCreate(doc => {
with
.onCreate((snap, context) => {
as described at
https://firebase.google.com/docs/functions/beta-v1-diff#cloud-firestore