Skip to content

Commit c934d46

Browse files
committed
Allow a single notify-zulip notification to send multiple Zulip messages
1 parent 1cf4ceb commit c934d46

File tree

3 files changed

+70
-30
lines changed

3 files changed

+70
-30
lines changed

src/config.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,14 @@ pub(crate) struct NotifyZulipConfig {
228228
pub(crate) struct NotifyZulipLabelConfig {
229229
pub(crate) zulip_stream: u64,
230230
pub(crate) topic: String,
231-
pub(crate) message_on_add: Option<String>,
232-
pub(crate) message_on_remove: Option<String>,
233-
pub(crate) message_on_close: Option<String>,
234-
pub(crate) message_on_reopen: Option<String>,
231+
#[serde(rename = "message_on_add", deserialize_with = "string_or_seq")]
232+
pub(crate) messages_on_add: Vec<String>,
233+
#[serde(rename = "message_on_remove", deserialize_with = "string_or_seq")]
234+
pub(crate) messages_on_remove: Vec<String>,
235+
#[serde(rename = "message_on_close", deserialize_with = "string_or_seq")]
236+
pub(crate) messages_on_close: Vec<String>,
237+
#[serde(rename = "message_on_reopen", deserialize_with = "string_or_seq")]
238+
pub(crate) messages_on_reopen: Vec<String>,
235239
#[serde(default)]
236240
pub(crate) required_labels: Vec<String>,
237241
}
@@ -384,6 +388,35 @@ impl fmt::Display for ConfigurationError {
384388
}
385389
}
386390

391+
fn string_or_seq<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
392+
where
393+
D: serde::Deserializer<'de>,
394+
{
395+
struct Visitor;
396+
397+
impl<'de> serde::de::Visitor<'de> for Visitor {
398+
type Value = Vec<String>;
399+
400+
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401+
f.write_str("string or sequence of strings")
402+
}
403+
404+
fn visit_unit<E: serde::de::Error>(self) -> Result<Self::Value, E> {
405+
Ok(Vec::new())
406+
}
407+
408+
fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
409+
Ok(vec![value.to_owned()])
410+
}
411+
412+
fn visit_seq<A: serde::de::SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
413+
serde::Deserialize::deserialize(serde::de::value::SeqAccessDeserializer::new(seq))
414+
}
415+
}
416+
417+
deserializer.deserialize_any(Visitor)
418+
}
419+
387420
#[cfg(test)]
388421
mod tests {
389422
use super::*;

src/handlers/notify_zulip.rs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,13 @@ fn parse_label_change_input(
6060
}
6161

6262
match event.action {
63-
IssuesAction::Labeled { .. } if config.message_on_add.is_some() => Some(NotifyZulipInput {
64-
notification_type: NotificationType::Labeled,
65-
label,
66-
}),
67-
IssuesAction::Unlabeled { .. } if config.message_on_remove.is_some() => {
63+
IssuesAction::Labeled { .. } if !config.messages_on_add.is_empty() => {
64+
Some(NotifyZulipInput {
65+
notification_type: NotificationType::Labeled,
66+
label,
67+
})
68+
}
69+
IssuesAction::Unlabeled { .. } if !config.messages_on_remove.is_empty() => {
6870
Some(NotifyZulipInput {
6971
notification_type: NotificationType::Unlabeled,
7072
label,
@@ -96,13 +98,13 @@ fn parse_close_reopen_input(
9698
}
9799

98100
match event.action {
99-
IssuesAction::Closed if config.message_on_close.is_some() => {
101+
IssuesAction::Closed if !config.messages_on_close.is_empty() => {
100102
Some(NotifyZulipInput {
101103
notification_type: NotificationType::Closed,
102104
label,
103105
})
104106
}
105-
IssuesAction::Reopened if config.message_on_reopen.is_some() => {
107+
IssuesAction::Reopened if !config.messages_on_reopen.is_empty() => {
106108
Some(NotifyZulipInput {
107109
notification_type: NotificationType::Reopened,
108110
label,
@@ -140,34 +142,39 @@ pub(super) async fn handle_input<'a>(
140142
for input in inputs {
141143
let config = &config.labels[&input.label.name];
142144

143-
let mut topic = config.topic.clone();
144-
topic = topic.replace("{number}", &event.issue.number.to_string());
145-
topic = topic.replace("{title}", &event.issue.title);
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);
146148
// Truncate to 60 chars (a Zulip limitation)
147149
let mut chars = topic.char_indices().skip(59);
148150
if let (Some((len, _)), Some(_)) = (chars.next(), chars.next()) {
149151
topic.truncate(len);
150152
topic.push('…');
151153
}
152154

153-
let mut msg = match input.notification_type {
154-
NotificationType::Labeled => config.message_on_add.as_ref().unwrap().clone(),
155-
NotificationType::Unlabeled => config.message_on_remove.as_ref().unwrap().clone(),
156-
NotificationType::Closed => config.message_on_close.as_ref().unwrap().clone(),
157-
NotificationType::Reopened => config.message_on_reopen.as_ref().unwrap().clone(),
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,
158160
};
159161

160-
msg = msg.replace("{number}", &event.issue.number.to_string());
161-
msg = msg.replace("{title}", &event.issue.title);
162-
163-
let zulip_req = crate::zulip::MessageApiRequest {
164-
recipient: crate::zulip::Recipient::Stream {
165-
id: config.zulip_stream,
166-
topic: &topic,
167-
},
168-
content: &msg,
162+
let recipient = crate::zulip::Recipient::Stream {
163+
id: config.zulip_stream,
164+
topic: &topic,
169165
};
170-
zulip_req.send(&ctx.github.raw()).await?;
166+
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+
171+
crate::zulip::MessageApiRequest {
172+
recipient,
173+
content: &msg,
174+
}
175+
.send(&ctx.github.raw())
176+
.await?;
177+
}
171178
}
172179

173180
Ok(())

src/zulip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ pub struct Member {
337337
pub user_id: u64,
338338
}
339339

340-
#[derive(serde::Serialize)]
340+
#[derive(Copy, Clone, serde::Serialize)]
341341
#[serde(tag = "type")]
342342
#[serde(rename_all = "snake_case")]
343343
pub enum Recipient<'a> {

0 commit comments

Comments
 (0)