Send notifications to android app using Firebase Functions - javascript

I am developing a chat app and so, I need to send notifications that new messages have been received.
For that, I am using Firebase Functions.
I'm using the sendToDevice function, that needs a token to send a notification. The problem is, I can't seem to retrieve token of the user that sent the message.
This is my .js code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref("/chats/{id}/messages/{messageId}/content")
.onWrite((change,context) => {
var content = change.after.val();
var payload = {
data:{
title: "Stranger has sent you a message",
text: content
}
};
// Here I need to the ID of the person who sent the message
// And then compare this Id with the two Ids of the to users that are in the conversation
// If the two Ids are different, then save the other Id as the token
// So that I can send a notification to the other user.
const senderId = database.ref("/chats/{id}/messages/{id}/sender/{senderId}");
admin.messaging().sendToDevice(senderId, payload)
.then(function(response){
console.log("Successfully sent message: ", response);
return null;
})
.catch(function(error){
console.log("Error sending message: ", error);
})
});
As you can see, I am checking for any changes in the messages/content child.
That as the content of my notification.
Then, I am trying to retrieve the message sender ID so I can know who sent the message and retrieve the other user Id to notify him.
This might be a little confusing so here is my Firebase Realtime Database:
What am I doing wrong so this piece of code works as it should? This is the activity I have in android to receive the message:
class MyFirebaseInstanceId : FirebaseMessagingService() {
override fun onMessageReceived(p0: RemoteMessage) {
if(p0.data.size > 0){
val payload :Map<String, String> = p0.data
sendNotification(payload)
}
}
private fun sendNotification(payload: Map<String, String>) {
val builder = NotificationCompat.Builder(this)
builder.setSmallIcon(R.drawable.common_google_signin_btn_icon_disabled)
builder.setContentTitle(payload.get("username"))
builder.setContentText(payload.get("email"))
val intent = Intent(this, MainActivity::class.java)
val stackBuilder = TaskStackBuilder.create(this)
stackBuilder.addNextIntent(intent)
val resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentIntent(resultPendingIntent)
val notificationManager = (getSystemService(Context.NOTIFICATION_SERVICE)) as NotificationManager
notificationManager.notify(0, builder.build())
}
}

Following our comments above, here is how to use the once() and val() methods in your Cloud Function:
//.....
const refSenderId = database.ref("/chats/{id}/messages/{id}/sender/{senderId}");
return refSenderId.once('value')
.then(dataSnapshot => {
const senderId = dataSnapshot.val();
return admin.messaging().sendToDevice(senderId, payload)
})
.then(function(response){
console.log("Successfully sent message: ", response);
return null;
})
.catch(function(error){
console.log("Error sending message: ", error);
return null; // <- Note the return here.
})
//.....

Related

How to get cloud function URL link?

This is my code of cloud function. I'm using it if data in Firebase changes it notify users. I have already deployed the cloud function but it is not giving me any cloud function URL.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.userStatusChange = functions.database.ref('/PatientReading/{$patient}/Humidty')
.onWrite(event => {
const original = event.data.val();
const previous = event.data.previous.val();
if (event.data.exists()) {
var title = "User Signed IN";
var body = "User " + original + " signed in";
}
var payload = {
notification: {
title: title,
body: body
}
};
var topic = "OnlineUsers";
return admin.messaging().sendToTopic(topic, payload)
.then(function(response) {
console.log("Successfully sent message:", response);
return true;
})
.catch(function(error) {
console.log("Error sending message:", error);
return true;
});
});
Your code is defining a Realtime Database trigger. These functions only run in response to changes in the database at the path you specify. These functions never have a URL - they can't be invoked directly.
If you need an URL to invoke some code in Cloud Functions, you will have to write an HTTP trigger.

Firebase cloud message not sending to device

I am trying to allow users to receive push notifications if an action happened ( like, comment, etc). In the log I sometimes get sucesscount: 1 however device does not receive a notification. But most of the time it is faliurecount:1 the second time. Regardless I am not getting the push notification. When I deployed my functions there was no errors.
When I do send myself a test message from Firebase cloud messaging, that however does work correctly and sends a push notification to everyones devices successfully.
Here is observing likes for example
exports.observeLikes = functions.database.ref('/user-likes/{uid}/{postId}').onCreate((snapshot, event) => {
var uid = event.params.uid;
var postId = event.params.postId;
return admin.database().ref('/users/' + uid).once('value', snapshot => {
var userThatLikedPost = snapshot.val();
return admin.database().ref('/posts/' + postId).once('value', snapshot => {
var post = snapshot.val();
if(uid === post.ownerUid) {
return Promise.resolve();
}
return admin.database().ref('/users/' + post.ownerUid).once('value', snapshot => {
var postOwner = snapshot.val();
var payload = {
notification: {
body: userThatLikedPost.username + ' liked your post ',
sound: 'default'
}
};
admin.messaging().sendToDevice(postOwner.fcmToken, payload)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
return response;
})
.catch((error) => {
console.log('Error sending message:', error);
throw new Error('Error sending message:', error);
});
})
})
})
})
Log
So I found the issue. I deleted the app from my device and created a new account ( and it created a new FCM token for the account) and push notifications does work. I did another check and manually changed the FCM token on another device to a new one it registered with , and push notifications are successful. It appears I now need to find a way to update every current test users FCM token because their current devices aren't receiving notifications.

RabbitMQ Node JS Validate User ID

I use RabbitMQ, SocketIO and MongoDB to make private messages for my app.
The plan is when new user register, app make new unique RabbitMQ Queue for that user, with that user is able to get messages when it is offline. So user send message through SocketIO and it is passed to RabbitMQ Publisher and then when consumer is online he get that message.
My questions now is how to set Validate User ID from sendToQueue (Publisher) function to be able later to read sender ID from consume function?
amqp.connect(CONN_URL, function(err, conn) {
conn.createChannel(function(err, channel) {
ch = channel;
console.log("RabbitMQ channel created...");
});
});
const publishToQueue = async (queueName, data) => {
ch.sendToQueue(queueName, Buffer.from(data.message));
};
const consumeToQueue = async queueName => {
ch.consume(
queueName,
function(msg) {
return msg.content.toString();
},
{ noAck: true }
);
};
I worked out...
const publishToQueue = async (queueName, data) => {
let properties = { headers: {userId: data.to }, timestamp: Date.now() };
ch.sendToQueue(queueName, Buffer.from(data.message), properties);
};
This will send headers with userId information and also timestamp of message

Message returned as undefined

I tried to send notifications through firebase functions when data is stored in my firebase database. It sends the message alright but a log tag I added to see if it got the name of the file that was uploaded to my firebase database came back as "Lecture note uploaded is: undefined". That's line 12 I don't understand why.
Below is my code.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.database.ref('/Lecture_Materials/{MIS}/{MISId}/name')
.onWrite(( change,context) =>{
// Grab the current value of what was written to the Realtime Database.
var eventSnapshot = change.after.val();
var str1 = "Lecture material uploaded is: " + eventSnapshot.name;
console.log(str1);
var topic = "Management.Information.System";
var payload = {
data: {
name: str1,
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(topic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
return;
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});

firebase functions push Notifications to specific user

i want to send Push notification via firebase functions to the user who posted the post when some other user likes his/her post.
i want to get the highlighted user-id in the image to get fcm token of this user id stored in other tree.
here is my firebase function code below.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/user-posts/{userID}/{pushId}/stars/')
.onWrite(event=> {
var request = event.data.val();
console.log("request",request);
console.log("key",Object.keys(request)[0]);
var key = Object.keys(request)[0];
var token;
const payload = {
notification: {
title: 'You have a new follower!',
body: 'is now following you.'
}
};
const getDeviceTokensPromise = admin.database()
.ref(`/users-notifications/${key}`)
.once('value').then(function(snapshot) {
console.log("val",snapshot.val());
token= snapshot.val();
admin.messaging().sendToDevice(token,payload)
.then(response=>{
console.log("Successfully sent message:", response);
})
.catch(function(error){
console.log("error sending message",error);
})
})
}, function(error) {
// The Promise was rejected.
console.error(error);
});
You can backwards traverse the DB tree by using the event ref's parent property.
userID = event.data.ref.parent.parent.parent.key
parent of event.data.ref is "stars"
parent of "stars" is your pushID
parent of pushID is userID
Try extracting it from the uri with event.params.userID

Categories

Resources