...
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)
}
})
})
}
|
...