whatsapp_rust/
mediaconn.rs

1use crate::client::Client;
2use crate::request::{InfoQuery, InfoQueryType, IqError};
3use serde::Deserialize;
4use std::time::{Duration, Instant};
5use wacore_binary::builder::NodeBuilder;
6use wacore_binary::jid::SERVER_JID;
7
8#[derive(Debug, Clone, Deserialize)]
9pub struct MediaConnHost {
10    pub hostname: String,
11}
12
13#[derive(Debug, Clone)]
14pub struct MediaConn {
15    pub auth: String,
16    pub ttl: u64,
17    pub hosts: Vec<MediaConnHost>,
18    pub fetched_at: Instant,
19}
20
21impl MediaConn {
22    pub fn is_expired(&self) -> bool {
23        self.fetched_at.elapsed() > Duration::from_secs(self.ttl)
24    }
25}
26
27impl Client {
28    pub(crate) async fn refresh_media_conn(&self, force: bool) -> Result<MediaConn, IqError> {
29        {
30            let guard = self.media_conn.read().await;
31            if !force
32                && let Some(conn) = &*guard
33                && !conn.is_expired()
34            {
35                return Ok(conn.clone());
36            }
37        }
38
39        let resp = self
40            .send_iq(InfoQuery {
41                namespace: "w:m",
42                query_type: InfoQueryType::Set,
43                to: SERVER_JID.parse().unwrap(),
44                target: None,
45                id: None,
46                content: Some(wacore_binary::node::NodeContent::Nodes(vec![
47                    NodeBuilder::new("media_conn").build(),
48                ])),
49                timeout: None,
50            })
51            .await?;
52
53        let media_conn_node =
54            resp.get_optional_child("media_conn")
55                .ok_or_else(|| IqError::ServerError {
56                    code: 500,
57                    text: "Missing media_conn node in response".to_string(),
58                })?;
59
60        let mut attrs = media_conn_node.attrs();
61        let auth = attrs.string("auth");
62        let ttl = attrs.optional_u64("ttl").unwrap_or(0);
63
64        let mut hosts = Vec::new();
65        for host_node in media_conn_node.get_children_by_tag("host") {
66            hosts.push(MediaConnHost {
67                hostname: host_node.attrs().string("hostname"),
68            });
69        }
70
71        let new_conn = MediaConn {
72            auth,
73            ttl,
74            hosts,
75            fetched_at: Instant::now(),
76        };
77
78        let mut write_guard = self.media_conn.write().await;
79        *write_guard = Some(new_conn.clone());
80
81        Ok(new_conn)
82    }
83}