use crate::client::{Client, ClientError};
use log::debug;
use thiserror::Error;
use wacore::WireEnum;
use wacore_binary::Jid;
use wacore_binary::builder::NodeBuilder;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ChatStateError {
#[error("{0}")]
Client(#[from] ClientError),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, WireEnum)]
#[non_exhaustive]
pub enum ChatStateType {
#[wire = "composing"]
Composing,
#[wire = "recording"]
Recording,
#[wire = "paused"]
Paused,
}
pub struct Chatstate<'a> {
client: &'a Client,
}
impl<'a> Chatstate<'a> {
pub(crate) fn new(client: &'a Client) -> Self {
Self { client }
}
pub async fn send(&self, to: &Jid, state: ChatStateType) -> Result<(), ChatStateError> {
debug!(target: "Chatstate", "Sending {} to {}", state, to);
let node = self.build_chatstate_node(to, state);
self.client.send_node(node).await?;
Ok(())
}
pub async fn send_composing(&self, to: &Jid) -> Result<(), ChatStateError> {
self.send(to, ChatStateType::Composing).await
}
pub async fn send_recording(&self, to: &Jid) -> Result<(), ChatStateError> {
self.send(to, ChatStateType::Recording).await
}
pub async fn send_paused(&self, to: &Jid) -> Result<(), ChatStateError> {
self.send(to, ChatStateType::Paused).await
}
fn build_chatstate_node(&self, to: &Jid, state: ChatStateType) -> wacore_binary::Node {
let child = match state {
ChatStateType::Composing => NodeBuilder::new("composing").build(),
ChatStateType::Recording => {
NodeBuilder::new("composing").attr("media", "audio").build()
}
ChatStateType::Paused => NodeBuilder::new("paused").build(),
};
NodeBuilder::new("chatstate")
.attr("to", to)
.children([child])
.build()
}
}
impl Client {
pub fn chatstate(&self) -> Chatstate<'_> {
Chatstate::new(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_chat_state_type_string_enum() {
assert_eq!(ChatStateType::Composing.as_str(), "composing");
assert_eq!(ChatStateType::Recording.to_string(), "recording");
assert_eq!(
ChatStateType::try_from("paused").unwrap(),
ChatStateType::Paused
);
}
}