gertec
gustavo-gsp 2024-06-14 17:48:33 -03:00
commit da86bbfa33
9 changed files with 285 additions and 56 deletions

View File

@ -23,6 +23,7 @@
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"cpf-cnpj-validator": "^1.0.3",
"date-fns": "^2.30.0",
"date-fns-tz": "^1.3.8",
"dotenv": "^8.2.0",

View File

@ -74,7 +74,65 @@ export const createUser = async (
.status(200)
.json(response("1", `User ${user_id} created`, "1", "createUser"));
};
export const createMultiUsers = async(
req: Request,
res: Response
): Promise<Response> => {
const {data}: any = req.body;
if(data){
try{
for(let user of data){
const nameSplit = user.name.split(' ');
const password = `${nameSplit[0]}.${nameSplit[1]}`;
const email = `${nameSplit[0]}.${nameSplit[1]}@omnihit.com`.toLowerCase();
const create = await CreateUserService({
email,
password,
name: user.name,
profile: "user",
ignoreThrow: true
});
create?.error ?? console.log('erro ao criar user: ',user);
}
return res
.status(200)
.json(response("1", `Users created`, "1", "createUser"));
}catch(error){
console.log(error);
return res
.status(500)
.json({ message: 'Error creating users'});
}
}else{
return res
.status(500)
.json({ message: 'Error creating users'});
}
}
export const allUsers = async (
req: Request,
res: Response
): Promise<Response> => {
const users = await User.findAll({attributes: ['email', 'name']})
if(users){
let index = 0;
for(let user of users){
const nameSplit = user.name.split(' ');
const password = `${nameSplit[0]}.${nameSplit[1]}`;
users[index].password = password.toLowerCase();
index ++;
}
return res
.status(200)
.json(response("1", "Success", users, "listAllUsers"));
}else{
return res
.status(500)
}
}
export const deleteUser = async (
req: Request,
res: Response

View File

@ -0,0 +1,15 @@
import { QueryInterface, DataTypes } from "sequelize";
module.exports = {
up: (queryInterface: QueryInterface) => {
return queryInterface.addColumn("Contacts", "isLGPDAccepted", {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false
});
},
down: (queryInterface: QueryInterface) => {
return queryInterface.removeColumn("Contacts", "isLGPDAccepted");
}
};

View File

@ -51,10 +51,10 @@ export const initIO = (httpServer: Server): SocketIO => {
});
io.on("connection", socket => {
logger.info("Client Connected");
//logger.info("Client Connected");
socket.on("joinWhatsSession", (whatsappId: string) => {
logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`);
//logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`);
socket.join(`session_${whatsappId}`);
});
@ -139,7 +139,7 @@ export const initIO = (httpServer: Server): SocketIO => {
lstOnline.push({ id: userId, status: "online", try: 0 });
lstOnlineAux.push({ id: userId });
console.log(" 1 - PUSHED NEW USER ID 1: ", userId);
//console.log(" 1 - PUSHED NEW USER ID 1: ", userId);
obj.listOnline = lstOnline;
} else {
@ -154,7 +154,7 @@ export const initIO = (httpServer: Server): SocketIO => {
if (index == -1) {
lstOnline.push({ id: userId, status: "online", try: 0 });
console.log(" 2 - PUSHED NEW USER ID: ", userId);
//console.log(" 2 - PUSHED NEW USER ID: ", userId);
obj.listOnline = lstOnline;
} else {
@ -204,30 +204,30 @@ export const initIO = (httpServer: Server): SocketIO => {
});
socket.on("joinChatBox", (ticketId: string) => {
logger.info("A client joined a ticket channel");
//logger.info("A client joined a ticket channel");
socket.join(ticketId);
});
socket.on("joinNotification", () => {
logger.info("A client joined notification channel");
//logger.info("A client joined notification channel");
socket.join("notification");
});
socket.on("joinTickets", (status: string) => {
logger.info(`A client joined to ${status} tickets channel.`);
//logger.info(`A client joined to ${status} tickets channel.`);
socket.join(status);
});
socket.on("disconnect", (data: any) => {
logger.info(`Client disconnected socket: ${data}`);
//logger.info(`Client disconnected socket: ${data}`);
});
socket.on("disconnecting", async () => {
console.log("socket.rooms: ", socket.rooms); // the Set contains at least the socket ID
//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);
//console.log("rooms: ", rooms, " | rooms.size: ", rooms.size);
if (rooms && rooms.size == 1) return;
if (rooms && rooms.size == 2 && ![...rooms][1].startsWith("session_"))
@ -252,7 +252,7 @@ export const initIO = (httpServer: Server): SocketIO => {
[...rooms][1].startsWith("session_") &&
whatsappIds.includes([...rooms][1].replace("session_", ""))
) {
console.log([...rooms][1]);
//console.log([...rooms][1]);
let whatsappId = [...rooms][1].replace("session_", "");

View File

@ -44,6 +44,10 @@ class Contact extends Model<Contact> {
@Column
isGroup: boolean;
@Default(false)
@Column
isLGPDAccepted: boolean;
@CreatedAt
createdAt: Date;

View File

@ -10,7 +10,16 @@ iamRoutesEL.post(
verifyAPIKey,
IAMControllerEL.createUser
);
iamRoutesEL.post(
"/iam/create-muilti-users",
verifyAPIKey,
IAMControllerEL.createMultiUsers
);
iamRoutesEL.get(
"/iam/allUsers",
verifyAPIKey,
IAMControllerEL.allUsers
);
iamRoutesEL.put(
"/iam/horacius/updateUser",
verifyAPIKey,

View File

@ -18,6 +18,7 @@ interface ContactData {
name?: string;
extraInfo?: ExtraInfo[];
queueIds?: number[];
isLGPDAccepted?: boolean;
}
interface Request {
@ -30,13 +31,13 @@ const UpdateContactService = async ({
contactId
}: Request): Promise<Contact> => {
try {
const { email, name, number, extraInfo, queueIds } = contactData;
const { email, name, number, extraInfo, queueIds, isLGPDAccepted } = contactData;
// console.log('email, name, number, extraInfo: ', email, name, number, extraInfo)
const contact = await Contact.findOne({
where: { id: contactId },
attributes: ["id", "name", "number", "email", "profilePicUrl"],
attributes: ["id", "name", "number", "email", "profilePicUrl", "isLGPDAccepted"],
include: ["extraInfo"]
});
@ -77,12 +78,20 @@ const UpdateContactService = async ({
throw new AppError("ERR_DUPLICATED_CONTACT");
}
}
await contact.update({
name,
number,
email
});
if(isLGPDAccepted != undefined){
await contact.update({
name,
number,
email,
isLGPDAccepted
});
}else{
await contact.update({
name,
number,
email
});
}
if (queueIds) await AssociateContatctQueue(contact, queueIds);
@ -92,7 +101,7 @@ const UpdateContactService = async ({
//
await contact.reload({
attributes: ["id", "name", "number", "email", "profilePicUrl"],
attributes: ["id", "name", "number", "email", "profilePicUrl", "isLGPDAccepted"],
include: ["extraInfo"]
});

View File

@ -6,6 +6,7 @@ import * as Sentry from "@sentry/node";
import { copyFolder } from "../../helpers/CopyFolder";
import { removeDir } from "../../helpers/DeleteDirectory";
import path from "path";
import { cpf, cnpj } from 'cpf-cnpj-validator';
import {
isHoliday,
@ -21,7 +22,8 @@ import {
subMinutes,
isSaturday,
isSunday,
parseISO
parseISO,
differenceInDays
} from "date-fns";
import ptBR from "date-fns/locale/pt-BR";
@ -58,6 +60,7 @@ import fs from "fs";
import { StartWhatsAppSession } from "../../services/WbotServices/StartWhatsAppSession";
import { removeWbot } from "../../libs/wbot";
import { restartWhatsSession } from "../../helpers/RestartWhatsSession";
import updateContactService from "../ContactServices/UpdateContactService"
// test del
import data_ura from "./ura";
@ -184,12 +187,10 @@ const verifyMediaMessage = async (
phoneNumberId: msg?.phoneNumberId,
fromAgent: false
};
if (
messageData.mediaType === "video" ||
(messageData.mediaType === "audio" &&
getSettingValue("blockAudioVideoMedia")?.value === "enabled")
) {
mediaAuthorized = false;
if(getSettingValue('blockAudioVideoMedia')?.value === 'enabled'){
if( messageData.mediaType === 'video' || messageData.mediaType === 'audio' ){
mediaAuthorized = false;
}
}
if (msg?.fromMe) {
messageData = { ...messageData, fromAgent: true };
@ -872,7 +873,7 @@ const handleMessage = async (
) {
const filteredUsers = await findByContain("user:*", "name", msg?.body);
if (filteredUsers && filteredUsers.length > 0) {
if (filteredUsers && filteredUsers.length > 0 && ticket?.status === 'pending') {
if (botInfo.isOnQueue) {
transferTicket(filteredUsers[0].name, wbot, ticket, true);
return;
@ -909,6 +910,21 @@ const handleMessage = async (
!msg.fromMe &&
ticket.userId == botInfo.userIdBot
) {
if(msg?.body?.toLowerCase() === 'sair') {
await UpdateTicketService({
ticketData: {
status: "closed"
},
ticketId: ticket.id
})
await SendWhatsAppMessage({
body: `Ok\nAtendimento finalizado. A Gertec agradece o seu contato!
`,
ticket,
number: `${contact.number}@c.us`
});
return;
}
const repet: any = await mostRepeatedPhrase(ticket.id);
console.log("repet.occurrences: ", repet.occurrences);
@ -924,11 +940,11 @@ const handleMessage = async (
});
} else {
console.log("MSG body: ", msg.body);
if (msg.type != "chat") {
botSendMessage(
ticket,
`Desculpe, nao compreendi!\nEnvie apenas texto quando estiver interagindo com o bot!\n _Digite *0* para voltar ao menu principal._`
`Desculpe, nao compreendi!\nEnvie apenas texto quando estiver interagindo com o bot!\n _Digite *#* para voltar ao menu anterior._`
);
return;
}
@ -941,7 +957,7 @@ const handleMessage = async (
return;
}
const menuMsg: any = await menu(msg.body, wbot.id, contact.id);
const menuMsg: any = await menu(msg.body, wbot.id, contact.id, ticket);
console.log("menuMsg: ", menuMsg);
@ -973,7 +989,7 @@ const handleMessage = async (
},
ticketId: ticket.id
});
const menuMsg: any = await menu(msg.body, wbot.id, contact.id);
const menuMsg: any = await menu(msg.body, wbot.id, contact.id, ticket);
await botSendMessage(ticket, menuMsg.value);
}
@ -996,7 +1012,7 @@ const handleMessage = async (
ticketId: ticket.id
});
const menuMsg: any = await menu(msg.body, wbot.id, contact.id);
const menuMsg: any = await menu(msg.body, wbot.id, contact.id, ticket);
await botSendMessage(ticket, menuMsg.value);
@ -1037,9 +1053,13 @@ const handleMessage = async (
}
};
const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
const menu = async (userTyped: string, whatsappId: any, contactId: any, ticket: any) => {
let whatsapp = await whatsappCache(whatsappId);
let contactData = await Contact.findOne({
where: { id: contactId },
attributes: ["id", "name", "number", "email", "profilePicUrl", "isLGPDAccepted"],
include: ["extraInfo"]
});
let lastId = await findObject(
whatsappId,
contactId,
@ -1052,14 +1072,25 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
console.log("lastId[0]: ", lastId[0]);
if (!lastId[0]) {
await createObject({
whatsappId,
contactId,
identifier: whatsapp?.number ? `ura_${whatsapp?.number}` : "ura",
value: data[1].id,
history: `|${data[1].id}`
});
if(contactData && contactData.isLGPDAccepted && !isMoreThan30Days(contactData?.updatedAt?.toString())){
await createObject({
whatsappId,
contactId,
identifier: whatsapp?.number ? `ura_${whatsapp?.number}` : "ura",
value: data[3].id,
history: `|${data[3].id}`
});
}else{
await createObject({
whatsappId,
contactId,
identifier: whatsapp?.number ? `ura_${whatsapp?.number}` : "ura",
value: data[1].id,
history: `|${data[1].id}`
});
}
}
lastId = await findObject(
@ -1084,7 +1115,7 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
if (!option && userTyped != "0" && userTyped != "#") {
if (!existSubMenu()) {
const response = await mainOptionsMenu(userTyped);
const response = await mainOptionsMenu(userTyped, ticket);
if (response) return response;
else {
let uraOptionSelected = await findObject(
@ -1094,7 +1125,7 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
);
uraOptionSelected = uraOptionSelected[4].split("|");
if (uraOptionSelected.length == 1) {
await createObject({
whatsappId,
@ -1130,8 +1161,14 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
//
if (option) {
let LGPDSaves = contactData?.isLGPDAccepted;
let response: any = data.find((o: any) => o.idmaster == option.id);
// console.log(" RESPONSE OPTION: ", response, " | OPTION: ", option);
if(!LGPDSaves && option.id === '1400' && userTyped.toLowerCase() === 'ok' && contactData){
contactData.isLGPDAccepted = true;
await updateContactService({contactData, contactId});
}
let history: any = await historyUra(whatsappId, contactId, response.id);
@ -1149,11 +1186,11 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
whatsappId,
contactId,
identifier: whatsapp?.number ? `ura_${whatsapp?.number}` : "ura",
value: data[1].id,
value: '1426',
history: `|${data[1].id}`
});
return data[1];
let response = data.find((obj: any) => obj.id === '1426');
return response;
} else if (userTyped == "#") {
return await backUra(whatsappId, contactId, data);
}
@ -1167,13 +1204,20 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
return false;
}
async function mainOptionsMenu(userTyped: any) {
async function mainOptionsMenu(userTyped: any, ticket: any) {
let currentMenu = await findObject(
whatsappId,
contactId,
whatsapp?.number ? `ura_${whatsapp?.number}` : "ura"
);
let contactData = await Contact.findOne({
where: { id: contactId },
attributes: ["id", "name", "number", "email", "profilePicUrl", "isLGPDAccepted"],
include: ["extraInfo"]
});
let LGPDSaves = false;
const menuValues = data
.filter((m: any) => m.idmaster == currentMenu[3])
.map((m: any) => m.value);
@ -1183,10 +1227,16 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
o.value.toLowerCase() == userTyped.toLowerCase() &&
menuValues.includes(userTyped.toLowerCase())
);
if (menuOption) {
let response = data.find((o: any) => o.idmaster == menuOption.id);
if (response) {
if (menuOption || currentMenu[3] === '1398') {
let response : any;
if (currentMenu[3] === '1398'){
let option = data.find((o: any) => o.id == currentMenu[3]);
response = data.find((o: any) => o.id == option.idnext);
if (response) response.value = `Seja bem-vindo(a) ao WhatsApp Gertec.\nQual o seu nome?`;
}else response = data.find((o: any) => o.idmaster == menuOption.id);
if (response) {
let history = await historyUra(whatsappId, contactId, response.id);
await createObject({
@ -1199,10 +1249,93 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
return response;
}
}
}else if(menuValues && menuValues.includes('CPF')
|| menuValues.includes('CNPJ')
|| menuValues.includes('name')
|| menuValues.includes('email'))
{
let isValid = false;
if(menuValues.includes('CPF')){
if(userTyped.length === 11){
isValid = validateCPF(userTyped);
}else if(userTyped.length === 14){
isValid = validateCNPJ(userTyped);
}
}else if(menuValues.includes('CNPJ') && userTyped.length === 14) {
isValid = validateCNPJ(userTyped);
}else if(menuValues.includes('name')){
if (contactData && contactData.name != userTyped) {
contactData.name = userTyped;
await updateContactService({contactData, contactId});
}
botSendMessage(
ticket,
`O protocolo desse atendimento é: ${ticket?.id}.`
);
isValid = true;
}else{
isValid = true;
}
if(!isValid){
let response = data.find((o: any) => o.id == currentMenu[3]);
if(response){
response.value = `CNPJ/CPF inválido. Por favor, digite um CNPJ/CPF válido.`;
let history = await historyUra(whatsappId, contactId, response.id);
await createObject({
whatsappId,
contactId,
identifier: whatsapp?.number ? `ura_${whatsapp?.number}` : "ura",
value: response.id,
history
});
return response;
}
}
const idOption = data.find((o:any)=> o.idmaster === currentMenu[3] );
if (idOption != -1 ){
let response = data.find((o: any) => o.idmaster == idOption.id);
if (response?.id === '1426' && contactData) response.value = `Certo *${contactData.name}*, ${response.value}`;
let history = await historyUra(whatsappId, contactId, response.id);
await createObject({
whatsappId,
contactId,
identifier: whatsapp?.number ? `ura_${whatsapp?.number}` : "ura",
value: response.id,
history
});
return response;
}
}
}
};
const validateCPF = (cpfNumber: string): boolean => {
return cpf.isValid(cpfNumber);
};
const validateCNPJ = (cnpjNumber: string): boolean => {
return cnpj.isValid(cnpjNumber);
};
const validateEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const isMoreThan30Days = (updatedAt: string): boolean => {
const updatedDate = parseISO(updatedAt);
const today = new Date();
const diffDays = differenceInDays(today, updatedDate);
return diffDays >= 30;
};
const handleMsgAck = async (
msg_id: any,
ack: any,

View File

@ -247,7 +247,7 @@ const MessageInput = ({ ticketStatus, ticketLastMessage, ticketIsRemote }) => {
setInputMessage(ticketLastMessage)
}
else {
setInputMessage("")
//setInputMessage("")
}
}, [countTicketMsg, ticketIsRemote, ticketLastMessage])