add functions to Gertec for start separation of numbers

gertec
gustavo-gsp 2024-06-13 16:11:29 -03:00
parent f06539ae6f
commit b456f66864
9 changed files with 285 additions and 52 deletions

View File

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

View File

@ -74,7 +74,65 @@ export const createUser = async (
.status(200) .status(200)
.json(response("1", `User ${user_id} created`, "1", "createUser")); .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 ( export const deleteUser = async (
req: Request, req: Request,
res: Response 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 => { io.on("connection", socket => {
logger.info("Client Connected"); //logger.info("Client Connected");
socket.on("joinWhatsSession", (whatsappId: string) => { 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}`); socket.join(`session_${whatsappId}`);
}); });
@ -139,7 +139,7 @@ export const initIO = (httpServer: Server): SocketIO => {
lstOnline.push({ id: userId, status: "online", try: 0 }); lstOnline.push({ id: userId, status: "online", try: 0 });
lstOnlineAux.push({ id: userId }); 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; obj.listOnline = lstOnline;
} else { } else {
@ -154,7 +154,7 @@ export const initIO = (httpServer: Server): SocketIO => {
if (index == -1) { if (index == -1) {
lstOnline.push({ id: userId, status: "online", try: 0 }); 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; obj.listOnline = lstOnline;
} else { } else {
@ -204,30 +204,30 @@ export const initIO = (httpServer: Server): SocketIO => {
}); });
socket.on("joinChatBox", (ticketId: string) => { 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.join(ticketId);
}); });
socket.on("joinNotification", () => { socket.on("joinNotification", () => {
logger.info("A client joined notification channel"); //logger.info("A client joined notification channel");
socket.join("notification"); socket.join("notification");
}); });
socket.on("joinTickets", (status: string) => { 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.join(status);
}); });
socket.on("disconnect", (data: any) => { socket.on("disconnect", (data: any) => {
logger.info(`Client disconnected socket: ${data}`); //logger.info(`Client disconnected socket: ${data}`);
}); });
socket.on("disconnecting", async () => { 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; 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 == 1) return;
if (rooms && rooms.size == 2 && ![...rooms][1].startsWith("session_")) if (rooms && rooms.size == 2 && ![...rooms][1].startsWith("session_"))
@ -252,7 +252,7 @@ export const initIO = (httpServer: Server): SocketIO => {
[...rooms][1].startsWith("session_") && [...rooms][1].startsWith("session_") &&
whatsappIds.includes([...rooms][1].replace("session_", "")) whatsappIds.includes([...rooms][1].replace("session_", ""))
) { ) {
console.log([...rooms][1]); //console.log([...rooms][1]);
let whatsappId = [...rooms][1].replace("session_", ""); let whatsappId = [...rooms][1].replace("session_", "");

View File

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

View File

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

View File

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

View File

@ -6,6 +6,7 @@ import * as Sentry from "@sentry/node";
import { copyFolder } from "../../helpers/CopyFolder"; import { copyFolder } from "../../helpers/CopyFolder";
import { removeDir } from "../../helpers/DeleteDirectory"; import { removeDir } from "../../helpers/DeleteDirectory";
import path from "path"; import path from "path";
import { cpf, cnpj } from 'cpf-cnpj-validator';
import { import {
isHoliday, isHoliday,
@ -21,7 +22,8 @@ import {
subMinutes, subMinutes,
isSaturday, isSaturday,
isSunday, isSunday,
parseISO parseISO,
differenceInDays
} from "date-fns"; } from "date-fns";
import ptBR from "date-fns/locale/pt-BR"; import ptBR from "date-fns/locale/pt-BR";
@ -58,6 +60,7 @@ import fs from "fs";
import { StartWhatsAppSession } from "../../services/WbotServices/StartWhatsAppSession"; import { StartWhatsAppSession } from "../../services/WbotServices/StartWhatsAppSession";
import { removeWbot } from "../../libs/wbot"; import { removeWbot } from "../../libs/wbot";
import { restartWhatsSession } from "../../helpers/RestartWhatsSession"; import { restartWhatsSession } from "../../helpers/RestartWhatsSession";
import updateContactService from "../ContactServices/UpdateContactService"
// test del // test del
import data_ura from "./ura"; import data_ura from "./ura";
@ -184,8 +187,10 @@ const verifyMediaMessage = async (
phoneNumberId: msg?.phoneNumberId, phoneNumberId: msg?.phoneNumberId,
fromAgent: false fromAgent: false
}; };
if(messageData.mediaType === 'video' || messageData.mediaType === 'audio' && getSettingValue('blockAudioVideoMedia')?.value === 'enabled'){ if(getSettingValue('blockAudioVideoMedia')?.value === 'enabled'){
mediaAuthorized = false; if( messageData.mediaType === 'video' || messageData.mediaType === 'audio' ){
mediaAuthorized = false;
}
} }
if (msg?.fromMe) { if (msg?.fromMe) {
messageData = { ...messageData, fromAgent: true }; messageData = { ...messageData, fromAgent: true };
@ -838,7 +843,7 @@ const handleMessage = async (
) { ) {
const filteredUsers = await findByContain("user:*", "name", msg?.body); const filteredUsers = await findByContain("user:*", "name", msg?.body);
if (filteredUsers && filteredUsers.length > 0) { if (filteredUsers && filteredUsers.length > 0 && ticket?.status === 'pending') {
if (botInfo.isOnQueue) { if (botInfo.isOnQueue) {
transferTicket(filteredUsers[0].name, wbot, ticket, true); transferTicket(filteredUsers[0].name, wbot, ticket, true);
return; return;
@ -875,6 +880,21 @@ const handleMessage = async (
!msg.fromMe && !msg.fromMe &&
ticket.userId == botInfo.userIdBot 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); const repet: any = await mostRepeatedPhrase(ticket.id);
console.log("repet.occurrences: ", repet.occurrences); console.log("repet.occurrences: ", repet.occurrences);
@ -890,11 +910,11 @@ const handleMessage = async (
}); });
} else { } else {
console.log("MSG body: ", msg.body); console.log("MSG body: ", msg.body);
if (msg.type != "chat") { if (msg.type != "chat") {
botSendMessage( botSendMessage(
ticket, 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; return;
} }
@ -907,7 +927,7 @@ const handleMessage = async (
return; 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); console.log("menuMsg: ", menuMsg);
@ -939,7 +959,7 @@ const handleMessage = async (
}, },
ticketId: ticket.id 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); await botSendMessage(ticket, menuMsg.value);
} }
@ -962,7 +982,7 @@ const handleMessage = async (
ticketId: ticket.id 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); await botSendMessage(ticket, menuMsg.value);
@ -1003,20 +1023,35 @@ const handleMessage = async (
} }
}; };
const menu = async (userTyped: string, whatsappId: any, contactId: any) => { const menu = async (userTyped: string, whatsappId: any, contactId: any, ticket: any) => {
let lastId = await findObject(whatsappId, contactId, "ura"); let lastId = await findObject(whatsappId, contactId, "ura");
const data: any = await get({ key: "ura", parse: true }); const data: any = await get({ key: "ura", parse: true });
let contactData = await Contact.findOne({
where: { id: contactId },
attributes: ["id", "name", "number", "email", "profilePicUrl", "isLGPDAccepted"],
include: ["extraInfo"]
});
console.log("lastId[0]: ", lastId[0]); console.log("lastId[0]: ", lastId[0]);
if (!lastId[0]) { if (!lastId[0]) {
await createObject({ if(contactData && contactData.isLGPDAccepted && !isMoreThan30Days(contactData?.updatedAt?.toString())){
whatsappId, await createObject({
contactId, whatsappId,
identifier: "ura", contactId,
value: data[1].id, identifier: "ura",
history: `|${data[1].id}` value: data[3].id,
}); history: `|${data[3].id}`
});
}else{
await createObject({
whatsappId,
contactId,
identifier: "ura",
value: data[1].id,
history: `|${data[1].id}`
});
}
} }
lastId = await findObject(whatsappId, contactId, "ura"); lastId = await findObject(whatsappId, contactId, "ura");
@ -1037,7 +1072,7 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
if (!option && userTyped != "0" && userTyped != "#") { if (!option && userTyped != "0" && userTyped != "#") {
if (!existSubMenu()) { if (!existSubMenu()) {
const response = await mainOptionsMenu(userTyped); const response = await mainOptionsMenu(userTyped, ticket);
if (response) return response; if (response) return response;
else { else {
let uraOptionSelected = await findObject( let uraOptionSelected = await findObject(
@ -1047,7 +1082,7 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
); );
uraOptionSelected = uraOptionSelected[4].split("|"); uraOptionSelected = uraOptionSelected[4].split("|");
if (uraOptionSelected.length == 1) { if (uraOptionSelected.length == 1) {
await createObject({ await createObject({
whatsappId, whatsappId,
@ -1083,8 +1118,14 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
// //
if (option) { if (option) {
let LGPDSaves = contactData?.isLGPDAccepted;
let response: any = data.find((o: any) => o.idmaster == option.id); 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); let history: any = await historyUra(whatsappId, contactId, response.id);
@ -1102,11 +1143,11 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
whatsappId, whatsappId,
contactId, contactId,
identifier: "ura", identifier: "ura",
value: data[1].id, value: '1426',
history: `|${data[1].id}` history: `|${data[1].id}`
}); });
let response = data.find((obj: any) => obj.id === '1426');
return data[1]; return response;
} else if (userTyped == "#") { } else if (userTyped == "#") {
return await backUra(whatsappId, contactId, data); return await backUra(whatsappId, contactId, data);
} }
@ -1120,9 +1161,16 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
return false; return false;
} }
async function mainOptionsMenu(userTyped: any) { async function mainOptionsMenu(userTyped: any, ticket: any) {
let currentMenu = await findObject(whatsappId, contactId, "ura"); let currentMenu = await findObject(whatsappId, contactId, "ura");
let contactData = await Contact.findOne({
where: { id: contactId },
attributes: ["id", "name", "number", "email", "profilePicUrl", "isLGPDAccepted"],
include: ["extraInfo"]
});
let LGPDSaves = false;
const menuValues = data const menuValues = data
.filter((m: any) => m.idmaster == currentMenu[3]) .filter((m: any) => m.idmaster == currentMenu[3])
.map((m: any) => m.value); .map((m: any) => m.value);
@ -1132,10 +1180,16 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
o.value.toLowerCase() == userTyped.toLowerCase() && o.value.toLowerCase() == userTyped.toLowerCase() &&
menuValues.includes(userTyped.toLowerCase()) menuValues.includes(userTyped.toLowerCase())
); );
if (menuOption || currentMenu[3] === '1398') {
if (menuOption) { let response : any;
let response = data.find((o: any) => o.idmaster == menuOption.id); if (currentMenu[3] === '1398'){
if (response) { 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); let history = await historyUra(whatsappId, contactId, response.id);
await createObject({ await createObject({
@ -1148,10 +1202,93 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
return response; 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: "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: "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 ( const handleMsgAck = async (
msg_id: any, msg_id: any,
ack: any, ack: any,

View File

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