From 766cb70f0c33f9534aebc0a77958bc350f472129 Mon Sep 17 00:00:00 2001 From: canove Date: Sat, 14 Nov 2020 20:02:25 -0300 Subject: [PATCH] feat: sync unread messages after connecting --- backend/src/libs/wbot.ts | 18 ++ .../WbotServices/StartWhatsAppSession.ts | 2 +- .../WbotServices/wbotMessageListener.ts | 182 ++++++++---------- 3 files changed, 102 insertions(+), 100 deletions(-) diff --git a/backend/src/libs/wbot.ts b/backend/src/libs/wbot.ts index 8538ee5..e3f447d 100644 --- a/backend/src/libs/wbot.ts +++ b/backend/src/libs/wbot.ts @@ -3,6 +3,7 @@ import { Client } from "whatsapp-web.js"; import { getIO } from "./socket"; import Whatsapp from "../models/Whatsapp"; import AppError from "../errors/AppError"; +import { handleMessage } from "../services/WbotServices/wbotMessageListener"; interface Session extends Client { id?: number; @@ -10,6 +11,21 @@ interface Session extends Client { const sessions: Session[] = []; +const syncUnreadMessages = async (wbot: Session) => { + const chats = await wbot.getChats(); + + chats.forEach(async chat => { + if (chat.unreadCount > 0) { + const unreadMessages = await chat.fetchMessages({ + limit: chat.unreadCount + }); + unreadMessages.forEach(msg => { + handleMessage(msg, wbot); + }); + } + }); +}; + export const initWbot = async (whatsapp: Whatsapp): Promise => { return new Promise((resolve, reject) => { try { @@ -89,6 +105,8 @@ export const initWbot = async (whatsapp: Whatsapp): Promise => { wbot.on("ready", async () => { console.log("Session:", sessionName, "READY"); + syncUnreadMessages(wbot); + await whatsapp.update({ status: "CONNECTED", qrcode: "", diff --git a/backend/src/services/WbotServices/StartWhatsAppSession.ts b/backend/src/services/WbotServices/StartWhatsAppSession.ts index b5f508e..16dc52a 100644 --- a/backend/src/services/WbotServices/StartWhatsAppSession.ts +++ b/backend/src/services/WbotServices/StartWhatsAppSession.ts @@ -1,6 +1,6 @@ import { initWbot } from "../../libs/wbot"; import Whatsapp from "../../models/Whatsapp"; -import wbotMessageListener from "./wbotMessageListener"; +import { wbotMessageListener } from "./wbotMessageListener"; import { getIO } from "../../libs/socket"; import wbotMonitor from "./wbotMonitor"; diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index acd2e6a..3e6902f 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -8,6 +8,7 @@ import * as Sentry from "@sentry/node"; import { Contact as WbotContact, Message as WbotMessage, + MessageAck, Client } from "whatsapp-web.js"; @@ -144,7 +145,7 @@ const verifyTicket = async ( return ticket; }; -const handlMedia = async ( +const verifyMedia = async ( msg: WbotMessage, ticket: Ticket, contact: Contact @@ -196,7 +197,7 @@ const handlMedia = async ( return newMessage; }; -const handleMessage = async ( +const verifyMessage = async ( msg: WbotMessage, ticket: Ticket, contact: Contact @@ -211,7 +212,7 @@ const handleMessage = async ( } if (msg.hasMedia) { - newMessage = await handlMedia(msg, ticket, contact); + newMessage = await verifyMedia(msg, ticket, contact); } else { const messageData = { id: msg.id.id, @@ -256,117 +257,100 @@ const isValidMsg = (msg: WbotMessage): boolean => { return false; }; -const wbotMessageListener = (wbot: Session): void => { - const whatsappId = wbot.id; - const io = getIO(); +const handleMessage = async ( + msg: WbotMessage, + wbot: Session +): Promise => { + if (!isValidMsg(msg)) { + return; + } - wbot.on("message_create", async msg => { - // console.log(msg); - if (!isValidMsg(msg)) { - return; + try { + let msgContact: WbotContact; + let groupContact: Contact | undefined; + + if (msg.fromMe) { + msgContact = await wbot.getContactById(msg.to); + + // media messages sent from me from cell phone, first comes with "hasMedia = false" and type = "image/ptt/etc" + // the media itself comes on body of message, as base64 + // if this is the case, return and let this media be handled by media_uploaded event + // it should be improoved to handle the base64 media here in future versions + + if (!msg.hasMedia && msg.type !== "chat" && msg.type !== "vcard") return; + } else { + msgContact = await msg.getContact(); } - try { - let msgContact: WbotContact; - let groupContact: Contact | undefined; + const chat = await msg.getChat(); + + if (chat.isGroup) { + let msgGroupContact; if (msg.fromMe) { - msgContact = await wbot.getContactById(msg.to); - - // media messages sent from me from cell phone, first comes with "hasMedia = false" and type = "image/ptt/etc" - // the media itself comes on body of message, as base64 - // if this is the case, return and let this media be handled by media_uploaded event - // it should be improoved to handle the base64 media here in future versions - - if (!msg.hasMedia && msg.type !== "chat" && msg.type !== "vcard") - return; + msgGroupContact = await wbot.getContactById(msg.to); } else { - msgContact = await msg.getContact(); + msgGroupContact = await wbot.getContactById(msg.from); } - const chat = await msg.getChat(); - - if (chat.isGroup) { - let msgGroupContact; - - if (msg.fromMe) { - msgGroupContact = await wbot.getContactById(msg.to); - } else { - msgGroupContact = await wbot.getContactById(msg.from); - } - - groupContact = await verifyGroup(msgGroupContact); - } - - const profilePicUrl = await msgContact.getProfilePicUrl(); - const contact = await verifyContact(msgContact, profilePicUrl); - const ticket = await verifyTicket(contact, whatsappId!, groupContact); - - await handleMessage(msg, ticket, contact); - } catch (err) { - Sentry.captureException(err); - console.log(err); + groupContact = await verifyGroup(msgGroupContact); } + + const profilePicUrl = await msgContact.getProfilePicUrl(); + const contact = await verifyContact(msgContact, profilePicUrl); + const ticket = await verifyTicket(contact, wbot.id!, groupContact); + + await verifyMessage(msg, ticket, contact); + } catch (err) { + Sentry.captureException(err); + console.log(err); + } +}; + +const handleMsgAck = async (msg: WbotMessage, ack: MessageAck) => { + await new Promise(r => setTimeout(r, 500)); + + const io = getIO(); + + try { + const messageToUpdate = await Message.findByPk(msg.id.id, { + include: [ + "contact", + { + model: Message, + as: "quotedMsg", + include: ["contact"] + } + ] + }); + if (!messageToUpdate) { + return; + } + await messageToUpdate.update({ ack }); + + io.to(messageToUpdate.ticketId.toString()).emit("appMessage", { + action: "update", + message: messageToUpdate + }); + } catch (err) { + Sentry.captureException(err); + console.log(err); + } +}; + +const wbotMessageListener = (wbot: Session): void => { + wbot.on("message_create", async msg => { + // console.log(msg); + handleMessage(msg, wbot); }); wbot.on("media_uploaded", async msg => { - try { - let groupContact: Contact | undefined; - const msgContact = await wbot.getContactById(msg.to); - - const chat = await msg.getChat(); - - if (chat.isGroup) { - let msgGroupContact; - - if (msg.fromMe) { - msgGroupContact = await wbot.getContactById(msg.to); - } else { - msgGroupContact = await wbot.getContactById(msg.from); - } - - groupContact = await verifyGroup(msgGroupContact); - } - - const profilePicUrl = await msgContact.getProfilePicUrl(); - const contact = await verifyContact(msgContact, profilePicUrl); - const ticket = await verifyTicket(contact, whatsappId!, groupContact); - - await handleMessage(msg, ticket, contact); - } catch (err) { - Sentry.captureException(err); - console.log(err); - } + handleMessage(msg, wbot); }); wbot.on("message_ack", async (msg, ack) => { - await new Promise(r => setTimeout(r, 500)); - - try { - const messageToUpdate = await Message.findByPk(msg.id.id, { - include: [ - "contact", - { - model: Message, - as: "quotedMsg", - include: ["contact"] - } - ] - }); - if (!messageToUpdate) { - return; - } - await messageToUpdate.update({ ack }); - - io.to(messageToUpdate.ticketId.toString()).emit("appMessage", { - action: "update", - message: messageToUpdate - }); - } catch (err) { - Sentry.captureException(err); - console.log(err); - } + handleMsgAck(msg, ack); }); }; -export default wbotMessageListener; +export { wbotMessageListener, handleMessage };