From 3eac002fb47f9f50645ed7e4a839034e508561d3 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 3 Jun 2022 12:22:07 +0200 Subject: [PATCH] feat: add queue to send rocket messages --- back/methods/chat/send.js | 41 ++------ back/methods/chat/sendCheckingPresence.js | 61 ++--------- back/methods/chat/sendQueued.js | 119 ++++++++++++++++++---- db/dump/fixtures.sql | 4 +- 4 files changed, 124 insertions(+), 101 deletions(-) diff --git a/back/methods/chat/send.js b/back/methods/chat/send.js index fcb49f4b8..ece0d4994 100644 --- a/back/methods/chat/send.js +++ b/back/methods/chat/send.js @@ -1,4 +1,3 @@ -const axios = require('axios'); module.exports = Self => { Self.remoteMethodCtx('send', { description: 'Send a RocketChat message', @@ -31,39 +30,19 @@ module.exports = Self => { const recipient = to.replace('@', ''); if (sender.name != recipient) { - await sendMessage(sender, to, message); + await models.Chat.create({ + senderFk: sender.id, + recipient: to, + dated: new Date(), + checkUserStatus: 0, + message: message, + status: 0, + attempts: 0 + }); return true; } - - return false; }; - async function sendMessage(sender, channel, message) { - if (process.env.NODE_ENV !== 'production') { - return new Promise(resolve => { - return resolve({ - statusCode: 200, - message: 'Fake notification sent' - }); - }); - } - - 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': channel, - 'avatar': avatar, - 'alias': sender.nickname, - 'text': message - }, options); - } + return false; }; diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js index 2217aaee2..be233c96f 100644 --- a/back/methods/chat/sendCheckingPresence.js +++ b/back/methods/chat/sendCheckingPresence.js @@ -1,5 +1,3 @@ -const axios = require('axios'); - module.exports = Self => { Self.remoteMethodCtx('sendCheckingPresence', { description: 'Sends a RocketChat message to a connected user or department channel', @@ -36,6 +34,7 @@ module.exports = Self => { const models = Self.app.models; const userId = ctx.req.accessToken.userId; + const sender = await models.Account.findById(userId); const recipient = await models.Account.findById(recipientId, null, myOptions); // Prevent sending messages to yourself @@ -44,54 +43,14 @@ module.exports = Self => { if (!recipient) throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`); - 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(recipientId, { - include: { - relation: 'department' - } - }, myOptions); - const department = workerDepartment && workerDepartment.department(); - const channelName = department && department.chatName; - - if (channelName) - return Self.send(ctx, `#${channelName}`, `@${recipient.name} ➔ ${message}`); - else - return Self.send(ctx, `@${recipient.name}`, message); - } else - return Self.send(ctx, `@${recipient.name}`, message); - } - }; - - /** - * 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 (process.env.NODE_ENV !== 'production') { - 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); + return models.Chat.create({ + senderFk: sender.id, + recipient: `@${recipient.name}`, + dated: new Date(), + checkUserStatus: 1, + message: message, + status: 0, + attempts: 0 + }); }; }; diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js index 0598688e1..1b4e5d68c 100644 --- a/back/methods/chat/sendQueued.js +++ b/back/methods/chat/sendQueued.js @@ -16,33 +16,75 @@ module.exports = Self => { Self.sendQueued = async ctx => { const models = Self.app.models; - + const maxAttempts = 3; const sentStatus = 1; + const errorStatus = 2; + const chats = await models.Chat.find({ where: { - status: {neq: sentStatus} + status: {neq: sentStatus}, + attempts: {lt: maxAttempts} } }); for (let chat of chats) { - if (chat.checkUserStatus) - await sendCheckingPresence(ctx, chat); - else - await sendMessage(chat); + if (chat.checkUserStatus) { + try { + await sendCheckingUserStatus(chat); + await updateChat(chat, sentStatus); + } catch (error) { + await updateChat(chat, errorStatus); + } + } else { + try { + await sendMessage(chat.senderFk, chat.recipient, chat.message); + await updateChat(chat, sentStatus); + } catch (error) { + await updateChat(chat, errorStatus); + } + } } }; - async function sendCheckingPresence(ctx, chat) { + async function sendCheckingUserStatus(chat) { const models = Self.app.models; + + const recipientName = chat.recipient.slice(1); const recipient = await models.Account.findOne({ where: { - name: chat.recipient + name: recipientName } }); - await models.Chat.sendCheckingPresence(ctx, recipient.id, chat.message); - } - async function sendMessage(chat) { + const {data} = await 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 sendMessage(chat.senderFk, `#${channelName}`, `@${recipient.name} ➔ ${message}`); + else + return sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); + } else + return sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); + } + } + /** + * Update status and attempts of a chat + * + * @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 + */ + async function sendMessage(senderFk, recipient, message) { if (process.env.NODE_ENV !== 'production') { return new Promise(resolve => { return resolve({ @@ -52,11 +94,8 @@ module.exports = Self => { }); } - const sender = await models.Account.findOne({ - where: { - name: chat.senderFk - } - }); + const models = Self.app.models; + const sender = await models.Account.findById(senderFk); const login = await Self.getServiceAuth(); const avatar = `${login.host}/avatar/${sender.name}`; @@ -69,10 +108,54 @@ module.exports = Self => { }; return axios.post(`${login.api}/chat.postMessage`, { - 'channel': `@${chat.recipient}`, + 'channel': recipient, 'avatar': avatar, 'alias': sender.nickname, - 'text': chat.message + 'text': message }, options); } + + /** + * Update status and attempts of a chat + * + * @param {object} chat - The chat + * @param {string} status - The new status + * @return {Promise} - The request promise + */ + async function updateChat(chat, status) { + return chat.updateAttributes({ + status: status, + attempts: ++chat.attempts + }); + } + + /** + * Returns the current user status on Rocketchat + * + * @param {string} username - The recipient user name + * @return {Promise} - The request promise + */ + async function getUserStatus(username) { + if (process.env.NODE_ENV !== 'production') { + 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); + } }; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 23b9be646..225484ff0 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2562,7 +2562,9 @@ INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackage INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`) VALUES - (1101, 'PetterParker', '2022-06-02', 1, 'First test message', 0, 0); + (1101, '@PetterParker', CURDATE(), 1, 'First test message', 0, 0), + (1101, '@PetterParker', CURDATE(), 0, 'Second test message', 0, 0); + INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`) VALUES