feat(telegram): add reaction indicator for message processing#433
feat(telegram): add reaction indicator for message processing#433
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughPropagates Changes
Sequence DiagramsequenceDiagram
actor User as User/Telegram
participant TG as Telegram API
participant Ch as TelegramChannel
participant Agent as Agent Loop
User->>TG: Send message
TG->>Ch: Deliver inbound message (includes telegram_message_id)
Ch->>Ch: Optionally set 👀 reaction (if enabled)
Ch->>Agent: Publish InboundMessage (with telegram_message_id metadata)
Agent->>Agent: Process and propagate telegram_message_id into OutboundMessage
Agent->>Ch: Send outbound response
Ch->>TG: Post reply (use ReplyParameters: reply_to or telegram_message_id)
Ch->>TG: Optionally set ✅ reaction on original message
TG->>User: Deliver threaded reply and reactions
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/agent/loop.rs`:
- Around line 240-244: The outbound metadata propagation currently copies only
"telegram_thread_id" in the direct tool publish paths, so ensure you also copy
"telegram_message_id" from inbound to outbound there; specifically, locate the
places that insert "telegram_thread_id" into outbound.metadata (the same scope
where inbound.metadata.get("telegram_thread_id") is read) and add the same
pattern used at the final/error/timeout path—check
inbound.metadata.get("telegram_message_id") and, if Some(mid), call
outbound.metadata.insert("telegram_message_id".to_string(), mid.clone()) so that
for_user tool messages preserve the Telegram message id for reply-thread
fallback and reaction updates.
In `@src/channels/telegram.rs`:
- Around line 1222-1232: The code sets the completion reaction (✅) immediately
after reading telegram_message_id, which can mark a message as processed even if
the outbound reply fails; move the bot.set_message_reaction call to run only
after the outgoing send succeeds—i.e., after the successful await of the send
function (the call around send_message at lines near where send_message is
awaited), so wrap or relocate the logic that checks
msg.metadata.get("telegram_message_id") and calls
bot.set_message_reaction(ChatId(chat_id), MessageId(mid)).reaction(...) to
execute only when the send_message future returns Ok; keep the same parsing of
mid_str.parse::<i32>() and error handling but perform it post-send to ensure the
✅ reaction is only applied on successful send.
- Around line 781-790: The reaction is being set unconditionally with
bot.set_message_reaction(...) (the 👀 emoji) before the early-return branches
(/model and /persona short-circuits and the if let Some(text) gate), which
leaves many inbound messages stuck at 👀; move the reaction setup so it only
runs when the message will reach the completion path (i.e., after the /model and
/persona short-circuits and after the if let Some(text) branch), or refactor by
calling the same completion helper used by the inline bot.send_message(...)
paths (the paths that currently add ✅ in send()) so both inline and async
completion flows reuse the same reaction logic instead of setting 👀
unconditionally.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2173bad7-79c2-4a9c-bb56-431a48069768
📒 Files selected for processing (2)
src/agent/loop.rssrc/channels/telegram.rs
| // React with 👀 to acknowledge receipt before processing. | ||
| { | ||
| use teloxide::types::ReactionType; | ||
| let _ = bot | ||
| .set_message_reaction(msg.chat.id, msg.id) | ||
| .reaction(vec![ReactionType::Emoji { | ||
| emoji: "\u{1F440}".to_string(), | ||
| }]) | ||
| .await; | ||
| } |
There was a problem hiding this comment.
Only add 👀 on paths that will hit the completion hook.
✅ is only set in send(), but this block runs before the /model and /persona short-circuits and before the if let Some(text) gate. Messages handled inline at Lines 853-930, 934-1014, and 1084-1089 — plus unsupported updates that never enter Lines 800-803 — will leave the inbound message stuck at 👀.
Either move the reaction setup below the early-return branches or reuse the same completion helper from those inline bot.send_message(...) paths.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/channels/telegram.rs` around lines 781 - 790, The reaction is being set
unconditionally with bot.set_message_reaction(...) (the 👀 emoji) before the
early-return branches (/model and /persona short-circuits and the if let
Some(text) gate), which leaves many inbound messages stuck at 👀; move the
reaction setup so it only runs when the message will reach the completion path
(i.e., after the /model and /persona short-circuits and after the if let
Some(text) branch), or refactor by calling the same completion helper used by
the inline bot.send_message(...) paths (the paths that currently add ✅ in
send()) so both inline and async completion flows reuse the same reaction logic
instead of setting 👀 unconditionally.
| // Clear the processing reaction (👀) set when the message was received. | ||
| if let Some(mid_str) = msg.metadata.get("telegram_message_id") { | ||
| if let Ok(mid) = mid_str.parse::<i32>() { | ||
| let _ = bot | ||
| .set_message_reaction(ChatId(chat_id), MessageId(mid)) | ||
| .reaction(vec![ReactionType::Emoji { | ||
| emoji: "\u{2705}".to_string(), | ||
| }]) | ||
| .await; | ||
| } | ||
| } |
There was a problem hiding this comment.
Set ✅ only after Telegram accepts the outbound message.
This marks the inbound message as complete before Line 1262 actually sends anything. If send_message fails (for example, bad HTML or a transport error), users will still see ✅ even though no reply was delivered.
🔧 Move the completion reaction after a successful send
- // Clear the processing reaction (👀) set when the message was received.
- if let Some(mid_str) = msg.metadata.get("telegram_message_id") {
- if let Ok(mid) = mid_str.parse::<i32>() {
- let _ = bot
- .set_message_reaction(ChatId(chat_id), MessageId(mid))
- .reaction(vec![ReactionType::Emoji {
- emoji: "\u{2705}".to_string(),
- }])
- .await;
- }
- }
-
let rendered = render_telegram_html(&msg.content);
let mut req = bot
.send_message(ChatId(chat_id), rendered)
.parse_mode(ParseMode::Html);
@@
req.await
.map_err(|e| ZeptoError::Channel(format!("Failed to send Telegram message: {}", e)))?;
+
+ if let Some(mid_str) = msg.metadata.get("telegram_message_id") {
+ if let Ok(mid) = mid_str.parse::<i32>() {
+ let _ = bot
+ .set_message_reaction(ChatId(chat_id), MessageId(mid))
+ .reaction(vec![ReactionType::Emoji {
+ emoji: "\u{2705}".to_string(),
+ }])
+ .await;
+ }
+ }Also applies to: 1262-1263
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/channels/telegram.rs` around lines 1222 - 1232, The code sets the
completion reaction (✅) immediately after reading telegram_message_id, which can
mark a message as processed even if the outbound reply fails; move the
bot.set_message_reaction call to run only after the outgoing send succeeds—i.e.,
after the successful await of the send function (the call around send_message at
lines near where send_message is awaited), so wrap or relocate the logic that
checks msg.metadata.get("telegram_message_id") and calls
bot.set_message_reaction(ChatId(chat_id), MessageId(mid)).reaction(...) to
execute only when the send_message future returns Ok; keep the same parsing of
mid_str.parse::<i32>() and error handling but perform it post-send to ensure the
✅ reaction is only applied on successful send.
|
Thanks for this! #432 has been merged, so this needs a rebase. A few things to address before merge:
|
React with eyes emoji when a message is received to give instant visual feedback, then replace with a checkmark when the response is sent. Reactions are best-effort — errors are silently ignored since the bot may lack reaction permissions in some groups. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add `telegram.reactions` config flag (default: true) for opt-out - Move 👀 after /model and /persona early returns so commands don't get stuck with eyes reaction - Move ✅ after successful send_message so failed sends aren't marked as complete - Restore removed log line before bot initialization - Add debug logging on reaction failures instead of silent ignore - Propagate telegram_message_id in tool for_user outbound paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3692f96 to
430bdd8
Compare
|
All four items addressed:
CI is green (build, clippy, fmt, tests all pass). Ready for re-review. |
|
Merged! Great turnaround @stuartbowness — all four review items addressed cleanly. The config gate and debug logging are exactly right. Nice work! |
Summary
Depends on #432. Replaces #430 (rebased to resolve conflicts from merged history).
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores