Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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, i = 0
  let processRooms = (i, size, listIds) => {
    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))
  }
  processRooms(i, 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)
      }
    })
  })
}

...