how to receive notification payload from cloud function to website using javascript - javascript

I am currently learning firebase cloud functions and firebase cloud messaging so I am fairly new to cloud functions and FCM on the web. How can I be able to receive a notification payload from a cloud function and display that notification on the web page? I would like to utilise Firebase Cloud Messaging to do so. So far the documents are kind of confusing for me. The website is using Javascript. The code of the cloud function is below:
'use-strict'
const functions = require('firebase-functions');
const admin = require ('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.firestore.document("Employee_Details/{user_id}/Notifications/{notification_id}")
.onWrite((change , context) =>{
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
//console.log("User ID:" + user_id + "| Notification ID : " + notification_id);
return admin.firestore().collection("Employee_Details").doc(user_id)
.collection("Notifications").doc(notification_id).get().then(queryResult => {
const from_user_id = queryResult.data().from;
const from_description = queryResult.data().description;
const from_incident = queryResult.data().incident;
const receiver_id = queryResult.data().myId;
const from_data = admin.firestore().collection("Employee_Details").doc(from_user_id).get();
const to_data = admin.firestore().collection("Employee_Details").doc(user_id).get();
// console.log("FROM_DAT:" + from_data + "TO_DATA:" + to_data);
return Promise.all([from_data , to_data]).then(result => {
const from_name = result[0].data().first_name;
const to_name = result[1].data().first_name;
const token_id = result[1].data().token_id;
const payload = {
notification: {
title:"Notification from :" + from_name,
body :from_incident + ":" +from_description,
icon : "default",
},
data:{
message: from_description,
from_user_id : from_user_id,
receiver_id : receiver_id
}
};
return admin.messaging().sendToDevice(token_id , payload).then(reuslt =>{
return console.log("Notification sent.");
});
});
});
});

messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/firebase-logo.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});

Related

error Missing JSDoc comment require-jsdoc cloud functions firebase

Hi I am getting this lint error 'error Missing JSDoc comment require-jsdoc' in my index .js file when doing firebase deploy. Can anyone help?
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.announceProduct = functions.database
.ref("/products/{productID}")
.onCreate((event) => {
const product = event.val();
sendNotification(product);
return event.ref.set(product);
});
function sendNotification(product) {
const title = product.title;
const cost = product.cost;
const payload = {
notification: {
title: "New Product Available",
body: title + " for £ " + cost,
sound: "default",
},
};
console.log(payload);
const topic = "newProducts";
admin.messaging().sendToTopic(topic, payload);
}
Thanks :-)

Delay in FCM “Firebase” and sometimes working without any delay

I found bug in FCM. Notification is delayed for hours or minutes and sometimes without any delay without changing in code or internet speed or something else so I can't understand what is happening. There is SS show my console of functions in firebase https://imgur.com/1pi20fG
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Noti/{receiver_user_id}/{notification_id}')
.onWrite((data, context) =>
{
const receiver_user_id = context.params.receiver_user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification to send to :' , receiver_user_id);
if (!data.after.val())
{
console.log('A notification has been deleted :' , notification_id);
return null;
}
const DeviceToken = admin.database().ref(`/userstoken/${receiver_user_id}/token`).once('value');
return DeviceToken.then(result =>
{
const token_id = result.val();
const payload =
{
notification:
{
title: "New ",
body: `you have a new Chat Request, Please Check.`,
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload)
.then(response =>
{
console.log('This was a notification feature.');
});
});
});

How can I get different types of notification?

I don't know how to send different types of notification to the device from Firebase cloud function in index.js I want to send (comments notification)(like notification).
I am using this code to get following notification to device but I don't know how to get other.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/notification/{user_id}/{notification_id}').onWrite((change, context) => {
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification to send to : ', user_id);
const fromUser = admin.database().ref(`/notification/${user_id}/${notification_id}`).once('value');
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
const from_message = fromUserResult.val().message;
console.log('You have new notification from : ', from_user_id);
const userQuery = admin.database().ref(`users/${from_user_id}/username`).once('value');
const deviceToken = admin.database().ref(`users/${user_id}/device_token`).once('value');
return Promise.all([userQuery,deviceToken]).then(result =>{
const userName = result[0].val();
const token_id = result[1].val();
const payload1 = {
notification:{
title: "some is following you",
body: `${userName} is following you`,
icon: "default",
click_action : "alpha.noname_TARGET_NOTFICATION"
},
data:{
from_user_id:from_user_id
}
};
return admin.messaging().sendToDevice(token_id, payload1).then(result=>{
console.log("notification sent");
});
})
.then(response => {
console.log('This was the notification Feature');
return true;
}).catch(error => {
console.log(error);
//response.status(500).send(error);
//any other error treatment
});
});
});
You can change what you are sending to the /notification/${user_id}/${notification_id} node to include fields that will let you identify and create different notifications in the cloud function.
For example, you could add a type field and then:
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
const from_message = fromUserResult.val().message;
const from_type = fromUserResult.val().type;
Then you could build your notification based on type:
if(from_type === NOTIFICATION_FOLLOW){
payload1 = {
notification:{
title: "some is following you",
body: `${userName} is following you`,
icon: "default",
click_action : "alpha.noname_TARGET_NOTFICATION"
},
data:{
from_user_id:from_user_id
}
};
}else{
//set payload1 for a different notification
}
Add whatever fields are necessary for your payload and extend the control structure as needed.

Firebase TypeError: Cannot read property 'val' of undefined

I have tried Firebase cloud function for sending a notification.My project structure
and this is the index.js,
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.pushNotification = functions.database.ref('/messages').onWrite( event => {
console.log('Push notification event triggered');
const message = event.data.val();
const user = event.data.val();
console.log(message);
console.log(user);
const topic = "myTopic";
const payload = {
"data": {
"title": "New Message from " + user,
"detail":message,
}
};
return admin.messaging().sendToTopic(topic, payload);
});
The above code is misconfigured, when I deploy in Node.js, LOG in Function shows:
"TypeError: Cannot read property 'val' of undefined".
What Actually I am trying to do :
I am trying to extract info from snapshot load into that index.js so that when a new child gets added to Real-time database, it should trigger a notification payload with a title and body.
In Android, I use a child listener, for listening when a new record is added
FirebaseDatabase.getInstance().getReference().child("messages")
OnChildAdded(.....){
if (dataSnapshot != null) {
MessageModel messageModel = dataSnapshot.getValue(MessageModel.class);
if (messageModel != null) {
// do whatever
}
}
But in index.js, I could not able to parse that.
A bit guidance how to fixate index.js according to my database structure would be immensely appreciated.
PS- I have never done coding in JS
If you want more context, I'd be happy to provide it.
Change this:
exports.pushNotification = functions.database.ref('/messages').onWrite( event => {
const message = event.data.val();
const user = event.data.val();
});
to this:
exports.pushNotification = functions.database.ref('/messages').onWrite(( change,context) => {
const message = change.after.val();
});
Please check this:
https://firebase.google.com/docs/functions/beta-v1-diff#realtime-database
The cloud functions were changed and now onWrite has two parameters change and context
The change has two properties before and after and each of these is a DataSnapshot with the methods listed here:
https://firebase.google.com/docs/reference/admin/node/admin.database.DataSnapshot
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/NOTIFICATIONS/{UserId}/{{notification_id}').onWrite((change, context) =>
{
const UserId = context.params.UserId;
const notification = context.params.notification;
console.log('The user Id is : ', UserId);
if(!change.after.exists())
{
return console.log('A Notification has been deleted from the database : ', notification_id);
}
if (!change.after.exists())
{
return console.log('A notification has been deleted from the database:', notification);
return null;
}
const deviceToken = admin.database().ref(`/USER/${UserId}/device_token`).once('value');
return deviceToken.then(result =>
{
const token_id = result.val();
const payload = {
notification : {
title : "Friend Request",
body : "You've received a new Friend Request",
icon : "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response => {
console.log('This was the notification Feature');
});
});
});

Firebase Cloud Messaging for sending notification to all the registered devices not working

For my magazine app,I am using Firebase service.One function of this android app is whenever new article is published;notification of new article is sent to all the devices.
I am saving all the device tokens in db like this:
FCMToken
{
userid:deviceToken
}
So whenever new node is added in "published" key in firebase db,FCM function is triggered and messages is sent to all the devices:
Below is my code in javascript for FCM function:
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/published/{msg_id}').onWrite(event => {
const snapshot = event.data;
// Only send a notification when a new message has been created.
if (snapshot.previous.val()) {
return;
}
const msg_id = event.params.msg_id;
const msg_val=admin.database().ref(`messages/${msg_id}`).once('value');
return msg_val.then(msgResult =>{
const msg_title=msgResult.val().title;
const user_id=msgResult.val().userId;
console.log('msg title is',msg_title);
console.log('We have a new article : ', msg_id);
const payload={
data : {
title:"New Article",
body: msg_title,
msgid : msg_id,
userid : user_id
}
};
// const deviceToken = admin.database().ref('/FCMToken/{user_id}').once('value');
admin.database().ref('/FCMToken').on("value", function(dbsnapshot)
{
dbsnapshot.forEach(function(childSnapshot) {
//var childKey = childSnapshot.key;
const childData = childSnapshot.val();
const deviceToken=console.log("device token" + childSnapshot.val());
return admin.messaging().sendToDevice(childData,payload).then(response=>{
console.log("This was notification feature")
console.log("response: ", response);
})
.catch(function(error)
{
console.log("error sending message",error)
});
});
});
});
});
For some reason,notification is only sent to only 1 device(the first token in FCM node).
Update:
I have updated my code and using promise,but for some reason it is still not working,just sending notification to first device token.
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/published/{msg_id}').onWrite(event => {
const snapshot = event.data;
// Only send a notification when a new message has been created.
if (snapshot.previous.val()) {
return;
}
const msg_id = event.params.msg_id;
const msg_val=admin.database().ref(`messages/${msg_id}`).once('value');
return msg_val.then(msgResult =>{
const msg_title=msgResult.val().title;
const user_id=msgResult.val().userId;
console.log('msg title is',msg_title);
console.log('We have a new article : ', msg_id);
const payload={
data : {
title:"New Article",
body: msg_title,
msgid : msg_id,
userid : user_id
}
};
const promises=[];
// const deviceToken = admin.database().ref('/FCMToken/{user_id}').once('value');
admin.database().ref('/FCMToken').once('value').then(function(dbsnapshot)
{
dbsnapshot.forEach(function(childSnapshot) {
//var childKey = childSnapshot.key;
const childData = childSnapshot.val();
const deviceToken=console.log("device token" + childSnapshot.val());
const promise = admin.messaging().sendToDevice(childData,payload).then(response=>{
promises.push(promise)
console.log("This was notification feature")
console.log("response: ", response);
})
return Promise.all(promises)
.catch(function(error)
{
console.log("error sending message",error)
});
});
});
});
});
Response object is giving this output: response: { results: [ { error: [Object] } ],
canonicalRegistrationTokenCount: 0,
failureCount: 1,
successCount: 0,
multicastId: 6411440389982586000 }
You're not using promises correctly throughout your function. There are two things wrong.
First, you should be querying the database using once() instead of on(), and using the promise returned from it in order to proceed to the next item of work:
admin.database().ref('/FCMToken').on("value")
.then(result => /* continue your work here */)
Also, you can't return a promise out of the forEach loop. Instead, you need to return a promise at the top level of the function, as the very last step in the function. This promise needs to resolve when all of the work is done in this function. For your function, this means when all of the messages are sent. You'll have to collect all the promises for all of the messages in an array, then return a single promise that resolves when they all resolve. The general form of that looks like this:
const promises = []
dbsnapshot.forEach(function(childSnapshot) {
// remember each promise for each message sent
const promise = return admin.messaging().sendToDevice(...)
promises.push(promise)
})
// return a single promise that resolves when everything is done
return Promise.all(promises)
Please take care to learn how promises work in JavaScript. You won't be able to write effective functions without dealing with promises correctly.
So I figured out another method to get values.
const tokens= Object.keys(tokensSnapshot.val()).map(e => tokensSnapshot.val()[e]);
Below is my complete method:
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
//Object.values = require('object.values');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/published/{msg_id}').onWrite(event => {
const snapshot = event.data;
// Only send a notification when a new message has been created.
if (snapshot.previous.val()) {
return;
}
const msg_id = event.params.msg_id;
const msg_val=admin.database().ref(`messages/${msg_id}`).once('value');
return msg_val.then(msgResult =>{
const msg_title=msgResult.val().title;
const user_id=msgResult.val().userId;
console.log('msg title is',msg_title);
console.log('We have a new article : ', msg_id);
const payload={
data : {
title:"New Article",
body: msg_title,
msgid : msg_id,
userid : user_id
}
};
const getDeviceTokensPromise = admin.database().ref('/FCMToken').once('value');
return Promise.all([getDeviceTokensPromise, msg_title]).then(results => {
const tokensSnapshot = results[0];
const msgi = results[1];
if (!tokensSnapshot.hasChildren()) {
return console.log('There are no notification tokens to send to.');
}
console.log('There are', tokensSnapshot.numChildren(), 'tokens to send notifications to.');
console.log("tokenslist",tokensSnapshot.val());
const tokens= Object.keys(tokensSnapshot.val()).map(e => tokensSnapshot.val()[e]);
//var values = Object.keys(o).map(e => obj[e])
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
}
});
return Promise.all(tokensToRemove);
});
});
});
});

Categories