feat: thread QR/status callbacks through session pool; persist to DB in main
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -122,6 +122,28 @@ async function bootstrap() {
|
||||
const map = await syncGroups(groups, accountId, prisma);
|
||||
groupMaps.set(accountId, map);
|
||||
},
|
||||
async (qr, accountId) => {
|
||||
await prisma.account.update({
|
||||
where: { id: accountId },
|
||||
data: { qrCode: qr },
|
||||
}).catch((err) => logger.error({ accountId, err }, 'Failed to store QR in DB'));
|
||||
logger.info({ accountId }, 'QR code updated');
|
||||
},
|
||||
async (status, accountId) => {
|
||||
if (status === 'connected') {
|
||||
await prisma.account.update({
|
||||
where: { id: accountId },
|
||||
data: { qrCode: null, status: 'ACTIVE' },
|
||||
}).catch((err) => logger.error({ accountId, err }, 'Failed to update account status'));
|
||||
logger.info({ accountId }, 'Account connected — QR cleared');
|
||||
} else if (status === 'logged_out') {
|
||||
await prisma.account.update({
|
||||
where: { id: accountId },
|
||||
data: { status: 'DISCONNECTED' },
|
||||
}).catch((err) => logger.error({ accountId, err }, 'Failed to update account status'));
|
||||
logger.info({ accountId }, 'Account logged out — awaiting QR scan');
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error({ accountId: account.id, err }, 'Failed to start session — skipping account');
|
||||
|
||||
@@ -89,4 +89,21 @@ describe('WhatsAppSessionPool', () => {
|
||||
await capturedOnMessage(fakeMsg);
|
||||
expect(onMessage).toHaveBeenCalledWith(fakeMsg, 'acc_1');
|
||||
});
|
||||
|
||||
it('add() injects accountId into onQr callback', async () => {
|
||||
const onQr = jest.fn();
|
||||
const { createWhatsAppSession } = require('./session');
|
||||
|
||||
let capturedOnQr: any;
|
||||
(createWhatsAppSession as jest.Mock).mockImplementationOnce(
|
||||
(_id: string, _path: string, _onMsg: any, _onReaction: any, _onGroups: any, _onReconnect: any, qrCb: any) => {
|
||||
capturedOnQr = qrCb;
|
||||
return Promise.resolve({ sendMessage: jest.fn(), logout: jest.fn(), end: jest.fn() });
|
||||
},
|
||||
);
|
||||
|
||||
await pool.add('acc_1', './sessions/1', jest.fn(), jest.fn(), jest.fn(), onQr);
|
||||
await capturedOnQr('test-qr');
|
||||
expect(onQr).toHaveBeenCalledWith('test-qr', 'acc_1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,8 @@ export type PoolMessageCallback = (msg: NormalizedMessage, accountId: string) =>
|
||||
export type PoolReactionCallback = (reaction: NormalizedReaction, accountId: string) => Promise<void> | void;
|
||||
// groups typed as `any` to avoid leaking GroupMetadata (Baileys type) into main.ts
|
||||
export type PoolGroupsCallback = (groups: any, accountId: string) => Promise<void> | void;
|
||||
export type PoolQrCallback = (qr: string, accountId: string) => Promise<void> | void;
|
||||
export type PoolStatusCallback = (status: string, accountId: string) => Promise<void> | void;
|
||||
|
||||
export class WhatsAppSessionPool {
|
||||
private sessions = new Map<string, WASocket>();
|
||||
@@ -21,6 +23,8 @@ export class WhatsAppSessionPool {
|
||||
onMessage: PoolMessageCallback,
|
||||
onReaction: PoolReactionCallback,
|
||||
onGroups: PoolGroupsCallback,
|
||||
onQr?: PoolQrCallback,
|
||||
onStatus?: PoolStatusCallback,
|
||||
): Promise<void> {
|
||||
logger.info({ accountId }, 'Starting session');
|
||||
const sock = await createWhatsAppSession(
|
||||
@@ -33,6 +37,8 @@ export class WhatsAppSessionPool {
|
||||
logger.info({ accountId }, 'Session reconnected — updating pool');
|
||||
this.sessions.set(accountId, newSocket);
|
||||
},
|
||||
onQr ? (qr) => onQr(qr, accountId) : undefined,
|
||||
onStatus ? (status) => onStatus(status, accountId) : undefined,
|
||||
);
|
||||
this.sessions.set(accountId, sock);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user