fix: normalize wrapped WhatsApp messages before reading content (#628)

WhatsApp wraps certain message types in container objects:
- viewOnceMessageV2 (listen-once voice, view-once media)
- ephemeralMessage (disappearing messages)
- editedMessage (edited messages)

Without calling Baileys' normalizeMessageContent(), the fields
conversation, extendedTextMessage, imageMessage, etc. are nested
inside the wrapper and invisible to our direct field access. This
causes these messages to be silently dropped with no error.

- Import and call normalizeMessageContent() early in messages.upsert
- Use the normalized content object for all field reads
- Add mock to test suite

Co-authored-by: Ethan M <ethan@nanoclaw.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
glifocat
2026-03-01 23:14:08 +01:00
committed by GitHub
parent 16d005fcbe
commit 16ab463148
2 changed files with 11 additions and 4 deletions

View File

@@ -87,6 +87,7 @@ vi.mock('@whiskeysockets/baileys', () => {
fetchLatestWaWebVersion: vi
.fn()
.mockResolvedValue({ version: [2, 3000, 0] }),
normalizeMessageContent: vi.fn((content: unknown) => content),
makeCacheableSignalKeyStore: vi.fn((keys: unknown) => keys),
useMultiFileAuthState: vi.fn().mockResolvedValue({
state: {

View File

@@ -8,6 +8,7 @@ import makeWASocket, {
WASocket,
fetchLatestWaWebVersion,
makeCacheableSignalKeyStore,
normalizeMessageContent,
useMultiFileAuthState,
} from '@whiskeysockets/baileys';
@@ -172,6 +173,11 @@ export class WhatsAppChannel implements Channel {
this.sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
if (!msg.message) continue;
// Unwrap container types (viewOnceMessageV2, ephemeralMessage,
// editedMessage, etc.) so that conversation, extendedTextMessage,
// imageMessage, etc. are accessible at the top level.
const normalized = normalizeMessageContent(msg.message);
if (!normalized) continue;
const rawJid = msg.key.remoteJid;
if (!rawJid || rawJid === 'status@broadcast') continue;
@@ -196,10 +202,10 @@ export class WhatsAppChannel implements Channel {
const groups = this.opts.registeredGroups();
if (groups[chatJid]) {
const content =
msg.message?.conversation ||
msg.message?.extendedTextMessage?.text ||
msg.message?.imageMessage?.caption ||
msg.message?.videoMessage?.caption ||
normalized.conversation ||
normalized.extendedTextMessage?.text ||
normalized.imageMessage?.caption ||
normalized.videoMessage?.caption ||
'';
// Skip protocol messages with no text content (encryption keys, read receipts, etc.)