whatsapp_rust/features/
chatstate.rs

1use crate::client::Client;
2use log::debug;
3use wacore_binary::builder::NodeBuilder;
4use wacore_binary::jid::Jid;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum ChatStateType {
8    Composing,
9
10    Recording,
11
12    Paused,
13}
14
15impl ChatStateType {
16    fn as_str(&self) -> &'static str {
17        match self {
18            ChatStateType::Composing => "composing",
19            ChatStateType::Recording => "recording",
20            ChatStateType::Paused => "paused",
21        }
22    }
23}
24
25impl std::fmt::Display for ChatStateType {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(f, "{}", self.as_str())
28    }
29}
30
31pub struct Chatstate<'a> {
32    client: &'a Client,
33}
34
35impl<'a> Chatstate<'a> {
36    pub(crate) fn new(client: &'a Client) -> Self {
37        Self { client }
38    }
39
40    pub async fn send(
41        &self,
42        to: &Jid,
43        state: ChatStateType,
44    ) -> Result<(), crate::client::ClientError> {
45        debug!(target: "Chatstate", "Sending {} to {}", state, to);
46
47        let node = self.build_chatstate_node(to, state);
48        self.client.send_node(node).await
49    }
50
51    pub async fn send_composing(&self, to: &Jid) -> Result<(), crate::client::ClientError> {
52        self.send(to, ChatStateType::Composing).await
53    }
54
55    pub async fn send_recording(&self, to: &Jid) -> Result<(), crate::client::ClientError> {
56        self.send(to, ChatStateType::Recording).await
57    }
58
59    pub async fn send_paused(&self, to: &Jid) -> Result<(), crate::client::ClientError> {
60        self.send(to, ChatStateType::Paused).await
61    }
62
63    fn build_chatstate_node(&self, to: &Jid, state: ChatStateType) -> wacore_binary::node::Node {
64        let child = match state {
65            ChatStateType::Composing => NodeBuilder::new("composing").build(),
66            ChatStateType::Recording => {
67                NodeBuilder::new("composing").attr("media", "audio").build()
68            }
69            ChatStateType::Paused => NodeBuilder::new("paused").build(),
70        };
71
72        NodeBuilder::new("chatstate")
73            .attr("to", to.to_string())
74            .children([child])
75            .build()
76    }
77}
78
79impl Client {
80    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_display() {
91        assert_eq!(ChatStateType::Composing.to_string(), "composing");
92        assert_eq!(ChatStateType::Recording.to_string(), "recording");
93        assert_eq!(ChatStateType::Paused.to_string(), "paused");
94    }
95
96    #[test]
97    fn test_chat_state_type_as_str() {
98        assert_eq!(ChatStateType::Composing.as_str(), "composing");
99        assert_eq!(ChatStateType::Recording.as_str(), "recording");
100        assert_eq!(ChatStateType::Paused.as_str(), "paused");
101    }
102}