Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/contacts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ The implementation automatically:
- Includes tokens in profile picture requests
- Skips tokens for groups and newsletters

`get_user_info` does the same for status/about: when the `profile_scraping_privacy_token_in_about_usync` AB prop is on, each queried JID's TC token is attached to its `<user>` node in the usync IQ, matching WhatsApp Web's `USyncStatusProtocol`. This is what lets `status`/`status_error` and `about` resolve correctly for a privacy-restricted contact instead of coming back hidden. See [TC Token](/api/tctoken#automatic-usage) for details.

## Async compatibility

`is_on_whatsapp` and `get_user_info` work correctly when called from `#[async_trait]` implementations or any context that boxes the returned future (`Box<dyn Future + Send>`). Earlier versions produced a compile error (`"implementation of FnOnce is not general enough"`) that could not be worked around in user code. Fixed in [#826](https://github.com/oxidezap/whatsapp-rust/pull/826) with no API changes.
Expand Down
4 changes: 4 additions & 0 deletions api/spam-report.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ if let Some(report_id) = result.report_id {
}
```

<Note>
When `from_jid` is set, `send_spam_report` automatically looks up and attaches that contact's TC token to the IQ, gated behind the `enable_spam_report_iq_with_privacy_token` AB prop. This matches WhatsApp Web's `OutSpamTCTokenMixin` and lets the report be accepted for privacy-restricted accounts. No caller action is needed — see [TC Token](/api/tctoken#automatic-usage).
</Note>

### Group spam report

```rust
Expand Down
15 changes: 15 additions & 0 deletions api/tctoken.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,19 @@ client.send_message(jid, message).await?;
let picture = client.contacts().get_profile_picture(&jid, true).await?;
```

The tctoken (no cstoken fallback) is also attached automatically on two other privacy-gated IQs, matching WA Web's `USyncStatusProtocol`/`OutSpamTCTokenMixin`:

- **`get_user_info`** — a per-recipient tctoken is attached to each queried `<user>` node in the usync IQ, so status/about for a privacy-restricted contact resolves instead of coming back hidden. Gated behind `profile_scraping_privacy_token_in_about_usync`.
- **`send_spam_report`** — when `SpamReportRequest::from_jid` is set, that contact's tctoken is attached to the spam report IQ so the report is accepted for a privacy-restricted account. Gated behind `enable_spam_report_iq_with_privacy_token`. Group reports that only set `group_jid`/`participant_jid` (no `from_jid`) don't get a token attached.

```rust
// Attaches the queried contact's tctoken automatically when the AB prop is on
let info = client.contacts().get_user_info(&[jid]).await?;

// Attaches the reported contact's tctoken automatically when the AB prop is on
let result = client.send_spam_report(request).await?;
```

### AB prop gating

Token inclusion on message stanzas is gated by two **independent** server-side AB props, matching WhatsApp Web's `MsgCreateFanoutStanza.js` (`Re = R(te) ?? D(te, s)`):
Expand All @@ -233,6 +246,8 @@ Token inclusion on message stanzas is gated by two **independent** server-side A

Token *issuance scheduling* (requesting new tokens from the server after sending) runs regardless of these flags.

The usync and spam-report attachment points each have their own independent gating prop (`profile_scraping_privacy_token_in_about_usync`, `enable_spam_report_iq_with_privacy_token`) — unrelated to the message-stanza props above, and with no cstoken fallback.

### Post-send issuance

After sending a 1:1 message, the library checks whether a new token should be issued for the recipient. If the sender-side bucket has rolled over since the last issuance, a background IQ request fires.
Expand Down