Versao beta da funcionalidade de multisessão completada

pull/21/head
adriano 2023-02-07 12:47:40 -03:00
parent 01478d91d1
commit 1dbd2a08db
41 changed files with 864 additions and 189 deletions

View File

@ -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);
}
})

View File

@ -96,11 +96,18 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
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<Response> => {
name,
number,
email,
profilePicUrl: profilePicUrl,
extraInfo,
profilePicUrl
});
const io = getIO();

View File

@ -30,7 +30,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
ticketId
});
SetTicketMessagesAsRead(ticket);
// SetTicketMessagesAsRead(ticket);
return res.json({ count, messages, ticket, hasMore });
};
@ -45,7 +45,7 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
console.log('TICKET ID: ', ticketId)
SetTicketMessagesAsRead(ticket);
// SetTicketMessagesAsRead(ticket);
if (medias) {
await Promise.all(

View File

@ -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<Response> => {
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<Response> => {
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<Response> => {
// 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" });
// };

View File

@ -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<Response> => {
const remove = async (req: Request, res: Response): Promise<Response> => {
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." });

View File

@ -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");
}
};

View File

@ -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)

View File

@ -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;

View File

@ -4,7 +4,9 @@ import GetDefaultWhatsApp from "./GetDefaultWhatsApp";
import Ticket from "../models/Ticket";
const GetTicketWbot = async (ticket: Ticket): Promise<Session> => {
if (!ticket.whatsappId) {
const defaultWhatsapp = await GetDefaultWhatsApp();
await ticket.$set("whatsapp", defaultWhatsapp);

View File

@ -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<WbotMessage> => {
const wbot = await GetTicketWbot(ticket);
): Promise<WbotMessage | any> => {
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<void | WbotMessage> => {
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");
}

View File

@ -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}`)

View File

@ -73,8 +73,6 @@ export const restoreMonit = (whatsappId: string | number) => {
}
console.log('888888888888888888 ENTROU NO SET TIMEOUT -----------> ')
}, 180000);
}

View File

@ -55,7 +55,7 @@ const monitor = async () => {
await ticket.update({status: 'open'})
}
SetTicketMessagesAsRead(ticket);
// SetTicketMessagesAsRead(ticket);
await SendWhatsAppMessage({
body: schedulingNotifies[i].message, ticket

View File

@ -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;

View File

@ -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;

View File

@ -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;
};

View File

@ -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 []
}

View File

@ -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();

View File

@ -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("joinWhatsSession", (whatsappId: string) => {
logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`);
socket.join(`session_${whatsappId}`);
});
socket.on("message_from_client", () => {
console.log('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

View File

@ -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();
}
}
};
@ -77,7 +81,7 @@ export const initWbot = async (whatsapp: Whatsapp, backupSessionRestore: boolean
// });
const args:String = process.env.CHROME_ARGS || "";
const args: String = process.env.CHROME_ARGS || "";
const wbot: Session = new Client({
session: sessionCfg,
@ -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<any> => {
// 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 => {

View File

@ -56,6 +56,9 @@ class Whatsapp extends Model<Whatsapp> {
@Column
number: string;
@Column
url: string;
@Default(false)
@AllowNull
@Column

View File

@ -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;

View File

@ -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;

View File

@ -1,8 +1,9 @@
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}`);
@ -17,5 +18,38 @@ if (global.gc) {
}
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)

View File

@ -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<Contact> => {
const numberExists = await Contact.findOne({
@ -35,6 +37,7 @@ const CreateContactService = async ({
name,
number,
email,
profilePicUrl,
extraInfo
},
{
@ -43,8 +46,9 @@ 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 })
//

View File

@ -19,7 +19,7 @@ interface Request {
const CreateMessageService = async ({ messageData }: Request): Promise<Message> => {
console.log('UPSERT MESSAGE messageData: ', messageData)
// console.log('UPSERT MESSAGE messageData: ', messageData)
await Message.upsert(messageData);
@ -57,9 +57,8 @@ const CreateMessageService = async ({ messageData }: Request): Promise<Message>
})
//
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())

View File

@ -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,7 +201,6 @@ const ListTicketsService = async ({
console.log('ENTROU NO LIST TICKET SERVICE')
const { count, rows: tickets } = await Ticket.findAndCountAll({
where: whereCondition,

View File

@ -26,6 +26,8 @@ const ShowTicketService = async (id: string | number): Promise<Ticket> => {
]
});
console.log('>>>>>>>>>>>>>>>>>>>>>>>> ShowTicketService: ',ticket?.whatsappId)
if (!ticket) {
throw new AppError("ERR_NO_TICKET_FOUND", 404);
}

View File

@ -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;

View File

@ -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<void> => {
const CheckIsValidContact = async (number: string): Promise<any> => {
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;

View File

@ -2,12 +2,12 @@ import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp";
import { getWbot } from "../../libs/wbot";
const CheckContactNumber = async (number: string): Promise<void> => {
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;

View File

@ -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<Message> => {
const DeleteWhatsAppMessage = async (messageId: string): Promise<Message | any> => {
const message = await Message.findByPk(messageId, {
include: [
{
@ -20,15 +22,35 @@ const DeleteWhatsAppMessage = async (messageId: string): Promise<Message> => {
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;
};

View File

@ -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<string> => {
const GetProfilePicUrl = async (number: string): Promise<any> => {
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;

View File

@ -6,47 +6,47 @@ import { logger } from "../../utils/logger";
import { createOrUpdateContactCache } from '../../helpers/ContactsCache'
const ImportContactsService = async (): Promise<void> => {
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;

View File

@ -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<WbotMessage> => {
}: Request): Promise<WbotMessage | any> => {
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;

View File

@ -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,22 +39,97 @@ const SendWhatsAppMessage = async ({
body,
ticket,
quotedMsg
}: Request): Promise<WbotMessage> => {
}: Request): Promise<WbotMessage | any> => {
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') {
@ -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;

View File

@ -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<Message> => {
): Promise<Message | any> => {
// 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}`);
@ -166,7 +179,6 @@ const verifyMessage = async (
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,21 +398,61 @@ 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<void> => {
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)))
@ -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) {
// 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);
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 };

View File

@ -1,26 +1,28 @@
import Whatsapp from "../../models/Whatsapp";
const ListWhatsAppsNumber = async (whatsappId: string | number, status: string): Promise<Whatsapp[]> => {
const ListWhatsAppsNumber = async (whatsappId: string | number, status: string): Promise<Whatsapp[] | any> => {
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 }
};

View File

@ -14,7 +14,7 @@ const ShowWhatsAppService = async (id: string | number): Promise<Whatsapp> => {
order: [["queues", "id", "ASC"]]
});
console.log('kkkkkkkkkkkkkkkkkkkk: ', whatsapp)
// console.log('kkkkkkkkkkkkkkkkkkkk: ', whatsapp)
if (!whatsapp) {
throw new AppError("ERR_NO_WAPP_FOUND", 404);

View File

@ -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 });
}
});

View File

@ -116,6 +116,20 @@ const NotificationsPopOver = () => {
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,13 +161,13 @@ const NotificationsPopOver = () => {
// });
if(user.profile === 'user'){
if (user.profile === 'user') {
if(_fifo){
if (_fifo) {
clearInterval(_fifo);
}
_fifo = setInterval(()=>{
_fifo = setInterval(() => {
console.log('user.id: ', user.id)
socket.emit("online", user.id)
}, 3000);
@ -168,7 +182,7 @@ const NotificationsPopOver = () => {
return () => {
socket.disconnect();
};
}, [user.id, handleLogout, user.profile ]);
}, [user.id, handleLogout, user.profile]);