Commit Graph

2202 Commits

Author SHA1 Message Date
Renato Alcara ef365246ea feat: add Android browser preset for companion device registration
Adds `Browsers.android(apiLevel)` preset that registers the companion
device as Android in WhatsApp's "Linked Devices" list, enabling
view-once messages and Android-specific features.

Inspired by PR #2201 (WhiskeySockets/Baileys#2201) which introduced
the concept, but with critical fixes discovered through extensive
reverse engineering and real-device testing.

## Usage

  const sock = makeWASocket({
    browser: Browsers.android('14'),
    auth: state
  })

The device appears as "Android (14)" in the phone's Linked Devices list.

## Investigation and Findings

### Two different platform fields

WhatsApp uses two separate platform identifiers that serve different
purposes:

1. `companion_platform_id` (pair code stanza) — validated by the server
   BEFORE showing the confirmation prompt on the phone. Controls whether
   the server accepts the pairing request.

2. `DeviceProps.PlatformType` (registration node) — sent AFTER pairing
   confirmation. Determines the display name in "Linked Devices".

These are independent: you can pair with Chrome (1) as companion but
register with ANDROID_PHONE (16) in DeviceProps, and the device will
correctly appear as "Android" in linked devices.

### Pair code platform testing results

Tested with real WhatsApp server via web protocol (WA\x06\x03):

| companion_platform_id | Result                                    |
|-----------------------|-------------------------------------------|
| Chrome (1)            | WORKS — phone shows "connect device?" prompt |
| ANDROID_PHONE (16)    | TIMEOUT — server silently ignores stanza    |
| UWP (21)              | REJECTED — "cannot connect device" error    |

When we sent `companion_platform_id: "16"` (ANDROID_PHONE), the server
did not respond at all — the request timed out after 30s with no
`link_code_pairing_ref` response. With Chrome ("1"), it responds
immediately.

This confirms: ANDROID_PHONE(16) is a primary device type, not a
companion type. The server expects companions with this type to use
the native Android protocol (WAM\x05 with key_attestation TEE
certificates). Since Baileys uses the web protocol (WA\x06\x03),
the server rejects it.

### UserAgent.Platform testing results

The original PR #2201 used `UserAgent.Platform = SMB_ANDROID` for
Android browser. Testing revealed this breaks pair code registration:

- With `SMB_ANDROID`: pair code generates, phone shows confirmation,
  user clicks "Yes", but registration FAILS with "cannot connect
  device" error. The mismatch between web protocol handshake
  (WA\x06\x03) and Android UserAgent causes the server to reject
  the registration.

- With `MACOS`: pair code works end-to-end. Device connects
  successfully and appears as "Android (14)" in linked devices.

Additionally, the upstream default `UserAgent.Platform = WEB` causes
405 connection failures on some server endpoints. Using `MACOS` (24)
resolves this.

### WhatsApp Desktop Windows investigation (Frida + binary analysis)

To understand how official WhatsApp clients handle platform identity,
we reverse-engineered WhatsApp Desktop for Windows:

- WhatsApp Desktop is a WebView2 wrapper loading
  `web.whatsapp.com?windows=1` — NOT a native client
- Uses the same web protocol (WA\x06\x03) as Chrome
- Registers with `DeviceProps.PlatformType = UWP (21)` to appear as
  "Windows" in linked devices
- Always shows as "Windows" regardless of QR or pair code connection

This confirmed our approach: the display name comes from DeviceProps,
not from the pair code stanza.

### Relevant protocol enums

ClientPayload.UserAgent.Platform (connection identity):
  MACOS = 24 (what we use — web-compatible)
  SMB_ANDROID = 10 (breaks pair code — DO NOT USE)
  WEB = 15 (causes 405 errors)

DeviceProps.PlatformType (linked device display name):
  CHROME = 1, FIREFOX = 2, SAFARI = 5, EDGE = 6
  DESKTOP = 7, CATALINA = 12, ANDROID_PHONE = 16, UWP = 21

## Changes

- Types/index.ts: add `android(apiLevel)` to BrowsersMap type
- browser-utils.ts: add `Browsers.android()` preset,
  `isAndroidBrowser()` helper, fix `getPlatformId()` to resolve
  ANDROID -> ANDROID_PHONE (16) since the enum only has
  ANDROID_PHONE, not ANDROID
- validate-connection.ts: use MACOS platform in UserAgent (fixes 405
  and pair code), map ANDROID -> ANDROID_PHONE in getPlatformType()
- socket.ts: auto-detect Android browser in pair code and fall back
  to Chrome (1) as companion_platform_id. Non-Android browsers are
  unaffected and continue using their native platform ID.

## How it works

With `Browsers.android('14')`:
- `getUserAgent()` -> platform: MACOS, device: Desktop (web identity)
- `getClientPayload()` -> includes webInfo as normal
- `getPlatformType('Android')` -> ANDROID_PHONE (in DeviceProps)
- Pair code -> companion_platform_id: '1' (Chrome fallback)
- QR code -> no override needed, works directly
- Result: device appears as "Android (14)" in Linked Devices
2026-03-02 22:28:01 -03:00
ShellTear ad5ea817f7 Merge pull request #2360 from WhiskeySockets/update-version/stable 2026-02-25 01:33:33 +09:00
github-actions[bot] 3841abca35 chore: update WhatsApp Web version 2026-02-22 00:43:34 +00:00
João Lucas 7a5b090616 fix: request placeholder resend for messages without encryption (CTWAads) (#2334)
* fix: request placeholder resend for messages without encryption (CTWA ads)

* fix: implement placeholder resend cache management and metadata preservation
2026-02-11 11:56:23 +02:00
vini 23156c833e feat(call): add caller phone number to offer call event (#2190) 2026-02-11 02:11:16 +02:00
github-actions[bot] a9ba11976e chore: update WhatsApp Web version (#2330)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-09 15:46:10 +02:00
João Lucas b02390123a fix: detect identity key changes and reset sessions (align with WA Web) (#2307)
* feat(signal): add RetryReason enum and MAC error-based session recreation

* feat(signal): add identity change detection with automatic session clearing

* fix(signal): integrate identity change detection with pkmsg decryption

This completes the identity change detection implementation by actually
calling saveIdentity() during pkmsg decryption, which is CRITICAL for
the feature to work.

Changes:
- Add extractIdentityFromPkmsg() function that parses PreKeyWhisperMessage
  protobuf to extract sender's identity key (33 bytes)
- Call saveIdentity() BEFORE decryption in decryptMessage() for pkmsg type
- Log when identity change is detected

Flow:
1. Receive pkmsg from sender
2. Extract identity key from PreKeyWhisperMessage protobuf
3. Call storage.saveIdentity() which compares with stored key
4. If key changed → session is cleared atomically
5. Decryption proceeds with re-established session

This matches WhatsApp Web's behavior where extractIdentityKey is called
before handleNewSession (GysEGRAXCvh.js:40917, 48815).

Ref: WhatsApp Web's extractIdentityKey (GysEGRAXCvh.js:48976-48998)
2026-02-05 21:31:26 +02:00
João Lucas b5c174111f feat: replace async crypto with sync Rust WASM for app state sync (#2315)
* feat: replace async crypto with sync Rust WASM for app state sync

* fix: remove unecessary buffer copying

* fix: update whatsapp-rust-bridge to version 0.5.2 and refactor async calls to sync. HKDF and MD5 in rust
2026-02-05 16:06:47 +02:00
João Lucas fa2a837a4a perf: reduce DB calls during sync with caching and batching (#2316)
* perf: reduce DB calls during sync with caching and batching

* refactor: clean up comments and improve LID-PN mapping storage during history sync
2026-02-05 16:06:15 +02:00
Ahmed Alwahib ffc019fb51 fix: align noise-handler buffer types for Baileys build (#2284)
* fix: align noise-handler buffer types for Baileys build

* Align noise handler buffer types

* Clarify noise handler buffer typing
2026-01-25 01:52:36 +02:00
Matheus Filype d514764686 feat: send unified session (#2294)
* fix: improve message resend logic by adding checks for message IDs

* Revert "fix: improve message resend logic by adding checks for message IDs"

This reverts commit c03f9d8e6fc6cbfbb9d1f8f67c169700e704213d.

* feat: add unified session handling and time constants

* refactor: improve socket variable destructuring and presence update logic

* fix: remove unnecessary semicolons in socket and time constants definitions

* fix: handle invalid server time offset parsing in makeSocket function
2026-01-25 01:51:47 +02:00
João Lucas de Oliveira Lopes f829b6d7a8 fix: extract LID-PN mappings from conversation objects in history sync (#2282)
* fix: extract LID-PN mappings from conversation objects in history sync

* fix: extract PN from userReceipt when pnJid is missing for LID chats
2026-01-22 15:00:41 +02:00
Gustavo Quadri 52fcad2b9c fix: optimize getLIDsForPNs and add getPNsForLIDs (#2274)
* fix: optimize lid-mapping and add getpnsforlids

* fix: lint

* fix: reintroduce store and fix partial returns

* fix: lint
2026-01-22 14:58:02 +02:00
João Lucas de Oliveira Lopes 92d4198ff1 fix: skip retry for expired status messages over 24 hours old (#2280) 2026-01-22 14:55:29 +02:00
João Lucas de Oliveira Lopes 5cbad3170b Fix connection showing "Online" but disconnected (#2132) (#2264)
* fix(messages): handle identity change notifications correctly (#2132)

* fix: tests and linting, add a helper like waweb
2026-01-22 14:54:10 +02:00
Rajeh Taher 1ef04d5329 socket: no sync warning!!!!! 2026-01-22 14:43:19 +02:00
Rajeh Taher bfde86bce7 example: cleanup 2026-01-22 14:42:56 +02:00
Rajeh Taher 0826895c6b history: add proper logging support in history 2026-01-22 14:34:46 +02:00
Rajeh Taher d4e5b4167d history: fortify contact data 2026-01-22 14:13:33 +02:00
Rajeh Taher c81c074dbd defaults, index: change shouldSyncHistoryMessage behavior 2026-01-22 14:13:00 +02:00
Rajeh Taher 506017b0c4 example: revamp logging for example 2026-01-22 14:12:25 +02:00
Rajeh Taher 75b0ba2652 chat-utils,sync-action-utils: provide alternatives for the contact name 2026-01-22 10:36:36 +02:00
Rajeh Taher b6b708ddfe chore(tests): lint 2026-01-20 12:47:05 +02:00
Enzo Nascimento a1d69f72c9 fix(utils.normalizeMessageContent): add associatedChildMessage as one of the options to normalize (#1874)
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2026-01-20 12:46:03 +02:00
Rajeh Taher 90e8ba82f4 Cache the children after a getBinaryNodeChild/ren call to avoid traversing arrays (#2093)
* generic-utils: cache the get

* generic-utils: increased type safety

* chore: lint
2026-01-20 12:43:27 +02:00
David ??? d36d9c194c Add groupStatusMessage checks in message handling (#2258) 2026-01-20 12:41:33 +02:00
João Lucas de Oliveira Lopes 8ff01b8bb3 fix: store LID-PN mapping from contactAction sync (#2266)
* fix: store LID-PN mapping from contactAction sync

* chore: improve testing of sync actions
2026-01-20 12:39:41 +02:00
João Lucas de Oliveira Lopes a89736f89d fix: extract LID-PN mappings from history sync phoneNumberToLidMappings (#2268) 2026-01-20 12:39:29 +02:00
Luiz Braga 32134a870e chore: Add messageTimestamp to message updates in messages-recv when receiving a message status update (#2277) 2026-01-20 12:37:34 +02:00
João Lucas de Oliveira Lopes 5887551d68 fix: resolve race condition in decodeFrame handling and improve encryption integrity (#2182)
* fix: resolve race condition in decodeFrame handling and improve encryption integrity

* chore: pr feedback
2026-01-20 12:37:04 +02:00
github-actions[bot] 4bdcedf96b chore: update WhatsApp Web version (#2269)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-20 12:35:35 +02:00
Rajeh Taher 5b5ac85443 example: revamp example and add options for unit tests 2026-01-18 17:53:09 +02:00
Rajeh Taher c4c22c9628 example: customizable socket URL 2026-01-18 17:26:17 +02:00
Rajeh Taher de6432cf5a example: improve ping-pong 2026-01-18 17:17:50 +02:00
Rajeh Taher b62cb40a70 chore: lint 2026-01-18 17:16:28 +02:00
Rajeh Taher 282f065f53 connection-deadlock, socket: improve socket end conditions 2026-01-18 17:16:28 +02:00
Vrypt db86cdc545 fix(proto-extract): regenerate corrupted yarn.lock to restore install process (#1981)
* fix(proto-extract): regenerate corrupted yarn.lock to restore install process

* chore(proto-extract): update acorn parser to latest version for compatibility with new WhatsApp JS syntax

* Update baileys version to 2.3000.1029027441

* Update version number in Defaults index

* Revert WAProto.proto to resolve merge conflict and restore expected structure

---------

Co-authored-by: Vrypt <vryptt@gmail.com>
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2026-01-18 01:45:23 +02:00
YonkoSam a2677c89dd Fix critical memory leak in event buffer (#2160) 2026-01-18 01:44:28 +02:00
Rajeh Taher 56ee829757 process-message: remove timeout before event emit 2026-01-18 01:35:50 +02:00
Rajeh Taher e740fc5b4a messages-send: revamp message type function 2026-01-18 01:35:50 +02:00
Rajeh Taher 2ec9d9ff1d gitignore: fix ignoring logs coming from example file 2026-01-18 01:34:55 +02:00
Rajeh Taher 83e0f22af8 messages-recv: decrease PDO response timeout 2026-01-18 01:34:39 +02:00
Rajeh Taher b1c76ebe2d chore: lint+bugfix 2026-01-18 01:31:56 +02:00
João Lucas de Oliveira Lopes e53fa7b8e5 Feat improve testing coverage e2e (#1799)
* fix: ensure proper socket closure and await connection termination in tests

* feat(tests): enhance E2E tests for image and video message handling, including downloads and group interactions
2026-01-18 01:16:24 +02:00
vini 0b3b2a88cd fix(messages): enhance nullish value checks in message content generation (#2180) 2026-01-18 01:11:33 +02:00
YonkoSam 1408499d7c moved retryCount before validating the session (#2167) 2026-01-18 01:11:10 +02:00
Matheus Filype 349e7bd771 feat: send tctoken to profile update and presence subscribe (#2257)
* fix: improve message resend logic by adding checks for message IDs

* Revert "fix: improve message resend logic by adding checks for message IDs"

This reverts commit c03f9d8e6fc6cbfbb9d1f8f67c169700e704213d.

* feat(tc-token): implement buildTcTokenFromJid utility and integrate into chats socket

* fix(tc-token): ensure consistent return value when tcTokenBuffer is absent

* fix(chats): update import path for buildTcTokenFromJid utility
2026-01-18 01:07:53 +02:00
João Lucas de Oliveira Lopes d4ef73aca5 feat: implement automated WhatsApp version update workflow and related scripts (#2130)
* feat: implement automated WhatsApp version update workflow and related scripts

* change cron to weekly

---------

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2026-01-18 01:07:05 +02:00
João Lucas de Oliveira Lopes 9611a1a982 fix(WAProto): Handle string values in long fields during JSON serialization (#1991)
* feat: add patch-tojson functionality for improved proto serialization

* Remove patch-tojson functionality and its import from the main index file to streamline the codebase.

* refactor: simplify longToString and longToNumber functions for better readability and performance
2026-01-14 08:33:45 +02:00
vini 432c26a07c fix(messages): handle encryption failures per recipient and fail when all fail (#2226) 2026-01-08 22:07:11 +02:00