feat: Update controller to use queueId assigned to a WhatsApp number for message sending in remote ticket creation

feat-scaling-ticket-remote-creation
adriano 2024-04-02 11:59:44 -03:00
parent 88a71e5758
commit 7df322d1ab
6 changed files with 163 additions and 98 deletions

View File

@ -183,11 +183,17 @@ socketIo.on('connect_error', async function (err) {
}) })
// //
const wwebVersion = '2.2402.5';
//NOVA OPÇÃO MD //NOVA OPÇÃO MD
client = new Client({ client = new Client({
authStrategy: new LocalAuth({ clientId: 'omnihit_sesssion' }), authStrategy: new LocalAuth({ clientId: 'omnihit_sesssion' }),
puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'], executablePath: process.env.CHROME_BIN || '/usr/bin/google-chrome-stable' }, puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'], executablePath: process.env.CHROME_BIN || '/usr/bin/google-chrome-stable' },
webVersionCache: {
type: 'remote',
remotePath: `https://raw.githubusercontent.com/wppconnect-team/wa-version/main/html/${wwebVersion}.html`,
},
}) })
client.initialize() client.initialize()

View File

@ -8,6 +8,9 @@ import UpdateQueueService from "../services/QueueService/UpdateQueueService";
import Queue from "../models/Queue"; import Queue from "../models/Queue";
import AppError from "../errors/AppError"; import AppError from "../errors/AppError";
import { del, get, set } from "../helpers/RedisClient"; import { del, get, set } from "../helpers/RedisClient";
import { Op } from "sequelize";
import ListWhatsAppsService from "../services/WhatsappService/ListWhatsAppsService";
import Whatsapp from "../models/Whatsapp";
export const index = async (req: Request, res: Response): Promise<Response> => { export const index = async (req: Request, res: Response): Promise<Response> => {
const queues = await ListQueuesService(); const queues = await ListQueuesService();
@ -15,6 +18,58 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
return res.status(200).json(queues); return res.status(200).json(queues);
}; };
export const listQueues = async (
req: Request,
res: Response
): Promise<Response> => {
const whatsapps = await Whatsapp.findAll({
where: {
name: { [Op.ne]: "botqueue" },
number: { [Op.ne]: "" },
phoneNumberId: false
},
attributes: ["number"],
include: [
{
model: Queue,
as: "queues",
attributes: ["id", "name"]
}
]
});
const whats = whatsapps
?.filter((w: any) => w?.queues?.length > 0)
?.map((w: any) => {
const { number, queues } = w;
return {
number,
queues: queues?.map((q: any) => {
const { id, name } = q;
return { id, name };
})
};
});
let _queues: any = [];
for (const w of whats) {
const { queues } = w;
for (const q of queues) {
const { id: queueId, name } = q;
const auxQueue = _queues.findIndex((q: any) => q.queueId == queueId);
if (auxQueue == -1) {
_queues.push({ queueId, name });
}
}
}
return res.status(200).json(_queues);
};
export const store = async (req: Request, res: Response): Promise<Response> => { export const store = async (req: Request, res: Response): Promise<Response> => {
const { name, color, greetingMessage } = req.body; const { name, color, greetingMessage } = req.body;

View File

@ -119,10 +119,10 @@ export const remoteTicketCreation = async (
req: Request, req: Request,
res: Response res: Response
): Promise<Response> => { ): Promise<Response> => {
const { contact_from, contact_to, msg, contact_name }: any = req.body; const { queueId, contact_to, msg, contact_name }: any = req.body;
const validate = ["contact_from", "contact_to", "msg"]; const validate = ["queueId", "contact_to", "msg"];
const validateOnlyNumber = ["contact_from", "contact_to"]; const validateOnlyNumber = ["queueId", "contact_to"];
for (let prop of validate) { for (let prop of validate) {
if (!req.body[prop]) if (!req.body[prop])
@ -139,109 +139,97 @@ export const remoteTicketCreation = async (
} }
} }
const whatsapp = await Whatsapp.findOne({ const whatsapps = await ListWhatsAppsForQueueService(queueId, "CONNECTED");
where: { number: contact_from, status: "CONNECTED" }
});
if (whatsapp) {
const { id: whatsappId, number, status } = whatsapp;
const queue: any = await WhatsappQueue.findOne({ if (!whatsapps || whatsapps?.length == 0) {
where: { whatsappId }, return res.status(500).json({
attributes: ["queueId"] msg: `queueId ${queueId} does not have a WhatsApp number associated with it or the number's session is disconnected.`
}); });
}
const { queueId } = queue; const { id: whatsappId } = whatsapps[0];
// const validNumber = await CheckIsValidContact(contact_to, true); // const validNumber = await CheckIsValidContact(contact_to, true);
const validNumber = contact_to; const validNumber = contact_to;
if (validNumber) { if (validNumber) {
let contact = await Contact.findOne({ where: { number: validNumber } }); let contact = await Contact.findOne({ where: { number: validNumber } });
if (!contact) { if (!contact) {
// const profilePicUrl = await GetProfilePicUrl(validNumber); // const profilePicUrl = await GetProfilePicUrl(validNumber);
contact = await CreateContactService({ contact = await CreateContactService({
name: contact_name ? contact_name : contact_to, name: contact_name ? contact_name : contact_to,
number: validNumber number: validNumber
// profilePicUrl // profilePicUrl
});
const io = getIO();
io.emit("contact", {
action: "create",
contact
});
}
const { id: contactId } = contact;
const botInfo = await BotIsOnQueue("botqueue");
let ticket = await Ticket.findOne({
where: {
[Op.or]: [
{ contactId, status: "queueChoice" },
{ contactId, status: "open", userId: botInfo.userIdBot }
]
}
}); });
if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") {
if (ticket) {
await UpdateTicketService({
ticketData: { status: "closed" },
ticketId: ticket.id
});
ticket = null;
}
} else {
if (ticket) {
await UpdateTicketService({
ticketData: { status: "closed" },
ticketId: ticket.id
});
}
}
if (!ticket) {
ticket = await FindOrCreateTicketService(
contact,
whatsappId,
0,
undefined,
queueId
);
botSendMessage(ticket, `${msg}`);
}
const io = getIO(); const io = getIO();
io.to(ticket.status).emit("ticket", { io.emit("contact", {
action: "update", action: "create",
ticket contact
}); });
console.log(
`REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success`
);
return res.status(200).json({ msg: "success" });
} }
const { id: contactId } = contact;
const botInfo = await BotIsOnQueue("botqueue");
let ticket = await Ticket.findOne({
where: {
[Op.or]: [
{ contactId, status: "queueChoice" },
{ contactId, status: "open", userId: botInfo.userIdBot }
]
}
});
if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") {
if (ticket) {
await UpdateTicketService({
ticketData: { status: "closed" },
ticketId: ticket.id
});
ticket = null;
}
} else {
if (ticket) {
await UpdateTicketService({
ticketData: { status: "closed" },
ticketId: ticket.id
});
}
}
if (!ticket) {
ticket = await FindOrCreateTicketService(
contact,
whatsappId,
0,
undefined,
queueId
);
botSendMessage(ticket, `${msg}`);
}
const io = getIO();
io.to(ticket.status).emit("ticket", {
action: "update",
ticket
});
console.log( console.log(
`REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: The number ${contact_to} does not exist on WhatsApp` `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success`
); );
return res return res.status(200).json({ msg: "success" });
.status(500)
.json({ msg: `The number ${contact_to} does not exist on WhatsApp` });
} }
console.log( console.log(
`REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit` `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: The number ${contact_to} does not exist on WhatsApp`
); );
return res.status(500).json({ return res
msg: `Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit` .status(500)
}); .json({ msg: `The number ${contact_to} does not exist on WhatsApp` });
}; };
export const store = async (req: Request, res: Response): Promise<Response> => { export const store = async (req: Request, res: Response): Promise<Response> => {

View File

@ -19,10 +19,11 @@ const isAuth = (req: Request, res: Response, next: NextFunction): void => {
throw new AppError("ERR_SESSION_EXPIRED", 401); throw new AppError("ERR_SESSION_EXPIRED", 401);
} }
const [, token] = authHeader.split(" "); const [, token] = authHeader.split(" ");
if ( if (
req.originalUrl == "/tickets/remote/create" && (req.originalUrl == "/queue/remote/list" ||
req.originalUrl == "/tickets/remote/create") &&
token === process.env.TOKEN_REMOTE_TICKET_CREATION token === process.env.TOKEN_REMOTE_TICKET_CREATION
) { ) {
return next(); return next();

View File

@ -11,6 +11,8 @@ queueRoutes.post("/queue", isAuth, QueueController.store);
queueRoutes.post("/queue/customization", QueueController.customization); queueRoutes.post("/queue/customization", QueueController.customization);
queueRoutes.get("/queue/remote/list", isAuth, QueueController.listQueues);
queueRoutes.get("/queue/:queueId", isAuth, QueueController.show); queueRoutes.get("/queue/:queueId", isAuth, QueueController.show);
queueRoutes.put("/queue/:queueId", isAuth, QueueController.update); queueRoutes.put("/queue/:queueId", isAuth, QueueController.update);

View File

@ -6,17 +6,30 @@ const { QueryTypes } = require("sequelize");
const sequelize = new Sequelize(dbConfig); const sequelize = new Sequelize(dbConfig);
const ListWhatsAppsForQueueService = async (queueId: number | string): Promise<any> => { const ListWhatsAppsForQueueService = async (
const distinctWhatsapps = await sequelize.query( queueId: number | string,
`SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId status?: string
FROM Whatsapps w ): Promise<any> => {
JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} let distinctWhatsapps: any;
GROUP BY w.number;`,
{ type: QueryTypes.SELECT } if (status) {
); distinctWhatsapps = await sequelize.query(
`SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId FROM Whatsapps w
JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} AND w.status = '${status}'
AND phoneNumberId = false
GROUP BY w.number;`,
{ type: QueryTypes.SELECT }
);
} else {
distinctWhatsapps = await sequelize.query(
`SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId FROM Whatsapps w
JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId}
GROUP BY w.number;`,
{ type: QueryTypes.SELECT }
);
}
return distinctWhatsapps; return distinctWhatsapps;
}; };
export default ListWhatsAppsForQueueService; export default ListWhatsAppsForQueueService;