whatsapp_rust/features/
comments.rs1use wacore_binary::Jid;
15use waproto::whatsapp as wa;
16
17use crate::client::Client;
18use crate::send::{SendError, SendResult};
19
20pub struct Comments<'a> {
21 client: &'a Client,
22}
23
24impl<'a> Comments<'a> {
25 pub(crate) fn new(client: &'a Client) -> Self {
26 Self { client }
27 }
28
29 pub async fn send_text(
36 &self,
37 chat: impl Into<Jid>,
38 parent_key: wa::MessageKey,
39 text: &str,
40 ) -> Result<SendResult, SendError> {
41 let chat = &chat.into();
42 let body = wa::Message {
44 extended_text_message: buffa::MessageField::some(wa::message::ExtendedTextMessage {
45 text: Some(text.to_string()),
46 ..Default::default()
47 }),
48 ..Default::default()
49 };
50 self.send_message(chat, parent_key, body).await
51 }
52
53 pub async fn send_message(
55 &self,
56 chat: impl Into<Jid>,
57 mut parent_key: wa::MessageKey,
58 body: wa::Message,
59 ) -> Result<SendResult, SendError> {
60 let chat = &chat.into();
61 let client = self.client;
62 let (author, secret) = client
63 .resolve_outgoing_addon_parent(chat, &parent_key)
64 .await?;
65 let parent_id = parent_key
66 .id
67 .clone()
68 .ok_or_else(|| SendError::InvalidRequest("parent message key missing id".into()))?;
69 let commenter = client
72 .lid()
73 .or_else(|| client.pn())
74 .map(|j| j.to_non_ad())
75 .ok_or(SendError::NotLoggedIn)?;
76
77 let (enc_payload, iv) = wacore::comment::encrypt_comment_with_secret(
78 &body,
79 &secret,
80 &parent_id,
81 &author.to_non_ad_string(),
82 &commenter.to_non_ad_string(),
83 )?;
84
85 if parent_key.participant.is_none() {
88 parent_key.participant = Some(author.to_non_ad_string());
89 }
90
91 let comment_secret: [u8; 32] = {
93 use rand::Rng;
94 let mut secret = [0u8; 32];
95 rand::rng().fill_bytes(&mut secret);
96 secret
97 };
98
99 let message = wa::Message {
100 enc_comment_message: buffa::MessageField::some(wa::message::EncCommentMessage {
101 target_message_key: buffa::MessageField::some(parent_key),
102 enc_payload: Some(enc_payload),
103 enc_iv: Some(iv.to_vec()),
104 }),
105 message_context_info: buffa::MessageField::some(wa::MessageContextInfo {
106 message_secret: Some(comment_secret.to_vec()),
107 ..Default::default()
108 }),
109 ..Default::default()
110 };
111 let result = client.send_message(chat, message).await?;
112
113 client
117 .persist_outbound_msg_secret(
118 chat,
119 &commenter,
120 &result.message_id,
121 &comment_secret,
122 wacore::msg_secret::RetentionClass::Text,
123 crate::send::SendInstant::now(),
124 )
125 .await;
126 Ok(result)
127 }
128}
129
130impl Client {
131 pub fn comments(&self) -> Comments<'_> {
132 Comments::new(self)
133 }
134}