@@ -21,21 +21,50 @@ pub struct Request {
2121 token : String ,
2222}
2323
24- #[ derive( Debug , serde:: Deserialize ) ]
24+ #[ derive( Clone , Debug , serde:: Deserialize ) ]
2525struct Message {
2626 sender_id : u64 ,
27+ /// A unique ID for the set of users receiving the message (either a
28+ /// stream or group of users). Useful primarily for hashing.
2729 #[ allow( unused) ]
2830 recipient_id : u64 ,
2931 sender_short_name : Option < String > ,
3032 sender_full_name : String ,
33+ sender_email : String ,
34+ /// The ID of the stream.
35+ ///
36+ /// `None` if it is a private message.
3137 stream_id : Option < u64 > ,
32- // The topic of the incoming message. Not the stream name.
38+ /// The topic of the incoming message. Not the stream name.
39+ ///
40+ /// Not currently set for private messages (though Zulip may change this in
41+ /// the future if it adds topics to private messages).
3342 subject : Option < String > ,
43+ /// The type of the message: stream or private.
3444 #[ allow( unused) ]
3545 #[ serde( rename = "type" ) ]
3646 type_ : String ,
3747}
3848
49+ impl Message {
50+ /// Creates a `Recipient` that will be addressed to the sender of this message.
51+ fn sender_to_recipient ( & self ) -> Recipient < ' _ > {
52+ match self . stream_id {
53+ Some ( id) => Recipient :: Stream {
54+ id,
55+ topic : self
56+ . subject
57+ . as_ref ( )
58+ . expect ( "stream messages should have a topic" ) ,
59+ } ,
60+ None => Recipient :: Private {
61+ id : self . sender_id ,
62+ email : & self . sender_email ,
63+ } ,
64+ }
65+ }
66+ }
67+
3968#[ derive( serde:: Serialize , serde:: Deserialize ) ]
4069struct Response {
4170 content : String ,
@@ -158,7 +187,7 @@ fn handle_command<'a>(
158187 . await
159188 . map_err ( |e| format_err ! ( "Failed to await at this time: {e:?}" ) )
160189 }
161- Some ( "docs-update" ) => return trigger_docs_update ( ) . await ,
190+ Some ( "docs-update" ) => return trigger_docs_update ( message_data ) ,
162191 _ => { }
163192 }
164193 }
@@ -710,16 +739,30 @@ async fn post_waiter(
710739 Ok ( None )
711740}
712741
713- async fn trigger_docs_update ( ) -> anyhow:: Result < Option < String > > {
714- match docs_update ( ) . await {
715- Ok ( None ) => Ok ( Some ( "No updates found." . to_string ( ) ) ) ,
716- Ok ( Some ( pr) ) => Ok ( Some ( format ! ( "Created docs update PR <{}>" , pr. html_url) ) ) ,
717- Err ( e) => {
718- // Don't send errors to Zulip since they may contain sensitive data.
719- log:: error!( "Docs update via Zulip failed: {e:?}" ) ;
720- Err ( format_err ! (
721- "Docs update failed, please check the logs for more details."
722- ) )
742+ fn trigger_docs_update ( message : & Message ) -> anyhow:: Result < Option < String > > {
743+ let message = message. clone ( ) ;
744+ // The default Zulip timeout of 10 seconds can be too short, so process in
745+ // the background.
746+ tokio:: task:: spawn ( async move {
747+ let response = match docs_update ( ) . await {
748+ Ok ( None ) => "No updates found." . to_string ( ) ,
749+ Ok ( Some ( pr) ) => format ! ( "Created docs update PR <{}>" , pr. html_url) ,
750+ Err ( e) => {
751+ // Don't send errors to Zulip since they may contain sensitive data.
752+ log:: error!( "Docs update via Zulip failed: {e:?}" ) ;
753+ "Docs update failed, please check the logs for more details." . to_string ( )
754+ }
755+ } ;
756+ let recipient = message. sender_to_recipient ( ) ;
757+ let message = MessageApiRequest {
758+ recipient,
759+ content : & response,
760+ } ;
761+ if let Err ( e) = message. send ( & reqwest:: Client :: new ( ) ) . await {
762+ log:: error!( "failed to send Zulip response: {e:?}\n response was:\n {response}" ) ;
723763 }
724- }
764+ } ) ;
765+ Ok ( Some (
766+ "Docs update in progress, I'll let you know when I'm finished." . to_string ( ) ,
767+ ) )
725768}
0 commit comments