Skip to content

Commit 64fdaa7

Browse files
committed
Port stream commands to Clap
1 parent 099b2a3 commit 64fdaa7

File tree

2 files changed

+75
-96
lines changed

2 files changed

+75
-96
lines changed

src/zulip.rs

Lines changed: 53 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::team_data::{people, teams};
1414
use crate::utils::pluralize;
1515
use crate::zulip::api::{MessageApiResponse, Recipient};
1616
use crate::zulip::client::ZulipClient;
17-
use crate::zulip::commands::{ChatCommand, LookupCmd, WorkqueueCmd, WorkqueueLimit};
17+
use crate::zulip::commands::{ChatCommand, LookupCmd, StreamCommand, WorkqueueCmd, WorkqueueLimit};
1818
use anyhow::{format_err, Context as _};
1919
use clap::Parser;
2020
use rust_team_data::v1::TeamKind;
@@ -180,12 +180,10 @@ fn handle_command<'a>(
180180
{
181181
Box::pin(async move {
182182
log::trace!("handling zulip command {:?}", command);
183-
let mut words = command.split_whitespace().peekable();
184-
let mut next = words.peek();
183+
let words: Vec<&str> = command.split_whitespace().collect();
185184

186-
if let Some(&"as") = next {
187-
words.next(); // skip `as`
188-
return execute_for_other_user(&ctx, words, message_data)
185+
if let Some(&"as") = words.get(0) {
186+
return execute_for_other_user(&ctx, words.iter().skip(1).copied(), message_data)
189187
.await
190188
.map_err(|e| {
191189
format_err!("Failed to parse; expected `as <username> <command...>`: {e:?}.")
@@ -211,97 +209,56 @@ fn handle_command<'a>(
211209
ChatCommand::Work(cmd) => workqueue_commands(ctx, gh_id, cmd).await,
212210
}
213211
} else {
214-
todo!()
212+
// We are in a stream, where someone wrote `@**triagebot** <command(s)>`
213+
let cmd_index = words
214+
.iter()
215+
.position(|w| *w == "@**triagebot**")
216+
.unwrap_or(words.len());
217+
let cmd_index = cmd_index + 1;
218+
if cmd_index >= words.len() {
219+
return Ok(Some("Unknown command".to_string()));
220+
}
221+
let cmd = StreamCommand::try_parse_from(&words[cmd_index..])?;
222+
match cmd {
223+
StreamCommand::EndTopic => {
224+
post_waiter(&ctx, message_data, WaitingMessage::end_topic())
225+
.await
226+
.map_err(|e| format_err!("Failed to await at this time: {e:?}"))
227+
}
228+
StreamCommand::EndMeeting => {
229+
post_waiter(&ctx, message_data, WaitingMessage::end_meeting())
230+
.await
231+
.map_err(|e| format_err!("Failed to await at this time: {e:?}"))
232+
}
233+
StreamCommand::Read => {
234+
post_waiter(&ctx, message_data, WaitingMessage::start_reading())
235+
.await
236+
.map_err(|e| format_err!("Failed to await at this time: {e:?}"))
237+
}
238+
StreamCommand::PingGoals {
239+
threshold,
240+
next_update,
241+
} => {
242+
if project_goals::check_project_goal_acl(&ctx.github, gh_id).await? {
243+
ping_project_goals_owners(
244+
&ctx.github,
245+
&ctx.zulip,
246+
false,
247+
threshold as i64,
248+
&format!("on {next_update}"),
249+
)
250+
.await
251+
.map_err(|e| format_err!("Failed to await at this time: {e:?}"))?;
252+
Ok(None)
253+
} else {
254+
Err(format_err!(
255+
"That command is only permitted for those running the project-goal program.",
256+
))
257+
}
258+
}
259+
StreamCommand::DocsUpdate => trigger_docs_update(message_data, &ctx.zulip),
260+
}
215261
}
216-
217-
// match next {
218-
// Some("acknowledge") | Some("ack") => acknowledge(&ctx, gh_id, words).await
219-
// .map_err(|e| format_err!("Failed to parse acknowledgement, expected `(acknowledge|ack) <identifier>`: {e:?}.")),
220-
// Some("add") => add_notification(&ctx, gh_id, words).await
221-
// .map_err(|e| format_err!("Failed to parse description addition, expected `add <url> <description (multiple words)>`: {e:?}.")),
222-
// Some("move") => move_notification(&ctx, gh_id, words).await
223-
// .map_err(|e| format_err!("Failed to parse movement, expected `move <from> <to>`: {e:?}.")),
224-
// Some("meta") => add_meta_notification(&ctx, gh_id, words).await
225-
// .map_err(|e| format_err!("Failed to parse `meta` command. Synopsis: meta <num> <text>: Add <text> to your notification identified by <num> (>0)\n\nError: {e:?}")),
226-
// Some("whoami") => whoami_cmd(&ctx, gh_id, words).await
227-
// .map_err(|e| format_err!("Failed to run the `whoami` command. Synopsis: whoami: Show to which Rust teams you are a part of\n\nError: {e:?}")),
228-
// Some("lookup") => lookup_cmd(&ctx, words).await
229-
// .map_err(|e| format_err!("Failed to run the `lookup` command. Synopsis: lookup (github <zulip-username>|zulip <github-username>): Show the GitHub username of a Zulip <user> or the Zulip username of a GitHub user\n\nError: {e:?}")),
230-
// Some("work") => workqueue_commands(ctx, gh_id, words).await
231-
// .map_err(|e| format_err!("Failed to parse `work` command. Help: {WORKQUEUE_HELP}\n\nError: {e:?}")),
232-
// _ => {
233-
// while let Some(word) = next {
234-
// if word == "@**triagebot**" {
235-
// let next = words.next();
236-
// match next {
237-
// Some("end-topic") | Some("await") => {
238-
// return post_waiter(&ctx, message_data, WaitingMessage::end_topic())
239-
// .await
240-
// .map_err(|e| {
241-
// format_err!("Failed to await at this time: {e:?}")
242-
// })
243-
// }
244-
// Some("end-meeting") => {
245-
// return post_waiter(
246-
// &ctx,
247-
// message_data,
248-
// WaitingMessage::end_meeting(),
249-
// )
250-
// .await
251-
// .map_err(|e| format_err!("Failed to await at this time: {e:?}"))
252-
// }
253-
// Some("read") => {
254-
// return post_waiter(
255-
// &ctx,
256-
// message_data,
257-
// WaitingMessage::start_reading(),
258-
// )
259-
// .await
260-
// .map_err(|e| format_err!("Failed to await at this time: {e:?}"))
261-
// }
262-
// Some("ping-goals") => {
263-
// let usage_err = |description: &str| Err(format_err!(
264-
// "Error: {description}\n\
265-
// \n\
266-
// Usage: triagebot ping-goals D N, where:\n\
267-
// \n\
268-
// * D is the number of days before an update is considered stale\n\
269-
// * N is the date of next update, like \"Sep-5\"\n",
270-
// ));
271-
//
272-
// let Some(threshold) = words.next() else {
273-
// return usage_err("expected number of days");
274-
// };
275-
// let threshold = match i64::from_str(threshold) {
276-
// Ok(v) => v,
277-
// Err(e) => return usage_err(&format!("ill-formed number of days, {e}")),
278-
// };
279-
//
280-
// let Some(next_update) = words.next() else {
281-
// return usage_err("expected date of next update");
282-
// };
283-
//
284-
// if project_goals::check_project_goal_acl(&ctx.github, gh_id).await? {
285-
// ping_project_goals_owners(&ctx.github, &ctx.zulip, false, threshold, &format!("on {next_update}"))
286-
// .await
287-
// .map_err(|e| format_err!("Failed to await at this time: {e:?}"))?;
288-
// return Ok(None);
289-
// } else {
290-
// return Err(format_err!(
291-
// "That command is only permitted for those running the project-goal program.",
292-
// ));
293-
// }
294-
// }
295-
// Some("docs-update") => return trigger_docs_update(message_data, &ctx.zulip),
296-
// _ => {}
297-
// }
298-
// }
299-
// next = words.next();
300-
// }
301-
//
302-
// Ok(Some(String::from("Unknown command")))
303-
// }
304-
// }
305262
})
306263
}
307264

src/zulip/commands.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::db::review_prefs::RotationMode;
33
use std::num::NonZeroU32;
44
use std::str::FromStr;
55

6+
/// Command sent in a DM with triagebot on Zulip.
67
#[derive(clap::Parser, Debug)]
78
pub enum ChatCommand {
89
/// Acknowledge a notification
@@ -133,3 +134,24 @@ impl FromStr for IdentifierCli {
133134
}
134135
}
135136
}
137+
138+
/// Command sent in a Zulip stream after `@**triagebot**`.
139+
#[derive(clap::Parser, Debug)]
140+
pub enum StreamCommand {
141+
/// End the current topic.
142+
#[clap(alias = "await")]
143+
EndTopic,
144+
/// End the current meeting.
145+
EndMeeting,
146+
/// Read a document.
147+
Read,
148+
/// Ping project goal owners.
149+
PingGoals {
150+
/// Number of days before an update is considered stale
151+
threshold: u64,
152+
/// Date of next update
153+
next_update: String,
154+
},
155+
/// Update docs
156+
DocsUpdate,
157+
}

0 commit comments

Comments
 (0)