const axios = require('axios'); const isProduction = require('vn-loopback/server/boot/isProduction'); module.exports = Self => { Self.remoteMethodCtx('sendQueued', { description: 'Send a RocketChat message', accessType: 'WRITE', returns: { type: 'object', root: true }, http: { path: `/sendQueued`, verb: 'POST' } }); Self.sendQueued = async() => { const models = Self.app.models; const chats = await models.Chat.find({ where: { status: { nin: [ 'sent', 'sending' ] }, attempts: {lt: 3} } }); for (let chat of chats) { if (chat.checkUserStatus) { try { await Self.sendCheckingUserStatus(chat); await Self.updateChat(chat, 'sent'); } catch (error) { await Self.updateChat(chat, 'error', error); } } else { try { await Self.sendMessage(chat.senderFk, chat.recipient, chat.message); await Self.updateChat(chat, 'sent'); } catch (error) { await Self.updateChat(chat, 'error', error); } } } }; /** * Check user status in Rocket * * @param {object} chat - The sender id * @return {Promise} - The request promise */ Self.sendCheckingUserStatus = async function sendCheckingUserStatus(chat) { const models = Self.app.models; const recipientName = chat.recipient.slice(1); const recipient = await models.VnUser.findOne({ where: { name: recipientName } }); const {data} = await Self.getUserStatus(recipient.name); if (data) { if (data.status === 'offline' || data.status === 'busy') { // Send message to department room const workerDepartment = await models.WorkerDepartment.findById(recipient.id, { include: { relation: 'department' } }); const department = workerDepartment && workerDepartment.department(); const channelName = department && department.chatName; if (channelName) return Self.sendMessage(chat.senderFk, `#${channelName}`, `@${recipient.name} ➔ ${chat.message}`); else return Self.sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); } else return Self.sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); } }; /** * Send a rocket message * * @param {object} senderFk - The sender id * @param {string} recipient - The user (@) or channel (#) to send the message * @param {string} message - The message to send * @return {Promise} - The request promise */ Self.sendMessage = async function sendMessage(senderFk, recipient, message) { if (!isProduction(false)) { return new Promise(resolve => { return resolve({ statusCode: 200, message: 'Fake notification sent' }); }); } const models = Self.app.models; const sender = await models.VnUser.findById(senderFk); const login = await Self.getServiceAuth(); const avatar = `${login.host}/avatar/${sender.name}`; const options = { headers: { 'X-Auth-Token': login.auth.token, 'X-User-Id': login.auth.userId }, }; return axios.post(`${login.api}/chat.postMessage`, { 'channel': recipient, 'avatar': avatar, 'alias': sender.nickname, 'text': message }, options); }; /** * Update status and attempts of a chat * * @param {object} chat - The chat * @param {string} status - The new status * @param {string} error - The error * @param {object} options - Query options * @return {Promise} - The request promise */ Self.updateChat = async(chat, status, error) => { return chat.updateAttributes({ status: status, attempts: ++chat.attempts, error: error }); }; /** * Returns the current user status on Rocketchat * * @param {string} username - The recipient user name * @return {Promise} - The request promise */ Self.getUserStatus = async function getUserStatus(username) { if (!isProduction(false)) { return new Promise(resolve => { return resolve({ data: { status: 'online' } }); }); } const login = await Self.getServiceAuth(); const options = { params: {username}, headers: { 'X-Auth-Token': login.auth.token, 'X-User-Id': login.auth.userId }, }; return axios.get(`${login.api}/users.getStatus`, options); }; };