@@ -21,21 +21,50 @@ pub struct Request {
21
21
token : String ,
22
22
}
23
23
24
- #[ derive( Debug , serde:: Deserialize ) ]
24
+ #[ derive( Clone , Debug , serde:: Deserialize ) ]
25
25
struct Message {
26
26
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.
27
29
#[ allow( unused) ]
28
30
recipient_id : u64 ,
29
31
sender_short_name : Option < String > ,
30
32
sender_full_name : String ,
33
+ sender_email : String ,
34
+ /// The ID of the stream.
35
+ ///
36
+ /// `None` if it is a private message.
31
37
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).
33
42
subject : Option < String > ,
43
+ /// The type of the message: stream or private.
34
44
#[ allow( unused) ]
35
45
#[ serde( rename = "type" ) ]
36
46
type_ : String ,
37
47
}
38
48
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
+
39
68
#[ derive( serde:: Serialize , serde:: Deserialize ) ]
40
69
struct Response {
41
70
content : String ,
@@ -158,7 +187,7 @@ fn handle_command<'a>(
158
187
. await
159
188
. map_err ( |e| format_err ! ( "Failed to await at this time: {e:?}" ) )
160
189
}
161
- Some ( "docs-update" ) => return trigger_docs_update ( ) . await ,
190
+ Some ( "docs-update" ) => return trigger_docs_update ( message_data ) ,
162
191
_ => { }
163
192
}
164
193
}
@@ -710,16 +739,30 @@ async fn post_waiter(
710
739
Ok ( None )
711
740
}
712
741
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}" ) ;
723
763
}
724
- }
764
+ } ) ;
765
+ Ok ( Some (
766
+ "Docs update in progress, I'll let you know when I'm finished." . to_string ( ) ,
767
+ ) )
725
768
}
0 commit comments