Files
accounted/extensions/general/whatsapp-inbox/lib/chat-mime.ts
T
MattssonandClaude Fable 5 c121d27996 feat(whatsapp-inbox): instant checkmark reaction when a receipt lands (#1893)
Users standing at a register saw nothing until the detailed ack, which
waits on extraction (10-60s) and reads as a black hole; failures could
take minutes longer via the sweep. Now the webhook reacts with a U+2705
checkmark on the sender's own media bubble right after the durable row
is persisted, so the 'correctly received' signal lands within seconds.

- sendReaction in graph-api: best-effort like mark-read, never throws,
  no outbound row (a reaction is not a message in the conversation model)
- gated on the chat MIME allowlist (moved to lib/chat-mime.ts so tests
  mocking process-inbound cannot lose it): junk earns M15, no checkmark
- no reaction for unknown, muted, or redelivered (23505) messages
- detailed M4/M5 combined ack and the one-message-per-burst design are
  unchanged

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 12:18:12 +02:00

21 lines
792 B
TypeScript

/**
* Chat intake accepts what phones actually produce. Narrower than the upload
* allowlist on purpose: WhatsApp transcodes photos to JPEG, so HEIC never
* arrives, and everything else gets the M15 nudge.
*
* Lives in its own dependency-free module because both the deferred worker
* (the M15 rejection) and the webhook (the instant checkmark reaction) gate
* on it, and tests that mock process-inbound must not lose the constant.
*/
export const CHAT_ALLOWED_MIME_TYPES: ReadonlySet<string> = new Set([
'image/jpeg',
'image/png',
'image/webp',
'application/pdf',
])
/** Normalize a raw MIME header value to what the allowlist stores. */
export function normalizeChatMime(mime: string | null | undefined): string {
return (mime ?? '').split(';')[0].trim().toLowerCase()
}