Documentation Index
Fetch the complete documentation index at: https://mintlify.com/jlucaso1/whatsapp-rust/llms.txt
Use this file to discover all available pages before exploring further.
The Chatstate trait provides methods for sending typing indicators and recording notifications to recipients.
Access
Access chatstate operations through the client:
let chatstate = client.chatstate();
Methods
send
Send a chat state update to a recipient.
pub async fn send(
&self,
to: &Jid,
state: ChatStateType,
) -> Result<(), ClientError>
Parameters:
to - Recipient JID (user or group)
state: ChatStateType - Type of chat state to send
Returns:
Result<(), ClientError> - Success or client error
Example:
use whatsapp_rust::features::chatstate::ChatStateType;
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
// Send typing indicator
client.chatstate().send(&recipient, ChatStateType::Composing).await?;
// Send recording indicator
client.chatstate().send(&recipient, ChatStateType::Recording).await?;
// Send paused (stopped typing)
client.chatstate().send(&recipient, ChatStateType::Paused).await?;
send_composing
Convenience method to send typing indicator.
pub async fn send_composing(&self, to: &Jid) -> Result<(), ClientError>
Example:
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
client.chatstate().send_composing(&recipient).await?;
send_recording
Convenience method to send audio recording indicator.
pub async fn send_recording(&self, to: &Jid) -> Result<(), ClientError>
Example:
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
client.chatstate().send_recording(&recipient).await?;
println!("Showing 'recording audio' indicator");
send_paused
Convenience method to send paused/stopped typing indicator.
pub async fn send_paused(&self, to: &Jid) -> Result<(), ClientError>
Example:
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
client.chatstate().send_paused(&recipient).await?;
println!("Cleared typing indicator");
ChatStateType Enum
pub enum ChatStateType {
Composing, // Typing text
Recording, // Recording audio
Paused, // Stopped typing/recording
}
Methods:
as_str() - Returns "composing", "recording", or "paused"
String conversion:
use whatsapp_rust::features::chatstate::ChatStateType;
let state = ChatStateType::Composing;
assert_eq!(state.as_str(), "composing");
assert_eq!(state.to_string(), "composing");
// Parse from string
let parsed = ChatStateType::try_from("recording")?;
assert_eq!(parsed, ChatStateType::Recording);
Composing (Typing)
<chatstate to="15551234567@s.whatsapp.net">
<composing/>
</chatstate>
Recording (Voice)
<chatstate to="15551234567@s.whatsapp.net">
<composing media="audio"/>
</chatstate>
Note: Recording uses <composing media="audio"> rather than a separate tag.
Paused (Stopped)
<chatstate to="15551234567@s.whatsapp.net">
<paused/>
</chatstate>
Usage Patterns
Typing Indicator Lifecycle
use whatsapp_rust::features::chatstate::ChatStateType;
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
// User starts typing
client.chatstate().send_composing(&recipient).await?;
// User is typing... (you may want to throttle these)
std::thread::sleep(std::time::Duration::from_secs(2));
// User stopped typing (optional, will auto-clear)
client.chatstate().send_paused(&recipient).await?;
// Send the actual message
client.send_text(&recipient, "Hello!").await?;
Recording Audio
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
// Start recording
client.chatstate().send_recording(&recipient).await?;
// Record audio...
let audio_data = record_audio();
// Stop indicator (optional)
client.chatstate().send_paused(&recipient).await?;
// Send audio message
client.send_audio(&recipient, audio_data).await?;
Throttling
To avoid spamming chat state updates:
use std::time::{Duration, Instant};
struct ChatStateThrottler {
last_sent: Option<Instant>,
interval: Duration,
}
impl ChatStateThrottler {
fn new() -> Self {
Self {
last_sent: None,
interval: Duration::from_secs(3),
}
}
fn should_send(&mut self) -> bool {
if let Some(last) = self.last_sent {
if last.elapsed() < self.interval {
return false;
}
}
self.last_sent = Some(Instant::now());
true
}
}
// Usage
let mut throttler = ChatStateThrottler::new();
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
// In your typing event handler
if throttler.should_send() {
client.chatstate().send_composing(&recipient).await?;
}
Group Chats
Chat state indicators work in group chats as well:
let group_jid: Jid = "123456789@g.us".parse()?;
// Show typing in group
client.chatstate().send_composing(&group_jid).await?;
// Send message
client.send_text(&group_jid, "Hello everyone!").await?;
Error Handling
All methods return Result<(), ClientError>. Common errors:
- Not connected: Client not connected to WhatsApp
- Invalid JID: Malformed recipient JID
- Network errors: Connection issues
use whatsapp_rust::client::ClientError;
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
match client.chatstate().send_composing(&recipient).await {
Ok(_) => println!("Sent typing indicator"),
Err(ClientError::NotConnected) => {
eprintln!("Not connected to WhatsApp");
}
Err(e) => eprintln!("Error: {}", e),
}
Best Practices
- Throttle updates: Don’t send chat state updates more than once every 2-3 seconds
- Clear on send: Send
Paused before sending the actual message
- Auto-timeout: Consider auto-clearing typing indicators after 10-15 seconds of inactivity
- Don’t spam: Only send when state actually changes
- Groups: Be mindful that all group members will see the indicator
Complete Example
use whatsapp_rust::features::chatstate::ChatStateType;
use std::time::Duration;
let recipient: Jid = "15551234567@s.whatsapp.net".parse()?;
// Simulate user typing
println!("User starts typing...");
client.chatstate().send_composing(&recipient).await?;
// Simulate typing delay
tokio::time::sleep(Duration::from_secs(2)).await;
// User still typing (throttled)
println!("Still typing...");
// User finishes and sends message
client.chatstate().send_paused(&recipient).await?;
client.send_text(&recipient, "Hello there!").await?;
println!("Message sent");
// Or simulate voice recording
println!("\nUser starts recording...");
client.chatstate().send_recording(&recipient).await?;
tokio::time::sleep(Duration::from_secs(3)).await;
client.chatstate().send_paused(&recipient).await?;
println!("Recording stopped (would send audio here)");