From 68a7080a5b67c94395217756c9b7109afcc0ffc7 Mon Sep 17 00:00:00 2001 From: estevez-dev Date: Sun, 17 May 2020 00:44:52 +0300 Subject: [PATCH] WIP: actionable notifications --- functions/index.js | 16 +++--- functions/worker.js | 119 ++++++++++++++++++++------------------------ 2 files changed, 61 insertions(+), 74 deletions(-) diff --git a/functions/index.js b/functions/index.js index 002d673..9e9dcf7 100644 --- a/functions/index.js +++ b/functions/index.js @@ -75,7 +75,7 @@ exports.sendPushNotification = functions.https.onRequest(async (req, res) => { } if(docData.deliveredCount > MAX_NOTIFICATIONS_PER_DAY) { - return res.status(429).send({ + return res.status(429).json({ errorType: 'RateLimited', message: 'The given target has reached the maximum number of notifications allowed per day. Please try again later.', target: token, @@ -99,7 +99,7 @@ exports.sendPushNotification = functions.https.onRequest(async (req, res) => { await setRateLimitDoc(ref, docExists, docData, res); - return res.status(201).send({ + return res.status(201).json({ messageId: messageId, sentPayload: payload, target: token, @@ -138,7 +138,7 @@ function legacyGetCurrentRateLimitsDocName() { function legacyHandleError(res, step, incomingError) { if (!incomingError) return null; console.error('InternalError during', step, incomingError); - return res.status(500).send({ + return res.status(500).json({ errorType: 'InternalError', errorStep: step, message: incomingError.message, @@ -156,10 +156,10 @@ async function handleRequest(req, res, payloadHandler) { var today = getToday(); var token = req.body.push_token; if (!token) { - return res.status(403).send({ 'errorMessage': 'Missed token' }); + return res.status(403).json({ 'errorMessage': 'Missed token' }); } if (token.indexOf(':') === -1) { - return res.status(403).send({'errorMessage': 'Invalid token'}); + return res.status(403).json({'errorMessage': 'Invalid token'}); } var workerResult = payloadHandler(req); @@ -189,7 +189,7 @@ async function handleRequest(req, res, payloadHandler) { } if (updateRateLimits && docData.deliveredCount > MAX_NOTIFICATIONS_PER_DAY) { - return res.status(429).send({ + return res.status(429).json({ errorType: 'RateLimited', message: 'You have exited the maximum number of notifications allowed per day. Please try again later.', target: token, @@ -219,7 +219,7 @@ async function handleRequest(req, res, payloadHandler) { if (debug) console.log('Not updating rate limits because notification is critical or command'); } - return res.status(201).send({ + return res.status(201).json({ messageId: messageId, sentPayload: payload, target: token, @@ -255,7 +255,7 @@ function handleError(res, payload, step, incomingError) { } else { console.error('InternalError during', step, incomingError); } - return res.status(500).send({ + return res.status(500).json({ errorType: 'InternalError', errorStep: step, message: incomingError.message, diff --git a/functions/worker.js b/functions/worker.js index bfb2f72..e2d7285 100644 --- a/functions/worker.js +++ b/functions/worker.js @@ -1,70 +1,57 @@ module.exports = { - createPayload: function createPayload(req) { - let payload = { - android: {}, - data: {}, - fcm_options: { - analytics_label: "androidV1Notification" + createPayload: function createPayload(req) { + var payload = { + android: {}, + notification: {}, + data: { + click_action: "FLUTTER_NOTIFICATION_CLICK" + }, + }; + var updateRateLimits = true; + + if (req.body.data) { + // Allow setting of ttl + // https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidConfig.html#optional-ttl + if (req.body.data.ttl) { + payload.android.ttl = req.body.data.ttl + } + + // https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidConfig.html#optional-priority + if (req.body.data.priority) { + payload.android.priority = req.body.data.priority + } + + // https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidNotification.html + for (const key of [ + 'icon', 'color', 'sound', 'tag', 'clickAction', + 'bodyLocKey', 'bodyLocArgs', 'titleLocKey', 'titleLocArgs', 'channelId', + 'ticker', 'sticky', 'eventTime', 'localOnly', 'notificationPriority', + 'defaultSound', 'defaultVibrateTimings', 'defaultLightSettings', 'vibrateTimings', + 'visibility', 'notificationCount', 'lightSettings', 'image']) { + if (req.body.data[key]) { + payload.data[key] = String(req.body.data[key]) } - }; - let updateRateLimits = true; - - if(req.body.data){ - - // Handle the web actions by changing them into a format the app can handle - // https://www.home-assistant.io/integrations/html5/#actions - if(req.body.data.actions) { - for (let i = 0; i < req.body.data.actions.length; i++) { - const action = req.body.data.actions[i]; - if(action.action){ - payload.data["action_"+(i+1)+"_key"] = action.action - } - if(action.title) { - payload.data["action_"+(i+1)+"_title"] = action.title - } - if(action.uri){ - payload.data["action_"+(i+1)+"_uri"] = action.uri - } - } - } - - // Allow setting of ttl - // https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidConfig.html#optional-ttl - if(req.body.data.ttl){ - payload.android.ttl = req.body.data.ttl - } - - // https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidConfig.html#optional-priority - if(req.body.data.priority){ - payload.android.priority = req.body.data.priority - } - - // https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidNotification.html - for (const key of [ - 'icon', 'color', 'sound', 'tag', 'clickAction', - 'bodyLocKey', 'bodyLocArgs', 'titleLocKey', 'titleLocArgs', 'channelId', - 'ticker', 'sticky', 'eventTime', 'localOnly', 'notificationPriority', - 'defaultSound', 'defaultVibrateTimings', 'defaultLightSettings', 'vibrateTimings', - 'visibility', 'notificationCount', 'lightSettings', 'image' - ]) { - if(req.body.data[key]){ - payload.data[key] = String(req.body.data[key]) - } - } - } - - // Always put message, title, and image in data so that the application can handle creating - // the notifications. This allows us to safely create actionable/imaged notifications. - if(req.body.message) { - payload.data.message = req.body.message - if(req.body.message in ['request_location_update', 'clear_notification']) { - updateRateLimits = false - } - } - if(req.body.title) { - payload.data.title = req.body.title - } - - return { updateRateLimits: updateRateLimits, payload: payload }; + } } + + if (req.body.message) { + payload.data.message = req.body.message; + if (req.body.message in ['request_location_update', 'clear_notification']) { + updateRateLimits = false + } else { + payload.notification.body = req.body.message; + } + } + + if (req.body.title) { + payload.data.title = req.body.title + if (req.body.message in ['request_location_update', 'clear_notification']) { + updateRateLimits = false + } else { + payload.notification.title = req.body.title; + } + } + + return { updateRateLimits: updateRateLimits, payload: payload }; + } } \ No newline at end of file