feat: add Baileys WhatsApp session with reconnect logic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 15:33:46 +05:30
parent 0d45bd8bd6
commit a4771aaf05
3 changed files with 74 additions and 0 deletions
+1
View File
@@ -8,6 +8,7 @@
"test": "jest"
},
"dependencies": {
"@hapi/boom": "^10.0.1",
"@tower/config": "workspace:*",
"@tower/logger": "workspace:*",
"@tower/types": "workspace:*",
+58
View File
@@ -0,0 +1,58 @@
import makeWASocket, {
useMultiFileAuthState,
fetchLatestBaileysVersion,
DisconnectReason,
WASocket,
proto,
GroupMetadata,
} from '@whiskeysockets/baileys';
import { Boom } from '@hapi/boom';
import { createLogger } from '@tower/logger';
const logger = createLogger('whatsapp-session');
export type OnMessageCallback = (msg: proto.IWebMessageInfo) => void;
export type OnGroupsCallback = (groups: Record<string, GroupMetadata>) => void;
export async function createWhatsAppSession(
sessionPath: string,
onMessage: OnMessageCallback,
onGroups: OnGroupsCallback,
): Promise<WASocket> {
const { state, saveCreds } = await useMultiFileAuthState(sessionPath);
const { version } = await fetchLatestBaileysVersion();
const sock = makeWASocket({
version,
auth: state,
printQRInTerminal: true,
logger: logger as any,
});
sock.ev.on('creds.update', saveCreds);
sock.ev.on('connection.update', async ({ connection, lastDisconnect }) => {
if (connection === 'close') {
const reason = (lastDisconnect?.error as Boom)?.output?.statusCode;
const shouldReconnect = reason !== DisconnectReason.loggedOut;
logger.info({ reason, shouldReconnect }, 'Connection closed');
if (shouldReconnect) {
logger.info('Reconnecting in 5s...');
setTimeout(() => createWhatsAppSession(sessionPath, onMessage, onGroups), 5000);
}
} else if (connection === 'open') {
logger.info('WhatsApp connected');
const groups = await sock.groupFetchAllParticipating();
onGroups(groups);
}
});
sock.ev.on('messages.upsert', ({ messages, type }) => {
if (type !== 'notify') return;
for (const msg of messages) {
onMessage(msg);
}
});
return sock;
}
+15
View File
@@ -142,6 +142,9 @@ importers:
apps/worker:
dependencies:
'@hapi/boom':
specifier: ^10.0.1
version: 10.0.1
'@tower/config':
specifier: workspace:*
version: link:../../packages/config
@@ -459,9 +462,15 @@ packages:
'@emnapi/runtime@1.10.0':
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
'@hapi/boom@10.0.1':
resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==}
'@hapi/boom@9.1.4':
resolution: {integrity: sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw==}
'@hapi/hoek@11.0.7':
resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==}
'@hapi/hoek@9.3.0':
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
@@ -4025,10 +4034,16 @@ snapshots:
tslib: 2.8.1
optional: true
'@hapi/boom@10.0.1':
dependencies:
'@hapi/hoek': 11.0.7
'@hapi/boom@9.1.4':
dependencies:
'@hapi/hoek': 9.3.0
'@hapi/hoek@11.0.7': {}
'@hapi/hoek@9.3.0': {}
'@img/colour@1.1.0': {}