Skip to content

fix: detect view-once media on stanza 1 for linked devices + fix mediatype in enc node#2435

Open
rsalcara wants to merge 4 commits intoWhiskeySockets:masterfrom
rsalcara:fix/view-once-linked-device
Open

fix: detect view-once media on stanza 1 for linked devices + fix mediatype in enc node#2435
rsalcara wants to merge 4 commits intoWhiskeySockets:masterfrom
rsalcara:fix/view-once-linked-device

Conversation

@rsalcara
Copy link
Copy Markdown

@rsalcara rsalcara commented Mar 20, 2026

Problem

Two bugs affecting view-once media (image/video/audio) on linked devices:

Bug 1 — decode-wa-message.ts

When a view-once message arrives at a linked device, the server sends two stanzas:

  • Stanza 1 (enc): full media metadata — viewOnceMessage > imageMessage/videoMessage/audioMessage { viewOnce: true, mediaKey, directPath, ... }
  • Stanza 2 (unavailable type="view_once"): fanout placeholder (already handled at line 294)

Stanza 1 was decoded but key.isViewOnce was never set, making it indistinguishable from regular media in messages.upsert. Consumers had no way to know the message was view-once.

Bug 2 — messages-send.ts

getMediaType() checks message.imageMessage, message.videoMessage, etc. directly. When viewOnce: true is set, generateWAMessageContent wraps the media inside viewOnceMessage.message, so message.imageMessage is undefined at the top level.

Result: mediatype attribute was missing from the enc node for all view-once media. WA servers silently dropped view-once video and audio messages (images were more lenient). Verified on production: image view-once arrived, video/audio did not — until this fix.

Fix

src/Utils/decode-wa-message.ts (+17 lines)
After decoding proto.Message, inspect viewOnceMessage / viewOnceMessageV2 / viewOnceMessageV2Extension wrappers for inner media with viewOnce: true. If found, set fullMessage.key.isViewOnce = true.

The viewOnceMessage wrapper is also used for interactive messages (carousel, buttons, lists) which carry interactiveMessage / listMessage inside — never imageMessage.viewOnce = true. The check is unambiguous.

src/Socket/messages-send.ts (+9 lines)
Before checking media fields in getMediaType(), unwrap viewOnceMessage / viewOnceMessageV2 / viewOnceMessageV2Extension recursively (same pattern as normalizeMessageContent). This ensures mediatype="image"/"video"/"audio" is correctly set on the enc node.

Testing

Verified on production (2026-03-20):

  • ✅ Image view-once: received with key.isViewOnce = true, mediatype="image" on enc
  • ✅ Video view-once: received and delivered (was silently dropped before fix)
  • ✅ Audio view-once: received and delivered
  • ✅ Interactive messages (carousel/buttons/lists): unaffected — viewOnceMessage wrapper with interactiveMessage inside is correctly not flagged as view-once media

Checklist

  • Only touches decode-wa-message.ts and messages-send.ts
  • No breaking changes
  • Backwards compatible (interactive messages unchanged)
  • Branch based on WhiskeySockets/Baileys master (not fork-specific commits)

rsalcara and others added 3 commits March 20, 2026 11:21
…d devices

When a view-once arrives at a linked device (InfiniteAPI), the server sends:
- Stanza 1: enc payload with full media metadata (mediaKey, directPath) wrapped in
  viewOnceMessage > imageMessage/videoMessage/audioMessage with viewOnce: true
- Stanza 2: unavailable view_once fanout placeholder (already handled)

Previously only stanza 2 set key.isViewOnce = true. Stanza 1 was emitted as
plain media with no view-once indicator, making it indistinguishable from regular
media on the consumer side (messages.upsert).

This fix inspects the decrypted proto for viewOnceMessage (v1/v2/v2Ext) wrappers
containing a media message with viewOnce=true and propagates key.isViewOnce=true.

The viewOnceMessage wrapper is also used for interactive messages (carousel,
buttons, lists) but those carry interactiveMessage/listMessage inside -- never
imageMessage.viewOnce / videoMessage.viewOnce / audioMessage.viewOnce.
The distinction is unambiguous and does not affect interactive message handling.

Verified via WA Desktop CDP capture (2026-03-19) and Android Frida DB capture
of view-once types 42/43/82 in msgstore.db (2026-03-20).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fullMessage.key is always present on WAMessage. Use consistent style
with stanza-2 handling at line 297.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e attribute

Without this fix, view-once media (image/video/audio) was sent without
mediatype="image/video/audio" on the enc node because getMediaType only
checked the top-level message fields. The viewOnceMessage wrapper hides
the inner imageMessage, causing mediatype to be empty and WA servers to
silently drop the message on the recipient side.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 20, 2026 14:22
@whiskeysockets-bot
Copy link
Copy Markdown
Contributor

whiskeysockets-bot commented Mar 20, 2026

Thanks for opening this pull request and contributing to the project!

The next step is for the maintainers to review your changes. If everything looks good, it will be approved and merged into the main branch.

In the meantime, anyone in the community is encouraged to test this pull request and provide feedback.

✅ How to confirm it works

If you’ve tested this PR, please comment below with:

Tested and working ✅

This helps us speed up the review and merge process.

📦 To test this PR locally:

# NPM
npm install @whiskeysockets/baileys@rsalcara/InfiniteAPI#fix/view-once-linked-device

# Yarn (v2+)
yarn add @whiskeysockets/baileys@rsalcara/InfiniteAPI#fix/view-once-linked-device

# PNPM
pnpm add @whiskeysockets/baileys@rsalcara/InfiniteAPI#fix/view-once-linked-device

If you encounter any issues or have feedback, feel free to comment as well.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes two linked-device view-once media bugs by correctly (1) marking incoming stanza-1 view-once media as view-once, and (2) ensuring outgoing view-once media sets the correct mediatype attribute on the enc node so servers don’t drop it.

Changes:

  • Detect view-once media in stanza 1 by inspecting view-once wrappers and setting fullMessage.key.isViewOnce = true during decryption.
  • Fix getMediaType() to unwrap view-once wrappers before checking message media fields, restoring mediatype="image"/"video"/"audio" for view-once sends.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Utils/decode-wa-message.ts Sets key.isViewOnce for linked-device stanza-1 view-once media by inspecting view-once wrappers’ inner media flags.
src/Socket/messages-send.ts Unwraps view-once wrappers in getMediaType() so enc node mediatype is populated for view-once media.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Salientekill
Copy link
Copy Markdown

I'm almost certain they'll ask you to split that PR into two, one for each fix.

@rsalcara
Copy link
Copy Markdown
Author

Thanks for the feedback! 🙌

For view-once messages sent from a linked device (API/companion):

- Only send DSM to primary phone (device=0). Companion devices (device>0)
  are omitted from participants — the WA server generates
  <unavailable type="view_once"/> for them automatically. Sending an
  explicit <unavailable> from a companion is silently rejected by the
  server and causes the message to not be delivered.

- Detect actual view-once media by inspecting the inner message's
  viewOnce flag (imageMessage.viewOnce / videoMessage.viewOnce /
  audioMessage.viewOnce). viewOnceMessage* wrappers are also used for
  interactive messages (buttons, lists) which must not be filtered.
  Consistent with the detection added in decode-wa-message.ts.

- assertSessions now uses only the recipients actually encrypted for,
  avoiding unnecessary session validation for omitted companions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

4 participants