@@ -57,15 +57,27 @@ pub async fn to_zulip_id(client: &GithubClient, github_id: i64) -> anyhow::Resul
57
57
. map ( |v| * v. 0 ) )
58
58
}
59
59
60
+ /// Top-level handler for Zulip webhooks.
61
+ ///
62
+ /// Returns a JSON response.
60
63
pub async fn respond ( ctx : & Context , req : Request ) -> String {
61
64
let content = match process_zulip_request ( ctx, req) . await {
62
- Ok ( s) => s,
65
+ Ok ( None ) => {
66
+ return serde_json:: to_string ( & ResponseNotRequired {
67
+ response_not_required : true ,
68
+ } )
69
+ . unwrap ( ) ;
70
+ }
71
+ Ok ( Some ( s) ) => s,
63
72
Err ( e) => format ! ( "{:?}" , e) ,
64
73
} ;
65
74
serde_json:: to_string ( & Response { content } ) . unwrap ( )
66
75
}
67
76
68
- async fn process_zulip_request ( ctx : & Context , req : Request ) -> anyhow:: Result < String > {
77
+ /// Processes a Zulip webhook.
78
+ ///
79
+ /// Returns a string of the response, or None if no response is needed.
80
+ async fn process_zulip_request ( ctx : & Context , req : Request ) -> anyhow:: Result < Option < String > > {
69
81
let expected_token = std:: env:: var ( "ZULIP_TOKEN" ) . expect ( "`ZULIP_TOKEN` set for authorization" ) ;
70
82
71
83
if !openssl:: memcmp:: eq ( req. token . as_bytes ( ) , expected_token. as_bytes ( ) ) {
@@ -91,7 +103,8 @@ fn handle_command<'a>(
91
103
gh_id : anyhow:: Result < i64 > ,
92
104
words : & ' a str ,
93
105
message_data : & ' a Message ,
94
- ) -> std:: pin:: Pin < Box < dyn std:: future:: Future < Output = anyhow:: Result < String > > + Send + ' a > > {
106
+ ) -> std:: pin:: Pin < Box < dyn std:: future:: Future < Output = anyhow:: Result < Option < String > > > + Send + ' a > >
107
+ {
95
108
Box :: pin ( async move {
96
109
log:: trace!( "handling zulip command {:?}" , words) ;
97
110
let mut words = words. split_whitespace ( ) ;
@@ -152,7 +165,7 @@ fn handle_command<'a>(
152
165
next = words. next ( ) ;
153
166
}
154
167
155
- Ok ( String :: from ( "Unknown command" ) )
168
+ Ok ( Some ( String :: from ( "Unknown command" ) ) )
156
169
}
157
170
}
158
171
} )
@@ -166,7 +179,7 @@ async fn execute_for_other_user(
166
179
ctx : & Context ,
167
180
mut words : impl Iterator < Item = & str > ,
168
181
message_data : & Message ,
169
- ) -> anyhow:: Result < String > {
182
+ ) -> anyhow:: Result < Option < String > > {
170
183
// username is a GitHub username, not a Zulip username
171
184
let username = match words. next ( ) {
172
185
Some ( username) => username,
@@ -222,7 +235,9 @@ async fn execute_for_other_user(
222
235
. find ( |m| m. user_id == zulip_user_id)
223
236
. ok_or_else ( || format_err ! ( "Could not find Zulip user email." ) ) ?;
224
237
225
- let output = handle_command ( ctx, Ok ( user_id as i64 ) , & command, message_data) . await ?;
238
+ let output = handle_command ( ctx, Ok ( user_id as i64 ) , & command, message_data)
239
+ . await ?
240
+ . unwrap_or_default ( ) ;
226
241
227
242
// At this point, the command has been run.
228
243
let sender = match & message_data. sender_short_name {
@@ -255,7 +270,7 @@ async fn execute_for_other_user(
255
270
}
256
271
}
257
272
258
- Ok ( output)
273
+ Ok ( Some ( output) )
259
274
}
260
275
261
276
#[ derive( serde:: Deserialize ) ]
@@ -441,7 +456,7 @@ async fn acknowledge(
441
456
ctx : & Context ,
442
457
gh_id : i64 ,
443
458
mut words : impl Iterator < Item = & str > ,
444
- ) -> anyhow:: Result < String > {
459
+ ) -> anyhow:: Result < Option < String > > {
445
460
let filter = match words. next ( ) {
446
461
Some ( filter) => {
447
462
if words. next ( ) . is_some ( ) {
@@ -489,14 +504,14 @@ async fn acknowledge(
489
504
resp
490
505
} ;
491
506
492
- Ok ( resp)
507
+ Ok ( Some ( resp) )
493
508
}
494
509
495
510
async fn add_notification (
496
511
ctx : & Context ,
497
512
gh_id : i64 ,
498
513
mut words : impl Iterator < Item = & str > ,
499
- ) -> anyhow:: Result < String > {
514
+ ) -> anyhow:: Result < Option < String > > {
500
515
let url = match words. next ( ) {
501
516
Some ( idx) => idx,
502
517
None => anyhow:: bail!( "url not present" ) ,
@@ -525,7 +540,7 @@ async fn add_notification(
525
540
)
526
541
. await
527
542
{
528
- Ok ( ( ) ) => Ok ( "Created!" . to_string ( ) ) ,
543
+ Ok ( ( ) ) => Ok ( Some ( "Created!" . to_string ( ) ) ) ,
529
544
Err ( e) => Err ( format_err ! ( "Failed to create: {e:?}" ) ) ,
530
545
}
531
546
}
@@ -534,7 +549,7 @@ async fn add_meta_notification(
534
549
ctx : & Context ,
535
550
gh_id : i64 ,
536
551
mut words : impl Iterator < Item = & str > ,
537
- ) -> anyhow:: Result < String > {
552
+ ) -> anyhow:: Result < Option < String > > {
538
553
let idx = match words. next ( ) {
539
554
Some ( idx) => idx,
540
555
None => anyhow:: bail!( "idx not present" ) ,
@@ -557,7 +572,7 @@ async fn add_meta_notification(
557
572
} ;
558
573
let mut db = ctx. db . get ( ) . await ;
559
574
match add_metadata ( & mut db, gh_id, idx, description. as_deref ( ) ) . await {
560
- Ok ( ( ) ) => Ok ( "Added metadata!" . to_string ( ) ) ,
575
+ Ok ( ( ) ) => Ok ( Some ( "Added metadata!" . to_string ( ) ) ) ,
561
576
Err ( e) => Err ( format_err ! ( "Failed to add: {e:?}" ) ) ,
562
577
}
563
578
}
@@ -566,7 +581,7 @@ async fn move_notification(
566
581
ctx : & Context ,
567
582
gh_id : i64 ,
568
583
mut words : impl Iterator < Item = & str > ,
569
- ) -> anyhow:: Result < String > {
584
+ ) -> anyhow:: Result < Option < String > > {
570
585
let from = match words. next ( ) {
571
586
Some ( idx) => idx,
572
587
None => anyhow:: bail!( "from idx not present" ) ,
@@ -588,7 +603,7 @@ async fn move_notification(
588
603
match move_indices ( & mut * ctx. db . get ( ) . await , gh_id, from, to) . await {
589
604
Ok ( ( ) ) => {
590
605
// to 1-base indices
591
- Ok ( format ! ( "Moved {} to {}." , from + 1 , to + 1 ) )
606
+ Ok ( Some ( format ! ( "Moved {} to {}." , from + 1 , to + 1 ) ) )
592
607
}
593
608
Err ( e) => Err ( format_err ! ( "Failed to move: {e:?}." ) ) ,
594
609
}
@@ -662,7 +677,7 @@ async fn post_waiter(
662
677
ctx : & Context ,
663
678
message : & Message ,
664
679
waiting : WaitingMessage < ' _ > ,
665
- ) -> anyhow:: Result < String > {
680
+ ) -> anyhow:: Result < Option < String > > {
666
681
let posted = MessageApiRequest {
667
682
recipient : Recipient :: Stream {
668
683
id : message
@@ -692,16 +707,13 @@ async fn post_waiter(
692
707
. context ( "emoji reaction failed" ) ?;
693
708
}
694
709
695
- Ok ( serde_json:: to_string ( & ResponseNotRequired {
696
- response_not_required : true ,
697
- } )
698
- . unwrap ( ) )
710
+ Ok ( None )
699
711
}
700
712
701
- async fn trigger_docs_update ( ) -> anyhow:: Result < String > {
713
+ async fn trigger_docs_update ( ) -> anyhow:: Result < Option < String > > {
702
714
match docs_update ( ) . await {
703
- Ok ( None ) => Ok ( "No updates found." . to_string ( ) ) ,
704
- Ok ( Some ( pr) ) => Ok ( format ! ( "Created docs update PR <{}>" , pr. html_url) ) ,
715
+ Ok ( None ) => Ok ( Some ( "No updates found." . to_string ( ) ) ) ,
716
+ Ok ( Some ( pr) ) => Ok ( Some ( format ! ( "Created docs update PR <{}>" , pr. html_url) ) ) ,
705
717
Err ( e) => {
706
718
// Don't send errors to Zulip since they may contain sensitive data.
707
719
log:: error!( "Docs update via Zulip failed: {e:?}" ) ;
0 commit comments