Jelajahi Sumber

dictionary: Improve knowing when bot is addressed

Previously it was case sensitive so the bot would not respond to
commands given with its nick not matching the case. Now it is not.
Will Storey 9 tahun lalu
induk
melakukan
f2c333d166
2 mengubah file dengan 79 tambahan dan 14 penghapusan
  1. 37 14
      dictionary.tcl
  2. 42 0
      dictionary_test.tcl

+ 37 - 14
dictionary.tcl

@@ -91,9 +91,9 @@ proc ::dictionary::public {nick host hand chan argv} {
     return
     return
   }
   }
 
 
-  # Ignore cases of '<mynick>:' because those are commands to us. We deal with
+  # Ignore cases of '<botnick>:' because those are commands to us. We deal with
   # them in a different proc.
   # them in a different proc.
-  if {[lindex [split $argv] 0] == "$botnick:"} {
+  if {[::dictionary::is_addressing_bot $argv $botnick]} {
     return
     return
   }
   }
 
 
@@ -150,8 +150,8 @@ proc ::dictionary::public {nick host hand chan argv} {
   puthelp "PRIVMSG $chan :$def"
   puthelp "PRIVMSG $chan :$def"
 }
 }
 
 
-# public trigger. this handles interaction to set/clear terms
-# and for responding directly by the bot.
+# Public trigger. This handles commands such as setting, deleting, and listing
+# terms the bot knows about.
 proc ::dictionary::publearn {nick host hand chan argv} {
 proc ::dictionary::publearn {nick host hand chan argv} {
   global botnick
   global botnick
   variable terms
   variable terms
@@ -161,15 +161,17 @@ proc ::dictionary::publearn {nick host hand chan argv} {
   }
   }
   set argv [stripcodes "uacgbr" $argv]
   set argv [stripcodes "uacgbr" $argv]
 
 
-  # we only respond to the case where the message starts
-  # with '<botnick>:'
-  if {[lindex [split $argv] 0] != "$botnick:"} {
+  # We only respond if we are directly addressed (botnick: ). This indicates
+  # someone is giving us a command.
+  if {![::dictionary::is_addressing_bot $argv $botnick]} {
     return
     return
   }
   }
 
 
-  # try to set a term.
-  # this can be done by: <botnick>: <term> is <definition>
-  # and: <botnick>: <term>, <definition>
+  # Try to set a term.
+  #
+  # This can be done by: <botnick>: <term> is <definition>
+  #
+  # Or: <botnick>: <term>, <definition>
   if {([lsearch $argv "is"] >= 0 && [llength $argv] >= 4) \
   if {([lsearch $argv "is"] >= 0 && [llength $argv] >= 4) \
     || ([string first "," $argv]>-1 && [llength $argv] >= 3)} \
     || ([string first "," $argv]>-1 && [llength $argv] >= 3)} \
   {
   {
@@ -201,7 +203,7 @@ proc ::dictionary::publearn {nick host hand chan argv} {
       return
       return
     }
     }
 
 
-    # set it, and send a random success response.
+    # Set it, and send a random success response.
     set term_dict [dict create]
     set term_dict [dict create]
     dict set term_dict def $description
     dict set term_dict def $description
     dict set term_dict include_term_in_def $include_term_in_def
     dict set term_dict include_term_in_def $include_term_in_def
@@ -211,7 +213,7 @@ proc ::dictionary::publearn {nick host hand chan argv} {
     return
     return
   }
   }
 
 
-  # delete a term. <botnick>: forget <term>
+  # Delete a term. <botnick>: forget <term>
   if {[lindex [split $argv] 1] == "forget" && [llength $argv] >= 3} {
   if {[lindex [split $argv] 1] == "forget" && [llength $argv] >= 3} {
     set term [lrange [split $argv] 2 end]
     set term [lrange [split $argv] 2 end]
     # if it does not exist, then send a random deny response.
     # if it does not exist, then send a random deny response.
@@ -225,7 +227,7 @@ proc ::dictionary::publearn {nick host hand chan argv} {
     return
     return
   }
   }
 
 
-  # message the nick all terms we have
+  # Message the nick all terms we have
   if {[lindex [split $argv] 1] == "listem" && [llength $argv] == 2} {
   if {[lindex [split $argv] 1] == "listem" && [llength $argv] == 2} {
     foreach term [lsort -dictionary [dict keys $terms]] {
     foreach term [lsort -dictionary [dict keys $terms]] {
       set term_dict [dict get $terms $term]
       set term_dict [dict get $terms $term]
@@ -235,11 +237,32 @@ proc ::dictionary::publearn {nick host hand chan argv} {
     return
     return
   }
   }
 
 
-  # unknown command. send a random chatty response.
+  # Unknown command. send a random chatty response.
   set response [::dictionary::get_chatty_response $nick]
   set response [::dictionary::get_chatty_response $nick]
   putserv "PRIVMSG $chan :$response"
   putserv "PRIVMSG $chan :$response"
 }
 }
 
 
+# Return 1 if the given line is addressing the bot.
+#
+# This is the case if the line is of the form:
+# <botnick>:
+#
+# For example if the bot's nick is:
+# bot: Hi there
+#
+# This is checked case insensitively.
+proc ::dictionary::is_addressing_bot {text botnick} {
+  set text [string trim $text]
+  set text [string tolower $text]
+
+  set prefix [string tolower $botnick]
+  append prefix :
+
+  set idx [string first $prefix $text]
+
+  return [expr $idx == 0]
+}
+
 # Return 1 if the string contains the term. This is tested case insensitively.
 # Return 1 if the string contains the term. This is tested case insensitively.
 #
 #
 # The term is present only if it is by itself surrounded whitespace or
 # The term is present only if it is by itself surrounded whitespace or

+ 42 - 0
dictionary_test.tcl

@@ -22,6 +22,10 @@ proc ::tests {} {
 		set success 0
 		set success 0
 	}
 	}
 
 
+	if {![::test_is_addressing_bot]} {
+		set success 0
+	}
+
 	if {$success} {
 	if {$success} {
 		puts "Success!"
 		puts "Success!"
 	} else {
 	} else {
@@ -94,4 +98,42 @@ proc ::test_string_contains_term {} {
 	return [expr $failed == 0]
 	return [expr $failed == 0]
 }
 }
 
 
+proc ::test_is_addressing_bot {} {
+	set tests [list \
+		[dict create line "bot: hi"    botnick "bot" want 1] \
+		[dict create line "BOT: hi"    botnick "bot" want 1] \
+		[dict create line "bot: hi"    botnick "BOT" want 1] \
+		[dict create line "bot:hi"     botnick "BOT" want 1] \
+		[dict create line "bot hi"     botnick "bot" want 0] \
+		[dict create line "bot2: hi"   botnick "bot" want 0] \
+		[dict create line ": hi"       botnick "bot" want 0] \
+		[dict create line "hi bot: hi" botnick "bot" want 0] \
+		[dict create line "bbot: hi"   botnick "bot" want 0] \
+		[dict create line "botbot: hi" botnick "bot" want 0] \
+	]
+
+	set failed 0
+
+	foreach test $tests {
+		set line [dict get $test line]
+		set botnick [dict get $test botnick]
+		set want [dict get $test want]
+
+		set output [::dictionary::is_addressing_bot $line $botnick]
+		if {$output != $want} {
+			puts [format "FAILURE: is_addressing_bot(\"%s\", \"%s\") = %d, wanted %d" \
+				$s $line $botnick $want]
+
+			incr failed
+		}
+	}
+
+	if {$failed != 0} {
+		puts [format "string_contains_term: %d/%d tests failed" $failed \
+			[llength $tests]]
+	}
+
+	return [expr $failed == 0]
+}
+
 ::tests
 ::tests