Explorar el Código

Support multiple different bot names

Currently the triagebot name on GitHub isn't owned by the Rust org, but seems to
be largely unused too. However, we're calling the tool triagebot, and users can
easily get it wrong by calling the tool triagebot on GitHub rather than rustbot
(the "real" name).

For now, just accept both names interchangeably. We do not issue a warning for
the time being.
Mark Rousskov hace 4 años
padre
commit
f346181e01
Se han modificado 2 ficheros con 44 adiciones y 20 borrados
  1. 42 18
      parser/src/command.rs
  2. 2 2
      src/handlers.rs

+ 42 - 18
parser/src/command.rs

@@ -12,7 +12,7 @@ pub mod relabel;
 pub mod second;
 pub mod second;
 
 
 pub fn find_command_start(input: &str, bot: &str) -> Option<usize> {
 pub fn find_command_start(input: &str, bot: &str) -> Option<usize> {
-    input.find(&format!("@{}", bot))
+    input.to_ascii_lowercase().find(&format!("@{}", bot))
 }
 }
 
 
 #[derive(Debug, PartialEq)]
 #[derive(Debug, PartialEq)]
@@ -32,7 +32,9 @@ pub struct Input<'a> {
     all: &'a str,
     all: &'a str,
     parsed: usize,
     parsed: usize,
     code: ColorCodeBlocks,
     code: ColorCodeBlocks,
-    bot: &'a str,
+
+    // A list of possible bot names.
+    bot: Vec<&'a str>,
 }
 }
 
 
 fn parse_single_command<'a, T, F, M>(
 fn parse_single_command<'a, T, F, M>(
@@ -56,7 +58,7 @@ where
 }
 }
 
 
 impl<'a> Input<'a> {
 impl<'a> Input<'a> {
-    pub fn new(input: &'a str, bot: &'a str) -> Input<'a> {
+    pub fn new(input: &'a str, bot: Vec<&'a str>) -> Input<'a> {
         Input {
         Input {
             all: input,
             all: input,
             parsed: 0,
             parsed: 0,
@@ -67,10 +69,15 @@ impl<'a> Input<'a> {
 
 
     fn parse_command(&mut self) -> Option<Command<'a>> {
     fn parse_command(&mut self) -> Option<Command<'a>> {
         let mut tok = Tokenizer::new(&self.all[self.parsed..]);
         let mut tok = Tokenizer::new(&self.all[self.parsed..]);
-        assert_eq!(
-            tok.next_token().unwrap(),
-            Some(Token::Word(&format!("@{}", self.bot)))
-        );
+        let name_length = if let Ok(Some(Token::Word(bot_name))) = tok.next_token() {
+            assert!(self
+                .bot
+                .iter()
+                .any(|name| bot_name.eq_ignore_ascii_case(&format!("@{}", name))));
+            bot_name.len()
+        } else {
+            panic!("no bot name?")
+        };
         log::info!("identified potential command");
         log::info!("identified potential command");
 
 
         let mut success = vec![];
         let mut success = vec![];
@@ -140,7 +147,7 @@ impl<'a> Input<'a> {
         self.parsed += if c.is_ok() {
         self.parsed += if c.is_ok() {
             tok.position()
             tok.position()
         } else {
         } else {
-            self.bot.len() + 1
+            name_length
         };
         };
         Some(c)
         Some(c)
     }
     }
@@ -151,7 +158,11 @@ impl<'a> Iterator for Input<'a> {
 
 
     fn next(&mut self) -> Option<Command<'a>> {
     fn next(&mut self) -> Option<Command<'a>> {
         loop {
         loop {
-            let start = find_command_start(&self.all[self.parsed..], self.bot)?;
+            let start = self
+                .bot
+                .iter()
+                .filter_map(|name| find_command_start(&self.all[self.parsed..], name))
+                .min()?;
             self.parsed += start;
             self.parsed += start;
             if let Some(command) = self.parse_command() {
             if let Some(command) = self.parse_command() {
                 return Some(command);
                 return Some(command);
@@ -184,14 +195,14 @@ impl<'a> Command<'a> {
 fn errors_outside_command_are_fine() {
 fn errors_outside_command_are_fine() {
     let input =
     let input =
         "haha\" unterminated quotes @bot modify labels: +bug. Terminating after the command";
         "haha\" unterminated quotes @bot modify labels: +bug. Terminating after the command";
-    let mut input = Input::new(input, "bot");
+    let mut input = Input::new(input, vec!["bot"]);
     assert!(input.next().unwrap().is_ok());
     assert!(input.next().unwrap().is_ok());
 }
 }
 
 
 #[test]
 #[test]
 fn code_1() {
 fn code_1() {
     let input = "`@bot modify labels: +bug.`";
     let input = "`@bot modify labels: +bug.`";
-    let mut input = Input::new(input, "bot");
+    let mut input = Input::new(input, vec!["bot"]);
     assert!(input.next().is_none());
     assert!(input.next().is_none());
 }
 }
 
 
@@ -200,32 +211,32 @@ fn code_2() {
     let input = "```
     let input = "```
     @bot modify labels: +bug.
     @bot modify labels: +bug.
     ```";
     ```";
-    let mut input = Input::new(input, "bot");
+    let mut input = Input::new(input, vec!["bot"]);
     assert!(input.next().is_none());
     assert!(input.next().is_none());
 }
 }
 
 
 #[test]
 #[test]
 fn edit_1() {
 fn edit_1() {
     let input_old = "@bot modify labels: +bug.";
     let input_old = "@bot modify labels: +bug.";
-    let mut input_old = Input::new(input_old, "bot");
+    let mut input_old = Input::new(input_old, vec!["bot"]);
     let input_new = "Adding labels: @bot modify labels: +bug. some other text";
     let input_new = "Adding labels: @bot modify labels: +bug. some other text";
-    let mut input_new = Input::new(input_new, "bot");
+    let mut input_new = Input::new(input_new, vec!["bot"]);
     assert_eq!(input_old.next(), input_new.next());
     assert_eq!(input_old.next(), input_new.next());
 }
 }
 
 
 #[test]
 #[test]
 fn edit_2() {
 fn edit_2() {
     let input_old = "@bot modify label: +bug.";
     let input_old = "@bot modify label: +bug.";
-    let mut input_old = Input::new(input_old, "bot");
+    let mut input_old = Input::new(input_old, vec!["bot"]);
     let input_new = "@bot modify labels: +bug.";
     let input_new = "@bot modify labels: +bug.";
-    let mut input_new = Input::new(input_new, "bot");
+    let mut input_new = Input::new(input_new, vec!["bot"]);
     assert_ne!(input_old.next(), input_new.next());
     assert_ne!(input_old.next(), input_new.next());
 }
 }
 
 
 #[test]
 #[test]
 fn move_input_along() {
 fn move_input_along() {
     let input = "@bot modify labels: +bug. Afterwards, delete the world.";
     let input = "@bot modify labels: +bug. Afterwards, delete the world.";
-    let mut input = Input::new(input, "bot");
+    let mut input = Input::new(input, vec!["bot"]);
     assert!(input.next().unwrap().is_ok());
     assert!(input.next().unwrap().is_ok());
     assert_eq!(&input.all[input.parsed..], " Afterwards, delete the world.");
     assert_eq!(&input.all[input.parsed..], " Afterwards, delete the world.");
 }
 }
@@ -233,8 +244,21 @@ fn move_input_along() {
 #[test]
 #[test]
 fn move_input_along_1() {
 fn move_input_along_1() {
     let input = "@bot modify labels\": +bug. Afterwards, delete the world.";
     let input = "@bot modify labels\": +bug. Afterwards, delete the world.";
-    let mut input = Input::new(input, "bot");
+    let mut input = Input::new(input, vec!["bot"]);
     assert!(input.next().unwrap().is_err());
     assert!(input.next().unwrap().is_err());
     // don't move input along if parsing the command fails
     // don't move input along if parsing the command fails
     assert_eq!(&input.all[..input.parsed], "@bot");
     assert_eq!(&input.all[..input.parsed], "@bot");
 }
 }
+
+#[test]
+fn multiname() {
+    let input = "@rustbot modify labels: +bug. Afterwards, delete the world. @triagebot prioritize";
+    let mut input = Input::new(input, vec!["triagebot", "rustbot"]);
+    assert!(dbg!(input.next().unwrap()).is_ok());
+    assert_eq!(
+        &input.all[input.parsed..],
+        " Afterwards, delete the world. @triagebot prioritize"
+    );
+    assert!(input.next().unwrap().is_ok());
+    assert!(input.next().is_none());
+}

+ 2 - 2
src/handlers.rs

@@ -156,9 +156,9 @@ macro_rules! command_handlers {
                 }
                 }
             }
             }
 
 
-            let input = Input::new(&body, &ctx.username);
+            let input = Input::new(&body, vec![&ctx.username, "triagebot"]);
             let commands = if let Some(previous) = event.comment_from() {
             let commands = if let Some(previous) = event.comment_from() {
-                let prev_commands = Input::new(&previous, &ctx.username).collect::<Vec<_>>();
+                let prev_commands = Input::new(&previous, vec![&ctx.username, "triagebot"]).collect::<Vec<_>>();
                 input.filter(|cmd| !prev_commands.contains(cmd)).collect::<Vec<_>>()
                 input.filter(|cmd| !prev_commands.contains(cmd)).collect::<Vec<_>>()
             } else {
             } else {
                 input.collect()
                 input.collect()