/** * Per-channel opt-out for recurring messages. * * Different from `LeadStore.optOut()` — that pauses the entire bot. * `ChannelOptOuts` lets a user mute *specific* channels (e.g. devotional) * while continuing to receive others (e.g. reading plan). * * Storage shape: one row per (whatsapp, channel). Default is "subscribed" * (no row); opting out inserts a row; opting back in deletes it. This * avoids per-channel boolean column bloat on the leads table (bibliafala * tried that — three columns to start, more queued behind it) and scales * to any number of channels without `ALTER TABLE`. * * Plugs into `Broadcast` audience queries via `notOptedOut()`, which * returns a Drizzle `SQL` fragment ready to drop into a `.where(and(...))`. * * From v0.2 onward: backed by Drizzle ORM. */ import { type SQL, type SQLWrapper } from 'drizzle-orm'; import type { DB } from '../db/client.js'; export interface ChannelOptOutsOptions { db: DB; } export declare class ChannelOptOuts { readonly db: DB; constructor({ db }: ChannelOptOutsOptions); /** * Mute one channel for one user. Idempotent. */ optOut(whatsapp: string, channel: string): Promise; /** * Re-subscribe to one channel. Idempotent (DELETE matches 0 or 1 row). */ optIn(whatsapp: string, channel: string): Promise; isOptedOut(whatsapp: string, channel: string): Promise; /** * @returns the set of channels this user has muted. */ listOptOuts(whatsapp: string): Promise; /** * Mass-mute: returns whatsapp numbers currently opted out of `channel`. */ listOptedOutFor(channel: string, { limit }?: { limit?: number; }): Promise; /** * Drizzle `SQL` fragment for audience queries. * * .where(and( * ..., * channels.notOptedOut('devotional', messageWindows.whatsapp) * )) * * Uses NOT EXISTS so it composes inside any WHERE clause without * disturbing the row count upstream. * * @param channel channel name to check (parameterized, safe from injection) * @param userColumn Drizzle column reference to the whatsapp number in * the outer query (e.g. `messageWindows.whatsapp`). */ notOptedOut(channel: string, userColumn: SQLWrapper): SQL; } //# sourceMappingURL=channel_opt_outs.d.ts.map