feat: Implement Redis solution for querying WhatsApp number in webhook controller

feat-scaling-ticket-remote-creation
adriano 2024-03-06 18:14:12 -03:00
parent 943d121ab1
commit 2fc732eec1
6 changed files with 127 additions and 52 deletions

View File

@ -27,6 +27,7 @@ import { splitDateTime } from "../helpers/SplitDateTime";
import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService"; import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService";
import { json } from "sequelize"; import { json } from "sequelize";
import { getSettingValue } from "../helpers/WhaticketSettings"; import { getSettingValue } from "../helpers/WhaticketSettings";
import { setBotInfo } from "../helpers/SetBotInfo"
type IndexQuery = { type IndexQuery = {
searchParam: string; searchParam: string;
@ -111,7 +112,6 @@ export const all = async (req: Request, res: Response): Promise<Response> => {
); );
if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") { if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") {
if (!userId) return res.json({ users: [], queues: [] }); if (!userId) return res.json({ users: [], queues: [] });
const obj = await ListUserByWhatsappQueuesService( const obj = await ListUserByWhatsappQueuesService(
@ -167,6 +167,11 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
queueIds queueIds
}); });
if (user) {
const { id, name } = user;
await set(`user:${id}`, { id, name });
}
const io = getIO(); const io = getIO();
io.emit("user", { io.emit("user", {
action: "create", action: "create",
@ -270,34 +275,11 @@ export const update = async (
let user: any = await UpdateUserService({ userData, userId }); let user: any = await UpdateUserService({ userData, userId });
if (user?.name?.trim() == "botqueue") { await setBotInfo(user)
let botInfo;
if ( if (user) {
user?.queues?.length > 0 && const { id, name } = user;
user.queues[0]?.name?.trim() == "botqueue" await set(`user:${id}`, { id, name });
) {
botInfo = JSON.stringify({
userId: user.id,
queueId: user.queues[0].id,
botIsOnQueue: true
});
botInfo = JSON.parse(botInfo);
await set("botInfo", botInfo);
} else if (
user?.queues?.length == 0 ||
user.queues[0]?.name?.trim() != "botqueue"
) {
botInfo = JSON.stringify({
userId: user.id,
queueId: 0,
botIsOnQueue: false
});
botInfo = JSON.parse(botInfo);
await set("botInfo", botInfo);
}
} }
const io = getIO(); const io = getIO();
@ -342,3 +324,5 @@ export const remove = async (
return res.status(200).json({ message: "User deleted" }); return res.status(200).json({ message: "User deleted" });
}; };

View File

@ -42,6 +42,7 @@ import { getSettingValue } from "../helpers/WhaticketSettings";
import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber"; import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber";
import SettingTicket from "../models/SettingTicket"; import SettingTicket from "../models/SettingTicket";
import { Op } from "sequelize"; import { Op } from "sequelize";
import { get, set } from "../helpers/RedisClient";
interface WhatsappData { interface WhatsappData {
name: string; name: string;
@ -229,6 +230,22 @@ export const weebhook = async (
req.body.entry[0].changes[0].value.metadata.display_phone_number; req.body.entry[0].changes[0].value.metadata.display_phone_number;
let type = message.type; let type = message.type;
const contact_from_exist = await get("whatsapp:*", `${contact_from}`);
if (!contact_from_exist) {
console.log(
"WHATSAPP OFFICIAL",
" | CONCTACT_FROM: ",
contact_from,
" | CONTACT_TO: ",
contact_to
);
console.log(
"NUMBER IGNORED. WHATSAPP NUMBER FROM ANOTHER OMNIHIT APPLICATION!"
);
return res.status(403).json({ error: "Unauthorized" });
}
let wbot = {}; let wbot = {};
let msg = {}; let msg = {};
let contacts = req.body.entry[0].changes[0].value.contacts[0]; let contacts = req.body.entry[0].changes[0].value.contacts[0];
@ -382,6 +399,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
number: getNumberFromName(name), number: getNumberFromName(name),
client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}` client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}`
}); });
} else {
await set(`whatsapp:${whatsapp.id}`, `${number}`);
} }
const io = getIO(); const io = getIO();
@ -441,6 +460,7 @@ export const update = async (
} else if (!isOfficial) { } else if (!isOfficial) {
whatsappData.phoneNumberId = ""; whatsappData.phoneNumberId = "";
whatsappData.wabaId = ""; whatsappData.wabaId = "";
whatsappData.number = "";
} }
const { whatsapp, oldDefaultWhatsapp } = await UpdateWhatsAppService({ const { whatsapp, oldDefaultWhatsapp } = await UpdateWhatsAppService({
@ -455,6 +475,8 @@ export const update = async (
number: getNumberFromName(whatsapp.name), number: getNumberFromName(whatsapp.name),
client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}` client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}`
}); });
} else {
await set(`whatsapp:${whatsapp.id}`, `${number}`);
} }
const io = getIO(); const io = getIO();

View File

@ -9,25 +9,42 @@ type WhatsappData = {
}; };
export async function set(key: string, value: string | object) { export async function set(key: string, value: string | object) {
await redis.set(key, JSON.stringify(value)); if (typeof value == "object") await redis.set(key, JSON.stringify(value));
else {
await redis.set(key, value);
}
} }
export async function get(key: string) { export async function get(key: string, value?: string) {
const value: any = await redis.get(key); if (key.includes("*")) {
return JSON.parse(value); const keys = await redis.keys(key);
}
export async function clearAllKeys() {
// Retrieve all keys matching the pattern '*'
const keys = await redis.keys("user:*");
// If there are keys, delete them // If there are keys, delete them
if (keys.length > 0) { if (keys.length > 0) {
console.log('keys: ', keys) for (const key of keys) {
await redis.del(...keys); const val = await redis.get(key);
if (value == val) return value;
}
}
return null;
} else {
const value: any = await redis.get(key);
return JSON.parse(value);
} }
} }
export async function clearAllKeys(...keys: string[]) {
for (const key of keys) {
// Retrieve all keys matching the pattern '*'
const del_keys = await redis.keys(key);
// If there are keys, delete them
if (del_keys.length > 0) {
console.log("del_keys: ", del_keys);
await redis.del(...del_keys);
}
}
}
export async function findByContain( export async function findByContain(
key: string, key: string,

View File

@ -0,0 +1,33 @@
import { get, set } from "../helpers/RedisClient";
export async function setBotInfo(user: any) {
if (user?.name?.trim() == "botqueue") {
let botInfo;
if (
user?.queues?.length > 0 &&
user.queues[0]?.name?.trim() == "botqueue"
) {
botInfo = JSON.stringify({
userId: user.id,
queueId: user.queues[0].id,
botIsOnQueue: true
});
botInfo = JSON.parse(botInfo);
await set("botInfo", botInfo);
} else if (
user?.queues?.length == 0 ||
user.queues[0]?.name?.trim() != "botqueue"
) {
botInfo = JSON.stringify({
userId: user.id,
queueId: 0,
botIsOnQueue: false
});
botInfo = JSON.parse(botInfo);
await set("botInfo", botInfo);
}
}
}

View File

@ -23,7 +23,10 @@ import fs from "fs";
import dir from "path"; import dir from "path";
import { getSettingValue } from "./helpers/WhaticketSettings"; import { getSettingValue } from "./helpers/WhaticketSettings";
import loadSettings from "./helpers/LoadSettings"; import loadSettings from "./helpers/LoadSettings";
import { clearAllKeys, set } from "./helpers/RedisClient"; import { clearAllKeys, get, set } from "./helpers/RedisClient";
import ShowUserService from "./services/UserServices/ShowUserService";
import { json } from "sequelize";
import { setBotInfo } from "./helpers/SetBotInfo";
const server = app.listen(process.env.PORT, () => { const server = app.listen(process.env.PORT, () => {
logger.info(`Server started on port: ${process.env.PORT}`); logger.info(`Server started on port: ${process.env.PORT}`);
@ -44,19 +47,25 @@ gracefulShutdown(server);
(async () => { (async () => {
console.log("os.tmpdir(): ", os.tmpdir()); console.log("os.tmpdir(): ", os.tmpdir());
await clearAllKeys(); await clearAllKeys("user:*", "whatsapp:*");
const users = await User.findAll(); const users = await User.findAll();
for (const user of users) { for (const user of users) {
const { id, name } = user; const { id, name } = user;
if (name == "botqueue") {
const userService = await ShowUserService(id);
await setBotInfo(userService);
}
await set(`user:${id}`, { id, name }); await set(`user:${id}`, { id, name });
} }
loadSettings(); loadSettings();
let whatsapps: any = await Whatsapp.findAll({ let whatsapps: any = await Whatsapp.findAll({
attributes: ["id", "url", "phoneNumberId"] attributes: ["id", "url", "phoneNumberId", "number"]
}); });
if (whatsapps && whatsapps.length > 0) { if (whatsapps && whatsapps.length > 0) {
@ -64,7 +73,14 @@ gracefulShutdown(server);
try { try {
const { phoneNumberId } = whatsapps[i]; const { phoneNumberId } = whatsapps[i];
if (phoneNumberId) continue; if (phoneNumberId) {
await set(
`whatsapp:${whatsapps[i].dataValues.id}`,
`${whatsapps[i].dataValues.number}`
);
continue;
}
console.log( console.log(
`API URL: ${whatsapps[i].dataValues.url}/api/connection/status` `API URL: ${whatsapps[i].dataValues.url}/api/connection/status`

View File

@ -22,6 +22,7 @@ interface WhatsappData {
greetingMessage?: string; greetingMessage?: string;
farewellMessage?: string; farewellMessage?: string;
queueIds?: number[]; queueIds?: number[];
number?:string;
} }
interface Request { interface Request {
@ -52,6 +53,7 @@ const UpdateWhatsAppService = async ({
phoneNumberId, phoneNumberId,
wabaId, wabaId,
isOfficial, isOfficial,
number,
url, url,
urlApi, urlApi,
session, session,
@ -116,6 +118,7 @@ const UpdateWhatsAppService = async ({
isOfficial, isOfficial,
phoneNumberId, phoneNumberId,
wabaId, wabaId,
number,
classification classification
}); });