@@ -14,7 +14,7 @@ use crate::team_data::{people, teams};
1414use crate :: utils:: pluralize;
1515use crate :: zulip:: api:: { MessageApiResponse , Recipient } ;
1616use crate :: zulip:: client:: ZulipClient ;
17- use crate :: zulip:: commands:: { ChatCommand , LookupCmd , WorkqueueCmd , WorkqueueLimit } ;
17+ use crate :: zulip:: commands:: { ChatCommand , LookupCmd , StreamCommand , WorkqueueCmd , WorkqueueLimit } ;
1818use anyhow:: { format_err, Context as _} ;
1919use clap:: Parser ;
2020use 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
0 commit comments