From 7de0fd6634c9f10ff14b8d05e251e3370aa8d7bf Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 1 Jun 2022 13:49:45 +0200 Subject: [PATCH 1/8] feat: create table chat --- back/methods/chat/sendQueued.js | 69 +++++++++++++++++++++++++++++ db/changes/10470-family/00-chat.sql | 10 +++++ 2 files changed, 79 insertions(+) create mode 100644 back/methods/chat/sendQueued.js create mode 100644 db/changes/10470-family/00-chat.sql diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js new file mode 100644 index 000000000..d31ff9686 --- /dev/null +++ b/back/methods/chat/sendQueued.js @@ -0,0 +1,69 @@ +const axios = require('axios'); +module.exports = Self => { + Self.remoteMethodCtx('sendQueued', { + description: 'Send a RocketChat message', + accessType: 'WRITE', + accepts: [{ + arg: 'to', + type: 'string', + required: true, + description: 'User (@) or channel (#) to send the message' + }, { + arg: 'message', + type: 'string', + required: true, + description: 'The message' + }], + returns: { + type: 'object', + root: true + }, + http: { + path: `/sendQueued`, + verb: 'POST' + } + }); + + Self.sendQueued = async(ctx, to, message) => { + const models = Self.app.models; + const accessToken = ctx.req.accessToken; + const sender = await models.Account.findById(accessToken.userId); + const recipient = to.replace('@', ''); + + if (sender.name != recipient) { + await sendMessage(sender, to, message); + + 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); + } +}; diff --git a/db/changes/10470-family/00-chat.sql b/db/changes/10470-family/00-chat.sql new file mode 100644 index 000000000..0c03f2bcb --- /dev/null +++ b/db/changes/10470-family/00-chat.sql @@ -0,0 +1,10 @@ +CREATE TABLE `vn`.`chat` ( + `id` int(11) DEFAULT NULL, + `senderFk` int(11) DEFAULT NULL, + `recipient` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `dated` date DEFAULT NULL, + `checkUserStatus` tinyint(1) DEFAULT NULL, + `message` varchar(200) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `status` tinyint(1) DEFAULT NULL, + `attempts` int(1) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci \ No newline at end of file From f6028316f4661d19707966b34575a0df9bebb66e Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 2 Jun 2022 14:55:39 +0200 Subject: [PATCH 2/8] feat: endpoint sendQueued addded --- back/methods/chat/sendQueued.js | 55 +++++++++++++++++------------ back/models/chat.js | 1 + back/models/chat.json | 33 +++++++++++++++++ db/changes/10470-family/00-chat.sql | 15 ++++---- db/dump/fixtures.sql | 6 +++- 5 files changed, 80 insertions(+), 30 deletions(-) diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js index d31ff9686..0598688e1 100644 --- a/back/methods/chat/sendQueued.js +++ b/back/methods/chat/sendQueued.js @@ -3,17 +3,7 @@ module.exports = Self => { Self.remoteMethodCtx('sendQueued', { description: 'Send a RocketChat message', accessType: 'WRITE', - accepts: [{ - arg: 'to', - type: 'string', - required: true, - description: 'User (@) or channel (#) to send the message' - }, { - arg: 'message', - type: 'string', - required: true, - description: 'The message' - }], + accepts: [], returns: { type: 'object', root: true @@ -24,22 +14,35 @@ module.exports = Self => { } }); - Self.sendQueued = async(ctx, to, message) => { + Self.sendQueued = async ctx => { const models = Self.app.models; - const accessToken = ctx.req.accessToken; - const sender = await models.Account.findById(accessToken.userId); - const recipient = to.replace('@', ''); - if (sender.name != recipient) { - await sendMessage(sender, to, message); + const sentStatus = 1; + const chats = await models.Chat.find({ + where: { + status: {neq: sentStatus} + } + }); - return true; + for (let chat of chats) { + if (chat.checkUserStatus) + await sendCheckingPresence(ctx, chat); + else + await sendMessage(chat); } - - return false; }; - async function sendMessage(sender, channel, message) { + async function sendCheckingPresence(ctx, chat) { + const models = Self.app.models; + const recipient = await models.Account.findOne({ + where: { + name: chat.recipient + } + }); + await models.Chat.sendCheckingPresence(ctx, recipient.id, chat.message); + } + + async function sendMessage(chat) { if (process.env.NODE_ENV !== 'production') { return new Promise(resolve => { return resolve({ @@ -49,6 +52,12 @@ module.exports = Self => { }); } + const sender = await models.Account.findOne({ + where: { + name: chat.senderFk + } + }); + const login = await Self.getServiceAuth(); const avatar = `${login.host}/avatar/${sender.name}`; @@ -60,10 +69,10 @@ module.exports = Self => { }; return axios.post(`${login.api}/chat.postMessage`, { - 'channel': channel, + 'channel': `@${chat.recipient}`, 'avatar': avatar, 'alias': sender.nickname, - 'text': message + 'text': chat.message }, options); } }; diff --git a/back/models/chat.js b/back/models/chat.js index 7d8468aae..95a1e2c29 100644 --- a/back/models/chat.js +++ b/back/models/chat.js @@ -3,4 +3,5 @@ module.exports = Self => { require('../methods/chat/send')(Self); require('../methods/chat/sendCheckingPresence')(Self); require('../methods/chat/notifyIssues')(Self); + require('../methods/chat/sendQueued')(Self); }; diff --git a/back/models/chat.json b/back/models/chat.json index 697d8c181..8fc3a6304 100644 --- a/back/models/chat.json +++ b/back/models/chat.json @@ -1,6 +1,39 @@ { "name": "Chat", "base": "VnModel", + "options": { + "mysql": { + "table": "chat" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "senderFk": { + "type": "number" + }, + "recipient": { + "type": "string" + }, + "dated": { + "type": "date" + }, + "checkUserStatus": { + "type": "boolean" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + }, + "attempts": { + "type": "number" + } + }, "acls": [{ "property": "validations", "accessType": "EXECUTE", diff --git a/db/changes/10470-family/00-chat.sql b/db/changes/10470-family/00-chat.sql index 0c03f2bcb..d4a8f068a 100644 --- a/db/changes/10470-family/00-chat.sql +++ b/db/changes/10470-family/00-chat.sql @@ -1,10 +1,13 @@ CREATE TABLE `vn`.`chat` ( - `id` int(11) DEFAULT NULL, - `senderFk` int(11) DEFAULT NULL, - `recipient` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `id` int(11) NOT NULL AUTO_INCREMENT, + `senderFk` int(10) unsigned DEFAULT NULL, + `recipient` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, `dated` date DEFAULT NULL, `checkUserStatus` tinyint(1) DEFAULT NULL, - `message` varchar(200) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `message` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, `status` tinyint(1) DEFAULT NULL, - `attempts` int(1) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci \ No newline at end of file + `attempts` int(1) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `chat_FK` (`senderFk`), + CONSTRAINT `chat_FK` FOREIGN KEY (`senderFk`) REFERENCES `account`.`user` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index c69012f41..23b9be646 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2558,7 +2558,11 @@ INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackage (2, 1, 60, 0.00, 0.00, NULL, 0, 5.00, 33), (3, 2, 0, 15.00, 0.00, NULL, 0, 0.00, 0), (4, 2, 0, 20.00, 0.00, NULL, 0, 0.00, 0), - (5, 442, 0, 0.00, 3.05, NULL, 0, 0.00, 0); + (5, 442, 0, 0.00, 3.05, NULL, 0, 0.00, 0); + +INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`) + VALUES + (1101, 'PetterParker', '2022-06-02', 1, 'First test message', 0, 0); INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`) VALUES From 3eac002fb47f9f50645ed7e4a839034e508561d3 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 3 Jun 2022 12:22:07 +0200 Subject: [PATCH 3/8] 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 From fa27e6dd5880022099f179fefba0696ff08d2c39 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 3 Jun 2022 13:36:21 +0200 Subject: [PATCH 4/8] fix: backTest --- back/methods/chat/send.js | 4 +- back/methods/chat/sendCheckingPresence.js | 4 +- back/methods/chat/sendQueued.js | 41 ++++++------- back/methods/chat/spec/send.spec.js | 4 +- .../chat/spec/sendCheckingPresence.spec.js | 57 ++++--------------- back/methods/chat/spec/sendQueued.spec.js | 41 +++++++++++++ 6 files changed, 79 insertions(+), 72 deletions(-) create mode 100644 back/methods/chat/spec/sendQueued.spec.js diff --git a/back/methods/chat/send.js b/back/methods/chat/send.js index ece0d4994..d62c84e04 100644 --- a/back/methods/chat/send.js +++ b/back/methods/chat/send.js @@ -42,7 +42,7 @@ module.exports = Self => { return true; } - }; - return false; + return false; + }; }; diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js index be233c96f..569ce3475 100644 --- a/back/methods/chat/sendCheckingPresence.js +++ b/back/methods/chat/sendCheckingPresence.js @@ -43,7 +43,7 @@ module.exports = Self => { if (!recipient) throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`); - return models.Chat.create({ + await models.Chat.create({ senderFk: sender.id, recipient: `@${recipient.name}`, dated: new Date(), @@ -52,5 +52,7 @@ module.exports = Self => { status: 0, attempts: 0 }); + + return true; }; }; diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js index 1b4e5d68c..e7ab777af 100644 --- a/back/methods/chat/sendQueued.js +++ b/back/methods/chat/sendQueued.js @@ -30,14 +30,14 @@ module.exports = Self => { for (let chat of chats) { if (chat.checkUserStatus) { try { - await sendCheckingUserStatus(chat); + await Self.sendCheckingUserStatus(chat); await updateChat(chat, sentStatus); } catch (error) { await updateChat(chat, errorStatus); } } else { try { - await sendMessage(chat.senderFk, chat.recipient, chat.message); + await Self.sendMessage(chat.senderFk, chat.recipient, chat.message); await updateChat(chat, sentStatus); } catch (error) { await updateChat(chat, errorStatus); @@ -46,7 +46,7 @@ module.exports = Self => { } }; - async function sendCheckingUserStatus(chat) { + Self.sendCheckingUserStatus = async function sendCheckingUserStatus(chat) { const models = Self.app.models; const recipientName = chat.recipient.slice(1); @@ -56,7 +56,7 @@ module.exports = Self => { } }); - const {data} = await getUserStatus(recipient.name); + const {data} = await Self.getUserStatus(recipient.name); if (data) { if (data.status === 'offline' || data.status === 'busy') { // Send message to department room @@ -75,7 +75,8 @@ module.exports = Self => { } else return sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); } - } + }; + /** * Update status and attempts of a chat * @@ -84,7 +85,7 @@ module.exports = Self => { * @param {string} message - The message to send * @return {Promise} - The request promise */ - async function sendMessage(senderFk, recipient, message) { + Self.sendMessage = async function sendMessage(senderFk, recipient, message) { if (process.env.NODE_ENV !== 'production') { return new Promise(resolve => { return resolve({ @@ -113,15 +114,15 @@ module.exports = Self => { 'alias': sender.nickname, '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 - */ + * 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, @@ -130,12 +131,12 @@ module.exports = Self => { } /** - * Returns the current user status on Rocketchat - * - * @param {string} username - The recipient user name - * @return {Promise} - The request promise - */ - async function getUserStatus(username) { + * 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({ @@ -157,5 +158,5 @@ module.exports = Self => { }; return axios.get(`${login.api}/users.getStatus`, options); - } + }; }; diff --git a/back/methods/chat/spec/send.spec.js b/back/methods/chat/spec/send.spec.js index 634e1d420..dd07a1342 100644 --- a/back/methods/chat/spec/send.spec.js +++ b/back/methods/chat/spec/send.spec.js @@ -1,14 +1,14 @@ const app = require('vn-loopback/server/server'); describe('Chat send()', () => { - it('should return a "Fake notification sent" as response', async() => { + it('should return true as response', async() => { let ctx = {req: {accessToken: {userId: 1}}}; let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something'); expect(response).toEqual(true); }); - it('should retrun false as response', async() => { + it('should return false as response', async() => { let ctx = {req: {accessToken: {userId: 18}}}; let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something'); diff --git a/back/methods/chat/spec/sendCheckingPresence.spec.js b/back/methods/chat/spec/sendCheckingPresence.spec.js index 712e7f947..5d1a1b3dd 100644 --- a/back/methods/chat/spec/sendCheckingPresence.spec.js +++ b/back/methods/chat/spec/sendCheckingPresence.spec.js @@ -1,58 +1,21 @@ const models = require('vn-loopback/server/server').models; describe('Chat sendCheckingPresence()', () => { - const today = new Date(); - today.setHours(6, 0); - const ctx = {req: {accessToken: {userId: 1}}}; - const chatModel = models.Chat; - const departmentId = 23; - const workerId = 1107; + it('should return true as response', async() => { + const workerId = 1107; - it(`should call to send() method with "@HankPym" as recipient argument`, async() => { - spyOn(chatModel, 'send').and.callThrough(); - spyOn(chatModel, 'getUserStatus').and.returnValue( - new Promise(resolve => { - return resolve({ - data: { - status: 'online' - } - }); - }) - ); + let ctx = {req: {accessToken: {userId: 1}}}; + let response = await models.Chat.sendCheckingPresence(ctx, workerId, 'I changed something'); - await chatModel.sendCheckingPresence(ctx, workerId, 'I changed something'); - - expect(chatModel.send).toHaveBeenCalledWith(ctx, '@HankPym', 'I changed something'); + expect(response).toEqual(true); }); - it(`should call to send() method with "#cooler" as recipient argument`, async() => { - spyOn(chatModel, 'send').and.callThrough(); - spyOn(chatModel, 'getUserStatus').and.returnValue( - new Promise(resolve => { - return resolve({ - data: { - status: 'offline' - } - }); - }) - ); + it('should return false as response', async() => { + const salesPersonId = 18; - const tx = await models.Claim.beginTransaction({}); + let ctx = {req: {accessToken: {userId: 18}}}; + let response = await models.Chat.sendCheckingPresence(ctx, salesPersonId, 'I changed something'); - try { - const options = {transaction: tx}; - - const department = await models.Department.findById(departmentId, null, options); - await department.updateAttribute('chatName', 'cooler'); - - await chatModel.sendCheckingPresence(ctx, workerId, 'I changed something'); - - expect(chatModel.send).toHaveBeenCalledWith(ctx, '#cooler', '@HankPym ➔ I changed something'); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(response).toEqual(false); }); }); diff --git a/back/methods/chat/spec/sendQueued.spec.js b/back/methods/chat/spec/sendQueued.spec.js new file mode 100644 index 000000000..bbf5a73c7 --- /dev/null +++ b/back/methods/chat/spec/sendQueued.spec.js @@ -0,0 +1,41 @@ +const models = require('vn-loopback/server/server').models; + +describe('Chat sendCheckingPresence()', () => { + const today = new Date(); + today.setHours(6, 0); + const chatModel = models.Chat; + + it(`should call to sendCheckingUserStatus()`, async() => { + spyOn(chatModel, 'sendCheckingUserStatus').and.callThrough(); + + const chat = { + checkUserStatus: 1, + status: 0, + attempts: 0 + }; + + await chatModel.destroyAll(); + await chatModel.create(chat); + + await chatModel.sendQueued(); + + expect(chatModel.sendCheckingUserStatus).toHaveBeenCalled(); + }); + + it(`should call to sendMessage() method`, async() => { + spyOn(chatModel, 'sendMessage').and.callThrough(); + + const chat = { + checkUserStatus: 0, + status: 0, + attempts: 0 + }; + + await chatModel.destroyAll(); + await chatModel.create(chat); + + await chatModel.sendQueued(); + + expect(chatModel.sendMessage).toHaveBeenCalled(); + }); +}); From 9f57481390611b1c6ec8265ac981d89be41348c7 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 3 Jun 2022 13:44:42 +0200 Subject: [PATCH 5/8] refator: change comments --- back/methods/chat/send.js | 2 +- back/methods/chat/sendCheckingPresence.js | 2 +- back/methods/chat/sendQueued.js | 10 ++++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/back/methods/chat/send.js b/back/methods/chat/send.js index d62c84e04..5a4e9ddb9 100644 --- a/back/methods/chat/send.js +++ b/back/methods/chat/send.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethodCtx('send', { - description: 'Send a RocketChat message', + description: 'Insert in model Chat', accessType: 'WRITE', accepts: [{ arg: 'to', diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js index 569ce3475..6d8ec3bf8 100644 --- a/back/methods/chat/sendCheckingPresence.js +++ b/back/methods/chat/sendCheckingPresence.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethodCtx('sendCheckingPresence', { - description: 'Sends a RocketChat message to a connected user or department channel', + description: 'Insert in model Chat', accessType: 'WRITE', accepts: [{ arg: 'workerId', diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js index e7ab777af..74c078d84 100644 --- a/back/methods/chat/sendQueued.js +++ b/back/methods/chat/sendQueued.js @@ -14,7 +14,7 @@ module.exports = Self => { } }); - Self.sendQueued = async ctx => { + Self.sendQueued = async() => { const models = Self.app.models; const maxAttempts = 3; const sentStatus = 1; @@ -46,6 +46,12 @@ module.exports = Self => { } }; + /** + * 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; @@ -78,7 +84,7 @@ module.exports = Self => { }; /** - * Update status and attempts of a chat + * Send a rocket message * * @param {object} senderFk - The sender id * @param {string} recipient - The user (@) or channel (#) to send the message From e30817644a82fbcb89a309862d6fb10512a7c783 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 3 Jun 2022 13:48:44 +0200 Subject: [PATCH 6/8] fix: bug --- back/methods/chat/sendQueued.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js index 74c078d84..bff56bd72 100644 --- a/back/methods/chat/sendQueued.js +++ b/back/methods/chat/sendQueued.js @@ -75,11 +75,11 @@ module.exports = Self => { const channelName = department && department.chatName; if (channelName) - return sendMessage(chat.senderFk, `#${channelName}`, `@${recipient.name} ➔ ${message}`); + return Self.sendMessage(chat.senderFk, `#${channelName}`, `@${recipient.name} ➔ ${message}`); else - return sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); + return Self.sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); } else - return sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); + return Self.sendMessage(chat.senderFk, `@${recipient.name}`, chat.message); } }; @@ -92,14 +92,14 @@ module.exports = Self => { * @return {Promise} - The request promise */ Self.sendMessage = async function sendMessage(senderFk, recipient, message) { - if (process.env.NODE_ENV !== 'production') { - return new Promise(resolve => { - return resolve({ - statusCode: 200, - message: 'Fake notification sent' - }); - }); - } + // if (process.env.NODE_ENV !== 'production') { + // return new Promise(resolve => { + // return resolve({ + // statusCode: 200, + // message: 'Fake notification sent' + // }); + // }); + // } const models = Self.app.models; const sender = await models.Account.findById(senderFk); @@ -115,7 +115,7 @@ module.exports = Self => { }; return axios.post(`${login.api}/chat.postMessage`, { - 'channel': recipient, + 'channel': '@vicent', 'avatar': avatar, 'alias': sender.nickname, 'text': message From e4b23fa14dc813e41a3565c4c152b6668cf7c24f Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 3 Jun 2022 14:02:23 +0200 Subject: [PATCH 7/8] fix: bugs --- back/methods/chat/sendQueued.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js index bff56bd72..c34642c7e 100644 --- a/back/methods/chat/sendQueued.js +++ b/back/methods/chat/sendQueued.js @@ -92,14 +92,14 @@ module.exports = Self => { * @return {Promise} - The request promise */ Self.sendMessage = async function sendMessage(senderFk, recipient, message) { - // if (process.env.NODE_ENV !== 'production') { - // return new Promise(resolve => { - // return resolve({ - // statusCode: 200, - // message: 'Fake notification sent' - // }); - // }); - // } + if (process.env.NODE_ENV !== 'production') { + return new Promise(resolve => { + return resolve({ + statusCode: 200, + message: 'Fake notification sent' + }); + }); + } const models = Self.app.models; const sender = await models.Account.findById(senderFk); @@ -115,7 +115,7 @@ module.exports = Self => { }; return axios.post(`${login.api}/chat.postMessage`, { - 'channel': '@vicent', + 'channel': recipient, 'avatar': avatar, 'alias': sender.nickname, 'text': message From 93bb6787389c1c4d56ae5c56718c94730f9ab62e Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 8 Jun 2022 13:08:53 +0200 Subject: [PATCH 8/8] updated endpoints description --- back/methods/chat/send.js | 2 +- back/methods/chat/sendCheckingPresence.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/methods/chat/send.js b/back/methods/chat/send.js index 5a4e9ddb9..c5c8feead 100644 --- a/back/methods/chat/send.js +++ b/back/methods/chat/send.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethodCtx('send', { - description: 'Insert in model Chat', + description: 'Creates a direct message in the chat model for a user or a channel', accessType: 'WRITE', accepts: [{ arg: 'to', diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js index 6d8ec3bf8..3bc022429 100644 --- a/back/methods/chat/sendCheckingPresence.js +++ b/back/methods/chat/sendCheckingPresence.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethodCtx('sendCheckingPresence', { - description: 'Insert in model Chat', + description: 'Creates a message in the chat model checking the user status', accessType: 'WRITE', accepts: [{ arg: 'workerId',