From 7df322d1ab115f6a252c11fe52dc14c9f476a51e Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 2 Apr 2024 11:59:44 -0300 Subject: [PATCH] feat: Update controller to use queueId assigned to a WhatsApp number for message sending in remote ticket creation --- TEST_SERVER1/whats/app.js | 6 + backend/src/controllers/QueueController.ts | 55 ++++++ backend/src/controllers/TicketController.ts | 162 ++++++++---------- backend/src/middleware/isAuth.ts | 5 +- backend/src/routes/queueRoutes.ts | 2 + .../ListWhatsAppsForQueueService.ts | 31 +++- 6 files changed, 163 insertions(+), 98 deletions(-) diff --git a/TEST_SERVER1/whats/app.js b/TEST_SERVER1/whats/app.js index 62f316e..f8c030e 100644 --- a/TEST_SERVER1/whats/app.js +++ b/TEST_SERVER1/whats/app.js @@ -183,11 +183,17 @@ socketIo.on('connect_error', async function (err) { }) // +const wwebVersion = '2.2402.5'; + //NOVA OPÇÃO MD client = new Client({ authStrategy: new LocalAuth({ clientId: 'omnihit_sesssion' }), puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'], executablePath: process.env.CHROME_BIN || '/usr/bin/google-chrome-stable' }, + webVersionCache: { + type: 'remote', + remotePath: `https://raw.githubusercontent.com/wppconnect-team/wa-version/main/html/${wwebVersion}.html`, + }, }) client.initialize() diff --git a/backend/src/controllers/QueueController.ts b/backend/src/controllers/QueueController.ts index 493b951..eeb3703 100644 --- a/backend/src/controllers/QueueController.ts +++ b/backend/src/controllers/QueueController.ts @@ -8,6 +8,9 @@ import UpdateQueueService from "../services/QueueService/UpdateQueueService"; import Queue from "../models/Queue"; import AppError from "../errors/AppError"; import { del, get, set } from "../helpers/RedisClient"; +import { Op } from "sequelize"; +import ListWhatsAppsService from "../services/WhatsappService/ListWhatsAppsService"; +import Whatsapp from "../models/Whatsapp"; export const index = async (req: Request, res: Response): Promise => { const queues = await ListQueuesService(); @@ -15,6 +18,58 @@ export const index = async (req: Request, res: Response): Promise => { return res.status(200).json(queues); }; +export const listQueues = async ( + req: Request, + res: Response +): Promise => { + const whatsapps = await Whatsapp.findAll({ + where: { + name: { [Op.ne]: "botqueue" }, + number: { [Op.ne]: "" }, + phoneNumberId: false + }, + attributes: ["number"], + include: [ + { + model: Queue, + as: "queues", + attributes: ["id", "name"] + } + ] + }); + + const whats = whatsapps + ?.filter((w: any) => w?.queues?.length > 0) + ?.map((w: any) => { + const { number, queues } = w; + return { + number, + queues: queues?.map((q: any) => { + const { id, name } = q; + return { id, name }; + }) + }; + }); + + let _queues: any = []; + + for (const w of whats) { + const { queues } = w; + + for (const q of queues) { + const { id: queueId, name } = q; + + const auxQueue = _queues.findIndex((q: any) => q.queueId == queueId); + + if (auxQueue == -1) { + _queues.push({ queueId, name }); + } + } + } + + return res.status(200).json(_queues); +}; + export const store = async (req: Request, res: Response): Promise => { const { name, color, greetingMessage } = req.body; diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index 1ad1bda..549e460 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -119,10 +119,10 @@ export const remoteTicketCreation = async ( req: Request, res: Response ): Promise => { - const { contact_from, contact_to, msg, contact_name }: any = req.body; + const { queueId, contact_to, msg, contact_name }: any = req.body; - const validate = ["contact_from", "contact_to", "msg"]; - const validateOnlyNumber = ["contact_from", "contact_to"]; + const validate = ["queueId", "contact_to", "msg"]; + const validateOnlyNumber = ["queueId", "contact_to"]; for (let prop of validate) { if (!req.body[prop]) @@ -139,109 +139,97 @@ export const remoteTicketCreation = async ( } } - const whatsapp = await Whatsapp.findOne({ - where: { number: contact_from, status: "CONNECTED" } - }); - - if (whatsapp) { - const { id: whatsappId, number, status } = whatsapp; + const whatsapps = await ListWhatsAppsForQueueService(queueId, "CONNECTED"); - const queue: any = await WhatsappQueue.findOne({ - where: { whatsappId }, - attributes: ["queueId"] + if (!whatsapps || whatsapps?.length == 0) { + return res.status(500).json({ + msg: `queueId ${queueId} does not have a WhatsApp number associated with it or the number's session is disconnected.` }); + } - const { queueId } = queue; + const { id: whatsappId } = whatsapps[0]; - // const validNumber = await CheckIsValidContact(contact_to, true); - const validNumber = contact_to; + // const validNumber = await CheckIsValidContact(contact_to, true); + const validNumber = contact_to; - if (validNumber) { - let contact = await Contact.findOne({ where: { number: validNumber } }); + if (validNumber) { + let contact = await Contact.findOne({ where: { number: validNumber } }); - if (!contact) { - // const profilePicUrl = await GetProfilePicUrl(validNumber); + if (!contact) { + // const profilePicUrl = await GetProfilePicUrl(validNumber); - contact = await CreateContactService({ - name: contact_name ? contact_name : contact_to, - number: validNumber - // profilePicUrl - }); - - const io = getIO(); - io.emit("contact", { - action: "create", - contact - }); - } - - const { id: contactId } = contact; - - const botInfo = await BotIsOnQueue("botqueue"); - - let ticket = await Ticket.findOne({ - where: { - [Op.or]: [ - { contactId, status: "queueChoice" }, - { contactId, status: "open", userId: botInfo.userIdBot } - ] - } + contact = await CreateContactService({ + name: contact_name ? contact_name : contact_to, + number: validNumber + // profilePicUrl }); - if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") { - if (ticket) { - await UpdateTicketService({ - ticketData: { status: "closed" }, - ticketId: ticket.id - }); - ticket = null; - } - } else { - if (ticket) { - await UpdateTicketService({ - ticketData: { status: "closed" }, - ticketId: ticket.id - }); - } - } - - if (!ticket) { - ticket = await FindOrCreateTicketService( - contact, - whatsappId, - 0, - undefined, - queueId - ); - botSendMessage(ticket, `${msg}`); - } - const io = getIO(); - io.to(ticket.status).emit("ticket", { - action: "update", - ticket + io.emit("contact", { + action: "create", + contact }); - - console.log( - `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success` - ); - return res.status(200).json({ msg: "success" }); } + const { id: contactId } = contact; + + const botInfo = await BotIsOnQueue("botqueue"); + + let ticket = await Ticket.findOne({ + where: { + [Op.or]: [ + { contactId, status: "queueChoice" }, + { contactId, status: "open", userId: botInfo.userIdBot } + ] + } + }); + + if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") { + if (ticket) { + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id + }); + ticket = null; + } + } else { + if (ticket) { + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id + }); + } + } + + if (!ticket) { + ticket = await FindOrCreateTicketService( + contact, + whatsappId, + 0, + undefined, + queueId + ); + botSendMessage(ticket, `${msg}`); + } + + const io = getIO(); + io.to(ticket.status).emit("ticket", { + action: "update", + ticket + }); + console.log( - `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: The number ${contact_to} does not exist on WhatsApp` + `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success` ); - return res - .status(500) - .json({ msg: `The number ${contact_to} does not exist on WhatsApp` }); + return res.status(200).json({ msg: "success" }); } console.log( - `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit` + `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: The number ${contact_to} does not exist on WhatsApp` ); - return res.status(500).json({ - msg: `Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit` - }); + return res + .status(500) + .json({ msg: `The number ${contact_to} does not exist on WhatsApp` }); }; export const store = async (req: Request, res: Response): Promise => { diff --git a/backend/src/middleware/isAuth.ts b/backend/src/middleware/isAuth.ts index b19552e..91061fc 100644 --- a/backend/src/middleware/isAuth.ts +++ b/backend/src/middleware/isAuth.ts @@ -19,10 +19,11 @@ const isAuth = (req: Request, res: Response, next: NextFunction): void => { throw new AppError("ERR_SESSION_EXPIRED", 401); } - const [, token] = authHeader.split(" "); + const [, token] = authHeader.split(" "); if ( - req.originalUrl == "/tickets/remote/create" && + (req.originalUrl == "/queue/remote/list" || + req.originalUrl == "/tickets/remote/create") && token === process.env.TOKEN_REMOTE_TICKET_CREATION ) { return next(); diff --git a/backend/src/routes/queueRoutes.ts b/backend/src/routes/queueRoutes.ts index 6de13d9..96bb509 100644 --- a/backend/src/routes/queueRoutes.ts +++ b/backend/src/routes/queueRoutes.ts @@ -11,6 +11,8 @@ queueRoutes.post("/queue", isAuth, QueueController.store); queueRoutes.post("/queue/customization", QueueController.customization); +queueRoutes.get("/queue/remote/list", isAuth, QueueController.listQueues); + queueRoutes.get("/queue/:queueId", isAuth, QueueController.show); queueRoutes.put("/queue/:queueId", isAuth, QueueController.update); diff --git a/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts b/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts index 1f16647..836ef9e 100644 --- a/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts +++ b/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts @@ -6,17 +6,30 @@ const { QueryTypes } = require("sequelize"); const sequelize = new Sequelize(dbConfig); -const ListWhatsAppsForQueueService = async (queueId: number | string): Promise => { - const distinctWhatsapps = await sequelize.query( - `SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId -FROM Whatsapps w -JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} -GROUP BY w.number;`, - { type: QueryTypes.SELECT } - ); +const ListWhatsAppsForQueueService = async ( + queueId: number | string, + status?: string +): Promise => { + let distinctWhatsapps: any; + + if (status) { + distinctWhatsapps = await sequelize.query( + `SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId FROM Whatsapps w + JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} AND w.status = '${status}' + AND phoneNumberId = false + GROUP BY w.number;`, + { type: QueryTypes.SELECT } + ); + } else { + distinctWhatsapps = await sequelize.query( + `SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId FROM Whatsapps w + JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} + GROUP BY w.number;`, + { type: QueryTypes.SELECT } + ); + } return distinctWhatsapps; }; export default ListWhatsAppsForQueueService; - \ No newline at end of file