import { rm } from "node:fs/promises"; import { join } from "node:path"; import { db } from "../db.js"; import { env } from "../env.js"; import { sessionManager } from "../whatsapp/session-manager.js"; import { writeAuditLog } from "../audit.js"; import { pgNotifyWeb } from "./notify.js"; import { logger } from "../logger.js"; /** * Unpair handler: stop the live Baileys session and remove the on-disk * session files. The web action keeps the account row alive (status = * 'unpaired') so the operator can re-pair without retyping the label; * the {intentional: true} stop tells the session manager not to race * the web's status write with its own "disconnected" update or * schedule a reconnect for a session we just chose to tear down. * * For the delete-account flow the row IS gone by the time we run; * the audit log lookup tolerates that. */ export async function handleUnpair(accountId: string): Promise { await sessionManager.stop(accountId, { intentional: true }); await rm(join(env.SESSIONS_DIR, accountId), { recursive: true, force: true }); try { const row = await db.query.whatsappAccounts.findFirst({ where: (a, { eq }) => eq(a.id, accountId), columns: { operatorId: true }, }); await writeAuditLog(db, { operatorId: row?.operatorId ?? null, source: "web", action: "account.unpaired", targetType: "whatsapp_account", targetId: accountId, payload: {}, }); } catch (err) { logger.warn({ err, accountId }, "unpair: audit log failed (non-fatal)"); } await pgNotifyWeb({ type: "session.disconnected", accountId }); }