Skip to main content

whatsapp_rust/
spam_report.rs

1//! Spam reporting feature.
2//!
3//! Types and IQ specification are defined in `wacore::iq::spam_report`.
4
5use crate::client::Client;
6use crate::request::IqError;
7use wacore::iq::spam_report::SpamReportSpec;
8
9// Re-export types from wacore
10pub use wacore::types::{SpamFlow, SpamReportRequest, SpamReportResult, build_spam_list_node};
11
12impl Client {
13    /// Send a spam report to WhatsApp.
14    ///
15    /// This sends a `spam_list` IQ stanza to report one or more messages as spam.
16    ///
17    /// # Arguments
18    /// * `request` - The spam report request containing message details
19    ///
20    /// # Returns
21    /// * `Ok(SpamReportResult)` - If the report was successfully submitted
22    /// * `Err` - If there was an error sending or processing the report
23    ///
24    /// # Example
25    /// ```rust,ignore
26    /// let result = client.send_spam_report(SpamReportRequest {
27    ///     message_id: "MSG_ID".to_string(),
28    ///     message_timestamp: 1234567890,
29    ///     from_jid: Some(sender_jid),
30    ///     spam_flow: SpamFlow::MessageMenu,
31    ///     ..Default::default()
32    /// }).await?;
33    /// ```
34    pub async fn send_spam_report(
35        &self,
36        request: SpamReportRequest,
37    ) -> Result<SpamReportResult, IqError> {
38        let spec = SpamReportSpec::new(request);
39        self.execute(spec).await
40    }
41}
42
43#[cfg(test)]
44#[allow(deprecated)]
45mod tests {
46    use super::*;
47    use wacore_binary::jid::Jid;
48
49    #[test]
50    fn test_spam_flow_as_str() {
51        assert_eq!(SpamFlow::MessageMenu.as_str(), "MessageMenu");
52        assert_eq!(
53            SpamFlow::GroupSpamBannerReport.as_str(),
54            "GroupSpamBannerReport"
55        );
56        assert_eq!(SpamFlow::ContactInfo.as_str(), "ContactInfo");
57    }
58
59    #[test]
60    fn test_build_spam_list_node_basic() {
61        let request = SpamReportRequest {
62            message_id: "TEST123".to_string(),
63            message_timestamp: 1234567890,
64            spam_flow: SpamFlow::MessageMenu,
65            ..Default::default()
66        };
67
68        let node = build_spam_list_node(&request);
69
70        assert_eq!(node.tag, "spam_list");
71        assert!(
72            node.attrs
73                .get("spam_flow")
74                .is_some_and(|v| v == "MessageMenu")
75        );
76
77        let message = node
78            .get_optional_child_by_tag(&["message"])
79            .expect("spam_list node should have message child");
80        assert!(message.attrs.get("id").is_some_and(|v| v == "TEST123"));
81        assert!(message.attrs.get("t").is_some_and(|v| v == "1234567890"));
82    }
83
84    #[test]
85    fn test_build_spam_list_node_with_raw_message() {
86        let request = SpamReportRequest {
87            message_id: "TEST456".to_string(),
88            message_timestamp: 1234567890,
89            from_jid: Some(Jid::pn("5511999887766")),
90            spam_flow: SpamFlow::MessageMenu,
91            raw_message: Some(vec![0x01, 0x02, 0x03]),
92            media_type: Some("image".to_string()),
93            ..Default::default()
94        };
95
96        let node = build_spam_list_node(&request);
97        let message = node
98            .get_optional_child_by_tag(&["message"])
99            .expect("spam_list node should have message child");
100        let raw = message
101            .get_optional_child_by_tag(&["raw"])
102            .expect("message node should have raw child");
103
104        assert!(raw.attrs.get("v").is_some_and(|v| v == "3"));
105        assert!(raw.attrs.get("mediatype").is_some_and(|v| v == "image"));
106    }
107
108    #[test]
109    fn test_build_spam_list_node_group() {
110        let request = SpamReportRequest {
111            message_id: "TEST789".to_string(),
112            message_timestamp: 1234567890,
113            group_jid: Some(Jid::group("120363025918861132")),
114            group_subject: Some("Test Group".to_string()),
115            participant_jid: Some(Jid::pn("5511999887766")),
116            spam_flow: SpamFlow::GroupInfoReport,
117            ..Default::default()
118        };
119
120        let node = build_spam_list_node(&request);
121
122        assert!(
123            node.attrs
124                .get("spam_flow")
125                .is_some_and(|v| v == "GroupInfoReport")
126        );
127        assert!(
128            node.attrs
129                .get("jid")
130                .is_some_and(|v| v == "120363025918861132@g.us")
131        );
132        assert!(node.attrs.get("subject").is_some_and(|v| v == "Test Group"));
133    }
134}