Fix reconnect logic and audio mimetype support
This commit is contained in:
@@ -340,6 +340,7 @@ class WhatsAppController extends BaseController
|
|||||||
|
|
||||||
$replyText = null;
|
$replyText = null;
|
||||||
$replyAudio = null;
|
$replyAudio = null;
|
||||||
|
$replyAudioMimeType = null;
|
||||||
|
|
||||||
if ($rule['trigger_type'] === 'keyword') {
|
if ($rule['trigger_type'] === 'keyword') {
|
||||||
if (empty($incomingText)) {
|
if (empty($incomingText)) {
|
||||||
@@ -413,6 +414,7 @@ class WhatsAppController extends BaseController
|
|||||||
);
|
);
|
||||||
if ($audioResponse && !empty($audioResponse['audio'])) {
|
if ($audioResponse && !empty($audioResponse['audio'])) {
|
||||||
$replyAudio = $audioResponse['audio'];
|
$replyAudio = $audioResponse['audio'];
|
||||||
|
$replyAudioMimeType = $audioResponse['mimeType'] ?? 'audio/mp4';
|
||||||
$replyText = '[صوت من الذكاء الاصطناعي]';
|
$replyText = '[صوت من الذكاء الاصطناعي]';
|
||||||
} else {
|
} else {
|
||||||
// Fallback to text output from audio
|
// Fallback to text output from audio
|
||||||
@@ -462,6 +464,9 @@ class WhatsAppController extends BaseController
|
|||||||
];
|
];
|
||||||
if (!empty($replyAudio)) {
|
if (!empty($replyAudio)) {
|
||||||
$payloadData['audio'] = $replyAudio;
|
$payloadData['audio'] = $replyAudio;
|
||||||
|
if (!empty($replyAudioMimeType)) {
|
||||||
|
$payloadData['mimetype'] = $replyAudioMimeType;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$payloadData['message'] = $replyText;
|
$payloadData['message'] = $replyText;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,25 +231,29 @@ async function startSession(session_key, webhook_url) {
|
|||||||
if (connection === 'close') {
|
if (connection === 'close') {
|
||||||
const statusCode = lastDisconnect?.error?.output?.statusCode;
|
const statusCode = lastDisconnect?.error?.output?.statusCode;
|
||||||
const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
|
const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
|
||||||
const retries = (retryCounters.get(session_key) || 0) + 1;
|
|
||||||
retryCounters.set(session_key, retries);
|
|
||||||
|
|
||||||
console.log(`[Connection] ${session_key} closed | code=${statusCode} | retry=${retries}/${MAX_RETRIES} | shouldReconnect=${shouldReconnect}`);
|
if (!shouldReconnect) {
|
||||||
|
console.log(`[Connection] ${session_key} permanently closed (logged out). Cleaning up.`);
|
||||||
if (shouldReconnect && retries <= MAX_RETRIES) {
|
|
||||||
// Try reconnecting with exponential backoff
|
|
||||||
sessions.delete(session_key);
|
sessions.delete(session_key);
|
||||||
const delay = Math.min(retries * 3000, 15000); // 3s, 6s, 9s, 12s, 15s
|
|
||||||
console.log(`[Connection] Reconnecting ${session_key} in ${delay}ms...`);
|
|
||||||
setTimeout(() => startSession(session_key, webhook_url), delay);
|
|
||||||
} else {
|
|
||||||
// Either logged out, banned, or max retries exceeded
|
|
||||||
console.log(`[Connection] ${session_key} permanently closed. Cleaning up.`);
|
|
||||||
await cleanupSession(session_key);
|
await cleanupSession(session_key);
|
||||||
await sendWebhook(webhook_url, {
|
await sendWebhook(webhook_url, {
|
||||||
session_key,
|
session_key,
|
||||||
state: 'disconnected'
|
state: 'disconnected'
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const retries = (retryCounters.get(session_key) || 0) + 1;
|
||||||
|
retryCounters.set(session_key, retries);
|
||||||
|
|
||||||
|
sessions.delete(session_key);
|
||||||
|
let delay;
|
||||||
|
if (retries <= MAX_RETRIES) {
|
||||||
|
delay = Math.min(retries * 3000, 15000); // 3s, 6s, 9s, 12s, 15s
|
||||||
|
console.log(`[Connection] Reconnecting ${session_key} (quick retry ${retries}/${MAX_RETRIES}) in ${delay}ms...`);
|
||||||
|
} else {
|
||||||
|
delay = 60000; // 60s
|
||||||
|
console.log(`[Connection] Reconnecting ${session_key} (long-term retry ${retries}) in 60s...`);
|
||||||
|
}
|
||||||
|
setTimeout(() => startSession(session_key, webhook_url), delay);
|
||||||
}
|
}
|
||||||
} else if (connection === 'open') {
|
} else if (connection === 'open') {
|
||||||
console.log(`[Connection] ✅ ${session_key} connected successfully!`);
|
console.log(`[Connection] ✅ ${session_key} connected successfully!`);
|
||||||
@@ -310,7 +314,7 @@ async function disconnectSession(session_key) {
|
|||||||
/**
|
/**
|
||||||
* Send a message using an active session
|
* Send a message using an active session
|
||||||
*/
|
*/
|
||||||
async function sendMessage(session_key, phone, message, mediaUrl = null, audioBase64 = null) {
|
async function sendMessage(session_key, phone, message, mediaUrl = null, audioBase64 = null, mimetype = null) {
|
||||||
const sock = sessions.get(session_key);
|
const sock = sessions.get(session_key);
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
throw new Error(`Session ${session_key} is not active or connected`);
|
throw new Error(`Session ${session_key} is not active or connected`);
|
||||||
@@ -323,7 +327,7 @@ async function sendMessage(session_key, phone, message, mediaUrl = null, audioBa
|
|||||||
const buffer = Buffer.from(audioBase64, 'base64');
|
const buffer = Buffer.from(audioBase64, 'base64');
|
||||||
sentMsg = await sock.sendMessage(jid, {
|
sentMsg = await sock.sendMessage(jid, {
|
||||||
audio: buffer,
|
audio: buffer,
|
||||||
mimetype: 'audio/mp4',
|
mimetype: mimetype || 'audio/mp4',
|
||||||
ptt: true
|
ptt: true
|
||||||
});
|
});
|
||||||
} else if (mediaUrl) {
|
} else if (mediaUrl) {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ app.get('/api/sessions/active', (req, res) => {
|
|||||||
|
|
||||||
// Send outbound message
|
// Send outbound message
|
||||||
app.post('/api/messages/send', async (req, res) => {
|
app.post('/api/messages/send', async (req, res) => {
|
||||||
const { session_key, phone, message, media_url, audio } = req.body;
|
const { session_key, phone, message, media_url, audio, mimetype } = req.body;
|
||||||
|
|
||||||
if (!session_key || !phone) {
|
if (!session_key || !phone) {
|
||||||
return res.status(400).json({ error: 'Missing session_key or phone' });
|
return res.status(400).json({ error: 'Missing session_key or phone' });
|
||||||
@@ -95,7 +95,7 @@ app.post('/api/messages/send', async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await sendMessage(session_key, phone, message, media_url, audio);
|
const result = await sendMessage(session_key, phone, message, media_url, audio, mimetype);
|
||||||
res.json({ status: 'success', data: result });
|
res.json({ status: 'success', data: result });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Error sending message via ${session_key} to ${phone}:`, err);
|
console.error(`Error sending message via ${session_key} to ${phone}:`, err);
|
||||||
|
|||||||
Reference in New Issue
Block a user