-
Notifications
You must be signed in to change notification settings - Fork 0
docs: document 🦀send command (whatsapp-rust#875) #338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| title: "June 15, 2026 — Example bot: 🦀send command" | ||
| description: "Adds a 🦀send <jid> <text> command to the demo bot that relays text to any group or DM JID and reports send latency back to the caller." | ||
| --- | ||
|
|
||
| PR [#875](https://github.com/oxidezap/whatsapp-rust/pull/875) adds a `🦀send` command to the demo bot in `src/main.rs`. | ||
|
|
||
| ## What changed | ||
|
|
||
| The example bot now handles `🦀send <jid> <text>` in addition to `🦀ping`. Sending this command from any chat relays the given text to an arbitrary JID — a group (`...@g.us`) or DM (`...@s.whatsapp.net`) — then replies in the originating chat with the send latency via `ctx.reply_quoting`. | ||
|
|
||
| ``` | ||
| 🦀send 1234567890@s.whatsapp.net Hello there! | ||
| ``` | ||
|
|
||
| The reply in the originating chat looks like: | ||
|
|
||
| ``` | ||
| âś… Sent to 1234567890@s.whatsapp.net | ||
| `3.42ms` | ||
| ``` | ||
|
|
||
| ## Implementation notes | ||
|
|
||
| The handler uses `split_once(char::is_whitespace)` to split the JID and message text in a single pass with no intermediate `Vec`. The JID is validated through `FromStr` — invalid JIDs are logged and the handler returns early. All failures (missing args, bad JID, send error) are logged rather than panicking, matching the rest of the example bot. | ||
|
|
||
| The message handler was also refactored to hoist the `text_content()` guard into a single `let … else { return }` at the top, avoiding repeated calls and making it straightforward to add new text-triggered commands. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -268,7 +268,7 @@ cargo run -- -p 15551234567 --code MYCODE12 # Custom 8-char pair code | |
| cargo run -- -p 15551234567 -c MYCODE12 # Short form | ||
| ``` | ||
|
|
||
| The demo bot responds to `🦀ping` with a quoted `🏓 Pong!` reply, edits the reply to append the send latency, and supports media ping/pong via CDN reuse. | ||
| The demo bot responds to `🦀ping` with a quoted `🏓 Pong!` reply and supports media ping/pong via CDN reuse. It also handles `🦀send <jid> <text>`, which relays a plain-text message to any group or DM JID and reports the send latency back to the originating chat. | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| ## Using MessageContext | ||
|
|
||
|
|
@@ -349,14 +349,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { | |
|
|
||
| ## Complete example with logging | ||
|
|
||
| Here's a production-ready example with proper logging, reactions, message editing, and media CDN reuse: | ||
| Here's a production-ready example with proper logging, reactions, message editing, media CDN reuse, and the `🦀send` relay command: | ||
|
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| ```rust src/main.rs | ||
| use log::{error, info}; | ||
| use whatsapp_rust::prelude::*; | ||
| use whatsapp_rust::pair_code::PairCodeOptions; | ||
|
|
||
| const PING_TRIGGER: &str = "🦀ping"; | ||
| const SEND_TRIGGER: &str = "🦀send"; | ||
| const PONG_TEXT: &str = "🏓 Pong!"; | ||
| const REACTION_EMOJI: &str = "🏓"; | ||
|
|
||
|
|
@@ -410,13 +411,54 @@ async fn handle_message(ctx: MessageContext) { | |
| return; | ||
| } | ||
|
|
||
| if ctx.message.text_content() == Some(PING_TRIGGER) { | ||
| let Some(text) = ctx.message.text_content() else { | ||
| return; | ||
| }; | ||
| if text == PING_TRIGGER { | ||
| if let Err(e) = ctx.react(REACTION_EMOJI).await { | ||
| error!("Failed to send reaction: {e}"); | ||
| } | ||
| if let Err(e) = ctx.reply_quoting(PONG_TEXT).await { | ||
| error!("Failed to send pong: {e}"); | ||
| } | ||
| } else if let Some(args) = text.strip_prefix(SEND_TRIGGER) { | ||
| handle_send_command(&ctx, args).await; | ||
|
Comment on lines
+424
to
+425
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the relayed text itself starts with Useful? React with 👍 / 👎. |
||
| } | ||
| } | ||
|
|
||
| /// Handles `🦀send <jid> <text>`, relaying text to an arbitrary group or DM JID. | ||
| async fn handle_send_command(ctx: &MessageContext, args: &str) { | ||
| let Some((target, text)) = args.trim_start().split_once(char::is_whitespace) else { | ||
| error!("Usage: {SEND_TRIGGER} <jid> <text>"); | ||
| return; | ||
| }; | ||
| let text = text.trim_start(); | ||
| if text.is_empty() { | ||
| error!("Usage: {SEND_TRIGGER} <jid> <text>"); | ||
| return; | ||
| } | ||
| let jid: Jid = match target.parse() { | ||
| Ok(jid) => jid, | ||
| Err(e) => { | ||
| error!("Invalid JID '{target}': {e}"); | ||
| return; | ||
| } | ||
| }; | ||
| let start = wacore::time::Instant::now(); | ||
| let sent = match ctx.client.send_message(jid, wa::Message::text(text)).await { | ||
| Ok(sent) => sent, | ||
| Err(e) => { | ||
| error!("Failed to send message: {e}"); | ||
| return; | ||
| } | ||
| }; | ||
| let duration = format!("{:.2?}", start.elapsed()); | ||
| info!("Sent message {} to {} in {}", sent.message_id, sent.to, duration); | ||
| if let Err(e) = ctx | ||
| .reply_quoting(format!("âś… Sent to {}\n`{duration}`", sent.to)) | ||
| .await | ||
| { | ||
| error!("Failed to send timing reply: {e}"); | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.