From 9ff95ff4bd826a20bcfab8687ed15c54dc5b53a4 Mon Sep 17 00:00:00 2001 From: adriano Date: Wed, 21 Feb 2024 17:47:23 -0300 Subject: [PATCH] feat: Add route for creating tickets from external endpoints and update authentication middleware --- backend/src/controllers/TicketController.ts | 134 +++++++++++++++++- backend/src/middleware/isAuth.ts | 13 +- backend/src/routes/ticketRoutes.ts | 5 + .../FindOrCreateTicketService.ts | 13 +- .../WbotServices/CheckIsValidContact.ts | 4 +- .../WbotServices/wbotMessageListener.ts | 3 +- 6 files changed, 153 insertions(+), 19 deletions(-) diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index 4f2bd61..3c1c930 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -68,6 +68,13 @@ import ListWhatsAppsForQueueService from "../services/WhatsappService/ListWhatsA import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber"; import Whatsapp from "../models/Whatsapp"; import AppError from "../errors/AppError"; +import CreateOrUpdateContactService from "../services/ContactServices/CreateOrUpdateContactService"; +import FindOrCreateTicketService from "../services/TicketServices/FindOrCreateTicketService"; +import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact"; +import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl"; +import CreateContactService from "../services/ContactServices/CreateContactService"; +import { botSendMessage } from "../services/WbotServices/wbotMessageListener"; +import WhatsappQueue from "../models/WhatsappQueue"; export const index = async (req: Request, res: Response): Promise => { const { @@ -106,6 +113,126 @@ export const index = async (req: Request, res: Response): Promise => { return res.status(200).json({ tickets, count, hasMore }); }; +export const remoteTicketCreation = async ( + req: Request, + res: Response +): Promise => { + const { contact_from, contact_to, msg, contact_name }: any = req.body; + + const validate = ["contact_from", "contact_to", "msg"]; + + for (let prop of validate) { + if (!req.body[prop]) + return res + .status(400) + .json({ error: `Property '${prop}' is undefined.` }); + } + + const whatsapp = await Whatsapp.findOne({ + where: { number: contact_from, status: "CONNECTED" } + }); + + if (whatsapp) { + const { id: whatsappId, number, status } = whatsapp; + + const queue: any = await WhatsappQueue.findOne({ + where: { whatsappId }, + attributes: ["queueId"] + }); + + const { queueId } = queue; + + // const validNumber = await CheckIsValidContact(contact_to, true); + const validNumber = contact_to; + + if (validNumber) { + let contact = await Contact.findOne({ where: { number: validNumber } }); + + if (!contact) { + // const profilePicUrl = await GetProfilePicUrl(validNumber); + + contact = await CreateContactService({ + name: contact_name ? contact_name : contact_to, + number: validNumber + // 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(); + io.to(ticket.status).emit("ticket", { + action: "update", + ticket + }); + + console.log( + `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success` + ); + return res.status(200).json({ msg: "success" }); + } + + console.log( + `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: The number ${contact_to} does not exist on WhatsApp` + ); + return res + .status(500) + .json({ msg: `The number ${contact_to} does not exist on WhatsApp` }); + } + + console.log( + `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected` + ); + return res + .status(500) + .json({ msg: `Whatsapp number ${contact_from} disconnected` }); +}; + export const store = async (req: Request, res: Response): Promise => { const { contactId, status, userId, msg, queueId, whatsappId }: TicketData = req.body; @@ -426,10 +553,3 @@ export const remove = async ( return res.status(200).json({ message: "ticket deleted" }); }; -// export async function setMessageAsRead(ticket: Ticket) { -// const wbot_url = await getWbot(ticket.whatsappId); - -// console.log('wbot_url: ', wbot_url, ' | ticket.contact.number: ', ticket.contact.number); - -// await endPointQuery(`${wbot_url}/api/sendSeen`, { number: `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us` }); -// } diff --git a/backend/src/middleware/isAuth.ts b/backend/src/middleware/isAuth.ts index 86428d3..b19552e 100644 --- a/backend/src/middleware/isAuth.ts +++ b/backend/src/middleware/isAuth.ts @@ -13,16 +13,23 @@ interface TokenPayload { } const isAuth = (req: Request, res: Response, next: NextFunction): void => { - const authHeader = req.headers.authorization; + const authHeader = req.headers.authorization; if (!authHeader) { throw new AppError("ERR_SESSION_EXPIRED", 401); } - const [, token] = authHeader.split(" "); + const [, token] = authHeader.split(" "); + + if ( + req.originalUrl == "/tickets/remote/create" && + token === process.env.TOKEN_REMOTE_TICKET_CREATION + ) { + return next(); + } try { - const decoded = verify(token, authConfig.secret); + const decoded = verify(token, authConfig.secret); const { id, profile } = decoded as TokenPayload; diff --git a/backend/src/routes/ticketRoutes.ts b/backend/src/routes/ticketRoutes.ts index 0524925..2c17f9e 100644 --- a/backend/src/routes/ticketRoutes.ts +++ b/backend/src/routes/ticketRoutes.ts @@ -14,6 +14,11 @@ ticketRoutes.get("/tickets", isAuth, TicketController.index); ticketRoutes.get("/tickets/:ticketId", isAuth, TicketController.show); +ticketRoutes.post( + "/tickets/remote/create", isAuth, + TicketController.remoteTicketCreation +); + ticketRoutes.post("/tickets", isAuth, TicketController.store); ticketRoutes.put("/tickets/:ticketId", isAuth, TicketController.update); diff --git a/backend/src/services/TicketServices/FindOrCreateTicketService.ts b/backend/src/services/TicketServices/FindOrCreateTicketService.ts index 66d51a7..29fe820 100644 --- a/backend/src/services/TicketServices/FindOrCreateTicketService.ts +++ b/backend/src/services/TicketServices/FindOrCreateTicketService.ts @@ -13,15 +13,12 @@ const FindOrCreateTicketService = async ( contact: Contact, whatsappId: number, unreadMessages: number, - groupContact?: Contact, + groupContact?: Contact, + queueId?: number | string ): Promise => { try { let ticket; - // else if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") { - - // } - if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") { let whats = await ListWhatsAppsNumber(whatsappId); @@ -45,7 +42,8 @@ const FindOrCreateTicketService = async ( }); } - const { queues, greetingMessage, phoneNumberId } = await ShowWhatsAppService(whatsappId); + const { queues, greetingMessage, phoneNumberId } = + await ShowWhatsAppService(whatsappId); const botInfo = { isOnQueue: false }; @@ -97,7 +95,7 @@ const FindOrCreateTicketService = async ( if (!ticket) { let status = "pending"; - if (queues.length > 1 && !botInfo.isOnQueue) { + if (queues.length > 1 && !botInfo.isOnQueue && !queueId) { status = "queueChoice"; } @@ -105,6 +103,7 @@ const FindOrCreateTicketService = async ( contactId: groupContact ? groupContact.id : contact.id, status: status, isGroup: !!groupContact, + queueId, unreadMessages, whatsappId, phoneNumberId diff --git a/backend/src/services/WbotServices/CheckIsValidContact.ts b/backend/src/services/WbotServices/CheckIsValidContact.ts index 888146a..4596f67 100644 --- a/backend/src/services/WbotServices/CheckIsValidContact.ts +++ b/backend/src/services/WbotServices/CheckIsValidContact.ts @@ -3,7 +3,7 @@ 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, ignoreThrow?:boolean): Promise => { const defaultWhatsapp = await GetDefaultWhatsApp({}); @@ -11,6 +11,8 @@ const CheckIsValidContact = async (number: string): Promise => { const isValidNumber = await endPointQuery(`${wbot_url}/api/validate`, { mobile: `${number}`, }) + if(ignoreThrow) return isValidNumber?.data?.number; + // console.log('isValidNumber.data.number: ', isValidNumber.data.number) try { diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index b105c71..d0b1a8f 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -1134,7 +1134,8 @@ export { verifyMediaMessage, verifyContact, isValidMsg, - mediaTypeWhatsappOfficial + mediaTypeWhatsappOfficial, + botSendMessage }; async function whatsappInfo(whatsappId: string | number) { return await Whatsapp.findByPk(whatsappId);