From 1dbd2a08db8bf7eab7bc00dc75cdce2cb3389f33 Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 7 Feb 2023 12:47:40 -0300 Subject: [PATCH] =?UTF-8?q?Versao=20beta=20da=20funcionalidade=20de=20mult?= =?UTF-8?q?isess=C3=A3o=20completada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/config/upload.ts | 2 + backend/src/controllers/ContactController.ts | 15 ++- backend/src/controllers/MessageController.ts | 6 +- .../src/controllers/WbotMonitorController.ts | 74 ++++++++++ .../controllers/WhatsAppSessionController.ts | 24 ++-- ...230131211304-add-url-field-to-whatsapps.ts | 13 ++ backend/src/helpers/AutoRestore.ts | 2 + backend/src/helpers/EndPointQuery.ts | 39 ++++++ backend/src/helpers/GetTicketWbot.ts | 2 + backend/src/helpers/GetWbotMessage.ts | 31 +++-- backend/src/helpers/RestartWhatsSession.ts | 2 + backend/src/helpers/RestoreMonit.ts | 4 +- .../helpers/SchedulingNotifySendMessage.ts | 2 +- .../helpers/SendWhatsappMessageMediaSocket.ts | 21 +++ .../src/helpers/SendWhatsappMessageSocket.ts | 34 +++++ backend/src/helpers/SerializeWbotMsgId.ts | 4 +- .../helpers/WhatsappIdMultiSessionControl.ts | 74 ++++++++++ backend/src/helpers/WhoIsOnlineMonitor.ts | 2 - backend/src/libs/socket.ts | 93 +++++++++---- backend/src/libs/wbot.ts | 64 +++++++-- backend/src/models/Whatsapp.ts | 3 + backend/src/routes/index.ts | 2 + backend/src/routes/wbotMonitorRoutes.ts | 12 ++ backend/src/server.ts | 44 +++++- .../ContactServices/CreateContactService.ts | 6 +- .../MessageServices/CreateMessageService.ts | 9 +- .../TicketServices/ListTicketsService.ts | 9 +- .../TicketServices/ShowTicketService.ts | 2 + .../TicketServices/UpdateTicketService.ts | 2 +- .../WbotServices/CheckIsValidContact.ts | 23 +++- .../src/services/WbotServices/CheckNumber.ts | 8 +- .../WbotServices/DeleteWhatsAppMessage.ts | 34 ++++- .../services/WbotServices/GetProfilePicUrl.ts | 21 ++- .../WbotServices/ImportContactsService.ts | 62 ++++----- .../WbotServices/SendWhatsAppMedia.ts | 18 ++- .../WbotServices/SendWhatsAppMessage.ts | 110 +++++++++++++-- .../WbotServices/wbotMessageListener.ts | 126 ++++++++++++++---- .../WhatsappService/ListWhatsAppsNumber.ts | 18 +-- .../WhatsappService/ShowWhatsAppService.ts | 2 +- frontend/src/components/MessagesList/index.js | 2 + .../components/NotificationsPopOver/index.js | 32 +++-- 41 files changed, 864 insertions(+), 189 deletions(-) create mode 100644 backend/src/controllers/WbotMonitorController.ts create mode 100644 backend/src/database/migrations/20230131211304-add-url-field-to-whatsapps.ts create mode 100644 backend/src/helpers/EndPointQuery.ts create mode 100644 backend/src/helpers/SendWhatsappMessageMediaSocket.ts create mode 100644 backend/src/helpers/SendWhatsappMessageSocket.ts create mode 100644 backend/src/helpers/WhatsappIdMultiSessionControl.ts create mode 100644 backend/src/routes/wbotMonitorRoutes.ts diff --git a/backend/src/config/upload.ts b/backend/src/config/upload.ts index e7d682d..8d54798 100644 --- a/backend/src/config/upload.ts +++ b/backend/src/config/upload.ts @@ -14,6 +14,8 @@ export default { filename(req, file, cb) { const fileName = new Date().getTime() + path.extname(file.originalname); + console.log('THE FILE NAME FROM MULTER: ',fileName) + return cb(null, fileName); } }) diff --git a/backend/src/controllers/ContactController.ts b/backend/src/controllers/ContactController.ts index 99bd018..29e4469 100644 --- a/backend/src/controllers/ContactController.ts +++ b/backend/src/controllers/ContactController.ts @@ -96,11 +96,18 @@ export const store = async (req: Request, res: Response): Promise => { throw new AppError(err.message); } - await CheckIsValidContact(newContact.number); - const validNumber: any = await CheckContactNumber(newContact.number) + const validNumber = await CheckIsValidContact(newContact.number); + + // const validNumber: any = await CheckContactNumber(newContact.number) + + if(!validNumber){ + throw new AppError("ERR_WAPP_CHECK_CONTACT"); + } const profilePicUrl = await GetProfilePicUrl(validNumber); + console.log('xxxxxxxxxxx profilePicUrl: ',profilePicUrl) + let name = newContact.name let number = validNumber let email = newContact.email @@ -110,8 +117,8 @@ export const store = async (req: Request, res: Response): Promise => { name, number, email, - extraInfo, - profilePicUrl + profilePicUrl: profilePicUrl, + extraInfo, }); const io = getIO(); diff --git a/backend/src/controllers/MessageController.ts b/backend/src/controllers/MessageController.ts index 16fa665..bff0869 100644 --- a/backend/src/controllers/MessageController.ts +++ b/backend/src/controllers/MessageController.ts @@ -30,7 +30,7 @@ export const index = async (req: Request, res: Response): Promise => { ticketId }); - SetTicketMessagesAsRead(ticket); + // SetTicketMessagesAsRead(ticket); return res.json({ count, messages, ticket, hasMore }); }; @@ -45,8 +45,8 @@ export const store = async (req: Request, res: Response): Promise => { console.log('TICKET ID: ', ticketId) - SetTicketMessagesAsRead(ticket); - + // SetTicketMessagesAsRead(ticket); + if (medias) { await Promise.all( medias.map(async (media: Express.Multer.File) => { diff --git a/backend/src/controllers/WbotMonitorController.ts b/backend/src/controllers/WbotMonitorController.ts new file mode 100644 index 0000000..f63be71 --- /dev/null +++ b/backend/src/controllers/WbotMonitorController.ts @@ -0,0 +1,74 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import ShowWhatsAppService from "../services/WhatsappService/ShowWhatsAppService"; +import { logger } from "../utils/logger"; +import * as Sentry from "@sentry/node"; + + +// type IndexQuery = { +// centro_custo: string; +// }; + +export const wbotMonitorRemote = async (req: Request, res: Response): Promise => { + + const { action, whatsappId, reason } = req.body + + console.log('-----------> ACTION: ', req.body['action']) + + let whatsapp = await ShowWhatsAppService(whatsappId) + + if (action === 'disconnected') { + logger.info(`Disconnected session: ${whatsapp.name}, reason: ${reason}`); + } + + const io = getIO(); + io.emit("whatsappSession", { + action: "update", + session: whatsapp + }); + + return res.status(200).json({ "message": "Ok" }); +}; + + + + +export const wbotMonitorQrcodeRemote = async (req: Request, res: Response): Promise => { + + const { whatsappId } = req.body + + console.log('-----------> whatsappId: ', req.body['whatsappId']) + + let whatsapp = await ShowWhatsAppService(whatsappId) + + const io = getIO(); + io.emit("whatsappSession", { + action: "update", + session: whatsapp + }); + + + return res.status(200).json({ "message": "Ok" }); +}; + + + + +// export const DeleteWhatsAppMessage = async (req: Request, res: Response): Promise => { + +// const { whatsappId } = req.body + +// console.log('-----------> whatsappId: ', req.body['whatsappId']) + +// let whatsapp = await ShowWhatsAppService(whatsappId) + +// const io = getIO(); +// io.emit("whatsappSession", { +// action: "update", +// session: whatsapp +// }); + + + +// return res.status(200).json({ "message": "Ok" }); +// }; \ No newline at end of file diff --git a/backend/src/controllers/WhatsAppSessionController.ts b/backend/src/controllers/WhatsAppSessionController.ts index dcb698d..af41482 100644 --- a/backend/src/controllers/WhatsAppSessionController.ts +++ b/backend/src/controllers/WhatsAppSessionController.ts @@ -14,6 +14,7 @@ import { stat } from "fs"; import { setRestoreControll, getRestoreControll, shifRestoreControll } from "../helpers/RestoreControll"; import autoRestore from "../helpers/AutoRestore"; +import axios from "axios"; // let lstRestore: any = [] @@ -75,22 +76,29 @@ const restart = async (req: Request, res: Response): Promise => { const remove = async (req: Request, res: Response): Promise => { + const { whatsappId } = req.params; - const whatsapp = await ShowWhatsAppService(whatsappId); - const wbot = getWbot(whatsapp.id); + // const whatsapp = await ShowWhatsAppService(whatsappId); - await wbot.logout(); + // const wbot = getWbot(whatsapp.id); + + // await wbot.logout(); + + try { + + const wbot_url = await getWbot(whatsappId); + + let response = await axios.post(`${wbot_url}/api/disconnect`); - // TEST DEL - // removeWbot(+whatsapp.id) + } catch (error) { - // await removeDir(path.join(process.cwd(), '.wwebjs_auth', 'sessions', `session-bd_${whatsappId}`)) + console.log('There was an error on try disconnect the whatsapp id: ', whatsappId) + + } - // console.log('REMOVEU!!!!!!!!!!!!!!!!!!!!!') - // return res.status(200).json({ message: "Session disconnected." }); diff --git a/backend/src/database/migrations/20230131211304-add-url-field-to-whatsapps.ts b/backend/src/database/migrations/20230131211304-add-url-field-to-whatsapps.ts new file mode 100644 index 0000000..b1ae98d --- /dev/null +++ b/backend/src/database/migrations/20230131211304-add-url-field-to-whatsapps.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "url", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "url"); + } +}; diff --git a/backend/src/helpers/AutoRestore.ts b/backend/src/helpers/AutoRestore.ts index e2c3b87..b0707b0 100644 --- a/backend/src/helpers/AutoRestore.ts +++ b/backend/src/helpers/AutoRestore.ts @@ -14,6 +14,8 @@ import { number } from "yargs"; const autoRestore = async (whatsappId: string | number, started_action_by: string = '') => { + return + const whatsapp = await ShowWhatsAppService(whatsappId); // console.log('>>>>>>>>>>> Whatsapp.id: ', whatsappId) diff --git a/backend/src/helpers/EndPointQuery.ts b/backend/src/helpers/EndPointQuery.ts new file mode 100644 index 0000000..bfe975b --- /dev/null +++ b/backend/src/helpers/EndPointQuery.ts @@ -0,0 +1,39 @@ +const fsPromises = require("fs/promises"); +const fs = require('fs') +import axios from 'axios'; +import * as https from "https"; + +const endPointQuery = async (url: string, data: any) => { + + let response: any = null + + try { + + response = await axios.post(url, data); + + console.log(`TEST URL CLIENT POST ROUTE: ${url} | STATUS CODE: ${response.status}`); + + + } catch (err: any) { + + if (err.response) { + // The client was given an error response (5xx, 4xx) + // console.log('err.response: ', err.response) + console.log('err.response: ', err.response) + + // return { data: err.response.data, status: err.response.status } + + } else if (err.request) { + // The client never received a response, and the request was never left + console.log('err.request: ', err.request) + } else { + // Anything else + console.error(`Erro ao consultar endpoint ${url}: ${err}`); + } + } + + return response + +} + +export default endPointQuery; \ No newline at end of file diff --git a/backend/src/helpers/GetTicketWbot.ts b/backend/src/helpers/GetTicketWbot.ts index 0caa6b0..d4cf471 100644 --- a/backend/src/helpers/GetTicketWbot.ts +++ b/backend/src/helpers/GetTicketWbot.ts @@ -4,7 +4,9 @@ import GetDefaultWhatsApp from "./GetDefaultWhatsApp"; import Ticket from "../models/Ticket"; const GetTicketWbot = async (ticket: Ticket): Promise => { + if (!ticket.whatsappId) { + const defaultWhatsapp = await GetDefaultWhatsApp(); await ticket.$set("whatsapp", defaultWhatsapp); diff --git a/backend/src/helpers/GetWbotMessage.ts b/backend/src/helpers/GetWbotMessage.ts index baf0b79..ed0aa5f 100644 --- a/backend/src/helpers/GetWbotMessage.ts +++ b/backend/src/helpers/GetWbotMessage.ts @@ -2,20 +2,35 @@ import { Message as WbotMessage } from "whatsapp-web.js"; import Ticket from "../models/Ticket"; import GetTicketWbot from "./GetTicketWbot"; import AppError from "../errors/AppError"; +import endPointQuery from "./EndPointQuery"; +import { getWbot } from "../libs/wbot"; export const GetWbotMessage = async ( ticket: Ticket, messageId: string -): Promise => { - const wbot = await GetTicketWbot(ticket); +): Promise => { + - const wbotChat = await wbot.getChatById( - `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us` - ); let limit = 20; + const wbot_url = await getWbot(ticket.whatsappId); + + const msgFound = await endPointQuery(`${wbot_url}/api/getWbotMessage`, { + number: `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, + messageId: messageId, + limit: limit + }) + + // console.log('----------> msgFound: ', msgFound) + + + // const wbot = await GetTicketWbot(ticket); + + /* const wbotChat = await wbot.getChatById(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`); + const fetchWbotMessagesGradually = async (): Promise => { + const chatMessages = await wbotChat.fetchMessages({ limit }); const msgFound = chatMessages.find(msg => msg.id.id === messageId); @@ -26,16 +41,16 @@ export const GetWbotMessage = async ( } return msgFound; - }; + };*/ try { - const msgFound = await fetchWbotMessagesGradually(); + // const msgFound = await fetchWbotMessagesGradually(); if (!msgFound) { throw new Error("Cannot found message within 100 last messages"); } - return msgFound; + return msgFound.data.data; } catch (err) { throw new AppError("ERR_FETCH_WAPP_MSG"); } diff --git a/backend/src/helpers/RestartWhatsSession.ts b/backend/src/helpers/RestartWhatsSession.ts index dee1c9f..9dc62de 100644 --- a/backend/src/helpers/RestartWhatsSession.ts +++ b/backend/src/helpers/RestartWhatsSession.ts @@ -13,6 +13,8 @@ const fs = require('fs') // Restart session export const restartWhatsSession = async (whatsapp: Whatsapp, backupSession: boolean = false) => { + return + console.log('RESTARTING THE whatsapp.id: ', whatsapp.id) const sourcePath = path.join(__dirname, `../../.wwebjs_auth/sessions/`, `session-bd_${whatsapp.id}`) diff --git a/backend/src/helpers/RestoreMonit.ts b/backend/src/helpers/RestoreMonit.ts index 365702e..967a8df 100644 --- a/backend/src/helpers/RestoreMonit.ts +++ b/backend/src/helpers/RestoreMonit.ts @@ -72,9 +72,7 @@ export const restoreMonit = (whatsappId: string | number) => { } } - - console.log('888888888888888888 ENTROU NO SET TIMEOUT -----------> ') - + }, 180000); } diff --git a/backend/src/helpers/SchedulingNotifySendMessage.ts b/backend/src/helpers/SchedulingNotifySendMessage.ts index bd50be4..c9d3d68 100644 --- a/backend/src/helpers/SchedulingNotifySendMessage.ts +++ b/backend/src/helpers/SchedulingNotifySendMessage.ts @@ -55,7 +55,7 @@ const monitor = async () => { await ticket.update({status: 'open'}) } - SetTicketMessagesAsRead(ticket); + // SetTicketMessagesAsRead(ticket); await SendWhatsAppMessage({ body: schedulingNotifies[i].message, ticket diff --git a/backend/src/helpers/SendWhatsappMessageMediaSocket.ts b/backend/src/helpers/SendWhatsappMessageMediaSocket.ts new file mode 100644 index 0000000..221de1c --- /dev/null +++ b/backend/src/helpers/SendWhatsappMessageMediaSocket.ts @@ -0,0 +1,21 @@ +import { MessageMedia } from "whatsapp-web.js"; +import { getIO } from "../libs/socket"; +import Ticket from "../models/Ticket"; + + + +function sendWhatsAppMediaSocket(ticket: Ticket, newMedia: MessageMedia) { + const io = getIO(); + + io.to(`session_${ticket.whatsappId.toString()}`).emit("send_media", { + action: "create", + msg: { + number: `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, + media: newMedia, + sendAudioAsVoice: true + } + }); + } + + + export default sendWhatsAppMediaSocket; \ No newline at end of file diff --git a/backend/src/helpers/SendWhatsappMessageSocket.ts b/backend/src/helpers/SendWhatsappMessageSocket.ts new file mode 100644 index 0000000..84f45e1 --- /dev/null +++ b/backend/src/helpers/SendWhatsappMessageSocket.ts @@ -0,0 +1,34 @@ +import { getIO } from "../libs/socket"; +import Ticket from "../models/Ticket"; + + +function sendWhatsAppMessageSocket(ticket: Ticket, body: string, quotedMsgSerializedId?: string | undefined) { + + + const io = getIO(); + + io.to(`session_${ticket.whatsappId.toString()}`).emit("send_message", { + action: "create", + msg: { + number: `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, + body: body, + quotedMessageId: quotedMsgSerializedId, + linkPreview: false + } + }); + + + // io.emit("send_message", { + // action: "create", + // msg: { + // number: `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, + // body: body, + // quotedMessageId: quotedMsgSerializedId, + // linkPreview: false + // } + // }); + + +} + +export default sendWhatsAppMessageSocket; \ No newline at end of file diff --git a/backend/src/helpers/SerializeWbotMsgId.ts b/backend/src/helpers/SerializeWbotMsgId.ts index 4b5886e..44964b0 100644 --- a/backend/src/helpers/SerializeWbotMsgId.ts +++ b/backend/src/helpers/SerializeWbotMsgId.ts @@ -2,9 +2,7 @@ import Message from "../models/Message"; import Ticket from "../models/Ticket"; const SerializeWbotMsgId = (ticket: Ticket, message: Message): string => { - const serializedMsgId = `${message.fromMe}_${ticket.contact.number}@${ - ticket.isGroup ? "g" : "c" - }.us_${message.id}`; + const serializedMsgId = `${message.fromMe}_${ticket.contact.number}@${ticket.isGroup ? "g" : "c" }.us_${message.id}`; return serializedMsgId; }; diff --git a/backend/src/helpers/WhatsappIdMultiSessionControl.ts b/backend/src/helpers/WhatsappIdMultiSessionControl.ts new file mode 100644 index 0000000..4866cb4 --- /dev/null +++ b/backend/src/helpers/WhatsappIdMultiSessionControl.ts @@ -0,0 +1,74 @@ +import os from 'os'; +import dir from 'path'; +import fs from 'fs'; + + +export const setWhatsappId = (whatsappId: string, split?: any) => { + + console.log('os.tmpdir(): ', os.tmpdir()) + + const whatsappIdFile = dir.join(os.tmpdir(), `whatsappIdInfo.txt`); + + try { + + if (split) { + fs.unlink(whatsappIdFile, (err) => { + + if (err) { + throw err; + } + + console.log(`Delete File ${whatsappIdFile} successfully.`); + }); + } + + fs.appendFile(whatsappIdFile, `${whatsappId},`, err => { + if (err) { + console.error(err); + } + // done! + }); + + } catch (error: any) { + + console.log('There was an error on try to read/delete the whatsappIdInfo.json file: ', error) + + } + +} + + +export const getWhatsappIds = () => { + + const whatsappIdFile = dir.join(os.tmpdir(), `whatsappIdInfo.txt`); + + try { + + if (fs.existsSync(whatsappIdFile)) { + + let whatsappInfo: any = fs.readFileSync(whatsappIdFile, { encoding: 'utf8', flag: 'r' }); + + + if (whatsappInfo && whatsappInfo.endsWith(',')) { + whatsappInfo = whatsappInfo.substring(0, whatsappInfo.length - 1); + } + + whatsappInfo = whatsappInfo.split(',') + + // console.log('xxxxxxxxxx whatsappInfo: ',whatsappInfo) + + return whatsappInfo + + } else { + + console.log('restoreInfo.json file not found!'); + + } + + } catch (error) { + console.log('There was an error on try to read the restoreInfo.json file: ', error) + } + + return [] + +} \ No newline at end of file diff --git a/backend/src/helpers/WhoIsOnlineMonitor.ts b/backend/src/helpers/WhoIsOnlineMonitor.ts index c897388..3296df5 100644 --- a/backend/src/helpers/WhoIsOnlineMonitor.ts +++ b/backend/src/helpers/WhoIsOnlineMonitor.ts @@ -51,8 +51,6 @@ const emitterOnline = (user: any, status: string, showOnlineTime: boolean = true } } - console.log('ENTROU NO EMMITER ONLINE: ', user.id) - // console.log('-------------> onlineTime: ', onlineTime) const io = getIO(); diff --git a/backend/src/libs/socket.ts b/backend/src/libs/socket.ts index 53cf1f2..7351637 100644 --- a/backend/src/libs/socket.ts +++ b/backend/src/libs/socket.ts @@ -15,8 +15,9 @@ import { splitDateTime } from "../helpers/SplitDateTime"; import format from 'date-fns/format'; import ptBR from 'date-fns/locale/pt-BR'; import ListUserOnlineOffline from "../services/UserServices/ListUsersOnlineOfflineService"; -import { handleMessage } from "../services/WbotServices/wbotMessageListener"; +import { handleMessage, handleMsgAck } from "../services/WbotServices/wbotMessageListener"; import { join } from "path"; +import Whatsapp from "../models/Whatsapp"; let count: number = 0 let listOnline: any[] = [] @@ -31,8 +32,6 @@ let lstOnline: any[] = [] let lstOnlineAux: any[] = [] let lstTry: any[] = [] - - let dateTime = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) @@ -40,7 +39,8 @@ export const initIO = (httpServer: Server): SocketIO => { io = new SocketIO(httpServer, { cors: { origin: process.env.FRONTEND_URL - } + }, + maxHttpBufferSize: 1e8 }); @@ -53,35 +53,32 @@ export const initIO = (httpServer: Server): SocketIO => { - socket.on("message_from_client", () => { - console.log('message_from_client!') + socket.on("joinWhatsSession", (whatsappId: string) => { + logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`); + socket.join(`session_${whatsappId}`); + }); + socket.on("message_from_client", () => { + socket.emit('message_from_server', 'Sent an event from the server!'); }) socket.on("message_create", async (data: any) => { - console.log('DATA: ', data) + handleMessage(data.msg, data); + }); + + + socket.on("media_uploaded", async (data: any) => { + handleMessage(data.msg, data); }); - socket.on("media_uploaded", async (file: any, callback: any) => { + socket.on("message_ack", async (data: any) => { - console.log('_______file: ', file); - - // handleMessage(data.msg, data); - - try { - - writeFileAsync(join(__dirname, "..", "..", "..", "..", "..", "public", file.filename), file.data, "base64"); - - } catch (err) { - - logger.error(`There was an error on try get data: ${err}`); - - } + handleMsgAck(data.id, data.ack) }); @@ -91,6 +88,9 @@ export const initIO = (httpServer: Server): SocketIO => { + + + socket.on("online", (userId: any) => { // console.log('userId: ', userId) @@ -234,8 +234,54 @@ export const initIO = (httpServer: Server): SocketIO => { socket.join(status); }); - socket.on("disconnect", () => { - logger.info("Client disconnected"); + socket.on("disconnect", (data: any) => { + logger.info(`Client disconnected socket: ${data}`); + }); + + socket.on("disconnecting", async () => { + console.log('socket.rooms: ', socket.rooms); // the Set contains at least the socket ID + + let rooms = socket.rooms + + console.log('rooms: ', rooms, ' | rooms.size: ', rooms.size) + + if(rooms && rooms.size==1) return + if(rooms && rooms.size==2 && !([...rooms][1].startsWith('session_'))) return + + let whatsappIds: any = await Whatsapp.findAll({ attributes: ['id'], raw: true }) + + if (whatsappIds && whatsappIds.length > 0) { + + whatsappIds = whatsappIds.map((e: any) => `${e.id}`) + + console.log('whatsappIds whatsappIds whatsappIds whatsappIds whatsappIds: ',whatsappIds) + + if (rooms && rooms.size == 2 && + [...rooms][1].startsWith('session_') && + whatsappIds.includes([...rooms][1].replace('session_', ''))) { + + console.log([...rooms][1]) + + let whatsappId = [...rooms][1].replace('session_', '') + + const whatsapp = await Whatsapp.findByPk(whatsappId, {}) + + if (whatsapp) { + + await whatsapp.update({ status: 'OPENING' }); + + io.emit("whatsappSession", { + action: "update", + session: whatsapp + }); + + } + + + } + + } + }); }); return io; @@ -253,6 +299,7 @@ export const getIO = (): SocketIO => { function writeFileAsync(arg0: any, data: any, arg2: string) { throw new Error("Function not implemented."); } + // exports.listOnlineUsers = listUserId // exports.listUserId diff --git a/backend/src/libs/wbot.ts b/backend/src/libs/wbot.ts index 8e216be..aaf8758 100644 --- a/backend/src/libs/wbot.ts +++ b/backend/src/libs/wbot.ts @@ -23,6 +23,7 @@ let backupSession: any[] = [] // import { insertOrUpeateWhatsCache } from "../helpers/WhatsCache"; import { json } from "sequelize/types"; import { restartWhatsSession } from "../helpers/RestartWhatsSession"; +import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber"; let miliseconds = [1000, 2000, 3000] @@ -32,7 +33,9 @@ const syncUnreadMessages = async (wbot: Session) => { /* eslint-disable no-restricted-syntax */ /* eslint-disable no-await-in-loop */ for (const chat of chats) { + if (chat.unreadCount > 0) { + const unreadMessages = await chat.fetchMessages({ limit: chat.unreadCount }); @@ -46,6 +49,7 @@ const syncUnreadMessages = async (wbot: Session) => { await chat.sendSeen(); } + } }; @@ -74,10 +78,10 @@ export const initWbot = async (whatsapp: Whatsapp, backupSessionRestore: boolean // session: sessionCfg, authStrategy: new LocalAuth({ clientId: 'bd_' + whatsapp.id }), // // puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'], executablePath: process.env.CHROME_BIN || undefined }, // puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'], executablePath: process.env.CHROME_BIN || '/usr/bin/google-chrome-stable' }, - + // }); - const args:String = process.env.CHROME_ARGS || ""; + const args: String = process.env.CHROME_ARGS || ""; const wbot: Session = new Client({ session: sessionCfg, @@ -156,7 +160,7 @@ export const initWbot = async (whatsapp: Whatsapp, backupSessionRestore: boolean logger.info(`Session: ${sessionName} READY`); if (whatsapp.name.includes(wbot.info["wid"]["user"])) { - console.log('-----------------> THIS IS THE RIGHT NUMBER') + console.log('-----------------> THIS IS THE RIGHT NUMBER') } else { console.log('-----------------> THIS IS THE WRONG NUMBER') @@ -238,7 +242,7 @@ export const initWbot = async (whatsapp: Whatsapp, backupSessionRestore: boolean console.log(' PASSOU NO TIMEOUT whatsapp.id: ', whatsapp.id) - } + } }); } catch (err) { logger.error(`${err}`); @@ -246,16 +250,54 @@ export const initWbot = async (whatsapp: Whatsapp, backupSessionRestore: boolean }); }; -export const getWbot = (whatsappId: number): Session => { - const sessionIndex = sessions.findIndex(s => s.id === whatsappId); +export const getWbot = async (whatsappId: number | string): Promise => { - // console.log('----------> sessionIndex: ', sessionIndex, ' | whatasappId: ', whatsappId) - // console.log('----------> sessions: ',sessions.map(s => s.id)) + console.log('getWbot whatsappId: ', whatsappId) + + let whatsapp = await Whatsapp.findByPk(whatsappId, { + attributes: ["url"] + }) + + if (whatsapp && whatsapp.status != 'CONNECTED') { + + let listWhatsapp: any = null + + // listWhatsapp = await searchWhatsappCache(`${ticket.whatsappId}`, 'CONNECTED') + + if (!listWhatsapp) { + + listWhatsapp = await ListWhatsAppsNumber(whatsappId, 'CONNECTED') + + } + + if (listWhatsapp.whatsapps && listWhatsapp.whatsapps.length > 0) { + + console.log('----------> getWbot has changed the whatsappId: ', listWhatsapp.whatsapps[0].id) + + whatsapp = await Whatsapp.findByPk(listWhatsapp.whatsapps[0].id, { + attributes: ["url"] + }) + + } - if (sessionIndex === -1) { - throw new AppError("ERR_WAPP_NOT_INITIALIZED"); } - return sessions[sessionIndex]; + + if (whatsapp && (whatsapp.url && whatsapp.url.length > 0)) { + + return whatsapp.url + + } + + return null + + + // const sessionIndex = sessions.findIndex(s => s.id === whatsappId); + + // if (sessionIndex === -1) { + // throw new AppError("ERR_WAPP_NOT_INITIALIZED"); + // } + + // return sessions[sessionIndex]; }; export const removeWbot = (whatsappId: number): void => { diff --git a/backend/src/models/Whatsapp.ts b/backend/src/models/Whatsapp.ts index 1a3a6fc..9f57db4 100644 --- a/backend/src/models/Whatsapp.ts +++ b/backend/src/models/Whatsapp.ts @@ -56,6 +56,9 @@ class Whatsapp extends Model { @Column number: string; + @Column + url: string; + @Default(false) @AllowNull @Column diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts index e52ded1..297e954 100644 --- a/backend/src/routes/index.ts +++ b/backend/src/routes/index.ts @@ -13,6 +13,7 @@ import quickAnswerRoutes from "./quickAnswerRoutes"; import reportRoutes from "./reportRoutes"; import schedulingNotifiyRoutes from "./SchedulingNotifyRoutes"; import statusChatEndRoutes from "./statusChatEndRoutes"; +import wbotMonitorRoutes from "./wbotMonitorRoutes"; const routes = Router(); @@ -31,5 +32,6 @@ routes.use(quickAnswerRoutes); routes.use(schedulingNotifiyRoutes); routes.use(reportRoutes); routes.use(statusChatEndRoutes); +routes.use(wbotMonitorRoutes); export default routes; diff --git a/backend/src/routes/wbotMonitorRoutes.ts b/backend/src/routes/wbotMonitorRoutes.ts new file mode 100644 index 0000000..fdce4d7 --- /dev/null +++ b/backend/src/routes/wbotMonitorRoutes.ts @@ -0,0 +1,12 @@ +import { Router } from "express"; + +import isAuth from "../middleware/isAuth"; +import * as WbotMonitorController from "../controllers/WbotMonitorController"; + +const userRoutes = Router(); + +userRoutes.post("/whatsapp/connection/monitor", WbotMonitorController.wbotMonitorRemote); +userRoutes.post("/whatsapp/connection/qrcode", WbotMonitorController.wbotMonitorQrcodeRemote); +// userRoutes.post("/whatsapp/delete/message", WbotMonitorController.DeleteWhatsAppMessage); + +export default userRoutes; diff --git a/backend/src/server.ts b/backend/src/server.ts index 9941d1b..7525f0b 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -1,21 +1,55 @@ import gracefulShutdown from "http-graceful-shutdown"; import app from "./app"; -import { initIO } from "./libs/socket"; +import { initIO, getIO } from "./libs/socket"; import { logger } from "./utils/logger"; import { StartAllWhatsAppsSessions } from "./services/WbotServices/StartAllWhatsAppsSessions"; +import User from "./models/User"; const server = app.listen(process.env.PORT, () => { logger.info(`Server started on port: ${process.env.PORT}`); }); -if (global.gc) { +if (global.gc) { console.log(">> Starting Garbage Collector..."); - global.gc(); + global.gc(); } else { console.warn('No GC hook! Start your program as `node --expose-gc file.js`.'); -} - +} + initIO(server); + // StartAllWhatsAppsSessions(); gracefulShutdown(server); + + +setTimeout(async () => { + + const io = getIO(); + + console.log('Triggered socket!') + + let users = await User.findAll({ raw: true, attributes: ["id"], }) + + + if (users && users.length > 0) { + for (let i = 0; i < users.length; i++) { + + io.emit("reload_page", { + action: "update", + userId: users[i].id + }); + + console.log('USER ID: ', users[i].id) + + await new Promise(f => setTimeout(f, 500)); + + } + } + + +}, 5000) + + + + diff --git a/backend/src/services/ContactServices/CreateContactService.ts b/backend/src/services/ContactServices/CreateContactService.ts index 172b1a6..87d9e7c 100644 --- a/backend/src/services/ContactServices/CreateContactService.ts +++ b/backend/src/services/ContactServices/CreateContactService.ts @@ -2,6 +2,7 @@ import AppError from "../../errors/AppError"; import Contact from "../../models/Contact"; import { createOrUpdateContactCache } from '../../helpers/ContactsCache' +import GetProfilePicUrl from "../WbotServices/GetProfilePicUrl"; interface ExtraInfo { name: string; @@ -20,6 +21,7 @@ const CreateContactService = async ({ name, number, email = "", + profilePicUrl='', extraInfo = [] }: Request): Promise => { const numberExists = await Contact.findOne({ @@ -35,6 +37,7 @@ const CreateContactService = async ({ name, number, email, + profilePicUrl, extraInfo }, { @@ -42,9 +45,10 @@ const CreateContactService = async ({ } ); + // TEST DEL - await createOrUpdateContactCache(`contact:${contact.id}`, {id: contact.id, name, number, profilePicUrl:'', isGroup:'false', extraInfo, email }) + await createOrUpdateContactCache(`contact:${contact.id}`, {id: contact.id, name, number, profilePicUrl, isGroup:'false', extraInfo, email }) // diff --git a/backend/src/services/MessageServices/CreateMessageService.ts b/backend/src/services/MessageServices/CreateMessageService.ts index 9dc9a4c..853cd07 100644 --- a/backend/src/services/MessageServices/CreateMessageService.ts +++ b/backend/src/services/MessageServices/CreateMessageService.ts @@ -19,7 +19,7 @@ interface Request { const CreateMessageService = async ({ messageData }: Request): Promise => { - console.log('UPSERT MESSAGE messageData: ', messageData) + // console.log('UPSERT MESSAGE messageData: ', messageData) await Message.upsert(messageData); @@ -55,11 +55,10 @@ const CreateMessageService = async ({ messageData }: Request): Promise 'contact.profilePicUrl': message.ticket.contact.profilePicUrl, unreadMessages: message.ticket.unreadMessages }) - // - - - console.log('Entrou no create message') + // + console.log('message.ticketId.toString(): ', message.ticketId.toString()) + console.log('message.ticket.status: ',message.ticket.status) const io = getIO(); io.to(message.ticketId.toString()) diff --git a/backend/src/services/TicketServices/ListTicketsService.ts b/backend/src/services/TicketServices/ListTicketsService.ts index 421361d..3f542d9 100644 --- a/backend/src/services/TicketServices/ListTicketsService.ts +++ b/backend/src/services/TicketServices/ListTicketsService.ts @@ -16,6 +16,7 @@ const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss import ListTicketServiceCache from "./ListTicketServiceCache" import { searchTicketCache, loadTicketsCache } from '../../helpers/TicketCache' +import { getWbot } from "../../libs/wbot"; @@ -55,6 +56,11 @@ const ListTicketsService = async ({ console.log('PAGE NUMBER TICKET: ', pageNumber) + //TEST DEL + // const url = await getWbot(46) + // console.log('---------> URL: ', url) + // + if (pageNumber.trim().length == 0) { pageNumber = '1' } @@ -195,8 +201,7 @@ const ListTicketsService = async ({ - console.log('ENTROU NO LIST TICKET SERVICE') - + const { count, rows: tickets } = await Ticket.findAndCountAll({ where: whereCondition, include: includeCondition, diff --git a/backend/src/services/TicketServices/ShowTicketService.ts b/backend/src/services/TicketServices/ShowTicketService.ts index 5efab0c..471ea3d 100644 --- a/backend/src/services/TicketServices/ShowTicketService.ts +++ b/backend/src/services/TicketServices/ShowTicketService.ts @@ -26,6 +26,8 @@ const ShowTicketService = async (id: string | number): Promise => { ] }); + console.log('>>>>>>>>>>>>>>>>>>>>>>>> ShowTicketService: ',ticket?.whatsappId) + if (!ticket) { throw new AppError("ERR_NO_TICKET_FOUND", 404); } diff --git a/backend/src/services/TicketServices/UpdateTicketService.ts b/backend/src/services/TicketServices/UpdateTicketService.ts index db89646..34e58dd 100644 --- a/backend/src/services/TicketServices/UpdateTicketService.ts +++ b/backend/src/services/TicketServices/UpdateTicketService.ts @@ -36,7 +36,7 @@ const UpdateTicketService = async ({ const { status, userId, queueId, statusChatEnd } = ticketData; const ticket = await ShowTicketService(ticketId); - await SetTicketMessagesAsRead(ticket); + // await SetTicketMessagesAsRead(ticket); const oldStatus = ticket.status; const oldUserId = ticket.user?.id; diff --git a/backend/src/services/WbotServices/CheckIsValidContact.ts b/backend/src/services/WbotServices/CheckIsValidContact.ts index daa56bf..b7c7aee 100644 --- a/backend/src/services/WbotServices/CheckIsValidContact.ts +++ b/backend/src/services/WbotServices/CheckIsValidContact.ts @@ -1,23 +1,36 @@ import AppError from "../../errors/AppError"; +import endPointQuery from "../../helpers/EndPointQuery"; import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import { getWbot } from "../../libs/wbot"; -const CheckIsValidContact = async (number: string): Promise => { +const CheckIsValidContact = async (number: string): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp(); - const wbot = getWbot(defaultWhatsapp.id); + const wbot_url = await getWbot(defaultWhatsapp.id); + + const isValidNumber = await endPointQuery(`${wbot_url}/api/validate`, { mobile: `${number}`, }) + + console.log('isValidNumber.data.number: ', isValidNumber.data.number) try { - const isValidNumber = await wbot.isRegisteredUser(`${number}@c.us`); - if (!isValidNumber) { + + // const isValidNumber = await wbot.isRegisteredUser(`${number}@c.us`); + + if (!isValidNumber || isValidNumber && !isValidNumber.data.isValid) { throw new AppError("invalidNumber"); } - } catch (err) { + } catch (err: any) { if (err.message === "invalidNumber") { throw new AppError("ERR_WAPP_INVALID_CONTACT"); } + throw new AppError("ERR_WAPP_CHECK_CONTACT"); } + + if (isValidNumber && isValidNumber.data.isValid) + return isValidNumber.data.number + }; export default CheckIsValidContact; diff --git a/backend/src/services/WbotServices/CheckNumber.ts b/backend/src/services/WbotServices/CheckNumber.ts index 80753d6..be44aa3 100644 --- a/backend/src/services/WbotServices/CheckNumber.ts +++ b/backend/src/services/WbotServices/CheckNumber.ts @@ -2,12 +2,12 @@ import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import { getWbot } from "../../libs/wbot"; const CheckContactNumber = async (number: string): Promise => { - const defaultWhatsapp = await GetDefaultWhatsApp(); + // const defaultWhatsapp = await GetDefaultWhatsApp(); - const wbot = getWbot(defaultWhatsapp.id); + // const wbot = getWbot(defaultWhatsapp.id); - const validNumber : any = await wbot.getNumberId(`${number}@c.us`); - return validNumber.user + // const validNumber : any = await wbot.getNumberId(`${number}@c.us`); + // return validNumber.user }; export default CheckContactNumber; diff --git a/backend/src/services/WbotServices/DeleteWhatsAppMessage.ts b/backend/src/services/WbotServices/DeleteWhatsAppMessage.ts index b9b3b17..c3785e5 100644 --- a/backend/src/services/WbotServices/DeleteWhatsAppMessage.ts +++ b/backend/src/services/WbotServices/DeleteWhatsAppMessage.ts @@ -1,9 +1,11 @@ import AppError from "../../errors/AppError"; +import endPointQuery from "../../helpers/EndPointQuery"; import GetWbotMessage from "../../helpers/GetWbotMessage"; +import { getWbot } from "../../libs/wbot"; import Message from "../../models/Message"; import Ticket from "../../models/Ticket"; -const DeleteWhatsAppMessage = async (messageId: string): Promise => { +const DeleteWhatsAppMessage = async (messageId: string): Promise => { const message = await Message.findByPk(messageId, { include: [ { @@ -20,15 +22,35 @@ const DeleteWhatsAppMessage = async (messageId: string): Promise => { const { ticket } = message; - const messageToDelete = await GetWbotMessage(ticket, messageId); + let limit = 20; - try { - await messageToDelete.delete(true); - } catch (err) { + const wbot_url = await getWbot(ticket.whatsappId); + + const messageToDelete = await endPointQuery(`${wbot_url}/api/DeleteWhatsAppMessage`, { + number: `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, + messageId: messageId, + limit: limit + }) + + // console.log('messageToDelete.data.data: ',messageToDelete.data.data) + + // const { ticket } = message; + + // const messageToDelete = await GetWbotMessage(ticket, messageId); + + // try { + // await messageToDelete.delete(true); + // } catch (err) { + // throw new AppError("ERR_DELETE_WAPP_MSG"); + // } + + if (messageToDelete && messageToDelete.data.data) { + await message.update({ isDeleted: true }); + } + else{ throw new AppError("ERR_DELETE_WAPP_MSG"); } - await message.update({ isDeleted: true }); return message; }; diff --git a/backend/src/services/WbotServices/GetProfilePicUrl.ts b/backend/src/services/WbotServices/GetProfilePicUrl.ts index 6e5829a..561e79f 100644 --- a/backend/src/services/WbotServices/GetProfilePicUrl.ts +++ b/backend/src/services/WbotServices/GetProfilePicUrl.ts @@ -1,14 +1,27 @@ +import endPointQuery from "../../helpers/EndPointQuery"; import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import { getWbot } from "../../libs/wbot"; -const GetProfilePicUrl = async (number: string): Promise => { +const GetProfilePicUrl = async (number: string): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp(); - const wbot = getWbot(defaultWhatsapp.id); + const wbot_url = await getWbot(defaultWhatsapp.id); - const profilePicUrl = await wbot.getProfilePicUrl(`${number}@c.us`); + // const profilePicUrl = await wbot.getProfilePicUrl(`${number}@c.us`); + + let profilePicUrl = await endPointQuery(`${wbot_url}/api/GetProfilePicUrl`, { number: `${number}`, }) + + console.log('profilePicUrl.data.data: ', profilePicUrl.data.data) + + if (profilePicUrl && profilePicUrl.data.data) { + + console.log('GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG') + return profilePicUrl.data.data; + } + + return null - return profilePicUrl; }; export default GetProfilePicUrl; diff --git a/backend/src/services/WbotServices/ImportContactsService.ts b/backend/src/services/WbotServices/ImportContactsService.ts index 7b0e60d..8060762 100644 --- a/backend/src/services/WbotServices/ImportContactsService.ts +++ b/backend/src/services/WbotServices/ImportContactsService.ts @@ -6,47 +6,47 @@ import { logger } from "../../utils/logger"; import { createOrUpdateContactCache } from '../../helpers/ContactsCache' const ImportContactsService = async (): Promise => { - const defaultWhatsapp = await GetDefaultWhatsApp(); + // const defaultWhatsapp = await GetDefaultWhatsApp(); - const wbot = getWbot(defaultWhatsapp.id); + // const wbot = getWbot(defaultWhatsapp.id); - let phoneContacts; + // let phoneContacts; - try { - phoneContacts = await wbot.getContacts(); - } catch (err) { - logger.error(`Could not get whatsapp contacts from phone. Err: ${err}`); - } + // try { + // phoneContacts = await wbot.getContacts(); + // } catch (err) { + // logger.error(`Could not get whatsapp contacts from phone. Err: ${err}`); + // } - if (phoneContacts) { - await Promise.all( - phoneContacts.map(async ({ number, name }) => { - if (!number) { - return null; - } - if (!name) { - name = number; - } + // if (phoneContacts) { + // await Promise.all( + // phoneContacts.map(async ({ number, name }) => { + // if (!number) { + // return null; + // } + // if (!name) { + // name = number; + // } - const numberExists = await Contact.findOne({ - where: { number } - }); + // const numberExists = await Contact.findOne({ + // where: { number } + // }); - if (numberExists) return null; + // if (numberExists) return null; - let contact = await Contact.create({ number, name }); + // let contact = await Contact.create({ number, name }); - // await contact.reload() + // // await contact.reload() - // TEST DEL - await createOrUpdateContactCache(`contact:${contact.id}`, {id:contact.id, name, number, profilePicUrl: contact.profilePicUrl, isGroup: contact.isGroup, extraInfo: '', email:'' }) - // + // // TEST DEL + // await createOrUpdateContactCache(`contact:${contact.id}`, {id:contact.id, name, number, profilePicUrl: contact.profilePicUrl, isGroup: contact.isGroup, extraInfo: '', email:'' }) + // // - // return Contact.create({ number, name }); - return contact - }) - ); - } + // // return Contact.create({ number, name }); + // return contact + // }) + // ); + // } }; export default ImportContactsService; diff --git a/backend/src/services/WbotServices/SendWhatsAppMedia.ts b/backend/src/services/WbotServices/SendWhatsAppMedia.ts index b090c1c..f15a9cb 100644 --- a/backend/src/services/WbotServices/SendWhatsAppMedia.ts +++ b/backend/src/services/WbotServices/SendWhatsAppMedia.ts @@ -6,6 +6,9 @@ import Ticket from "../../models/Ticket"; import { updateTicketCacheByTicketId } from '../../helpers/TicketCache' import { date } from "faker"; +import { getIO } from "../../libs/socket"; +import sendWhatsAppMessageSocket from "../../helpers/SendWhatsappMessageSocket"; +import sendWhatsAppMediaSocket from "../../helpers/SendWhatsappMessageMediaSocket"; interface Request { media: Express.Multer.File; @@ -15,13 +18,15 @@ interface Request { const SendWhatsAppMedia = async ({ media, ticket -}: Request): Promise => { +}: Request): Promise => { try { - const wbot = await GetTicketWbot(ticket); + // const wbot = await GetTicketWbot(ticket); const newMedia = MessageMedia.fromFilePath(media.path); - const sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, newMedia, { sendAudioAsVoice: true }); + //const sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, newMedia, { sendAudioAsVoice: true }); + + sendWhatsAppMediaSocket(ticket, newMedia); await ticket.update({ lastMessage: media.filename }); @@ -29,12 +34,17 @@ const SendWhatsAppMedia = async ({ await updateTicketCacheByTicketId(ticket.id, { lastMessage: media.filename, updatedAt: new Date(ticket.updatedAt).toISOString() }) // + console.log('media.path: ', media.path) fs.unlinkSync(media.path); - return sentMessage; + // return sentMessage; + } catch (err) { throw new AppError("ERR_SENDING_WAPP_MSG"); } }; export default SendWhatsAppMedia; + + + diff --git a/backend/src/services/WbotServices/SendWhatsAppMessage.ts b/backend/src/services/WbotServices/SendWhatsAppMessage.ts index f615d3b..76b1673 100644 --- a/backend/src/services/WbotServices/SendWhatsAppMessage.ts +++ b/backend/src/services/WbotServices/SendWhatsAppMessage.ts @@ -24,6 +24,8 @@ import { restartWhatsSession } from "../../helpers/RestartWhatsSession"; import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import autoRestore from "../../helpers/AutoRestore"; import { _restore } from "../../helpers/RestoreControll"; +import { getIO } from "../../libs/socket"; +import sendWhatsAppMessageSocket from "../../helpers/SendWhatsappMessageSocket"; @@ -37,27 +39,102 @@ const SendWhatsAppMessage = async ({ body, ticket, quotedMsg -}: Request): Promise => { +}: Request): Promise => { let timestamp = Math.floor(Date.now() / 1000) var timetaken = `########################################${timestamp}| TicketId: ${ticket.id} => Time taken to send the message`; - console.time(timetaken) - let quotedMsgSerializedId: string | undefined; + if (quotedMsg) { + await GetWbotMessage(ticket, quotedMsg.id); + quotedMsgSerializedId = SerializeWbotMsgId(ticket, quotedMsg); } - const whatsapp = await Whatsapp.findByPk(ticket.whatsappId); + console.log('quotedMsgSerializedId: ', quotedMsgSerializedId) + + + let whatsapps: any + + let listWhatsapp = null + + // listWhatsapp = await searchWhatsappCache(`${ticket.whatsappId}`, 'CONNECTED') + + console.log('ticket.whatsappIdticket.whatsappIdticket.whatsappIdticket: ', ticket.whatsappId) + + if (!listWhatsapp) { + listWhatsapp = await ListWhatsAppsNumber(ticket.whatsappId, 'CONNECTED') + } + + if (listWhatsapp.whatsapp && listWhatsapp.whatsapp.status != 'CONNECTED' && listWhatsapp.whatsapps.length > 0) { + + console.log('kkkkkkkkkkkkkkkkkkkkkkkkkkkk: ', listWhatsapp.whatsapps[0].id) + + await ticket.update({ whatsappId: + listWhatsapp.whatsapps[0].id }); + + let _ticket = await Ticket.findByPk(listWhatsapp.whatsapps[0].id) + + } + + + + + if (listWhatsapp.whatsapps.length > 1) { + + const _whatsapp = listWhatsapp.whatsapps[Math.floor(Math.random() * listWhatsapp.whatsapps.length)]; + + await ticket.update({ whatsappId: +_whatsapp.id }); + // await ticket.reload(); + + + } + + console.log('listWhatsapp.whatsapps.length: ', listWhatsapp.whatsapps.length) + console.log('listWhatsapp.whatsapp.status: ', listWhatsapp.whatsapp.status) + + + if (listWhatsapp.whatsapps.length == 0 && listWhatsapp.whatsapp.status != 'CONNECTED') { + + console.log('listWhatsapp.whatsapps == 0') + + whatsapps = await wbotByUserQueue(ticket.userId) + + console.log('============> The whatsapps: ', whatsapps) + + if (whatsapps.length > 0) { + + if (whatsapps.length > 1) { + + await ticket.update({ whatsappId: whatsapps[+WhatsIndex(whatsapps)].id }); + + } + else { + + await ticket.update({ whatsappId: whatsapps[0].id }); + + } + + } + + } + + console.log('1 --------> ticket.whatsappId: ', ticket.whatsappId) + + // const wbot = await GetTicketWbot(ticket); + + + + + /*const whatsapp = await Whatsapp.findByPk(ticket.whatsappId); if (whatsapp && whatsapp.status != 'CONNECTED') { let whatsapps = await wbotByUserQueue(ticket.userId) - + if (whatsapps.length > 0) { if (whatsapps.length > 1) { @@ -76,28 +153,41 @@ const SendWhatsAppMessage = async ({ } const wbot = await GetTicketWbot(ticket); +*/ + + + console.log('2 --------> send from whatsapp ticket.whatsappId: ', ticket.whatsappId) - try { - const sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, body, { quotedMessageId: quotedMsgSerializedId, linkPreview: false }); + sendWhatsAppMessageSocket(ticket, body, quotedMsgSerializedId); await ticket.update({ lastMessage: body }); await updateTicketCacheByTicketId(ticket.id, { lastMessage: body, updatedAt: new Date(ticket.updatedAt).toISOString() }) - console.timeEnd(timetaken) - return sentMessage; + + // const sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, body, { quotedMessageId: quotedMsgSerializedId, linkPreview: false }); + + // await ticket.update({ lastMessage: body }); + + // await updateTicketCacheByTicketId(ticket.id, { lastMessage: body, updatedAt: new Date(ticket.updatedAt).toISOString() }) + + // return sentMessage; + + console.timeEnd(timetaken) } catch (err) { - const whatsapp = await ShowWhatsAppService(ticket.whatsappId); + // const whatsapp = await ShowWhatsAppService(ticket.whatsappId); throw new AppError("ERR_SENDING_WAPP_MSG"); } }; export default SendWhatsAppMessage; + + diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index ff47cf8..3be0655 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -57,10 +57,12 @@ import { updateTicketCacheByTicketId } from '../../helpers/TicketCache' import { insertMessageContactCache, getLastId } from '../../helpers/LastMessageIdByContactCache' import autoRestore from "../../helpers/AutoRestore"; import { _restore } from "../../helpers/RestoreControll"; +import sendWhatsAppMessageSocket from "../../helpers/SendWhatsappMessageSocket"; +import { getWhatsappIds, setWhatsappId } from "../../helpers/WhatsappIdMultiSessionControl"; -// var lst: any[] = [] +var lst: any[] = getWhatsappIds() interface Session extends Client { @@ -108,17 +110,24 @@ const verifyMediaMessage = async ( msg: any, ticket: Ticket, contact: Contact, + media: any, quotedMsg?: any, -): Promise => { +): Promise => { // const quotedMsg = await verifyQuotedMessage(msg); - const media = await msg.downloadMedia(); + // const media = await msg.downloadMedia(); if (!media) { throw new Error("ERR_WAPP_DOWNLOAD_MEDIA"); } + console.log('MEDIA.FILENAME: ', media.fileName, ' | msg.fromMe: ', msg.fromMe) + if (!media.filename) { + + console.log('No file name -----------------------------------------') + + const ext = media.mimetype.split("/")[1].split(";")[0]; media.filename = `${new Date().getTime()}.${ext}`; } @@ -130,11 +139,15 @@ const verifyMediaMessage = async ( // "base64" // ); + console.log('FROM wbotMessageListener.ts media.filename: ', media.filename) + + await writeFileAsync( join(__dirname, "..", "..", "..", "..", "..", "public", media.filename), media.data, "base64" ); + } catch (err) { Sentry.captureException(err); logger.error(`There was an error: wbotMessageLitener.ts: ${err}`); @@ -160,13 +173,12 @@ const verifyMediaMessage = async ( }; const verifyMessage = async ( - msg: WbotMessage, + msg: WbotMessage, ticket: Ticket, contact: Contact, quotedMsg?: any, ) => { - console.log('Entrou no verify message...') // const quotedMsg = await verifyQuotedMessage(msg); @@ -281,9 +293,11 @@ const verifyQueue = async ( body = `\u200e${choosenQueue.greetingMessage}`; } - const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); + // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); + // await verifyMessage(sentMessage, ticket, contact); + + sendWhatsAppMessageSocket(ticket, body) - await verifyMessage(sentMessage, ticket, contact); } else { @@ -307,8 +321,13 @@ const verifyQueue = async ( const debouncedSentMessage = debounce( async () => { - const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); - verifyMessage(sentMessage, ticket, contact); + + // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); + // verifyMessage(sentMessage, ticket, contact); + + sendWhatsAppMessageSocket(ticket, body) + + }, 3000, ticket.id @@ -379,20 +398,60 @@ const botSendMessage = (ticket: Ticket, contact: Contact, wbot: Session, msg: st } -// const _clear_lst = () => { +const _clear_lst = () => { -// if (lst.length <= 199) return + console.log('THE lst.length: ', lst.length) -// const chunk: any = Math.floor((lst.length / 2)) + if (lst.length <= 199) return -// lst = lst.slice(chunk, chunk + lst.length); + const chunk: any = Math.floor((lst.length / 2)) -// } + lst = lst.slice(chunk, chunk + lst.length); + + let whatsappIdsSplited = lst.map((e)=>`${e.id}`).toString() + + setWhatsappId(whatsappIdsSplited, true) + +} const handleMessage = async ( msg: any, wbot: any ): Promise => { + + if (!msg.fromMe) { + + _clear_lst() + + let index = lst.findIndex((x: any) => x.id == msg.id.id) + + console.log('INDEX: ', index) + + if (index == -1) { + + // console.log('-----------------> LST: ', lst) + + lst.push({ id: msg.id.id }) + + setWhatsappId(msg.id.id) + + } + else { + console.log('IGNORED ID: ', msg.id.id) + + return + } + + // console.log('LIST OF ID MESSAGE lst: ', lst) + + console.log('PASSOU.................................FROM: ', msg.from.split("@")[0], ' | ID: ', msg.id.id) + } + + + + + + if (!isValidMsg(msg)) { return; @@ -403,15 +462,22 @@ const handleMessage = async ( // let groupContact: Contact | undefined; if (msg.fromMe) { + + // console.log('FROM ME: ', msg.fromMe, ' | /\u200e/.test(msg.body[0]: ', (/\u200e/.test(msg.body[0]))) + // messages sent automatically by wbot have a special character in front of it // if so, this message was already been stored in database; - if (/\u200e/.test(msg.body[0])) return; + // if (/\u200e/.test(msg.body[0])) return; + + // console.log('PASSOU 1') // media messages sent from me from cell phone, first comes with "hasMedia = false" and type = "image/ptt/etc" // in this case, return and let this message be handled by "media_uploaded" event, when it will have "hasMedia = true" - + if (!msg.hasMedia && msg.type !== "chat" && msg.type !== "vcard") return; + // console.log('PASSOU 2') + // msgContact = await wbot.getContactById(msg.to); // console.log('1 --------------> msgContat: ', JSON.parse(JSON.stringify(msgContact))) @@ -454,11 +520,11 @@ const handleMessage = async ( // groupContact = await verifyContact(msgGroupContact); // } - + const whatsapp = await ShowWhatsAppService(wbot.id!); - + // const whatsapp = await ShowWhatsAppService(46); const unreadMessages = msg.fromMe ? 0 : chat.unreadCount; @@ -483,18 +549,24 @@ const handleMessage = async ( // Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen if (wbot.id != ticket.whatsappId) { - await ticket.update({ whatsappId: wbot.id }); + + // console.log('PARA RESPONDER PELO MEMOS WHATSAPP wbot.id: ', wbot.id, ' | wbot.status: ', wbot.status) + // console.log('WHATSAPP STATUS ticket.whatsappId: ', ticket.whatsappId) + + await ticket.update({ whatsappId: wbot.id }); + } // + - - if (msg.hasMedia) { - await verifyMediaMessage(msg, ticket, contact, wbot.quotedMsg); + if (msg.hasMedia) { + await verifyMediaMessage(msg, ticket, contact, wbot.media, wbot.quotedMsg); } else { + + // console.log('>>>>>>> msg.fromMe: ',msg.fromMe ) await verifyMessage(msg, ticket, contact, wbot.quotedMsg); } - //setTimeout(()=>verifyQueue(wbot, msg, ticket, contact), 3000); if ( !ticket.queue && @@ -852,13 +924,13 @@ const handleMessage = async ( } }; -const handleMsgAck = async (msg: WbotMessage, ack: MessageAck) => { +const handleMsgAck = async (msg_id: any, ack: any) => { await new Promise(r => setTimeout(r, 500)); const io = getIO(); try { - const messageToUpdate = await Message.findByPk(msg.id.id, { + const messageToUpdate = await Message.findByPk(msg_id, { include: [ "contact", { @@ -873,7 +945,7 @@ const handleMsgAck = async (msg: WbotMessage, ack: MessageAck) => { } await messageToUpdate.update({ ack }); - console.log('ACK messageToUpdate: ', JSON.parse(JSON.stringify(messageToUpdate))) + // console.log('ACK messageToUpdate: ', JSON.parse(JSON.stringify(messageToUpdate))) io.to(messageToUpdate.ticketId.toString()).emit("appMessage", { action: "update", @@ -901,4 +973,4 @@ const wbotMessageListener = (wbot: Session): void => { }); }; -export { wbotMessageListener, handleMessage }; +export { wbotMessageListener, handleMessage, handleMsgAck, lst }; diff --git a/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts b/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts index b9c921f..44b5589 100644 --- a/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts +++ b/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts @@ -1,26 +1,28 @@ import Whatsapp from "../../models/Whatsapp"; -const ListWhatsAppsNumber = async (whatsappId: string | number, status: string): Promise => { +const ListWhatsAppsNumber = async (whatsappId: string | number, status: string): Promise => { - const whatsapp = await Whatsapp.findOne({ - raw: true, - where: { id: whatsappId } - }) + // const whatsapp = await Whatsapp.findOne({ + // raw: true, + // where: { id: whatsappId } + // }) + + const whatsapp = await Whatsapp.findByPk(whatsappId, { raw: true }) if (whatsapp) { const whatsapps = await Whatsapp.findAll({ raw: true, where: { number: whatsapp.number, status: status }, - attributes: ['id', 'number', 'status', 'isDefault'] + attributes: ['id', 'number', 'status', 'isDefault', 'url'] }); - return whatsapps; + return { whatsapps, whatsapp }; } - return [] + return { whatsapps: [], whatsapp: null } }; diff --git a/backend/src/services/WhatsappService/ShowWhatsAppService.ts b/backend/src/services/WhatsappService/ShowWhatsAppService.ts index db386a1..866725d 100644 --- a/backend/src/services/WhatsappService/ShowWhatsAppService.ts +++ b/backend/src/services/WhatsappService/ShowWhatsAppService.ts @@ -14,7 +14,7 @@ const ShowWhatsAppService = async (id: string | number): Promise => { order: [["queues", "id", "ASC"]] }); - console.log('kkkkkkkkkkkkkkkkkkkk: ', whatsapp) + // console.log('kkkkkkkkkkkkkkkkkkkk: ', whatsapp) if (!whatsapp) { throw new AppError("ERR_NO_WAPP_FOUND", 404); diff --git a/frontend/src/components/MessagesList/index.js b/frontend/src/components/MessagesList/index.js index 75f778a..5c02bf0 100644 --- a/frontend/src/components/MessagesList/index.js +++ b/frontend/src/components/MessagesList/index.js @@ -374,6 +374,8 @@ const MessagesList = ({ ticketId, isGroup }) => { if (data.action === "update") { + console.log('joinChatBox update: ',data.action) + dispatch({ type: "UPDATE_MESSAGE", payload: data.message }); } }); diff --git a/frontend/src/components/NotificationsPopOver/index.js b/frontend/src/components/NotificationsPopOver/index.js index 2af43e2..86b8363 100644 --- a/frontend/src/components/NotificationsPopOver/index.js +++ b/frontend/src/components/NotificationsPopOver/index.js @@ -111,11 +111,25 @@ const NotificationsPopOver = () => { }, [ticketIdUrl]); - + useEffect(() => { const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + socket.on("reload_page", (data) => { + + console.log('UPDATING THE PAGE: ', data.userId, ' | user.id: ', user.id) + + if (user.id === data.userId) { + + window.location.reload(true); + + } + + + + }) + socket.on("onlineStatus", (data) => { if (data.action === "logout") { @@ -147,28 +161,28 @@ const NotificationsPopOver = () => { // }); - if(user.profile === 'user'){ + if (user.profile === 'user') { - if(_fifo){ - clearInterval(_fifo); + if (_fifo) { + clearInterval(_fifo); } - - _fifo = setInterval(()=>{ + + _fifo = setInterval(() => { console.log('user.id: ', user.id) socket.emit("online", user.id) }, 3000); - } + } + - return () => { socket.disconnect(); }; - }, [user.id, handleLogout, user.profile ]); + }, [user.id, handleLogout, user.profile]);