whatsapp_rust/
mediaconn.rs1use crate::client::Client;
6use crate::request::IqError;
7use std::time::Duration;
8use wacore::iq::mediaconn::MediaConnSpec;
9use wacore::time::Instant;
10
11pub use wacore::iq::mediaconn::MediaConnHost;
13
14pub(crate) const MEDIA_AUTH_REFRESH_RETRY_ATTEMPTS: usize = 1;
17
18pub(crate) fn is_media_auth_error(status_code: u16) -> bool {
21 matches!(status_code, 401 | 403)
22}
23
24#[derive(Debug, Clone)]
26pub struct MediaConn {
27 pub auth: String,
29 pub ttl: u64,
31 pub auth_ttl: Option<u64>,
33 pub hosts: Vec<MediaConnHost>,
35 pub fetched_at: Instant,
37}
38
39impl MediaConn {
40 pub fn is_expired(&self) -> bool {
43 let effective_ttl = self.auth_ttl.map_or(self.ttl, |at| self.ttl.min(at));
44 self.fetched_at.elapsed() > Duration::from_secs(effective_ttl)
45 }
46}
47
48impl Client {
49 pub(crate) async fn invalidate_media_conn(&self) {
50 *self.media_conn.write().await = None;
51 }
52
53 pub async fn refresh_media_conn(&self, force: bool) -> Result<MediaConn, IqError> {
54 {
55 let guard = self.media_conn.read().await;
56 if !force
57 && let Some(conn) = &*guard
58 && !conn.is_expired()
59 {
60 return Ok(conn.clone());
61 }
62 }
63
64 let response = self.execute(MediaConnSpec::new()).await?;
65
66 let new_conn = MediaConn {
67 auth: response.auth,
68 ttl: response.ttl,
69 auth_ttl: response.auth_ttl,
70 hosts: response.hosts,
71 fetched_at: Instant::now(),
72 };
73
74 let mut write_guard = self.media_conn.write().await;
75 *write_guard = Some(new_conn.clone());
76
77 Ok(new_conn)
78 }
79}