whatsapp_rust/
spam_report.rs1use crate::client::Client;
6use crate::request::IqError;
7use wacore::iq::spam_report::SpamReportSpec;
8
9pub use wacore::types::{SpamFlow, SpamReportRequest, SpamReportResult, build_spam_list_node};
11
12impl Client {
13 pub async fn send_spam_report(
35 &self,
36 request: SpamReportRequest,
37 ) -> Result<SpamReportResult, IqError> {
38 use wacore::iq::abprops::web;
39
40 let mut spec = SpamReportSpec::new(request);
41
42 if self
45 .ab_props()
46 .is_enabled(web::ENABLE_SPAM_REPORT_IQ_WITH_PRIVACY_TOKEN)
47 .await
48 && let Some(reported) = spec.request.from_jid.clone()
49 && let Some(token) = self.lookup_tc_token_for_jid(&reported).await
50 {
51 spec = spec.with_tc_token(token);
52 }
53
54 self.execute(spec).await
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use wacore_binary::Jid;
62
63 #[test]
64 fn test_spam_flow_as_str() {
65 assert_eq!(SpamFlow::MessageMenu.as_str(), "MessageMenu");
66 assert_eq!(
67 SpamFlow::GroupSpamBannerReport.as_str(),
68 "GroupSpamBannerReport"
69 );
70 assert_eq!(SpamFlow::ContactInfo.as_str(), "ContactInfo");
71 }
72
73 #[test]
74 fn test_build_spam_list_node_basic() {
75 let request = SpamReportRequest {
76 message_id: "TEST123".to_string(),
77 message_timestamp: 1234567890,
78 spam_flow: SpamFlow::MessageMenu,
79 ..Default::default()
80 };
81
82 let node = build_spam_list_node(&request);
83
84 assert_eq!(node.tag, "spam_list");
85 assert!(
86 node.attrs
87 .get("spam_flow")
88 .is_some_and(|v| v == "MessageMenu")
89 );
90
91 let message = node
92 .get_optional_child_by_tag(&["message"])
93 .expect("spam_list node should have message child");
94 assert!(message.attrs.get("id").is_some_and(|v| v == "TEST123"));
95 assert!(message.attrs.get("t").is_some_and(|v| v == "1234567890"));
96 }
97
98 #[test]
99 fn test_build_spam_list_node_with_raw_message() {
100 let request = SpamReportRequest {
101 message_id: "TEST456".to_string(),
102 message_timestamp: 1234567890,
103 from_jid: Some(Jid::pn("5511999887766")),
104 spam_flow: SpamFlow::MessageMenu,
105 raw_message: Some(vec![0x01, 0x02, 0x03]),
106 media_type: Some("image".to_string()),
107 ..Default::default()
108 };
109
110 let node = build_spam_list_node(&request);
111 let message = node
112 .get_optional_child_by_tag(&["message"])
113 .expect("spam_list node should have message child");
114 let raw = message
115 .get_optional_child_by_tag(&["raw"])
116 .expect("message node should have raw child");
117
118 assert!(raw.attrs.get("v").is_some_and(|v| v == "3"));
119 assert!(raw.attrs.get("mediatype").is_some_and(|v| v == "image"));
120 }
121
122 #[test]
123 fn test_build_spam_list_node_group() {
124 let request = SpamReportRequest {
125 message_id: "TEST789".to_string(),
126 message_timestamp: 1234567890,
127 group_jid: Some(Jid::group("120363025918861132")),
128 group_subject: Some("Test Group".to_string()),
129 participant_jid: Some(Jid::pn("5511999887766")),
130 spam_flow: SpamFlow::GroupInfoReport,
131 ..Default::default()
132 };
133
134 let node = build_spam_list_node(&request);
135
136 assert!(
137 node.attrs
138 .get("spam_flow")
139 .is_some_and(|v| v == "GroupInfoReport")
140 );
141 assert!(
142 node.attrs
143 .get("jid")
144 .is_some_and(|v| v == "120363025918861132@g.us")
145 );
146 assert!(node.attrs.get("subject").is_some_and(|v| v == "Test Group"));
147 }
148}