prioritize.rs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. use crate::{
  2. config::PrioritizeConfig,
  3. github::{self, Event},
  4. handlers::{Context, Handler},
  5. interactions::ErrorComment,
  6. };
  7. use futures::future::{BoxFuture, FutureExt};
  8. use parser::command::prioritize::PrioritizeCommand;
  9. use parser::command::{Command, Input};
  10. pub(super) struct PrioritizeHandler;
  11. impl Handler for PrioritizeHandler {
  12. type Input = PrioritizeCommand;
  13. type Config = PrioritizeConfig;
  14. fn parse_input(&self, ctx: &Context, event: &Event) -> Result<Option<Self::Input>, String> {
  15. let body = if let Some(b) = event.comment_body() {
  16. b
  17. } else {
  18. // not interested in other events
  19. return Ok(None);
  20. };
  21. if let Event::Issue(e) = event {
  22. if e.action != github::IssuesAction::Opened {
  23. log::debug!("skipping event, issue was {:?}", e.action);
  24. // skip events other than opening the issue to avoid retriggering commands in the
  25. // issue body
  26. return Ok(None);
  27. }
  28. }
  29. let mut input = Input::new(&body, &ctx.username);
  30. match input.parse_command() {
  31. Command::Prioritize(Ok(cmd)) => Ok(Some(cmd)),
  32. _ => Ok(None),
  33. }
  34. }
  35. fn handle_input<'a>(
  36. &self,
  37. ctx: &'a Context,
  38. config: &'a Self::Config,
  39. event: &'a Event,
  40. _cmd: Self::Input,
  41. ) -> BoxFuture<'a, anyhow::Result<()>> {
  42. handle_input(ctx, config, event).boxed()
  43. }
  44. }
  45. async fn handle_input(ctx: &Context, config: &PrioritizeConfig, event: &Event) -> anyhow::Result<()> {
  46. let is_team_member = if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.github).await {
  47. false
  48. } else {
  49. true
  50. };
  51. let issue = event.issue().unwrap();
  52. if !is_team_member {
  53. let cmnt = ErrorComment::new(&issue, "Only Rust team members can prioritize issues.");
  54. cmnt.post(&ctx.github).await?;
  55. return Ok(());
  56. }
  57. if issue.labels().iter().any(|l| l.name == "I-prioritize") {
  58. let cmnt = ErrorComment::new(&issue, "This issue is already prioritized!");
  59. cmnt.post(&ctx.github).await?;
  60. return Ok(());
  61. }
  62. let mut labels = issue.labels().to_owned();
  63. labels.push(github::Label {
  64. name: "I-prioritize".to_string(),
  65. });
  66. let github_req = issue.set_labels(&ctx.github, labels);
  67. let mut zulip_topic = format!("I-pri #{} {}", issue.number, issue.title);
  68. zulip_topic.truncate(60); // Zulip limitation
  69. let client = reqwest::Client::new(); // TODO: have a Zulip Client akin to GithubClient
  70. let zulip_req = client.post("https://rust-lang.zulipchat.com/api/v1/messages")
  71. .form(&[
  72. ("type", "stream"),
  73. ("to", config.zulip_stream.to_string().as_str()),
  74. ("topic", &zulip_topic),
  75. ("content", "@*WG-prioritization*"),
  76. ])
  77. .send();
  78. let (gh_res, zulip_res) = futures::join!(github_req, zulip_req);
  79. gh_res?;
  80. zulip_res?;
  81. Ok(())
  82. }