...
Edit package.json file, add a 2 new line lines for "request": "^2.88.0" and "emojione": "^4.5.0" to dependencies section as below
Code Block |
---|
{ "name": "functions", .... "engines": { "node": "816" }, "dependencies": { ..... "request": "^2.88.0", "emojione": "^4.5.0" }, .... } |
Then run cd functions/ && npm install (from project folder) to update project modules.
...
Code Block |
---|
const functions = require('firebase-functions') const admin = require('firebase-admin') const request = require('request') const emojione = require('emojione/lib/js/emojione') admin.initializeApp() const firestore = admin.firestore() exports.sendPushNotification = functions.firestore.document( 'rooms/{roomId}/messages/{messageId}').onCreate(event => { const writeData = event.data() const sender = writeData.sender const recipient = writeData.receiver const threadId = writeData.thread_id if (!writeData.sender_id || !writeData.server_key) { return false } const notifyTo = { recipient: recipient, sender_id: writeData.sender_id, server_key: writeData.server_key } firestore.doc('users/' + recipient).get().then(doc => { const senderData = doc.data() if (senderData.rooms) { let roomList = [], rooms = senderData.rooms, roomListId = [] for (let i in rooms) { let room = rooms[i] if (room.active && room.messages && room.id !== threadId) { roomList.push(room) } } roomList.sort(dynamicSort('-last_update')) for (let i = 0; i < roomList.length; i++) { roomListId.push(roomList[i].id) } let roomListIds = [], chunk = 10; for (let i = 0; i < roomListId.length; i += chunk) { if (roomListIds.length < 10) { roomListIds.push(roomListId.slice(i, i + chunk)) } else { break } } return processNotificationBadge(roomListIds, sender, recipient, writeData, notifyTo) } else { return prepareSendNotification(sender, writeData, notifyTo, 1) } }).catch(e => console.warn(e)) return true }) dynamicSort = (property) => { let sortOrder = 1 if (property[0] === "-") { sortOrder = -1 property = property.substr(1) } return (a, b) => { let result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0 return result * sortOrder } } processNotificationBadge = (roomListId, sender, recipient, writeData, notifyTo) => { let badge = 1 let processRooms = (i, size, listIds) => { if (size === 0 || typeof listIds[i] === "undefined") { return prepareSendNotification(sender, writeData, notifyTo, badge) } firestore.collection('rooms'). where('id', 'in', listIds[i]).get().then(snapShot => { if (snapShot.size) { snapShot.forEach(doc => { let roomData = doc.data() if (roomData && roomData['users'][recipient] && roomData['users'][recipient] > 0) { badge++ } }) } if (i === (size - 1)) { return prepareSendNotification(sender, writeData, notifyTo, badge) } else { return processRooms(i + 1, size, listIds) } }).catch(e => console.warn(e)) return true } processRooms(0, roomListId.length, roomListId) } prepareSendNotification = (sender, writeData, notifyTo, badge) => { let payload = {} firestore.doc('users/' + sender).get().then(doc => { const senderData = doc.data() payload = { notification: { title: senderData.name, body: writeData.text ? emojione.shortnameToUnicode(writeData.text) : '[FILE]', sound: 'default', badge: badge > 99 ? '99+' : badge.toString() }, data: { resource_link: 'chat/' + senderData.id, web_link: 'chat/' + senderData.id } } return getTokenToSend(payload, notifyTo) }).catch(e => console.warn(e)) return true }) function getTokenToSend = (payload, notifyTo) => { const recipientId = Buffer.from(notifyTo.recipient, 'base64'). toString('ascii') const notificationKeyName = 'user-' + recipientId return getNotificationKey({ senderId: notifyTo.sender_id, serverKey: notifyTo.server_key }, notificationKeyName). then(notificationKey => admin.messaging(). sendToDeviceGroup(notificationKey, payload)) } function getNotificationKey = (options, notificationTokenName) => { return new Promise((resolve, reject) => { request({ url: 'https://fcm.googleapis.com/fcm/notification', method: 'GET', json: true, headers: { Authorization: 'key=' + options.serverKey, project_id: options.senderId, 'Content-Type': 'application/json' }, qs: { notification_key_name: notificationTokenName } }, (error, httpResponse, body) => { if (!error && body.notification_key) { resolve(body.notification_key) } else { reject(error || body) } }) }) } |
...