diff --git a/apps/bot/src/whatsapp/group-sync.ts b/apps/bot/src/whatsapp/group-sync.ts index 00afcd2..d1d97ed 100644 --- a/apps/bot/src/whatsapp/group-sync.ts +++ b/apps/bot/src/whatsapp/group-sync.ts @@ -1,4 +1,4 @@ -import { sql } from "drizzle-orm"; +import { and, eq, notInArray, sql } from "drizzle-orm"; import type { WASocket } from "@whiskeysockets/baileys"; import { whatsappGroups } from "@cmbot/db"; import { db } from "../db.js"; @@ -7,13 +7,35 @@ import { logger } from "../logger.js"; export async function syncGroupsForAccount( accountId: string, socket: WASocket, -): Promise<{ synced: number }> { +): Promise<{ synced: number; removed: number }> { const meta = await socket.groupFetchAllParticipating(); const entries = Object.values(meta); + const liveJids = entries.map((g) => g.id); + + // Remove DB rows for groups that are no longer in the live participant list + // (group was deleted, bot was removed, etc.). Only run the delete when we + // got at least one live group back — an empty result is more likely a + // transient WA fetch failure than a genuine "all groups gone" signal, and + // we don't want to nuke valid data on a hiccup. + let removed: { id: string }[] = []; + if (liveJids.length > 0) { + removed = await db + .delete(whatsappGroups) + .where( + and( + eq(whatsappGroups.accountId, accountId), + notInArray(whatsappGroups.waGroupJid, liveJids), + ), + ) + .returning({ id: whatsappGroups.id }); + } if (entries.length === 0) { - logger.info({ accountId }, "group-sync: no groups"); - return { synced: 0 }; + logger.info( + { accountId }, + "group-sync: empty fetch — skipping delete sweep (treating as transient)", + ); + return { synced: 0, removed: 0 }; } const rows = entries.map((g) => ({ @@ -37,6 +59,9 @@ export async function syncGroupsForAccount( }, }); - logger.info({ accountId, count: rows.length }, "group-sync: synced"); - return { synced: rows.length }; + logger.info( + { accountId, count: rows.length, removed: removed.length }, + "group-sync: synced", + ); + return { synced: rows.length, removed: removed.length }; }