@@ -16,6 +16,7 @@ use whatsapp_rust_tokio_transport::TokioWebSocketTransportFactory;
1616use whatsapp_rust_ureq_http_client:: UreqHttpClient ;
1717use waproto:: whatsapp:: Message as WhatsappMessage ;
1818use waproto:: whatsapp:: message:: { self as wa} ;
19+ use wacore:: proto_helpers:: build_quote_context;
1920use prost:: Message ;
2021use tokio:: signal;
2122use tracing:: { debug, error, info, warn} ;
@@ -214,6 +215,106 @@ impl TryxClient {
214215 Ok ( message_id. to_string ( ) )
215216 } )
216217 }
218+ #[ pyo3( signature = ( to, text, quoted=None ) ) ]
219+ fn send_text < ' py > ( & self , py : Python < ' py > , to : Py < JID > , text : String , quoted : Option < Py < WAMessage > > ) -> PyResult < Bound < ' py , PyAny > > {
220+ let client = self . client_rx . borrow ( ) . clone ( ) . ok_or_else ( || {
221+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( "Bot is not running" )
222+ } ) ?;
223+ let jid = to. bind ( py) . borrow ( ) . as_whatsapp_jid ( ) ;
224+ let locals = get_current_locals ( py) ?;
225+ let context_info = quoted. as_ref ( ) . map ( |q| {
226+ let quote = q. bind ( py) . borrow ( ) ;
227+ let msg = quote. inner . as_ref ( ) ;
228+ build_quote_context (
229+ quote. message_info . id . clone ( ) ,
230+ quote. message_info . inner . source . chat . clone ( ) ,
231+ msg,
232+ )
233+ } ) ;
234+ future_into_py_with_locals ( py, locals, async move {
235+ match quoted {
236+ Some ( _) => {
237+ let message = WhatsappMessage {
238+ extended_text_message : Some ( Box :: new ( wa:: ExtendedTextMessage {
239+ text : Some ( text) ,
240+ context_info : context_info. map ( Box :: new) ,
241+ ..Default :: default ( )
242+ } ) ) ,
243+ ..Default :: default ( )
244+ } ;
245+ let message_id = client
246+ . send_message ( jid, message)
247+ . await
248+ . map_err ( |e| PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( e. to_string ( ) ) ) ?;
249+ Ok ( message_id. to_string ( ) )
250+ }
251+ None => {
252+ let message = WhatsappMessage {
253+ conversation : Some ( text) ,
254+ ..Default :: default ( )
255+ } ;
256+ let message_id = client
257+ . send_message ( jid, message)
258+ . await
259+ . map_err ( |e| PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( e. to_string ( ) ) ) ?;
260+ Ok ( message_id. to_string ( ) )
261+ }
262+ }
263+ } )
264+ }
265+ #[ pyo3( signature = ( to, photo_data, caption, quoted=None ) ) ]
266+ fn send_photo < ' py > ( & self , py : Python < ' py > , to : Py < JID > , photo_data : & [ u8 ] , caption : String , quoted : Option < Py < WAMessage > > ) -> PyResult < Bound < ' py , PyAny > > {
267+ let client = self . client_rx . borrow ( ) . clone ( ) . ok_or_else ( || {
268+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( "Bot is not running" )
269+ } ) ?;
270+ let jid = to. bind ( py) . borrow ( ) . as_whatsapp_jid ( ) ;
271+ let photo_clone = photo_data. to_vec ( ) ;
272+ let locals = get_current_locals ( py) ?;
273+ let context_info = quoted. as_ref ( ) . map ( |q| {
274+ let quote = q. bind ( py) . borrow ( ) ;
275+ let msg = quote. inner . as_ref ( ) ;
276+ build_quote_context (
277+ quote. message_info . id . clone ( ) ,
278+ quote. message_info . inner . source . chat . clone ( ) ,
279+ msg,
280+ )
281+ } ) ;
282+ future_into_py_with_locals ( py, locals, async move {
283+ let upload = client
284+ . upload ( photo_clone, wacore:: download:: MediaType :: Image )
285+ . await
286+ . map_err ( |e| PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( e. to_string ( ) ) ) ?;
287+ // let image_message = wa::ImageMessage {
288+ // url: Some(upload.url),
289+ // direct_path: Some(upload.direct_path),
290+ // media_key: Some(upload.media_key),
291+ // file_enc_sha256: Some(upload.file_enc_sha256),
292+ // file_sha256: Some(upload.file_sha256),
293+ // file_length: Some(upload.file_length),
294+ // caption: Some(caption),
295+ // ..Default::default()
296+ // };
297+ let message = WhatsappMessage {
298+ image_message : Some ( Box :: new ( wa:: ImageMessage {
299+ url : Some ( upload. url ) ,
300+ direct_path : Some ( upload. direct_path ) ,
301+ media_key : Some ( upload. media_key ) ,
302+ file_enc_sha256 : Some ( upload. file_enc_sha256 ) ,
303+ file_sha256 : Some ( upload. file_sha256 ) ,
304+ file_length : Some ( upload. file_length ) ,
305+ caption : Some ( caption) ,
306+ context_info : context_info. map ( Box :: new) ,
307+ ..Default :: default ( )
308+ } ) ) ,
309+ ..Default :: default ( )
310+ } ;
311+ let message_id = client
312+ . send_message ( jid, message)
313+ . await
314+ . map_err ( |e| PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( e. to_string ( ) ) ) ?;
315+ Ok ( message_id. to_string ( ) )
316+ } )
317+ }
217318}
218319
219320impl Tryx {
@@ -230,7 +331,7 @@ impl Tryx {
230331 (
231332 dispatcher. pairing_qr_handlers ( py) ,
232333 dispatcher. message_handlers ( py) ,
233- dispatcher. conneccted_handlers ( py) ,
334+ dispatcher. connected_handlers ( py) ,
234335 dispatcher. logout_handlers ( py) ,
235336 )
236337 } ) ;
0 commit comments