whatsapp_rust/
groups.rs

1use crate::client::Client;
2use wacore::client::context::GroupInfo;
3use wacore_binary::builder::NodeBuilder;
4use wacore_binary::jid::Jid;
5
6impl Client {
7    pub async fn query_group_info(&self, jid: &Jid) -> Result<GroupInfo, anyhow::Error> {
8        if let Some(cached) = self.group_cache.get(jid) {
9            return Ok(cached.value().clone());
10        }
11
12        use wacore_binary::node::NodeContent;
13        let query_node = NodeBuilder::new("query")
14            .attr("request", "interactive")
15            .build();
16        let iq = crate::request::InfoQuery {
17            namespace: "w:g2",
18            query_type: crate::request::InfoQueryType::Get,
19            to: jid.clone(),
20            content: Some(NodeContent::Nodes(vec![query_node])),
21            id: None,
22            target: None,
23            timeout: None,
24        };
25
26        let resp_node = self.send_iq(iq).await?;
27
28        let group_node = resp_node
29            .get_optional_child("group")
30            .ok_or_else(|| anyhow::anyhow!("<group> not found in group info response"))?;
31
32        let mut participants = Vec::new();
33        let mut lid_to_pn_map = std::collections::HashMap::new();
34
35        let addressing_mode_str = group_node
36            .attrs()
37            .optional_string("addressing_mode")
38            .unwrap_or("pn");
39        let addressing_mode = match addressing_mode_str {
40            "lid" => crate::types::message::AddressingMode::Lid,
41            _ => crate::types::message::AddressingMode::Pn,
42        };
43
44        for participant_node in group_node.get_children_by_tag("participant") {
45            let participant_jid = participant_node.attrs().jid("jid");
46            participants.push(participant_jid.clone());
47
48            // If this is a LID group, extract the phone_number mapping
49            if addressing_mode == crate::types::message::AddressingMode::Lid
50                && let Some(phone_number) = participant_node.attrs().optional_jid("phone_number")
51            {
52                // Store mapping: LID user -> phone number JID (for device queries)
53                lid_to_pn_map.insert(participant_jid.user.clone(), phone_number);
54            }
55        }
56
57        let mut info = GroupInfo::new(participants, addressing_mode);
58        if !lid_to_pn_map.is_empty() {
59            info.set_lid_to_pn_map(lid_to_pn_map);
60        }
61        self.group_cache.insert(jid.clone(), info.clone());
62
63        Ok(info)
64    }
65}