whatsapp qr code polling, validate token before save, fix bot startup timing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,6 @@ import {
|
||||
isWhatsAppBotRunning,
|
||||
getWhatsAppBotPhone,
|
||||
getWhatsAppQR,
|
||||
subscribeQR,
|
||||
disconnectWhatsApp,
|
||||
} from './whatsapp/bot';
|
||||
import { generatePairingCode } from './pairing';
|
||||
@@ -268,13 +267,12 @@ channelsRouter.put('/whatsapp/config', async (ctx) => {
|
||||
|
||||
if (enabled === true) {
|
||||
await upsertServerIntegration('whatsapp', {}, true);
|
||||
try {
|
||||
await startWhatsAppBot();
|
||||
} catch (err) {
|
||||
// Don't await — initialization is slow (launches Chromium) and QR events
|
||||
// are delivered via SSE. Return immediately so the client can connect SSE.
|
||||
startWhatsAppBot().catch((err) => {
|
||||
console.error('[channels] Failed to start WhatsApp bot:', err);
|
||||
return ctx.json({ success: true, botStarted: false, error: String(err) });
|
||||
}
|
||||
return ctx.json({ success: true, botStarted: true });
|
||||
});
|
||||
return ctx.json({ success: true, botStarted: false });
|
||||
}
|
||||
|
||||
if (enabled === false) {
|
||||
@@ -300,51 +298,12 @@ channelsRouter.get('/whatsapp/qr', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
// SSE stream for QR code updates
|
||||
return new Response(
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
const sendEvent = (data: Record<string, unknown>) => {
|
||||
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
|
||||
};
|
||||
|
||||
// Send current QR if available
|
||||
const currentQR = getWhatsAppQR();
|
||||
if (currentQR) {
|
||||
sendEvent({ type: 'qr', qr: currentQR });
|
||||
} else if (isWhatsAppBotRunning()) {
|
||||
sendEvent({ type: 'authenticated', phone: getWhatsAppBotPhone() });
|
||||
} else {
|
||||
sendEvent({ type: 'waiting' });
|
||||
}
|
||||
|
||||
const unsubscribe = subscribeQR((qr, event) => {
|
||||
if (event === 'qr' && qr) {
|
||||
sendEvent({ type: 'qr', qr });
|
||||
} else if (event === 'authenticated') {
|
||||
sendEvent({ type: 'authenticated', phone: getWhatsAppBotPhone() });
|
||||
} else if (event === 'disconnected') {
|
||||
sendEvent({ type: 'disconnected' });
|
||||
}
|
||||
});
|
||||
|
||||
// Clean up when client disconnects
|
||||
ctx.req.raw.signal.addEventListener('abort', () => {
|
||||
unsubscribe();
|
||||
controller.close();
|
||||
});
|
||||
},
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
Connection: 'keep-alive',
|
||||
},
|
||||
},
|
||||
);
|
||||
const qr = getWhatsAppQR();
|
||||
return ctx.json({
|
||||
qr,
|
||||
running: isWhatsAppBotRunning(),
|
||||
phone: getWhatsAppBotPhone(),
|
||||
});
|
||||
});
|
||||
|
||||
// ── User: WhatsApp pairing ──
|
||||
|
||||
Reference in New Issue
Block a user