User name empty when sending notification with firebase - javascript

I want to send notification to users when they receive new messages with the below JavaScript code
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.pushNotification = functions.database.ref('/messages/{user_id}/{message_id}').onWrite( (change, context) => {
const user_id = context.params.user_id;
const message_id = context.params.message_id;
console.log('We Have A Notification for :', user_id);
if (!change.after.val()){
return console.log("A Notification Has Been Deleted From The Database: ", message_id)
}
const fromUser = admin.database().ref(`/messages/${user_id}/${message_id}`).once('value');
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
console.log("You have new notification from : ", from_user_id)
const userQuery = admin.database().ref(`/Users/${from_user_id}/name`).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 payload = {
notification: {
title: "Chat+",
body: `You have a new notification from ${userName}`,
icon: "default",
click_action: "com.mani.eric.quickch_TARGET_NOTIFICATION"
},
};
return admin.messaging().sendToDevice(token_id, payload ).then(Response =>{
console.log('this is the notification')
});
});
});
});
the notification actually gets delivered but on both devices(sender and receiver gets same notification) with the user name of the sender as null.
my question now is, how can i retrieve the sender user name and display the notification only on the receivers device?

You have a type on the path that triggers the function:
functions.database.ref('/messages/{user_id/{message_id}')
Should be:
functions.database.ref('/messages/{user_id}/{message_id}')
So with a closing parenthesis after user_id.
Please read how to create a minimal, complete, verifiable example, as the code you shared is quite a bit more complex than needed to reproduce the problem. For example, your console.log('We Have A Notification for :', user_id); already should show that user_id is null, so the code after that can't work, and is irrelevant to the problem. Reducing the scope of the problem this way increases the chances that you'll find the cause yourself. Or at worst, it reduces the code we need to look at, which increases the chance that somebody will spot the problem and answer.

Related

Firebase Funtions push notifications

I'm new to firebase and there is something I can't do. I want to send a notification to the phone with firebase functions. I want to receive notifications on the phone when someone follows me. My Firebase collection is as in the photo. I want to access the Followers array and send its information with notification. The codes I could write are as follows. What do I need to add?
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.sendPushNotification = functions.firestore.document('/users/{uid}').onCreate((snap, context) => {
var values = snap.data();
var token = values.fcmTokens;
var payload = {
notification: {
title: values.title,
body: values.message
}
}
return admin.messaging().sendToDevice(token, payload);
});
First, onCreate() function is triggered when a document is created. I assume followers array will be updated everytime someone follows a user? In that case you should be using onUpdate() that'll trigger the function when the document is updated. You can just check if length of followers array has changed in the update, if yes then send the notification as shown below:
exports.sendPushNotification = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const newValue = change.after.data();
const previousValue = change.before.data();
if (newValue.followers.length > previousValue.followers.length) {
// followers count increased, send notification
const token = newValue.fcmTokens;
const payload = {
notification: {
title: "New Follower",
body: "Someone followed you"
}
}
await admin.messaging().sendToDevice(token, payload);
}
return null;
});
Here, we send notification only if the followers field has changed since this function will trigger whenever any field in this user document is updated.
If you want to specify who followed the user, then you'll have to find the new UID added in followers array and query that user's data.
Firestore documents have a max size limit of 1 MB so if a user can have many followers then I'll recommend creating a followers sub-collection. Then you'll be able to use onCreate() on the sub-document path /users/{userId}/followers/{followerId}

Firebase Listener for specific text in reference

Firebase Event Listener. I want to execute if data says: "friend request" and not just on data change.
I've tried to search for listeners. I found:
https://firebase.google.com/docs/database/admin/retrieve-data
I feel like I'm close, but I need help with the specifics.
exports.sendNotification = functions.database.ref('/Notifications/{user_id}/{notification_id}').onWrite((change, context) => {
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
const deviceToken = admin.database().ref('/' + user_id +'/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! <3",
icon: "default"
}
};
});
});
My code executes(as expected), both when I write but also when I delete. However: Is there a way to instead, check if something specific is written to the database?
Bear with me, coming from java. But something like:
functions.database.ref('/Notifications/{user_id}/{notification_id}/type("friend request")')
.onWrite((write, context) => {.....
I want a listener, to check what data/notification type, I'm writing to the database. And then execute accordingly.
Best regards.
If I understand correctly, you need to do as follows, checking the value of type:
exports.sendNotification = functions.database.ref('/Notifications/{user_id}/{notification_id}').onWrite((change, context) => {
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
const afterData = change.after.val();
if (afterData.type === "friend request") {
const deviceToken = admin.database().ref('/' + user_id + '/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! <3",
icon: "default"
}
};
//Here you need to return the promise returned by an asynchronous operation, probably return admin.messaging()....
});
} else {
console.log("Not a friend request");
return null;
}
});
You can limit when a Cloud Function gets triggered:
by the path that data is written to, and
by the type of write operation (create, update, delete) that is being performed.
There is no way to limit the Cloud Functions trigger on the content that is being written.
If you must filter on the content, you will have to do that inside of the code of your Cloud Function, as Renaud's answer shows.
Alternatively, you can consider moving the relevant value into the path of the write operation. For example, you could put all friend requests into a separate path in your database (e.g. "friend_requests") and then have the Cloud Function trigger only on that path.
If you only want to trigger your Cloud Function when a new request is written, and not on a delete, you can change your declaration to onCreate:
exports.sendNotification = functions.database.ref('/Notifications/{user_id}/{notification_id}')
.onCreate((snapshot, context) => {

Make many types of notification in same app in FCM by Functions which written by JavaScript in android/java

I build an app which i need to add in it many types of notifications but i can't do it with myself because am have tiny knowledge about JS
I tried to deploy many functions by differnt body , title ..etc but it seems not able to deploy many functions in Firebase Functions
'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(`/user/${receiver_user_id}/token`).once('value');
return DeviceToken.then(result =>
{
const token_id = result.val();
const payload =
{
notification:
{
title: "Open this notification now",
body: `I have a problem in my car `,
icon: "default" ,
sound: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload)
.then(response =>
{
console.log('This was a notification feature.');
});
});
});
thats all i have to describe my issue
Yes, you can deploy various functions, but you need to set different names for each one of them. The function name is after exports., so you can have:
exports.sendNotification
exports.newMessageNotification
exports.newFollowerNotification
...
and each one of them will make what you wish them to do.

Push Notification from Firestore

I need to send notification when data change in my Cloud Firestore database. I have this fields
I need to get the all users tokens and send the push notification. I have a code, but this only give me a token if i know the user name this is my code :
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.useWildcard = functions.firestore
.document('notification/{id}')
.onWrite((change, context) => {
const payload = {
notification: {
title: 'Message from Cloud',
body: 'This is your body',
badge: '1',
sound: 'default'
}
};
admin.firestore().collection('notification').doc('fcm-token').get().then(doc => {
console.log("Token: " + doc.data().user1.token);
});
});
To loop over all users in the document:
admin.firestore().collection('notification').doc('fcm-token').get().then(doc => {
let data = doc.data();
Object.keys(data).forEach((user) {
console.log("Token: " + data[user].token);
});
});
But as Doug commented: storing the tokens for all users in a single document is bound to become a scalability problem at some point.

Use UID for path in Firebase Cloud Functions

There are a-lot of answers on Stack Overflow about how to get the uid once you do an onCreate() in cloud functions, but none to use the uid as a path. In my situation I want to monitor when a particular user gains a follower. I then what to alert that user that they have gained a follower.
Here is my code:
console.log('uid valll ' + exports.auth.uid)
exports.announceFollower = functions.database
.ref('users/{exports.auth.uid}/followers/{followerId}')
.onCreate(event => {
let follower = event.data.val()
sendNotification(follower)
})
function sendNotification(follower){
let uid = follower.val
let payload = {
notification: {
title: 'New Follower',
sound: 'default'
}
}
console.log(payload)
let topic = functions.database.ref('users/{exports.auth.uid}/followerTopicId')
console.log('topic val' + topic)
admin.messaging().sendToTopic(topic.val , payload)
}
where it says exports.auth.uid I am attempting to grab to uid of the currently logged in user.
I try that using this function :
exports.auth = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const tokenId = req.get('Authorization').split('Bearer ')[1];
return admin.auth().verifyIdToken(tokenId)
.then((decoded) => res.status(200).send(decoded))
.catch((err) => res.status(401).send(err));
});
});
Yet I get the message in Firebase cloud func console :
uid valll undefined
After reviewing the documentation here:
https://firebase.google.com/docs/functions/database-events
It still is unclear. What is the appropriate way to access the uid of a currently logged in user For path usage?

Categories

Resources