I have a problem, when I send multiple messages to whatsapp through the api webhook it falls in a loop even though I am validating returning a 200 status for each message sent
I have a cycle to send the messages one by one that I store in an array of objects where each type of message that is sent to whatsapp goes. I even have a delay of 2 seconds for each message that is sent, but it falls into a loop, for each response that I send, it keeps responding without rest until I restart the server
I don't know what else to try, I even have a filter to try to avoid messages that have been received for a certain time to avoid repetitions in receiving them, but nothing. Even create a DB in Supabase to call the message that has already been sent and verify how much it does to avoid repeating the message
I ask for your help because I don't know what else to try now, I appreciate any kind of help in advance, please help
async function sendMessagesToWhatsApp(messages: any[]): Promise<void> {
for (const msg of messages) {
try {
await SendMessageWhatsApp(msg);
await delay(2000); // Wait 2 seconds between messages
} catch (error) {
await registerEvents(msg, 500, "Server Error Internal", String(error));
}
}
}
export const receiveMessage = async (req: Request, res: Response, next: NextFunction) => {
let entry = req.body.entry[0];
let changes = entry.changes[0];
let value = changes.value;
try {
// First we record the log
await registerEvents(req.body, 200, "Get Webhook Whatsapp Api Cloud", null);
const messageReceived = req.body;
if (!messageReceived) {
// No message received but a status 200 is returned to avoid errors
console.log('evaluating when nothing is received in the body');
res.sendStatus(200)
}
let messageObject = value?.messages ?? undefined;
const changesResult = messageReceived.entry[0].changes[0].value;
if (changesResult?.statuses !== undefined) {
const messageStatus = messageReceived.entry[0].changes[0].value.statuses[0].status;
if (messageStatus === "sent") {
res.sendStatus(200);
}
if (messageStatus === "delivered") {
res.sendStatus(200);
}
if (messageStatus === "read") {
res.sendStatus(200);
}
if (messageStatus === "failed") {
await registerEvents(messageReceived, 500, "Webhook Events", "Message Failed");
res.sendStatus(200);
}
} else {
if (messageObject !== undefined) {
messageObject = messageObject.filter((message) => message.timestamp > (Date.now() - 1000 * 60 * 60 * 0.2) / 1000);
if (messageObject.length > 0) {
const messages: Message = messageObject[0];
const from = messageObject[0]?.from;
// Type message
let typeMessage = messages?.type;
// validate the type of messaging
if (typeMessage === "text") {
sendStatusMessage("Typing...", from);
const messagesToSend = await textProcess(messages, from);
if (Array.isArray(messagesToSend)) {
sendMessagesToWhatsApp(messagesToSend)
.then(() => {
console.log("Messages sent successfully.");
res.sendStatus(200);
})
.catch(error => {
console.error("Error sending messages:", error);
res.sendStatus(200);
});
} else {
SendMessageWhatsApp(messagesToSend);
res.sendStatus(200);
}
}
if (typeMessage === "audio") {
console.log('is audio');
const data = await audioProcess(messages, from);
SendMessageWhatsApp(data);
res.sendStatus(200);
}
if (typeMessage === "button") {
const data = await buttonProcess(messages, from);
SendMessageWhatsApp(data);
res.sendStatus(200);
}
if (typeMessage === "interactive") {
const data = await interactiveProcess(messages, from);
SendMessageWhatsApp(data);
res.sendStatus(200);
}
} else {
// when resubmitted they still contain the timestamp from when they were initially sent
console.log('The message was filtered by the sending time');
res.sendStatus(200);
}
} else {
res.sendStatus(200);
}
}
} catch (error) {
console.log(error);
await registerEvents(req.body, 500, "Error Webhook Whatsapp Api Cloud", error)
// Evitar lopp webhook
console.log('An internal server error occurred but 200 should always be sent');
res.sendStatus(200);
}
}
async function textProcess(messages: Message, from: string) {
let message = messages.text.body;
const answer = await askOpenAI(message);
const answertoLowerCase = answer.toLocaleLowerCase();
if (answertoLowerCase.includes("app")) {
const ifAnswerIsMarkdown = isMarkdownFormat(answer);
if (ifAnswerIsMarkdown) {
const formattedContent = parseMarkdown(answer);
const messages_ = buildDataToWhatsapp(formattedContent, from);
console.log('lenght msj', messages_.length);
// for await (const msg of messages_) {
// SendMessageWhatsApp(msg);
// await delay(2000); // Espera un tiempo entre cada mensaje
// }
return messages_
} else {
console.log('no need to format the text because it is not markdown');
const dataToSend = {
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": from,
"type": "text",
"text": {
"preview_url": false,
"body": answer
}
}
// SendMessageWhatsApp(dataToSend);
return dataToSend
}
} else {
const dataToSend = {
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": from,
"type": "text",
"text": {
"preview_url": false,
"body": answer
}
}
return dataToSend
}
}
function SendMessageWhatsApp(message: any) {
const data = JSON.stringify(message);
const options = {
host: "graph.facebook.com",
path: `/v16.0/${ID_CELL}/messages`,
method: "POST",
body: data,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${TOKEN_CLOUD_API_WSP}`
}
};
const req = https.request(options, res => {
res.on("data", d => {
process.stdout.write(d);
});
});
req.on("error", error => {
console.error(error);
supabase.from('logs').insert([
{
message: error,
status: 500,
task: "Internal server",
error: null
}
]);
});
req.write(data);
req.end();
registerEvents(data, 200, "SendMessageWhatsApp", Date.now());
}