fix(retry): match WA Web's bot gate so bot DM retry receipts aren't dropped - #705
Conversation
…ropped send_retry_receipt suppressed the retry whenever the sender is a bot and we are not (!we_are_bot && sender_is_bot). For a bot DM that means a message we failed to decrypt is silently never recovered. WA Web aborts only on !to.isBot() && participant.isBot(), and participant is null for DMs, so it always sends the retry for a bot DM. Use the existing MessageSource::is_bot_authored_non_bot_chat() helper (!chat.is_bot() && sender.is_bot()), already used by the ack and self-fanout paths, which suppresses a bot reply in a non-bot group but not a bot DM.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbitRelease Notes
WalkthroughRefined retry receipt suppression logic to align with WhatsApp Web by replacing the previous ChangesBot-authored message filtering in retry receipts
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Benchmark Results67 unchanged benchmark(s)
|
Problem
send_retry_receiptsuppressed the retry receipt whenever!we_are_bot && sender_is_bot, i.e. any time the message sender is a bot and our own account is not. For a 1:1 chat with a bot (Meta AI, etc.), a message we failed to decrypt is then silently never recovered:send_retry_receiptreturnsOk(())early,run_retry_receipttreats it as sent, the transport ack clears the stanza from the server queue, and no<receipt type="retry">is ever emitted.WA Web's
sendRetryReceiptaborts on a different condition:!to.isBot() && participant.isBot(), wheretois the sender (getFrom) andparticipantisnullfor DMs (MsgSendReceiptpassesparticipant = type === CHAT ? null : ...). So for a bot DMparticipantis null, the abort never fires, and WA Web sends the retry. Ourwe_are_botterm has no counterpart in WA Web's condition at all.Fix
Replace the hand-rolled gate with the existing
MessageSource::is_bot_authored_non_bot_chat()helper, which already encodes WA Web's!chat.isBot() && author.isBot()and is already used on the success/ack path (message.rs) and the self-fanout decrypt-failure path:chat == sender == bot, so!chat.is_bot() && sender.is_bot()isfalse, the retry is sent (matches WA Web).chatis the group (non-bot),senderis the bot, so it is suppressed (matches WA Web).we_are_botterm and makes the retry path consistent with the ack and self-fanout paths, which already route through the same helper.Tests
New
is_bot_authored_non_bot_chat_matches_wa_weblocks the gate semantics: bot DM not suppressed, group bot reply suppressed, normal user DM not suppressed.Breaking
None. Internal gate change; the only behavior change is that bot DM retry receipts are now sent (and a local bot account no longer over-sends in groups).