feat: sync unread messages after connecting

This commit is contained in:
canove
2020-11-14 20:02:25 -03:00
parent 3914d63794
commit 766cb70f0c
3 changed files with 102 additions and 100 deletions

View File

@@ -3,6 +3,7 @@ import { Client } from "whatsapp-web.js";
import { getIO } from "./socket"; import { getIO } from "./socket";
import Whatsapp from "../models/Whatsapp"; import Whatsapp from "../models/Whatsapp";
import AppError from "../errors/AppError"; import AppError from "../errors/AppError";
import { handleMessage } from "../services/WbotServices/wbotMessageListener";
interface Session extends Client { interface Session extends Client {
id?: number; id?: number;
@@ -10,6 +11,21 @@ interface Session extends Client {
const sessions: Session[] = []; 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<Session> => { export const initWbot = async (whatsapp: Whatsapp): Promise<Session> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
@@ -89,6 +105,8 @@ export const initWbot = async (whatsapp: Whatsapp): Promise<Session> => {
wbot.on("ready", async () => { wbot.on("ready", async () => {
console.log("Session:", sessionName, "READY"); console.log("Session:", sessionName, "READY");
syncUnreadMessages(wbot);
await whatsapp.update({ await whatsapp.update({
status: "CONNECTED", status: "CONNECTED",
qrcode: "", qrcode: "",

View File

@@ -1,6 +1,6 @@
import { initWbot } from "../../libs/wbot"; import { initWbot } from "../../libs/wbot";
import Whatsapp from "../../models/Whatsapp"; import Whatsapp from "../../models/Whatsapp";
import wbotMessageListener from "./wbotMessageListener"; import { wbotMessageListener } from "./wbotMessageListener";
import { getIO } from "../../libs/socket"; import { getIO } from "../../libs/socket";
import wbotMonitor from "./wbotMonitor"; import wbotMonitor from "./wbotMonitor";

View File

@@ -8,6 +8,7 @@ import * as Sentry from "@sentry/node";
import { import {
Contact as WbotContact, Contact as WbotContact,
Message as WbotMessage, Message as WbotMessage,
MessageAck,
Client Client
} from "whatsapp-web.js"; } from "whatsapp-web.js";
@@ -144,7 +145,7 @@ const verifyTicket = async (
return ticket; return ticket;
}; };
const handlMedia = async ( const verifyMedia = async (
msg: WbotMessage, msg: WbotMessage,
ticket: Ticket, ticket: Ticket,
contact: Contact contact: Contact
@@ -196,7 +197,7 @@ const handlMedia = async (
return newMessage; return newMessage;
}; };
const handleMessage = async ( const verifyMessage = async (
msg: WbotMessage, msg: WbotMessage,
ticket: Ticket, ticket: Ticket,
contact: Contact contact: Contact
@@ -211,7 +212,7 @@ const handleMessage = async (
} }
if (msg.hasMedia) { if (msg.hasMedia) {
newMessage = await handlMedia(msg, ticket, contact); newMessage = await verifyMedia(msg, ticket, contact);
} else { } else {
const messageData = { const messageData = {
id: msg.id.id, id: msg.id.id,
@@ -256,117 +257,100 @@ const isValidMsg = (msg: WbotMessage): boolean => {
return false; return false;
}; };
const wbotMessageListener = (wbot: Session): void => { const handleMessage = async (
const whatsappId = wbot.id; msg: WbotMessage,
const io = getIO(); wbot: Session
): Promise<void> => {
if (!isValidMsg(msg)) {
return;
}
wbot.on("message_create", async msg => { try {
// console.log(msg); let msgContact: WbotContact;
if (!isValidMsg(msg)) { let groupContact: Contact | undefined;
return;
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 { const chat = await msg.getChat();
let msgContact: WbotContact;
let groupContact: Contact | undefined; if (chat.isGroup) {
let msgGroupContact;
if (msg.fromMe) { if (msg.fromMe) {
msgContact = await wbot.getContactById(msg.to); msgGroupContact = 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 { } else {
msgContact = await msg.getContact(); msgGroupContact = await wbot.getContactById(msg.from);
} }
const chat = await msg.getChat(); groupContact = await verifyGroup(msgGroupContact);
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);
} }
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 => { wbot.on("media_uploaded", async msg => {
try { handleMessage(msg, wbot);
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);
}
}); });
wbot.on("message_ack", async (msg, ack) => { wbot.on("message_ack", async (msg, ack) => {
await new Promise(r => setTimeout(r, 500)); handleMsgAck(msg, ack);
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);
}
}); });
}; };
export default wbotMessageListener; export { wbotMessageListener, handleMessage };