Commit Graph

2997 Commits

Author SHA1 Message Date
Renato Alcara 466c14ff82 chore: update WhatsApp Web version to v2.3000.1035718650 (#318)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-23 06:53:55 -03:00
Renato Alcara 03bc03b318 Merge branch 'master' of https://github.com/rsalcara/InfiniteAPI 2026-03-23 01:59:15 -03:00
Renato Alcara d83971d15e fix: remove duplicate isViewOnceMsg/viewOnceMeRecipients declarations
Merge duplicou o bloco — TS2451 Cannot redeclare block-scoped variable.
Mantida a versão correta (verifica viewOnceInner?.imageMessage?.viewOnce).

Co-Authored-By: Renato Alcara
2026-03-23 01:59:08 -03:00
github-actions[bot] 14f0321d7c chore: update proto/version to v2.3000.1035715252 (#317)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-23 01:56:01 -03:00
Renato Alcara b65a8a334b chore: resolve merge conflict in messages-send.ts (comment-only)
Conflict was between Portuguese and English comment for phash/DSM block.
Kept HEAD (our) version.

Co-Authored-By: Renato Alcara
2026-03-23 01:54:46 -03:00
Renato Alcara 28e9e5b912 feat: implement view-once message sending and receiving
- Add viewonce-image/video/audio to MEDIA_PATH_MAP and MEDIA_HKDF_KEY_MAPPING
- messages-send: use viewOnceMessageV2 wrapper, omit companion devices for DSM
  (server auto-generates <unavailable type="view_once"/> for linked devices)
- messages-send: fix mediatype detection by unwrapping viewOnce before getMediaType
- messages-recv: handle <unavailable type="view_once"/> sync from primary device
- messages-recv: note — do NOT send view_once_read from linked device

Co-Authored-By: Renato Alcara
2026-03-23 01:53:55 -03:00
Renato Alcara 962e7de0bf chore: mark upstream commits as reviewed (3841abca35 ad5ea817f7 d077902695 c4e5d1262a 802d5f6efa)
- 3841abca35 / ad5ea817f7: WA version updates — applied separately via our own version bumps
- d077902695: WA version update — same as above
- c4e5d1262a: Fix ack handling — high-risk 2718-line diff in messages-recv.ts, intentionally skipped
- 802d5f6efa: Fix mentions regression — already covered by existing rsalcara contextInfo logic
- 6afde71691: feat groups mentionAll — applied in previous commit
2026-03-23 01:53:00 -03:00
Renato Alcara c6cb29fd80 feat: groups mention all + fix view-once upload path and wrapper
- Add mentionAll?: boolean to Mentionable type (upstream 6afde71691)
- Set contextInfo.nonJidMentions=1 for @everyone group mentions
- Use viewOnceMessageV2 (field 55) wrapper instead of legacy viewOnceMessage (field 37)
- Set viewOnce=true on inner imageMessage/videoMessage/audioMessage
- Route view-once media uploads to /o1/mms/* CDN via mediaTypeOverride

Co-Authored-By: Renato Alcará
2026-03-23 01:52:43 -03:00
Renato Alcara a283d858c6 docs: rewrite INTERACTIVE_MESSAGES.md — complete API guide
Full rewrite covering all 8 interactive message types:
1. Menu Texto
2. Botões Quick Reply (tested up to 16 buttons)
3. Botões CTA — URL, Copy, Call
4. Lista Dropdown (10 sections × 3 rows = 30 items max)
5. Enquete/Poll
6. Apenas Botões Reply sem CTA
7. Apenas CTAs sem Quick Reply
8. Carrossel com Imagens (up to 10 cards)

Each type includes:
- Complete curl example with realistic data
- All parameters documented with types and limits
- Webhook payload structure received on click/select
- JavaScript helpers to parse each response type

Also includes:
- Platform compatibility table (Android / iOS / WA Web)
- Universal webhook router for all interactive response types
- Complete limits table per message type
- Account restrictions (hosted vs non-hosted)

Co-Authored-By: Renato Alará
2026-03-23 01:27:45 -03:00
Renato Alcara 9c626801b0 docs: add hosted account restriction warning to VIEW_ONCE.md
Accounts registered as hosted (Meta Business Cloud API) have view-once
blocked by the WA server for all clients (Android, iOS, Web).
This is a server-side policy with no code workaround.

Added prominent warning block in section 1 and dedicated row in the
limitations table.

Co-Authored-By: Renato Alcará
2026-03-23 01:17:27 -03:00
Renato Alcara 4ca1878705 docs: add VIEW_ONCE.md — view-once implementation guide
Complete guide for the view-once (visualização única) feature:
- Send examples (curl) for image, video and audio
- Webhook payload structure with key.isViewOnce detection
- JavaScript helpers to identify and access view-once media
- Frontend/CRM rendering guide with placeholder after open
- Implemented code with inline explanations
- Full send/receive flow diagram
- Known limitations and validation checklist

Co-Authored-By: Renato Alcara
2026-03-23 01:12:36 -03:00
Renato Alcara 452df5d409 Feat/view once receive (#316)
* fix: detect view-once media (image/video/audio) on stanza 1 for linked devices
2026-03-23 00:38:05 -03:00
Renato Alcara e633d62a3b chore: update WhatsApp Web version to v2.3000.1035697879 (#315)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-22 06:22:56 -03:00
github-actions[bot] 2a321b881e chore: update proto/version to v2.3000.1035693752 (#314)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-22 01:46:05 -03:00
Rajeh Taher 802d5f6efa messages: Fix regression where missing contextInfo caused no mentions 2026-03-22 02:43:03 +02:00
Renato Alcara e0038bde36 chore: update WhatsApp Web version to v2.3000.1035675348 (#313)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-21 06:22:45 -03:00
github-actions[bot] 1cbf1b18b7 chore: update proto/version to v2.3000.1035661795 (#312)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-21 01:22:14 -03:00
Renato Alcara c3a021fcde fix: use newsletter-specific upload paths for channel media (#311)
fix: use newsletter-specific upload paths for channel media (#311)
2026-03-20 12:02:36 -03:00
Renato Alcara e6ea7e4563 Feat/view once receive (#310)
* fix: unwrap viewOnceMessage in getMediaType so enc node gets mediatype 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.
2026-03-20 10:49:25 -03:00
Renato Alcara 3ab578aadf fix: detect view-once media (image/video/audio) (#309)
* fix: detect view-once media (image/video/audio) on stanza 1 for linked 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
2026-03-20 10:11:49 -03:00
Renato Alcara d2db4cec97 chore: update WhatsApp Web version to v2.3000.1035595667 (#308)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-20 06:31:30 -03:00
github-actions[bot] be44c5fdb0 chore: update proto/version to v2.3000.1035577069 (#307)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-20 01:30:09 -03:00
Renato Alcara f63f0a766f fix: align Bad MAC retry receipt with WA Desktop behavior
fix: align Bad MAC retry receipt with WA Desktop behavior
2026-03-19 23:48:44 -03:00
Renato Alcara fbefa6a0ad fix: replace magic numbers with RetryReason enum constants
Address remaining Copilot review comments on PR #306:

- Import RetryReason enum from Utils (already re-exported via Utils/index.ts)
- Replace all numeric literals (0/1/2/3/4/7) in retryErrorCode with the
  corresponding enum members (UnknownError / SignalErrorNoSession / etc.)
- Removes inline comments that were only needed to explain magic numbers
- If RetryReason values ever change, the compiler will surface the drift

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 23:44:34 -03:00
Renato Alcara 9c4cdc3e02 fix: use DECRYPTION_RETRY_CONFIG constants for retry error code derivation
Address Copilot review comments on PR #306:

1. Replace ad-hoc regexes with the canonical DECRYPTION_RETRY_CONFIG error
   lists from decode-wa-message.ts (single source of truth). Any future
   additions to those lists are automatically picked up here.

2. Add coverage for MessageCounterError ('Key used already or never filled')
   which was previously returning code 0. It now correctly maps to code 4
   (SignalErrorInvalidMessage) via corruptedSessionErrors.

3. Broaden session-error matching to also catch libsignal variants like
   'No sessions', 'No open session', 'No sessions available' via the
   /no (open )?sessions?/ regex alongside sessionRecordErrors.

4. Fix comment: clarify that code 7 = BadMac and code 4 = InvalidMessage
   are distinct codes (previous comment conflated them).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 23:29:46 -03:00
Renato Alcara ba1c1b0fdb fix: align Bad MAC retry receipt with WA Desktop behavior
Three issues corrected in sendRetryRequest (receiver side):

1. BUG — error code hardcoded as '0' (UnknownError) in retry receipt.
   The peer (especially another InfiniteAPI instance) could not detect
   the failure type and would fall back to the 1-hour session recreation
   timeout instead of recreating immediately.
   Fix: derive error code from the actual libsignal decryption error
   message stored in messageStubParameters[0].

2. BUG — shouldRecreateSession block was reading the wrong node: it
   called getBinaryNodeChild(node, 'retry') on the incoming bad-MAC
   message, which never has a <retry> child. errorCode was always
   undefined, so MAC_ERROR_CODES never matched — the logic was dead.

3. BUG (consequence of #2) — when shouldRecreateSession accidentally
   did fire (no-session or 1-hour timeout), it deleted the receiver's
   session BEFORE the sender's pkmsg arrived. This opened a race window
   where concurrent messages would fail with "No Session".
   Fix: remove the entire session-deletion block from sendRetryRequest.
   The Signal Protocol pkmsg automatically overwrites the corrupted
   session — no explicit delete needed on the receiver side.

WA Desktop reference (CDP capture 2026-03-19):
- Retry receipt sent ~99ms after Bad MAC with specific error code
- pkmsg arrives ~304ms later, new session established automatically
- Old session is never deleted; pkmsg overwrites it implicitly
- Full recovery in ~1.3s without any race window

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 23:10:59 -03:00
Renato Alcara 876af2e96c fix: HistorySync LID improvements — raw_id mapping, prekey pool strategy, keepalive jitter, CDN cleanup
fix: HistorySync LID improvements — raw_id mapping, prekey pool strategy, keepalive jitter, CDN cleanup
2026-03-19 18:24:20 -03:00
Renato Alcara 5bb18da6bf fix: address PR #305 review comments — Origin header, lowServerCount threshold, keepalive guard
- history.ts: add Origin: DEFAULT_ORIGIN to CDN DELETE request headers —
  the download path injects it internally but options does not carry it
- socket.ts: fix lowServerCount comparison — was preKeyCount <= topUpAmount
  which triggered uploads even when above MIN_PREKEY_COUNT (e.g. 250 prekeys
  → topUp=550 → 250<=550=true → unnecessary upload). Now uses correct
  threshold: preKeyCount < MIN_PREKEY_COUNT
- socket.ts: guard scheduleNextKeepAlive() with !closed check to prevent
  orphan timers when end() was called concurrently on a different path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:23:41 -03:00
Renato Alcara 52d8ddae32 fix: prevent double prekey upload when concurrent uploads race on count=0
uploadPreKeys() waited for a concurrent upload but then proceeded to upload
again. With top-up logic and count=0, both handleEncryptNotification and
uploadPreKeysToServerIfRequired fire simultaneously, both see count=0, first
wins and uploads 800, second waits then uploads another 800 → 1600 prekeys.

Fix: return immediately after awaiting the concurrent upload — it already
replenished the pool.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:23:41 -03:00
Renato Alcara 8c8c5a312e fix: address PR review comments — CDN DELETE timing, keepalive leak, spread order
- history.ts: move CDN DELETE from downloadHistory() to
  downloadAndProcessHistorySyncNotification(), after processHistoryMessage()
  succeeds — prevents permanent history loss if processing throws post-download
- history.ts: fix fetch spread order: { ...options, method: 'DELETE' } so
  options.method cannot shadow the intended DELETE verb
- socket.ts: add early return after void end() in onKeepAliveTick to prevent
  scheduleNextKeepAlive() from leaking a timer while connection is closing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:23:28 -03:00
Renato Alcara 52756fb50d fix: histsync LID improvements — raw_id mapping, prekeys, keepalive jitter, CDN DELETE
1. USyncQuery: extract raw_id attr from node attrs into rawId field; implement
   side_list parsing (was TODO/commented) reusing shared parseNodeList helper

2. getUSyncDevices: add 4th LID→PN source via raw_id pairing from device-list
   WA Business sends zero phoneNumberToLidMappings in HistorySync — raw_id is
   the only way to resolve LID↔PN for those accounts during message send

3. MIN_PREKEY_COUNT: 5 → 25 (WA Business maintains ~812; 5 was too low a buffer
   before triggering replenishment upload)

4. startKeepAliveRequest: replace fixed setInterval with recursive setTimeout
   + ±15% jitter, matching WA Desktop's ~25-30s variable heartbeat pattern;
   clearInterval → clearTimeout for the handle

5. downloadHistory: fire-and-forget DELETE to CDN after successful download,
   mirroring WA Desktop behaviour (server-side one-time file cleanup)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:23:27 -03:00
Renato Alcara bd8465d9b8 fix: histsync LID improvements — raw_id mapping, prekeys, keepalive j… (#304)
* fix: histsync LID improvements — raw_id mapping, prekeys, keepalive jitter, CDN DELETE

* fix: prekey pool strategy — 800 initial, top-up to 800 when below 200

- INITIAL_PREKEY_COUNT: 812 → 800 (rounded, matches WA Business ~812 from CDP capture)
- MIN_PREKEY_COUNT: 25 → 200 (replenishment trigger threshold)
- uploadPreKeysToServerIfRequired: top-up to INITIAL_PREKEY_COUNT instead of
  uploading a flat MIN_PREKEY_COUNT — restores full 800-key pool on each replenish
- handleEncryptNotification: same top-up logic (INITIAL_PREKEY_COUNT - count)
  so server notification path also restores to 800, not just adds 200

uploadPreKeys(5) in error recovery path intentionally left unchanged.
2026-03-19 17:58:30 -03:00
Renato Alcara 6c52b01ea7 fix: add pastParticipants to HistorySync with LID normalization and deduplication (#303)
Two bugs fixed compared to prior implementation:

1. history.ts — normalize userJid LID→PN
   pastParticipants[].userJid may arrive as a LID identifier (e.g. "46802258641027@lid").
   The consumer expects a phone number. After building the lidPnMap from conversations
   and phoneNumberToLidMappings, each userJid is resolved to its PN equivalent.
   If the mapping is not available the original value is preserved (no data loss).

2. event-buffer.ts — deduplicate by groupJid + userJid across chunks
   Multiple HistorySync chunks can contain the same group. The previous approach
   concatenated blindly, producing duplicate entries. Now a keyed map
   { [groupJid]: IPastParticipant[] } is used so each group appears once and
   each participant within a group appears at most once.

Types updated (Events.ts):
   - messaging-history.set event includes pastParticipants?: IPastParticipants[]
   - BufferedEventData.historySets.pastParticipants typed as keyed map
2026-03-19 16:44:14 -03:00
Renato Alcara 5926da9493 Merge branch 'master' of https://github.com/rsalcara/InfiniteAPI 2026-03-19 12:22:07 -03:00
Renato Alcara a9e926b907 fix: correct w:mex QueryIds and response fields for newsletter operations (#302)
Reverse-engineered from WA Web JS bundle and live CDP interception.
All QueryIds and XWAPaths were wrong; mute/unmute also had wrong variables structure.

- FOLLOW QueryId: 7871414976211147 → 24404358912487870
- UNFOLLOW QueryId: 7238632346214362 → 9767147403369991
- MUTE QueryId: 29766401636284406 → 31938993655691868
- UNMUTE QueryId: 9864994326891137 → 31938993655691868 (same mutation as MUTE)
- xwa2_newsletter_follow: 'xwa2_newsletter_follow' → 'xwa2_newsletter_join_v2'
- xwa2_newsletter_unfollow: 'xwa2_newsletter_unfollow' → 'xwa2_newsletter_leave_v2'
- xwa2_newsletter_mute_v2: 'xwa2_newsletter_mute_v2' → 'xwa2_newsletter_update_user_setting'
- xwa2_newsletter_unmute_v2: 'xwa2_newsletter_unmute_v2' → 'xwa2_newsletter_update_user_setting'
- newsletterMute/Unmute variables: flat {newsletter_id} → {input: {newsletter_id, type, value}}

Fixes #2346
2026-03-19 11:49:42 -03:00
Renato Alcara 2b2c3f9155 Merge branch 'master' of https://github.com/rsalcara/InfiniteAPI 2026-03-19 11:24:01 -03:00
Renato Alcara 71fe69fd21 chore: update WhatsApp Web version to v2.3000.1035504971 (#301)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-19 06:33:42 -03:00
github-actions[bot] eecf6df2a2 chore: update proto/version to v2.3000.1035484955 (#300)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-19 01:48:35 -03:00
Renato Alcara d04a3e1af8 fix: restore working carousel send/render path (#297)
fix: restore working carousel send/render path (#297)
2026-03-18 20:30:18 -03:00
Renato Alcara 21462c26d5 chore: update WhatsApp Web version to v2.3000.1035406580 (#299)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-18 06:42:44 -03:00
github-actions[bot] fc2122b11a chore: update proto/version to v2.3000.1035370989 (#298)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-18 01:49:58 -03:00
Renato Alcara 11eed3aedc chore: update WhatsApp Web version to v2.3000.1035317910 (#296)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-17 06:16:35 -03:00
github-actions[bot] dbc6dd6aed chore: update proto/version to v2.3000.1035302375 (#295)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-17 00:46:29 -03:00
Renato Alcara e152aee740 Fix/pn lid session reuse (#294)
* fix: unify PN and LID session reuse for 1:1 sends

* fix: limit PN/LID reuse changes to session cache
2026-03-16 23:22:05 -03:00
Renato Alcara ff9b84c561 fix: unify PN and LID session reuse for 1:1 sends (#293)
fix: unify PN and LID session reuse for 1:1 sends (#293)
2026-03-16 22:59:28 -03:00
Renato Alcara 50c13398c4 fix: harden carousel live rendering path (#292)
* fix: harden carousel live rendering path

* fix: flatten carousel thumbnail fallback
2026-03-16 22:09:14 -03:00
Renato Alcara d991d0212d fix: add biz node injection and quality_control for carousel WhatsApp Web rendering (#291)
- Add interactive message detection helpers (getButtonType, isCarouselMessage, etc.)
- Inject biz node with interactive/native_flow for non-carousel interactive messages
- Inject biz + quality_control with decision_id for carousel messages
- Skip bot node for native_flow/carousel/catalog (breaks Web rendering)
- Force device-identity inclusion for carousel messages
- Append deferred biz/bot/quality_control nodes after device-identity and tctoken
- Store tctoken under both LID and PN for reliable lookup
2026-03-16 21:25:29 -03:00
Renato Alcara 7c095c84a5 chore: update WhatsApp Web version to v2.3000.1035223526 (#289)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-16 06:20:34 -03:00
github-actions[bot] a25e6740fd chore: update proto/version to v2.3000.1035216863 (#288)
Co-authored-by: rsalcara <rsalcara@users.noreply.github.com>
2026-03-16 00:58:19 -03:00
github-actions[bot] d077902695 chore: update WhatsApp Web version (#2420)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-15 22:49:39 +02:00