11use crate :: {
2- config:: { NotifyZulipConfig , NotifyZulipLabelConfig } ,
2+ config:: { NotifyZulipConfig , NotifyZulipLabelConfig , NotifyZulipNameConfig } ,
33 github:: { Issue , IssuesAction , IssuesEvent , Label } ,
44 handlers:: Context ,
55} ;
@@ -12,6 +12,8 @@ pub(super) struct NotifyZulipInput {
1212 /// For example, if an `I-prioritize` issue is closed,
1313 /// this field will be `I-prioritize`.
1414 label : Label ,
15+ is_default_valid : bool ,
16+ names : Vec < String > ,
1517}
1618
1719pub ( super ) enum NotificationType {
@@ -52,24 +54,67 @@ pub(super) async fn parse_input(
5254fn parse_label_change_input (
5355 event : & IssuesEvent ,
5456 label : Label ,
55- config : & NotifyZulipLabelConfig ,
57+ config : & NotifyZulipNameConfig ,
5658) -> Option < NotifyZulipInput > {
57- if !has_all_required_labels ( & event. issue , config) {
58- // Issue misses a required label, ignore this event
59+ let mut is_default_valid = false ;
60+ let mut names: Vec < String > = vec ! [ ] ;
61+
62+ match & config. default {
63+ Some ( label_config) => {
64+ if has_all_required_labels ( & event. issue , & label_config) {
65+ match event. action {
66+ IssuesAction :: Labeled { .. } if !label_config. messages_on_add . is_empty ( ) => {
67+ is_default_valid = true ;
68+ }
69+ IssuesAction :: Unlabeled { .. } if !label_config. messages_on_remove . is_empty ( ) => {
70+ is_default_valid = true ;
71+ }
72+ _ => ( ) ,
73+ }
74+ }
75+ }
76+ None => ( )
77+ }
78+
79+ match & config. others {
80+ Some ( other_configs) => {
81+ for ( name, label_config) in other_configs {
82+ if has_all_required_labels ( & event. issue , & label_config) {
83+ match event. action {
84+ IssuesAction :: Labeled { .. } if !label_config. messages_on_add . is_empty ( ) => {
85+ names. push ( name. to_string ( ) ) ;
86+ }
87+ IssuesAction :: Unlabeled { .. } if !label_config. messages_on_remove . is_empty ( ) => {
88+ names. push ( name. to_string ( ) ) ;
89+ }
90+ _ => ( ) ,
91+ }
92+ }
93+ }
94+ }
95+ None => ( )
96+ }
97+
98+ if !is_default_valid && names. is_empty ( ) {
99+ // It seems that there is no match between this event and any notify-zulip config, ignore this event
59100 return None ;
60101 }
61102
62103 match event. action {
63- IssuesAction :: Labeled { .. } if !config . messages_on_add . is_empty ( ) => {
104+ IssuesAction :: Labeled { .. } => {
64105 Some ( NotifyZulipInput {
65106 notification_type : NotificationType :: Labeled ,
66107 label,
108+ is_default_valid,
109+ names,
67110 } )
68111 }
69- IssuesAction :: Unlabeled { .. } if !config . messages_on_remove . is_empty ( ) => {
112+ IssuesAction :: Unlabeled { .. } => {
70113 Some ( NotifyZulipInput {
71114 notification_type : NotificationType :: Unlabeled ,
72115 label,
116+ is_default_valid,
117+ names,
73118 } )
74119 }
75120 _ => None ,
@@ -92,22 +137,65 @@ fn parse_close_reopen_input(
92137 . map ( |config| ( label, config) )
93138 } )
94139 . flat_map ( |( label, config) | {
95- if !has_all_required_labels ( & event. issue , config) {
96- // Issue misses a required label, ignore this event
140+ let mut is_default_valid = false ;
141+ let mut names: Vec < String > = vec ! [ ] ;
142+
143+ match & config. default {
144+ Some ( label_config) => {
145+ if has_all_required_labels ( & event. issue , & label_config) {
146+ match event. action {
147+ IssuesAction :: Closed if !label_config. messages_on_close . is_empty ( ) => {
148+ is_default_valid = true ;
149+ }
150+ IssuesAction :: Reopened if !label_config. messages_on_reopen . is_empty ( ) => {
151+ is_default_valid = true ;
152+ }
153+ _ => ( ) ,
154+ }
155+ }
156+ }
157+ None => ( )
158+ }
159+
160+ match & config. others {
161+ Some ( other_configs) => {
162+ for ( name, label_config) in other_configs {
163+ if has_all_required_labels ( & event. issue , & label_config) {
164+ match event. action {
165+ IssuesAction :: Closed if !label_config. messages_on_close . is_empty ( ) => {
166+ names. push ( name. to_string ( ) ) ;
167+ }
168+ IssuesAction :: Reopened if !label_config. messages_on_reopen . is_empty ( ) => {
169+ names. push ( name. to_string ( ) ) ;
170+ }
171+ _ => ( ) ,
172+ }
173+ }
174+ }
175+ }
176+ None => ( )
177+ }
178+
179+ if !is_default_valid && names. is_empty ( ) {
180+ // It seems that there is no match between this event and any notify-zulip config, ignore this event
97181 return None ;
98182 }
99183
100184 match event. action {
101- IssuesAction :: Closed if !config . messages_on_close . is_empty ( ) => {
185+ IssuesAction :: Closed => {
102186 Some ( NotifyZulipInput {
103187 notification_type : NotificationType :: Closed ,
104188 label,
189+ is_default_valid,
190+ names,
105191 } )
106192 }
107- IssuesAction :: Reopened if !config . messages_on_reopen . is_empty ( ) => {
193+ IssuesAction :: Reopened => {
108194 Some ( NotifyZulipInput {
109195 notification_type : NotificationType :: Reopened ,
110196 label,
197+ is_default_valid,
198+ names,
111199 } )
112200 }
113201 _ => None ,
@@ -140,41 +228,54 @@ pub(super) async fn handle_input<'a>(
140228 inputs : Vec < NotifyZulipInput > ,
141229) -> anyhow:: Result < ( ) > {
142230 for input in inputs {
143- let config = & config. labels [ & input. label . name ] ;
144-
145- let topic = & config. topic ;
146- let topic = topic. replace ( "{number}" , & event. issue . number . to_string ( ) ) ;
147- let mut topic = topic. replace ( "{title}" , & event. issue . title ) ;
148- // Truncate to 60 chars (a Zulip limitation)
149- let mut chars = topic. char_indices ( ) . skip ( 59 ) ;
150- if let ( Some ( ( len, _) ) , Some ( _) ) = ( chars. next ( ) , chars. next ( ) ) {
151- topic. truncate ( len) ;
152- topic. push ( '…' ) ;
231+ let name_config = & config. labels [ & input. label . name ] ;
232+
233+ // Get valid label configs
234+ let mut label_configs: Vec < & NotifyZulipLabelConfig > = vec ! [ ] ;
235+ if input. is_default_valid {
236+ label_configs. push ( name_config. default . as_ref ( ) . unwrap ( ) ) ;
237+ }
238+ for name in input. names {
239+ label_configs. push ( & name_config. others . as_ref ( ) . unwrap ( ) [ & name] ) ;
153240 }
154241
155- let msgs = match input. notification_type {
156- NotificationType :: Labeled => & config. messages_on_add ,
157- NotificationType :: Unlabeled => & config. messages_on_remove ,
158- NotificationType :: Closed => & config. messages_on_close ,
159- NotificationType :: Reopened => & config. messages_on_reopen ,
160- } ;
242+ for label_config in label_configs {
243+ let config = label_config;
161244
162- let recipient = crate :: zulip:: Recipient :: Stream {
163- id : config. zulip_stream ,
164- topic : & topic,
165- } ;
245+ let topic = & config. topic ;
246+ let topic = topic. replace ( "{number}" , & event. issue . number . to_string ( ) ) ;
247+ let mut topic = topic. replace ( "{title}" , & event. issue . title ) ;
248+ // Truncate to 60 chars (a Zulip limitation)
249+ let mut chars = topic. char_indices ( ) . skip ( 59 ) ;
250+ if let ( Some ( ( len, _) ) , Some ( _) ) = ( chars. next ( ) , chars. next ( ) ) {
251+ topic. truncate ( len) ;
252+ topic. push ( '…' ) ;
253+ }
166254
167- for msg in msgs {
168- let msg = msg. replace ( "{number}" , & event. issue . number . to_string ( ) ) ;
169- let msg = msg. replace ( "{title}" , & event. issue . title ) ;
170- let msg = replace_team_to_be_nominated ( & event. issue . labels , msg) ;
255+ let msgs = match input. notification_type {
256+ NotificationType :: Labeled => & config. messages_on_add ,
257+ NotificationType :: Unlabeled => & config. messages_on_remove ,
258+ NotificationType :: Closed => & config. messages_on_close ,
259+ NotificationType :: Reopened => & config. messages_on_reopen ,
260+ } ;
171261
172- crate :: zulip:: MessageApiRequest {
173- recipient,
174- content : & msg,
262+ let recipient = crate :: zulip:: Recipient :: Stream {
263+ id : config. zulip_stream ,
264+ topic : & topic,
265+ } ;
266+
267+ for msg in msgs {
268+ let msg = msg. replace ( "{number}" , & event. issue . number . to_string ( ) ) ;
269+ let msg = msg. replace ( "{title}" , & event. issue . title ) ;
270+ let msg = replace_team_to_be_nominated ( & event. issue . labels , msg) ;
271+
272+ crate :: zulip:: MessageApiRequest {
273+ recipient,
274+ content : & msg,
275+ }
276+ . send ( & ctx. github . raw ( ) )
277+ . await ?;
175278 }
176- . send ( & ctx. github . raw ( ) )
177- . await ?;
178279 }
179280 }
180281
0 commit comments