whatsapp_rust/
mediaconn.rs1use 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}