Skip to content

Commit

Permalink
Supports sending hide notification background pushes, small cleanups (#…
Browse files Browse the repository at this point in the history
…470)

* Supports sending hide notification background pushes, small cleanups
see openhab/openhab-addons#16934

Signed-off-by: Dan Cunningham <[email protected]>

* support tag as an alternative to severity

Signed-off-by: Dan Cunningham <[email protected]>

* Always set tag if severity is used

Signed-off-by: Dan Cunningham <[email protected]>

* protect against empty data values

Signed-off-by: Dan Cunningham <[email protected]>

---------

Signed-off-by: Dan Cunningham <[email protected]>
  • Loading branch information
digitaldan authored Jul 2, 2024
1 parent da5e4e7 commit 1346bd2
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 50 deletions.
105 changes: 57 additions & 48 deletions notificationsender/firebase.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const system = require('../system');
const firebase = require('firebase-admin');
const logger = require('../logger.js');
const redis = require('../redis-helper');
const crypto = require("crypto")
const crypto = require("crypto");

if (system.isGcmConfigured()) {
const serviceAccount = require(system.getFirebaseServiceFile());
Expand All @@ -22,62 +21,73 @@ function sendMessage(message) {
};

exports.sendFCMNotification = function (registrationIds, notification) {
// We can safely remove androidNotificationId, our android client has removed the need for this, but i need to double check
redis.incr("androidNotificationId", function (error, androidNotificationId) {
if (error) {
return;
}
const data = notification.payload;
let data = notification.payload;

//for IOS we need to set an actual notification payload so they show up when the app is not running
//we can remove badge/sound/alert after our IOS app dynamically adds these
const apns = {
payload: {
aps: {
'mutable-content': 1, // Enables mutable content for iOS
badge: 0,
sound: { name: 'default' },
alert: { body: data.message },
}
}
}
const apns = {
payload: {
aps: {}
},
headers: {}
}

const android = {
priority: 'high',
const android = {
priority: 'high',
}

// make sure all our values are strings per FCM requirements
Object.keys(data).forEach(key => {
const value = data[key];
if(value === undefined){
delete data[key]
} else if (typeof value !== 'string') {
data[key] = JSON.stringify(value)
}
})

const updatedData = {
type: 'notification',
severity: notification.severity || '',
icon: notification.icon || '',
persistedId: notification._id.toString(),
timestamp: notification.created.getTime().toString(),
notificationId: androidNotificationId.toString()
};
data.type = data.type || 'notification' // default to sending notifications

Object.assign(data, updatedData)
// this a silent/background notification
if (data.type === "hideNotification") {
// required for silent notifications on IOS
apns.payload.aps["content-available"] = 1
apns.headers["apns-priority"] = "5"
} else {
// Normal notification
data.persistedId = notification._id.toString()
data.timestamp = notification.created.getTime().toString()

if (data.actions) {
if (data.actions instanceof Array) {
data.actions = JSON.stringify(data.actions)
}
// for apple, create a unique hash for the category, secret sauce for dynamic actions
apns.payload.aps.category = crypto.createHash('sha256').update(data.actions).digest('hex');
// Setting title and body is really only necessary for the legacy IOS app (V1)
// The non-legacy app will set these from the payload data before surfacing the notification
apns.payload.aps = {
'mutable-content': 1, // allows for background processing - required
title: data.title,
badge: 0,
alert: { body: data.message },
sound: { name: 'default' }
}

if(data.title){
apns.payload.aps.alert.title = data.title
//set the user supplied id for the collapse header so notifications can be replaced with new ones
const refId = data["reference-id"]
if (refId) {
apns.headers["apns-collapse-id"] = refId;
android.collapseKey = refId;
}

const message = {
android: android,
apns: apns,
data: data,
tokens: Array.isArray(registrationIds) ? registrationIds : [registrationIds],
};
if (data.actions) {
// for apple, create a unique hash for the category, secret sauce for dynamic actions
apns.payload.aps.category = crypto.createHash('sha256').update(data.actions).digest('hex');
}
}

sendMessage(message);
});
const message = {
android: android,
apns: apns,
data: data,
tokens: Array.isArray(registrationIds) ? registrationIds : [registrationIds]
};
console.info("sending message", message)
//console.info("sending message", JSON.stringify(message, null, 2))
sendMessage(message);
};

exports.hideNotification = function (registrationIds, notificationId) {
Expand All @@ -93,6 +103,5 @@ exports.hideNotification = function (registrationIds, notificationId) {
priority: 'high',
}
};

sendMessage(message, data);
};
3 changes: 2 additions & 1 deletion notificationsender/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ function sendNotification(userId, data) {

var fcmRegistrations = [];
var iosDeviceTokens = [];
data.tag = data.tag || data.severity // tag is replacing severity in OH 4.2
var newNotification = new Notification({
user: userId,
message: data.message,
icon: data.icon,
severity: data.severity,
severity: data.tag, //legacy field
payload: data
});
newNotification.save(function (error) {
Expand Down
3 changes: 2 additions & 1 deletion routes/devices.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ exports.devicessendmessage = function (req, res) {
const message = req.form.messagetext;
const newNotification = new Notification({
user: req.user.id,
message: message
message: message,
payload: {message : message}
});
newNotification.save(function (error) {
if (error) {
Expand Down

0 comments on commit 1346bd2

Please sign in to comment.