feat: add Baileys WhatsApp session with reconnect logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/boom": "^10.0.1",
|
||||
"@tower/config": "workspace:*",
|
||||
"@tower/logger": "workspace:*",
|
||||
"@tower/types": "workspace:*",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Generated
+15
@@ -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': {}
|
||||
|
||||
Reference in New Issue
Block a user