How to send notification with functions firebase/firestore - firebase

I have a little problem. I want to send notifications when someone add comment to posts in my app. I dont use database only firestore. I have something like this for now.
export const sendNotification = functions.firestore
.document('Comments/{commentId}')
.onCreate((snap, context) => {
const senderUid = snap.get('idUser');
const receiverUid = snap.get('idUserImage');
const comment = snap.get('comment');
});
Now how to send ntification to receiverUid with text - comment?

You have to use Firebase Cloud Messaging.
Take a look on this example: https://github.com/flutter/plugins/blob/master/packages/firebase_messaging/example/lib/main.dart

Related

Send an email using Firebase Cloud Functions in React Native

I would like to send emails in my React Native using Firebase Cloud Functions. Users should be able to send an email for reporting issues/feedback in the app. I have created a text input and a button in my react native app. The user should be able to specify their issue/feedback in the text input box and when they press the button I will receive their response as an email in my gmail or hotmail account. Can I achieve this using onCreate in Firebase Cloud Functions? If so how can I achieve this? What would the onCreate method look like as well as the button function in react native? I am very new to react native and firebase cloud functions. Unfortunately, I haven't seen any links about this.
Thank you.
Please see below:
const nodemailer = require('nodemailer');
const email = functions.config().email_credentials.email;
const password = functions.config().email_credentials.password;
const mailTransport = nodemailer.createTransport(`smtps://${email}:${password}#smtp.gmail.com`);
functions.database.ref('/feedbacks/{currentId}').onCreate((snapshot, context) => {
const feedback = snapshot.val().feedback;
const name = snapshot.val().name;
const mailOptions = {
from: snapshot.val().email,
replyTo: snapshot.val().email,
to: functions.config().email_credentials.email,
subject: `Feedback from `+name,
html: feedback,
};
try {
mailTransport.sendMail(mailOptions);
} catch(error) {
console.log(error);
}
return null;
});
Realtime database:
Your cloud function could look like this:
import * as functions from "firebase-functions";
import admin from "firebase-admin";
import nodemailer from "nodemailer";
const { email, password } = functions.config().gmail;
const mailTransport = nodemailer.createTransport(
`smtps://${email}:${password}#smtp.gmail.com`
);
export default functions.database
.ref("/feedbacks/{uid}")
.onCreate(async (eventSnapshot, context) => {
const data = eventSnapshot.val();
const { feedback } = data;
const mailOptions = {
from: functions.config().email_credentials.email,
replyTo: functions.config().email_credentials.email,
to: snapshot.val().email,
subject: `Feedback from `+name,
html: feedback,
};
await mailTransport.sendMail(mailOptions);
return null;
});
Make sure to save your email credentials under the firebase cloud function configs and NOT in the code. If you put it anywhere in the code it could potentialy been read by someone in some time. This is very importand.
In your Gmail ensure "Unsercure Apps" are enabled. More about it here.
Now if someon adds some data to the path feeds and email will be send.
Don't forget to deplyo your function with the configs.

Is there a way to get email or text notifications each time data is written to my Google Cloud Firestore bucket?

I have a google cloud bucket and firebase writes my app data there. I would like to monitor my data, and have any new update (write) to my firebase database it sent via a text or email to me. I currently have Twilio set up on Nodejs to send texts on Firebase and my code is:
const functions = require('firebase-functions');
var twilio = require('twilio');
const admin = require('firebase-admin');
admin.initializeApp();
var accountSid = 'account id'; // Account SID from www.twilio.com/console
var authToken = 'account token'; // Auth Token from www.twilio.com/console
var client = new twilio(accountSid, authToken);
exports.useWildcard = functions.firestore
.document('comments/{commentContent}')
.onWrite((change, context) => {
client.messages.create({
body: context.params.commentContent,
to: '+15555555555', // Text this number
from: '+15555555556' // From a valid Twilio number
})
.then((message) => console.log(message.sid));
});
Currently, I would like to build it out for just the comments document, which are organized inside firebase through comments/{commentContent}. Later, I would like to expand to other trees. I am however, unsure if the above will run each time there is a write to my comments tree. Does it require the firebase-admin module as I have put above? Thanks!
Yes, the onWrite method will not only run when there is a write to the comments tree, but will also be triggered by any change in any document and on the deletion of a document. This means that right now your code will responde in the same way to any of the above cases, and this could cause problems, especially in the case of a document being deleted since it will try to send a comment that doesent exist and will likely get some null exceptions.
Said that you have different solutions.
If you only want the function to react to a new comment, but not to an update or deletion you should use onCreate trigger instead of onWrite.
If you also want to handle a comment update notification you can use both onCreate and onUpdate, but sending different messages by doing something like:
exports.useWildcardCreate = functions.firestore
.document('comments/{commentContent}')
.onCreate((change, context) => {
client.messages.create({
body: context.params.commentContent,
to: '+15555555555', // Text this number
from: '+15555555556' // From a valid Twilio number
})
.then((message) => console.log(message.sid));
});
exports.useWildcardUpdate = functions.firestore
.document('comments/{commentContent}')
.onUpdate((change, context) => {
const newComment = change.after.data();
const previuosComment = change.before.data();
client.messages.create({
body: 'The comment ${previuosComment} has been changed to ${newComment}',
to: '+15555555555', // Text this number
from: '+15555555556' // From a valid Twilio number
})
.then((message) => console.log(message.sid));
});
At last if you also need to notify when a comment has been deleted you should use onWrite method but differentiating between the 3 different cases as shown below:
exports.useWildcard = functions.firestore
.document('comments/{commentContent}')
.onWrite((change, context) => {
var textBody;
const oldComment = change.before.data();
const newComment = change.after.data();
if (change.after.exists == false) { // comment has been deleted
textBody = 'The comment ${oldComment} has been deleted';
}
else if (oldComment != newComment) { // comment has been updated
textBody = 'The comment ${oldComment} has been changed to ${newComment}';
}
else { // if its not an update or a deletion its a new comment
textBody = newComment;
}
client.messages.create({
body: textBody,
to: '+15555555555', // Text this number
from: '+15555555556' // From a valid Twilio number
})
.then((message) => console.log(message.sid));
});
Finally require('firebase-admin') is needed since it will allow you to interact with Firebase from privileged environments. Here you can find all the information to the Firebase Admin SDK

Making automated notifications with Firebase Cloud Functions, Messaging,Firestore

I've been trying to push notifications with .onUpdate() trigger but It doesn't work. I'm not sure what is wrong since anything I find on docs is useless pretty much and it's my first time working with Node.js.
I want to notify the user (with Firebase Messaging) when any product gets updated (in Firebase Realtime Database) using Firebase Cloud Functions, which is after submitting an order, and the requirement is that the product stock is <= 5.
Structure of the collection is like this:
products (collection) -> {productID} (document) -> attributes: {name, barcode, price, stock, sold}
//import firebase
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/products/{product}')
.onUpdate((change, context) => {
const prodName = context.data.child('name');
const numProd = context.data.child('stock');
if(numProd<=5){
const payload = {
notification: {
title: 'Low stock!',
body: `Product ${prodName} is running out.`
}
}
const registrationToken = 'token';
return admin.messaging().sendToDevice(registrationToken,payload)
.then(function(response){
console.log('Notification sent successfully:',response);
return 1;
})
.catch(function(error){
console.log('Notification sent failed:',error);
});
}
});
Apparently you are mixing up the two Firebase's database services: Firestore and the Realtime Database.
As a matter of fact, you indicate that your data is organised in collections ("Structure of the collection is like this: products (collection) -> {productID} (document)") which means that you are using Firestore (Realtime Database doesn't have collections).
But your background trigger is corresponding to a Realtime Database trigger, see https://firebase.google.com/docs/functions/database-events.
If the assumption that you are mixing up the two database services is right, you need to use a background trigger for Firestore, see https://firebase.google.com/docs/functions/firestore-events, in particular the onUpdate() one, as follows:
exports.updateUser = functions.firestore
.document('/products/{productId}')
.onUpdate((change, context) => {
// Get an object representing the document
const newValue = change.after.data();
const prodName = newValue.name;
const numProd = newValue.stock;
// ...
});
Note that it seems that you are not handling correctly the case when numProd > 5. You may throw an error or just do return null;
It is a also a good idea to watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/.

How to delete image stored in Firebase storage after triggering Firestore onDelete in Cloud Function?

I want to use a cloud function background trigger, so when I delete a user data in Firestore, I want to also delete their profile picture in the Firebase storage.
the userID is used as the image name of that picture. and the image is located inside the profilepicture folder
export const removeProfilePictureWhenDeletingUserData = functions.firestore
.document('userss/{userID}')
.onDelete((snap, context) => {
const userID = context.params.userID
// how to delete the image in here?
});
I have tried to read the documentation, but I am confused about how to implement that method :(. really need your help. thanks in advance
The following Cloud Function code will do the job.
// Adapted following Doug's advice in his comment //
....
const admin = require('firebase-admin');
admin.initializeApp();
....
var defaultStorage = admin.storage();
exports.removeProfilePictureWhenDeletingUserData = functions.firestore
.document('users/{userID}')
.onDelete((snap, context) => {
const userID = context.params.userID;
const bucket = defaultStorage.bucket();
const file = bucket.file('profilePicture/' + userID + '.png');
// Delete the file
return file.delete();
});
See the following doc items for more detail:
https://firebase.google.com/docs/reference/admin/node/admin.storage.Storage
https://cloud.google.com/nodejs/docs/reference/storage/1.7.x/File#delete

Firebase Functions - push notification when new document is created

I have the following Firestore DB structure:
users
$USER_ID
notifications
$DOC1
$DOC2
$DOC3
I want to push a new notification when a document is created at the user notification collection.
It should be something like this, but I don't know of any way to this for each $UID:
exports.newSubscriberNotification = functions.firestore
.document('users/$UID/notifications')
.onCreate(async event => {
How can I use Firebase Functions to do this? If there is no way, any suggestions for a workaround?
You should use the following code to trigger your Cloud Function:
exports.newSubscriberNotification = functions.firestore
.document('users/{userId}/notifications/{docId}')
.onCreate((snap, context) => {
//You get the values of the newly created doc as follows:
const newValue = snap.data();
console.log(newValue);
//You get the parameters as follows:
const userId = context.params.userId;
//console.log(userId);
const docId = context.params.docId;
//console.log(docId);
// You perform here the notification sending
});
For the code for the notification sending, have a look at this official Firebase Cloud Function sample: https://github.com/firebase/functions-samples/blob/master/fcm-notifications/functions/index.js

Resources