feat: Adapt migration from Dialogflow to Redis-based bot and optimize bot access using Redis
parent
ad89d3ccdb
commit
bc93d3a9d6
|
@ -0,0 +1,176 @@
|
|||
import { Request, Response } from "express";
|
||||
import BotIsOnQueue from "../helpers/BotIsOnQueue";
|
||||
import GetDefaultWhatsApp from "../helpers/GetDefaultWhatsApp";
|
||||
import { getIO } from "../libs/socket";
|
||||
import { getWbot } from "../libs/wbot";
|
||||
import Ticket from "../models/Ticket";
|
||||
import ContactByCustomField from "../services/HitServices/ShowContactByCustomFieldValueService";
|
||||
import ShowQueueService from "../services/QueueService/ShowQueueService";
|
||||
import CreateTicketService from "../services/TicketServices/CreateTicketService";
|
||||
import ShowTicketService from "../services/TicketServices/ShowTicketService";
|
||||
import UpdateTicketService from "../services/TicketServices/UpdateTicketService";
|
||||
import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage";
|
||||
|
||||
import { Op, where, Sequelize } from "sequelize";
|
||||
import ShowTicketServiceByContactId from "../services/TicketServices/ShowTicketServiceByContactId";
|
||||
import hitPortalMonitoring from "../helpers/HitPortalMonitoring";
|
||||
import FindOrCreateTicketServiceBot from "../services/TicketServices/FindOrCreateTicketServiceBot";
|
||||
import Contact from "../models/Contact";
|
||||
|
||||
// type IndexQuery = {
|
||||
// centro_custo: string;
|
||||
// };
|
||||
|
||||
export const hit = async (req: Request, res: Response): Promise<Response> => {
|
||||
console.log("req.body: ", req.body);
|
||||
|
||||
if (req.headers["auth"] === "0424bd59b807674191e7d77572075f33") {
|
||||
let contact = null;
|
||||
|
||||
try {
|
||||
contact = await ContactByCustomField(req.body["centro_custo"]);
|
||||
} catch (error) {
|
||||
console.log("There was an error on try get centro_custo info: ", error);
|
||||
}
|
||||
|
||||
if (!contact) {
|
||||
return res.status(200).json({ message: "Ok" });
|
||||
}
|
||||
|
||||
if (req.body["action"] === "atdfechou") {
|
||||
console.log("FECHOU");
|
||||
|
||||
try {
|
||||
console.log("atdfechou ----------> THE CONTACT: ", contact);
|
||||
|
||||
let data = req.body;
|
||||
let str = "";
|
||||
let str2 = "";
|
||||
|
||||
str = `*Cliente*: ${contact["contact.name"]}`;
|
||||
|
||||
let historico = data["historico"];
|
||||
|
||||
for (const key in historico) {
|
||||
const hist = Object.keys(historico[key]);
|
||||
|
||||
hist.forEach((keys, index) => {
|
||||
str2 += `*${keys}*: ${historico[key][keys]}\n`;
|
||||
});
|
||||
|
||||
str2 += "\n";
|
||||
}
|
||||
|
||||
await statuschange(
|
||||
req,
|
||||
res,
|
||||
contact,
|
||||
`*Olá. Somos a TI Espaçolaser.*\nO chamado da sua loja ${contact["contact.name"]} foi fechado pela operadora. Abaixo seguem informações sobre o incidente.\n\n*Situação do chamado na Operadora*\n\n*Incidente:*\n\n ${str}\n\n*Atualizações*:\n\n${str2}`,
|
||||
false
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(`Error on try sending the monitor message closed: `, error);
|
||||
}
|
||||
} else if (req.body["action"] === "atdatualizou") {
|
||||
console.log("status: atdatualizou --------------> contact: ", contact);
|
||||
|
||||
await statuschange(
|
||||
req,
|
||||
res,
|
||||
contact,
|
||||
`*Olá. Somos a TI Espaçolaser.*\nAtualização do chamado para sua loja ${contact["contact.name"]}. Abaixo seguem informações sobre o incidente para que possam acompanhar.\n\n`
|
||||
);
|
||||
} else if (req.body["action"] === "atdabriu") {
|
||||
console.log("PASS 1");
|
||||
|
||||
await statuschange(
|
||||
req,
|
||||
res,
|
||||
contact,
|
||||
`*Olá. Somos a TI Espaçolaser.*\nIdentificamos em nossos monitoramentos que há um problema na internet da sua loja ${contact["contact.name"]} e já estamos resolvendo. Abaixo seguem informações sobre o incidente para que possam acompanhar.\n\n`
|
||||
);
|
||||
console.log("PASS 2");
|
||||
}
|
||||
} else {
|
||||
res.status(401).json({ message: "Token Inválido!" });
|
||||
}
|
||||
|
||||
return res.status(200).json({ message: "Ok" });
|
||||
};
|
||||
|
||||
async function sendMessageHitMonitoring(msg: string, ticket: Ticket) {
|
||||
if (msg && msg.length > 0) {
|
||||
console.log("MESSAGE WILL BE SENT!");
|
||||
|
||||
await SendWhatsAppMessage({ body: msg, ticket });
|
||||
}
|
||||
}
|
||||
|
||||
async function statuschange(
|
||||
req: Request,
|
||||
res: Response,
|
||||
contact: any,
|
||||
header_msg: string,
|
||||
request: boolean = true
|
||||
) {
|
||||
try {
|
||||
const botInfo = await BotIsOnQueue("botqueue");
|
||||
|
||||
let ticket: any = await ShowTicketServiceByContactId(contact.contactId);
|
||||
|
||||
console.log("PASS 01");
|
||||
|
||||
if (!ticket.dataValues.id) {
|
||||
const defaultWhatsapp = await GetDefaultWhatsApp({});
|
||||
|
||||
let _contact: any = await Contact.findByPk(contact.contactId);
|
||||
|
||||
let ticket_obj: any = await FindOrCreateTicketServiceBot(
|
||||
_contact,
|
||||
defaultWhatsapp.id!,
|
||||
0
|
||||
);
|
||||
|
||||
ticket = ticket_obj.ticket;
|
||||
}
|
||||
|
||||
console.log("PASS 02");
|
||||
|
||||
let _response: string;
|
||||
|
||||
if (request) {
|
||||
let response = await hitPortalMonitoring(req.body["centro_custo"]);
|
||||
|
||||
if (!response || response.length == 0) {
|
||||
console.log(
|
||||
"Empty result from hit portal monitoring. Centro_de_custo: ",
|
||||
req.body["centro_custo"]
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
_response = `${header_msg} *Situação do chamado na Operadora*\n\n*Incidente*:\n\n ${response[0].header}\n${response[0].body}`;
|
||||
} else {
|
||||
_response = header_msg;
|
||||
}
|
||||
|
||||
console.log("PASS 03");
|
||||
|
||||
if (ticket.id && ticket.status == "pending") {
|
||||
await sendMessageHitMonitoring(_response, ticket);
|
||||
} else if (ticket.id && ticket.userId == botInfo.userIdBot) {
|
||||
let queue = await ShowQueueService(botInfo.botQueueId);
|
||||
|
||||
await UpdateTicketService({
|
||||
ticketData: { queueId: queue.id },
|
||||
ticketId: ticket.id
|
||||
});
|
||||
|
||||
ticket = await ShowTicketService(ticket.id);
|
||||
|
||||
await sendMessageHitMonitoring(_response, ticket);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`Error on try sending the message monitor: `, error);
|
||||
}
|
||||
}
|
|
@ -60,9 +60,11 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
" | quotedMsg: ",
|
||||
quotedMsg,
|
||||
" | params: ",
|
||||
params
|
||||
params, ' | body: ', JSON.stringify(body, null, 6)
|
||||
);
|
||||
|
||||
|
||||
|
||||
const { phoneNumberId, whatsappId } = ticket;
|
||||
|
||||
if (phoneNumberId) {
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
const fsPromises = require("fs/promises");
|
||||
const fs = require("fs");
|
||||
import axios from "axios";
|
||||
import * as https from "https";
|
||||
|
||||
const endPointQuery = async (
|
||||
url: string,
|
||||
method: string,
|
||||
param: string = ""
|
||||
) => {
|
||||
let response: any = null;
|
||||
|
||||
try {
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
||||
|
||||
if (method == "get") {
|
||||
// const url = 'https://sos.espacolaser.com.br/api/whatsapp/ticket/R32656'
|
||||
response = await axios.get(url, {
|
||||
httpsAgent,
|
||||
headers: {
|
||||
"x-access-token":
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOnsiaWQiOjEsInJvbGUiOiJjbGllbnQiLCJob3N0Ijoic29zLmVzcGFjb2xhc2VyLmNvbS5iciIsInRlbmFudCI6ImVzcGFjb2xhc2VyIiwibmFtZSI6IlNFTlNSLklUIiwiY29tcGFueSI6eyJpZCI6NDR9fSwiZGF0ZSI6MTY2MTI2MjY0MywiaWF0IjoxNjYxMjYyNjQzLCJleHAiOjE3NDc2NjI2NDN9.zf91OmRs4_C7B8OlVpLLrQMiRBYc7edP4qAdH_hqxpk",
|
||||
Origin: "espacolaser"
|
||||
}
|
||||
});
|
||||
console.log(
|
||||
`TEST URL CLIENT GET ROUTE: ${url} | STATUS CODE: ${response.status}`
|
||||
);
|
||||
} else if (method == "post") {
|
||||
// const url = 'http://177.107.193.124:8095/labs/zabbix-frontend/api/api.php'
|
||||
|
||||
response = await axios.post(
|
||||
url,
|
||||
{
|
||||
auth: "0424bd59b807674191e7d77572075f33",
|
||||
jsonrpc: "2.0",
|
||||
method: "chamado.ematendimento",
|
||||
"params[ccusto]": param,
|
||||
id: "101"
|
||||
},
|
||||
{
|
||||
httpsAgent,
|
||||
headers: { "Content-Type": "multipart/form-data" }
|
||||
}
|
||||
);
|
||||
console.log(
|
||||
`TEST URL CLIENT POST ROUTE: ${url} | STATUS CODE: ${response.status}`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Erro ao consultar endpoint ${url}: ${error}`);
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
export default endPointQuery;
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
const fsPromises = require("fs/promises");
|
||||
const fs = require('fs')
|
||||
|
||||
import endPointQuery2 from './EndpointQuery2'
|
||||
import WhatsQueueIndex from "./WhatsQueueIndex";
|
||||
|
||||
|
||||
const hitPortalMonitoring = async (centro_de_custo: string) => {
|
||||
|
||||
let msg_endpoint: any = []
|
||||
|
||||
let response2 = await endPointQuery2('http://177.107.193.124:8095/labs/zabbix-frontend/api/api.php', 'post', centro_de_custo.trim())
|
||||
|
||||
if (response2 && response2.data.result) {
|
||||
|
||||
response2 = response2.data.result;
|
||||
|
||||
for (let i = 0; i < response2.length; i++) {
|
||||
|
||||
let data = ''
|
||||
let sub_data = '*Atualizações:*\n\n'
|
||||
|
||||
const properties: any = Object.entries(response2[i]);
|
||||
|
||||
for (let x = 0; x < properties.length; x++) {
|
||||
|
||||
if (typeof (properties[x][1]) != 'object') {
|
||||
|
||||
data += `*${properties[x][0]}*: ${properties[x][1].replace(/(\r\n|\n|\r)/gm, "")}\n`
|
||||
|
||||
}
|
||||
else if (typeof (properties[x][1]) == 'object') {
|
||||
|
||||
const sub_properties = properties[x][1];
|
||||
|
||||
for (let k = 0; k < sub_properties.length; k++) {
|
||||
|
||||
const inner_properties: any = Object.entries(sub_properties[k]);
|
||||
|
||||
for (let y = 0; y < inner_properties.length; y++) {
|
||||
|
||||
sub_data += `*${inner_properties[y][0]}*: ${inner_properties[y][1].replace(/(\r\n|\n|\r)/gm, "")}\n`
|
||||
|
||||
}
|
||||
|
||||
sub_data += '\n'
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
msg_endpoint.push({ header: data, body: sub_data })
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
msg_endpoint = null
|
||||
}
|
||||
|
||||
return msg_endpoint
|
||||
|
||||
}
|
||||
|
||||
export default hitPortalMonitoring
|
|
@ -2,20 +2,25 @@ const Redis = require("ioredis");
|
|||
const redis = new Redis(process.env.REDIS_URI);
|
||||
|
||||
type WhatsappData = {
|
||||
whatsappId: string;
|
||||
contactId: string;
|
||||
whatsappId: string | number;
|
||||
contactId: string | number;
|
||||
identifier: string;
|
||||
value?: string;
|
||||
};
|
||||
|
||||
export async function set(key: string, value: string) {
|
||||
export async function set(key: string, value: string, expire: boolean = false) {
|
||||
await redis.set(key, JSON.stringify(value));
|
||||
|
||||
if (expire) await redis.expire(key, 300);
|
||||
}
|
||||
|
||||
export async function get(key: string) {
|
||||
const value: any = await redis.get(key);
|
||||
return JSON.parse(value);
|
||||
}
|
||||
export async function del(key: string) {
|
||||
await redis.del(key);
|
||||
}
|
||||
|
||||
export async function createObject({
|
||||
whatsappId,
|
||||
|
@ -51,8 +56,8 @@ export async function updateObject({
|
|||
}
|
||||
|
||||
export async function findObject(
|
||||
whatsappId: string,
|
||||
contactId: string,
|
||||
whatsappId: string | number,
|
||||
contactId: string | number,
|
||||
identifier: string
|
||||
) {
|
||||
const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import express from "express";
|
||||
|
||||
import * as HitController from "../controllers/HitController"
|
||||
|
||||
const hitRoutes = express.Router();
|
||||
|
||||
hitRoutes.post("/espacolaser/incidente", HitController.hit);
|
||||
|
||||
export default hitRoutes;
|
|
@ -13,6 +13,7 @@ import quickAnswerRoutes from "./quickAnswerRoutes";
|
|||
import reportRoutes from "./reportRoutes";
|
||||
import schedulingNotifiyRoutes from "./SchedulingNotifyRoutes";
|
||||
import statusChatEndRoutes from "./statusChatEndRoutes";
|
||||
import hitRoutes from "./hitRoutes";
|
||||
import wbotMonitorRoutes from "./wbotMonitorRoutes";
|
||||
|
||||
const routes = Router();
|
||||
|
@ -32,6 +33,7 @@ routes.use(quickAnswerRoutes);
|
|||
routes.use(schedulingNotifiyRoutes);
|
||||
routes.use(reportRoutes);
|
||||
routes.use(statusChatEndRoutes);
|
||||
routes.use(hitRoutes);
|
||||
routes.use(wbotMonitorRoutes);
|
||||
|
||||
export default routes;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import { raw } from "express";
|
||||
import AppError from "../../errors/AppError";
|
||||
import ContactCustomField from "../../models/ContactCustomField";
|
||||
|
||||
const ShowContactCustomFieldService = async (contactId: number | string): Promise<ContactCustomField[]> => {
|
||||
|
||||
const queue = await ContactCustomField.findAll({
|
||||
where: { contactId: contactId },
|
||||
raw: true
|
||||
}
|
||||
);
|
||||
|
||||
// if (!queue) {
|
||||
// throw new AppError("ERR_CONTACT_CUSTOM_FIELD_NOT_FOUND");
|
||||
// }
|
||||
|
||||
return queue;
|
||||
};
|
||||
|
||||
export default ShowContactCustomFieldService;
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
import Contact from "../../models/Contact";
|
||||
import ContactCustomField from "../../models/ContactCustomField";
|
||||
|
||||
const ContactByCustomField = async (value: string | number): Promise<any> => {
|
||||
|
||||
const contact = await ContactCustomField.findOne({
|
||||
where: { value },
|
||||
raw: true,
|
||||
attributes: ['id', 'value', 'contactId'],
|
||||
|
||||
include: [
|
||||
{
|
||||
model: Contact,
|
||||
required: true,
|
||||
attributes: ['id', 'name', 'number'],
|
||||
|
||||
},
|
||||
|
||||
],
|
||||
|
||||
});
|
||||
|
||||
return contact;
|
||||
};
|
||||
|
||||
export default ContactByCustomField;
|
|
@ -0,0 +1,73 @@
|
|||
import Ticket from "../../models/Ticket";
|
||||
import AppError from "../../errors/AppError";
|
||||
import Contact from "../../models/Contact";
|
||||
import User from "../../models/User";
|
||||
import Queue from "../../models/Queue";
|
||||
|
||||
import Message from "../../models/Message";
|
||||
import { userInfo } from "os";
|
||||
|
||||
import { Op, where } from "sequelize";
|
||||
|
||||
import { Sequelize } from "sequelize";
|
||||
import moment from "moment";
|
||||
|
||||
import { startOfDay, endOfDay, parseISO, getDate } from "date-fns";
|
||||
import { string } from "yup/lib/locale";
|
||||
|
||||
//Report by user, startDate, endDate
|
||||
const ShowTicketMessage = async (
|
||||
ticketId: string | number,
|
||||
onlyNumber: boolean = false,
|
||||
fromMe?: boolean,
|
||||
limit?: number,
|
||||
regexp?: string
|
||||
): Promise<Message[]> => {
|
||||
let where_clause = {};
|
||||
|
||||
if (onlyNumber) {
|
||||
where_clause = {
|
||||
ticketId: ticketId,
|
||||
fromMe: fromMe ? fromMe : 0,
|
||||
//body: {[Op.regexp]: '^[0-9]*$'},
|
||||
// body: {[Op.regexp]: '^[0-3]$'},
|
||||
body: { [Op.regexp]: regexp }
|
||||
};
|
||||
} else {
|
||||
where_clause = {
|
||||
ticketId: ticketId,
|
||||
fromMe: fromMe ? fromMe : 0
|
||||
};
|
||||
}
|
||||
|
||||
const ticket = await Message.findAll({
|
||||
where: where_clause,
|
||||
limit: limit ? limit : 10000,
|
||||
raw: true,
|
||||
attributes: [
|
||||
"body",
|
||||
"read",
|
||||
"mediaType",
|
||||
"fromMe",
|
||||
"mediaUrl",
|
||||
[
|
||||
Sequelize.fn(
|
||||
"DATE_FORMAT",
|
||||
Sequelize.col("createdAt"),
|
||||
"%d/%m/%Y %H:%i:%s"
|
||||
),
|
||||
"createdAt"
|
||||
]
|
||||
],
|
||||
|
||||
order: [["createdAt", "DESC"]]
|
||||
});
|
||||
|
||||
if (!ticket) {
|
||||
throw new AppError("ERR_NO_TICKET_FOUND", 404);
|
||||
}
|
||||
|
||||
return ticket;
|
||||
};
|
||||
|
||||
export default ShowTicketMessage;
|
|
@ -0,0 +1,44 @@
|
|||
import Ticket from "../../models/Ticket";
|
||||
import AppError from "../../errors/AppError";
|
||||
import Contact from "../../models/Contact";
|
||||
import User from "../../models/User";
|
||||
import Queue from "../../models/Queue";
|
||||
|
||||
import { Op } from "sequelize";
|
||||
|
||||
const ShowTicketServiceByContactId = async (contactId: string | number): Promise<Ticket> => {
|
||||
|
||||
const ticket = await Ticket.findOne({
|
||||
|
||||
where: { contactId, [Op.or]: [{ status: 'open' }, { status: 'pending' }] },
|
||||
|
||||
include: [
|
||||
{
|
||||
model: Contact,
|
||||
as: "contact",
|
||||
attributes: ["id", "name", "number", "profilePicUrl", "useQueues"],
|
||||
include: ["extraInfo"]
|
||||
},
|
||||
{
|
||||
model: User,
|
||||
as: "user",
|
||||
attributes: ["id", "name"]
|
||||
},
|
||||
{
|
||||
model: Queue,
|
||||
as: "queue",
|
||||
attributes: ["id", "name", "color"],
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
if (!ticket) {
|
||||
|
||||
return new Ticket
|
||||
|
||||
}
|
||||
|
||||
return ticket;
|
||||
};
|
||||
|
||||
export default ShowTicketServiceByContactId;
|
|
@ -68,6 +68,9 @@ import { splitDateTime } from "../../helpers/SplitDateTime";
|
|||
//
|
||||
|
||||
import { updateTicketCacheByTicketId } from "../../helpers/TicketCache";
|
||||
|
||||
import endPointQuery from "../../helpers/EndpointQuery2";
|
||||
|
||||
import {
|
||||
insertMessageContactCache,
|
||||
getLastId
|
||||
|
@ -81,6 +84,7 @@ import {
|
|||
} from "../../helpers/WhatsappIdMultiSessionControl";
|
||||
import AppError from "../../errors/AppError";
|
||||
import { setMessageAsRead } from "../../helpers/SetMessageAsRead";
|
||||
import FindOrCreateTicketServiceBot from "../TicketServices/FindOrCreateTicketServiceBot";
|
||||
import { getSettingValue } from "../../helpers/WhaticketSettings";
|
||||
|
||||
import { Op } from "sequelize";
|
||||
|
@ -88,7 +92,15 @@ import { Op } from "sequelize";
|
|||
import SettingTicket from "../../models/SettingTicket";
|
||||
import mostRepeatedPhrase from "../../helpers/MostRepeatedPhrase";
|
||||
import ListWhatsAppsNumber from "../WhatsappService/ListWhatsAppsNumber";
|
||||
import { createObject, findObject, get } from "../../helpers/RedisClient";
|
||||
import {
|
||||
createObject,
|
||||
del,
|
||||
findObject,
|
||||
get,
|
||||
set
|
||||
} from "../../helpers/RedisClient";
|
||||
import ShowContactCustomFieldService from "../ContactServices/ShowContactCustomFieldsService";
|
||||
import ShowTicketService from "../TicketServices/ShowTicketService"
|
||||
|
||||
var lst: any[] = getWhatsappIds();
|
||||
|
||||
|
@ -197,73 +209,6 @@ const verifyMediaMessage = async (
|
|||
return newMessage;
|
||||
};
|
||||
|
||||
// const verifyMediaMessage = async (
|
||||
// msg: any,
|
||||
// ticket: Ticket,
|
||||
// contact: Contact,
|
||||
// media: any,
|
||||
// quotedMsg?: any
|
||||
// ): Promise<Message | any> => {
|
||||
// // const quotedMsg = await verifyQuotedMessage(msg);
|
||||
|
||||
// // 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}`;
|
||||
// }
|
||||
|
||||
// try {
|
||||
// // await writeFileAsync(
|
||||
// // join(__dirname, "..", "..", "..", "public", media.filename),
|
||||
// // media.data,
|
||||
// // "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}`);
|
||||
// }
|
||||
|
||||
// const messageData = {
|
||||
// id: msg.id.id,
|
||||
// ticketId: ticket.id,
|
||||
// contactId: msg.fromMe ? undefined : contact.id,
|
||||
// body: msg.body || media.filename,
|
||||
// fromMe: msg.fromMe,
|
||||
// read: msg.fromMe,
|
||||
// mediaUrl: media.filename,
|
||||
// mediaType: media.mimetype.split("/")[0],
|
||||
// quotedMsgId: quotedMsg
|
||||
// // quotedMsgId: quotedMsg?.id
|
||||
// };
|
||||
|
||||
// await ticket.update({ lastMessage: msg.body || media.filename });
|
||||
// const newMessage = await CreateMessageService({ messageData });
|
||||
|
||||
// return newMessage;
|
||||
// };
|
||||
|
||||
const verifyMessage = async (
|
||||
msg: any,
|
||||
ticket: Ticket,
|
||||
|
@ -287,6 +232,374 @@ const verifyMessage = async (
|
|||
await CreateMessageService({ messageData });
|
||||
};
|
||||
|
||||
const queryEndPointHit = async (centro_de_custo: string) => {
|
||||
let msg_endpoint: any = [];
|
||||
|
||||
let response2 = await endPointQuery(
|
||||
"http://177.107.193.124:8095/labs/zabbix-frontend/api/api.php",
|
||||
"post",
|
||||
centro_de_custo.trim()
|
||||
);
|
||||
|
||||
if (response2 && response2.data.result) {
|
||||
response2 = response2.data.result;
|
||||
|
||||
for (let i = 0; i < response2.length; i++) {
|
||||
let data = "";
|
||||
let sub_data = "*Atualizações:*\n\n";
|
||||
|
||||
const properties: any = Object.entries(response2[i]);
|
||||
|
||||
for (let x = 0; x < properties.length; x++) {
|
||||
if (typeof properties[x][1] != "object") {
|
||||
data += `*${properties[x][0]}*: ${properties[x][1].replace(
|
||||
/(\r\n|\n|\r)/gm,
|
||||
""
|
||||
)}\n`;
|
||||
} else if (typeof properties[x][1] == "object") {
|
||||
const sub_properties = properties[x][1];
|
||||
|
||||
for (let k = 0; k < sub_properties.length; k++) {
|
||||
const inner_properties: any = Object.entries(sub_properties[k]);
|
||||
|
||||
for (let y = 0; y < inner_properties.length; y++) {
|
||||
sub_data += `*${inner_properties[y][0]}*: ${inner_properties[
|
||||
y
|
||||
][1].replace(/(\r\n|\n|\r)/gm, "")}\n`;
|
||||
}
|
||||
|
||||
sub_data += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg_endpoint.push({ header: data, body: sub_data });
|
||||
}
|
||||
} else {
|
||||
msg_endpoint = null;
|
||||
}
|
||||
|
||||
return msg_endpoint;
|
||||
};
|
||||
|
||||
const monitoramento_response2 = async (
|
||||
response: any | null,
|
||||
wbot: any,
|
||||
contact: any,
|
||||
ticket: any,
|
||||
centro_de_custo: any,
|
||||
final_message: string = "",
|
||||
send_empty_incident?: boolean
|
||||
) => {
|
||||
if (!response) {
|
||||
await SendWhatsAppMessage({
|
||||
body: `Houve um erro ao tentar consultar o monitoramento da Operadora!${final_message}`,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
} else if (response.length > 0) {
|
||||
for (let i = 0; i < response.length; i++) {
|
||||
await SendWhatsAppMessage({
|
||||
body: `*Situação do chamado na Operadora*\n\n*Incidente*:\n\n ${response[i].header}\n${response[i].body}${final_message}`,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
}
|
||||
} else if (send_empty_incident) {
|
||||
await SendWhatsAppMessage({
|
||||
body: `Conforme Monitoramento a internet da unidade está operacional${final_message}`,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async function sendDelayedMessages(
|
||||
wbot: Session,
|
||||
ticket: Ticket,
|
||||
contact: Contact,
|
||||
message: string,
|
||||
_msg?: WbotMessage
|
||||
) {
|
||||
const body = message.replace(/\\n/g, "\n");
|
||||
|
||||
if (body.search("dialog_actions") != -1) {
|
||||
let msgAction = botMsgActions(body);
|
||||
|
||||
if (msgAction.actions[0] == "request_endpoint") {
|
||||
await SendWhatsAppMessage({
|
||||
body: msgAction.msgBody,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
|
||||
// const url = 'https://sos.espacolaser.com.br/api/whatsapps/ticket/R32656'
|
||||
let endPointResponse = await endPointQuery(msgAction.actions[1], "get");
|
||||
|
||||
await del(
|
||||
`whatsappId:${wbot.id}:contactId:${contact.id}:identifier:query`
|
||||
);
|
||||
|
||||
console.log(
|
||||
"Object.entries(endPointResponse.data).length: ",
|
||||
Object.entries(endPointResponse.data).length
|
||||
);
|
||||
|
||||
if (
|
||||
endPointResponse &&
|
||||
endPointResponse.status == 200 &&
|
||||
Object.entries(endPointResponse.data).length > 0
|
||||
) {
|
||||
if (
|
||||
endPointResponse.data.categoria != "INFRAESTRUTURA" &&
|
||||
endPointResponse.data.categoria != "ELOS"
|
||||
) {
|
||||
botSendMessage(
|
||||
ticket,
|
||||
`A categorização desse chamado não se enquadra no atendimento deste canal!\n\n _Digite *0* para voltar ao menu principal._`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = Object.entries(endPointResponse.data);
|
||||
let msg_endpoint_response = "";
|
||||
let msg_endpoint2: any = [];
|
||||
let centro_de_custo = "";
|
||||
|
||||
for (let i = 0; i < response.length; i++) {
|
||||
if (
|
||||
[
|
||||
"id_solicitante",
|
||||
"centro_custo_departamento",
|
||||
"departamento_do_formulario",
|
||||
"centro_de_custo_do_departamento_do_formulario"
|
||||
].includes(response[i][0])
|
||||
)
|
||||
continue;
|
||||
|
||||
msg_endpoint_response += `*${response[i][0]}*: ${String(
|
||||
response[i][1]
|
||||
).replace(/(<([^>]+)>)/gi, "")}\n`;
|
||||
}
|
||||
|
||||
if (
|
||||
endPointResponse.data.centro_custo_departamento &&
|
||||
endPointResponse.data.centro_custo_departamento.trim().length > 0 &&
|
||||
endPointResponse.data.categoria == "INFRAESTRUTURA" &&
|
||||
endPointResponse.data.subcategoria == "INTERNET"
|
||||
) {
|
||||
centro_de_custo = endPointResponse.data.centro_custo_departamento;
|
||||
|
||||
msg_endpoint2 = await queryEndPointHit(centro_de_custo);
|
||||
}
|
||||
|
||||
const itsm_response = async (
|
||||
message1: string = "",
|
||||
message2: string = ""
|
||||
) => {
|
||||
await SendWhatsAppMessage({
|
||||
body: `*Situação do chamado ${extractCallCode(
|
||||
msgAction.msgBody
|
||||
)}:*${message1}${msg_endpoint_response}${message2}\n_Digite *0* para voltar ao menu principal._`,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
};
|
||||
|
||||
const sendMessageBot = async (
|
||||
message1: string = "",
|
||||
message2: string = ""
|
||||
) => {
|
||||
await SendWhatsAppMessage({
|
||||
body: `${message1}${message2}`,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
};
|
||||
|
||||
if (body.search("dialog_options") != -1) {
|
||||
let msgAction = botMsgActions(body);
|
||||
|
||||
let index = msgAction.actions.findIndex(i => i == "dialog_options");
|
||||
|
||||
if (index != -1) {
|
||||
let dialog_options = msgAction.actions[index + 1];
|
||||
|
||||
if (
|
||||
dialog_options == "3" &&
|
||||
endPointResponse.data.categoria == "ELOS"
|
||||
) {
|
||||
index = msgAction.actions.findIndex(i => i == "queue_transfer");
|
||||
|
||||
if (index != -1) {
|
||||
await itsm_response("\n\n");
|
||||
|
||||
await monitoramento_response2(
|
||||
msg_endpoint2,
|
||||
wbot,
|
||||
contact,
|
||||
ticket,
|
||||
centro_de_custo,
|
||||
"\n\n",
|
||||
false
|
||||
);
|
||||
|
||||
botSendMessage(
|
||||
ticket,
|
||||
`Estamos direcionando seu atendimento para o Suporte. Em breve você será atendido por um de nossos atendentes!\n\nPara voltar ao atendimento *automatizado* e sair da fila de atendimento *humano* digite *0*`
|
||||
);
|
||||
|
||||
await transferTicket(
|
||||
+msgAction.actions[index + 1],
|
||||
wbot,
|
||||
ticket
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
(endPointResponse.data.categoria == "INFRAESTRUTURA" &&
|
||||
endPointResponse.data.subcategoria == "INTERNET" &&
|
||||
endPointResponse.data.terceiro_nivel == "QUEDA TOTAL") ||
|
||||
(endPointResponse.data.categoria == "INFRAESTRUTURA" &&
|
||||
endPointResponse.data.subcategoria == "INTERNET" &&
|
||||
endPointResponse.data.terceiro_nivel == "PROBLEMA DE LENTIDÃO") ||
|
||||
(endPointResponse.data.categoria == "ELOS" &&
|
||||
endPointResponse.data.subcategoria == "VENDAS") ||
|
||||
(endPointResponse.data.categoria == "ELOS" &&
|
||||
endPointResponse.data.subcategoria == "INDISPONIBILIDADE")
|
||||
) {
|
||||
await itsm_response("\n\n");
|
||||
|
||||
if (
|
||||
endPointResponse.data.categoria == "INFRAESTRUTURA" &&
|
||||
endPointResponse.data.subcategoria == "INTERNET" &&
|
||||
centro_de_custo
|
||||
) {
|
||||
await monitoramento_response2(
|
||||
msg_endpoint2,
|
||||
wbot,
|
||||
contact,
|
||||
ticket,
|
||||
centro_de_custo,
|
||||
"\n\n _Digite *0* para voltar ao menu principal._",
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
await sendMessageBot(
|
||||
"Se deseja solicitar atendimento de urgência, digite *1*!",
|
||||
"\n\n _Digite *0* para voltar ao menu principal._"
|
||||
);
|
||||
|
||||
return;
|
||||
} else {
|
||||
await itsm_response("\n\n");
|
||||
|
||||
if (
|
||||
endPointResponse.data.categoria == "INFRAESTRUTURA" &&
|
||||
endPointResponse.data.subcategoria == "INTERNET" &&
|
||||
centro_de_custo
|
||||
) {
|
||||
await monitoramento_response2(
|
||||
msg_endpoint2,
|
||||
wbot,
|
||||
contact,
|
||||
ticket,
|
||||
centro_de_custo,
|
||||
"\n\n _Digite *0* para voltar ao menu principal._",
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
await sendMessageBot(
|
||||
"Acompanhe a evolução do atendimento através do SOS"
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
} else if (
|
||||
endPointResponse &&
|
||||
endPointResponse.status == 200 &&
|
||||
Object.entries(endPointResponse.data).length == 0
|
||||
) {
|
||||
botSendMessage(
|
||||
ticket,
|
||||
`Não existe nenhum chamado para consulta com esse número!\n _Digite *0* para voltar ao menu principal._`
|
||||
);
|
||||
return;
|
||||
} else if (endPointResponse && endPointResponse.status == 500) {
|
||||
botSendMessage(
|
||||
ticket,
|
||||
`Houve um erro ao realizar a consulta no sos espacolaser!\n _Digite *0* para voltar ao menu principal._`
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
botSendMessage(
|
||||
ticket,
|
||||
`Desculpe, nao foi possível realizar a consulta!\n _Digite *0* para voltar ao menu principal._`
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else if (msgAction.actions[0] == "queue_transfer") {
|
||||
console.log(
|
||||
">>>>>>>>>>>>>>> msgAction: ",
|
||||
msgAction,
|
||||
" | msgAction.actions[1]: ",
|
||||
msgAction.actions[1]
|
||||
);
|
||||
|
||||
const contact_custom_field = await ShowContactCustomFieldService(
|
||||
contact.id
|
||||
);
|
||||
|
||||
if (contact_custom_field && contact_custom_field.length > 0) {
|
||||
const msg_endpoint = await queryEndPointHit(
|
||||
contact_custom_field[0].value
|
||||
);
|
||||
|
||||
await monitoramento_response2(
|
||||
msg_endpoint,
|
||||
wbot,
|
||||
contact,
|
||||
ticket,
|
||||
contact_custom_field[0].value
|
||||
);
|
||||
}
|
||||
|
||||
console.log("************* contact_custom_field: ", contact_custom_field);
|
||||
|
||||
await SendWhatsAppMessage({
|
||||
body: msgAction.msgBody,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
|
||||
await transferTicket(+msgAction.actions[1], wbot, ticket);
|
||||
} else if (msgAction.actions[0] == "send_file") {
|
||||
const sourcePath = path.join(__dirname, `../../../public/bot`);
|
||||
|
||||
await SendWhatsAppMessage({
|
||||
body: msgAction.msgBody,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
}
|
||||
} else {
|
||||
sendWhatsAppMessageSocket(ticket, body);
|
||||
}
|
||||
}
|
||||
|
||||
const extractCallCode = (str: string) => {
|
||||
if (str.includes("*") && str.indexOf("*") < str.lastIndexOf("*")) {
|
||||
return str
|
||||
.substring(str.indexOf("*"), str.lastIndexOf("*") + 1)
|
||||
.split("*")
|
||||
.join("");
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const verifyQueue = async (
|
||||
wbot: Session,
|
||||
msg: WbotMessage,
|
||||
|
@ -457,6 +770,17 @@ const mediaTypeWhatsappOfficial = (mimetype: string): object => {
|
|||
return { type: null, mbsize: 0 };
|
||||
};
|
||||
|
||||
const botMsgActions = (params: string) => {
|
||||
let lstActions = params.split("dialog_actions=");
|
||||
let bodyMsg = lstActions[0];
|
||||
let obj = {};
|
||||
|
||||
console.log("lstActions: ", lstActions[1].split("="));
|
||||
let actions = lstActions[1].split("=");
|
||||
|
||||
return { msgBody: bodyMsg, actions: actions };
|
||||
};
|
||||
|
||||
const isValidMsg = (msg: any): boolean => {
|
||||
if (msg.from === "status@broadcast") return false;
|
||||
if (
|
||||
|
@ -663,12 +987,38 @@ const handleMessage = async (
|
|||
)
|
||||
return;
|
||||
|
||||
const ticket = await FindOrCreateTicketService(
|
||||
contact,
|
||||
wbot.id!,
|
||||
unreadMessages
|
||||
// groupContact
|
||||
);
|
||||
let ticket;
|
||||
|
||||
const _botInfo = await BotIsOnQueue("botqueue");
|
||||
|
||||
if (_botInfo.isOnQueue) {
|
||||
let ticket_obj: any = await FindOrCreateTicketServiceBot(
|
||||
contact,
|
||||
wbot.id!,
|
||||
unreadMessages
|
||||
// groupContact
|
||||
);
|
||||
|
||||
ticket = ticket_obj.ticket;
|
||||
|
||||
if (ticket_obj.created) {
|
||||
let queue = await ShowQueueService(_botInfo.botQueueId);
|
||||
|
||||
await UpdateTicketService({
|
||||
ticketData: { queueId: queue.id },
|
||||
ticketId: ticket.id
|
||||
});
|
||||
|
||||
ticket = await ShowTicketService(ticket.id);
|
||||
}
|
||||
} else {
|
||||
ticket = await FindOrCreateTicketService(
|
||||
contact,
|
||||
wbot.id!,
|
||||
unreadMessages
|
||||
// groupContact
|
||||
);
|
||||
}
|
||||
|
||||
if (getSettingValue("oneContactChatWithManyWhats")?.value == "disabled") {
|
||||
// Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen
|
||||
|
@ -739,6 +1089,63 @@ 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._`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.type == "chat" && String(msg.body).length > 120) {
|
||||
botSendMessage(
|
||||
ticket,
|
||||
`Desculpe, nao compreendi!\nTexto acima de 120 caracteres!\n _Digite *0* para voltar ao menu principal._`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let query = await get(
|
||||
`whatsappId:${wbot.id}:contactId:${contact?.id}:identifier:query`
|
||||
);
|
||||
|
||||
if (query && msg?.body?.trim() != "0") {
|
||||
query = JSON.parse(query);
|
||||
|
||||
const regexString = query?.queryRegex?.slice(1, -1);
|
||||
|
||||
query.queryRegex = new RegExp(regexString);
|
||||
|
||||
if (!query?.queryRegex.test(msg.body)) {
|
||||
await botSendMessage(ticket, query?.queryMsgInvalidParam);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query?.value?.trim()?.length == 0) {
|
||||
await set(
|
||||
`whatsappId:${wbot.id}:contactId:${contact?.id}:identifier:query`,
|
||||
JSON.stringify({ ...query, value: msg.body }),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
let message = "";
|
||||
|
||||
// Refactor later
|
||||
if (query?.optionsMenu == "3") {
|
||||
message = `Consultando *${msg?.body?.trim()}* aguarde...
|
||||
dialog_actions=request_endpoint=https://sos.espacolaser.com.br/api/whatsapp/ticket/${msg?.body?.trim()}=dialog_options=3=queue_transfer=1`;
|
||||
} else if (query?.optionsMenu == "1") {
|
||||
message = `Consultando *${msg.body}* aguarde...
|
||||
dialog_actions=request_endpoint=https://sos.espacolaser.com.br/api/whatsapp/ticket/${msg?.body?.trim()}`;
|
||||
}
|
||||
|
||||
if (message.trim().length > 0)
|
||||
await sendDelayedMessages(wbot, ticket, contact, message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const menuMsg: any = await menu(msg.body, wbot.id, contact.id);
|
||||
|
||||
console.log("menuMsg: ", menuMsg);
|
||||
|
@ -755,6 +1162,22 @@ const handleMessage = async (
|
|||
);
|
||||
|
||||
transferTicket(menuMsg.transferToQueue.trim(), wbot, ticket);
|
||||
} else if (menuMsg?.query) {
|
||||
await set(
|
||||
`whatsappId:${wbot.id}:contactId:${contact?.id}:identifier:query`,
|
||||
JSON.stringify({
|
||||
whatsappId: wbot.id,
|
||||
contactId: contact.id,
|
||||
identifier: "query",
|
||||
value: "",
|
||||
queryRegex: menuMsg?.queryRegex,
|
||||
query: menuMsg?.query,
|
||||
queryMsg: menuMsg?.queryMsg,
|
||||
queryMsgInvalidParam: menuMsg?.queryMsgInvalidParam,
|
||||
optionsMenu: menuMsg?.optionsMenu
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -894,6 +1317,10 @@ const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
|
|||
value: data[1].id
|
||||
});
|
||||
|
||||
await del(
|
||||
`whatsappId:${whatsappId}:contactId:${contactId}:identifier:query`
|
||||
);
|
||||
|
||||
return data[1];
|
||||
} else {
|
||||
console.log("INVALID SEARCH");
|
||||
|
|
|
@ -321,16 +321,34 @@ const MessageInput = ({ ticketStatus }) => {
|
|||
setTabOption('open')
|
||||
}
|
||||
|
||||
const message = {
|
||||
|
||||
if (templateParams) {
|
||||
for (let key in templateParams) {
|
||||
if (templateParams.hasOwnProperty(key)) {
|
||||
// let value = templateParams[key]
|
||||
// console.log('key: ', key, ' | ', 'VALUE: ', value)
|
||||
|
||||
if (key === '_reactName') {
|
||||
templateParams = null
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let message = {
|
||||
read: 1,
|
||||
fromMe: true,
|
||||
mediaUrl: "",
|
||||
body: (signMessage && !templateParams)
|
||||
? `*${user?.name}:*\n${inputMessage.trim()}`
|
||||
: inputMessage.trim(),
|
||||
quotedMsg: replyingMessage,
|
||||
params: templateParams
|
||||
body: (signMessage && !templateParams) ? `*${user?.name}:*\n${inputMessage.trim()}` : inputMessage.trim(),
|
||||
quotedMsg: replyingMessage
|
||||
}
|
||||
|
||||
if (templateParams) {
|
||||
message = { ...message, params: templateParams }
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
|
||||
const { data } = await api.post(`/messages/${ticketId}`, message)
|
||||
|
|
Loading…
Reference in New Issue