whatsapp_rust/features/
chatstate.rs1use crate::client::{Client, ClientError};
4use log::debug;
5use thiserror::Error;
6use wacore::WireEnum;
7use wacore_binary::Jid;
8use wacore_binary::builder::NodeBuilder;
9
10#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum ChatStateError {
14 #[error("{0}")]
16 Client(#[from] ClientError),
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, WireEnum)]
21#[non_exhaustive]
22pub enum ChatStateType {
23 #[wire = "composing"]
24 Composing,
25 #[wire = "recording"]
26 Recording,
27 #[wire = "paused"]
28 Paused,
29}
30
31pub struct Chatstate<'a> {
33 client: &'a Client,
34}
35
36impl<'a> Chatstate<'a> {
37 pub(crate) fn new(client: &'a Client) -> Self {
38 Self { client }
39 }
40
41 pub async fn send(&self, to: &Jid, state: ChatStateType) -> Result<(), ChatStateError> {
43 debug!(target: "Chatstate", "Sending {} to {}", state, to);
44
45 let node = self.build_chatstate_node(to, state);
46 self.client.send_node(node).await?;
47 Ok(())
48 }
49
50 pub async fn send_composing(&self, to: &Jid) -> Result<(), ChatStateError> {
51 self.send(to, ChatStateType::Composing).await
52 }
53
54 pub async fn send_recording(&self, to: &Jid) -> Result<(), ChatStateError> {
55 self.send(to, ChatStateType::Recording).await
56 }
57
58 pub async fn send_paused(&self, to: &Jid) -> Result<(), ChatStateError> {
59 self.send(to, ChatStateType::Paused).await
60 }
61
62 fn build_chatstate_node(&self, to: &Jid, state: ChatStateType) -> wacore_binary::Node {
63 let child = match state {
64 ChatStateType::Composing => NodeBuilder::new("composing").build(),
65 ChatStateType::Recording => {
66 NodeBuilder::new("composing").attr("media", "audio").build()
67 }
68 ChatStateType::Paused => NodeBuilder::new("paused").build(),
69 };
70
71 NodeBuilder::new("chatstate")
72 .attr("to", to)
73 .children([child])
74 .build()
75 }
76}
77
78impl Client {
79 pub fn chatstate(&self) -> Chatstate<'_> {
81 Chatstate::new(self)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_chat_state_type_string_enum() {
91 assert_eq!(ChatStateType::Composing.as_str(), "composing");
92 assert_eq!(ChatStateType::Recording.to_string(), "recording");
93 assert_eq!(
94 ChatStateType::try_from("paused").unwrap(),
95 ChatStateType::Paused
96 );
97 }
98}