]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/salut.rb
ircbot: do not use debug in sendmsg() because it breaks script. script plugin: handle...
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / salut.rb
index 1a301b438e13619011b75ba1e387bd733f525407..feff2dd63c9efe880d5acf0b3f2d0129cf143e99 100644 (file)
@@ -1,16 +1,17 @@
-# vim: set sw=2 et:\r
+#-- vim:sw=2:et\r
+#++\r
+#\r
+# :title: Salutations plugin for rbot\r
+#\r
+# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>\r
+# Copyright:: (C) 2006-2007 Giuseppe Bilotta\r
+# License:: GPL v2\r
+#\r
 # Salutations plugin: respond to salutations\r
-\r
-unless Array.respond_to?(:pick_one)\r
-  debug "Defining the pick_one method for Array"\r
-  class ::Array\r
-    def pick_one\r
-      return nil if self.empty?\r
-      self[rand(self.length)]\r
-    end\r
-  end\r
-end\r
-\r
+#\r
+# TODO:: allow online editing of salutations\r
+#\r
+# TODO:: *REMEMBER* to set @changed to true after edit or changes won't be saved\r
 \r
 class SalutPlugin < Plugin\r
   BotConfig.register BotConfigBooleanValue.new('salut.all_languages',\r
@@ -18,13 +19,21 @@ class SalutPlugin < Plugin
     :desc => "Check for a salutation in all languages and not just in the one defined by core.language",\r
     :on_change => Proc.new {|bot, v| bot.plugins['salut'].reload}\r
   )\r
+  BotConfig.register BotConfigBooleanValue.new('salut.address_only',\r
+    :default => true, \r
+    :desc => "When set to true, the bot will only reply to salutations directed at him",\r
+    :on_change => Proc.new {|bot, v| bot.plugins['salut'].reload}\r
+  )\r
+\r
 \r
   def initialize\r
     @salutations = Hash.new\r
-    @match = nil\r
+    @match = Hash.new\r
+    @match_langs = Array.new\r
     @main_lang_str = nil\r
     @main_lang = nil\r
     @all_langs = true\r
+    @changed = false\r
     super\r
     reload\r
   end\r
@@ -34,13 +43,20 @@ class SalutPlugin < Plugin
   end\r
 \r
   def create_match\r
-    @match = Hash.new\r
+    @match.clear\r
+    ar_dest = Array.new\r
     ar_in = Array.new\r
     ar_out = Array.new\r
     ar_both = Array.new\r
     @salutations.each { |lang, hash|\r
+      ar_dest.clear\r
+      ar_in.clear\r
+      ar_out.clear\r
+      ar_both.clear\r
       hash.each { |situation, array|\r
         case situation.to_s\r
+        when /^generic-dest$/\r
+          ar_dest += array\r
         when /in$/\r
           ar_in += array\r
         when /out$/\r
@@ -49,30 +65,55 @@ class SalutPlugin < Plugin
           ar_both += array\r
         end\r
       }\r
+      @match[lang] = Hash.new\r
+      @match[lang][:in] = Regexp.new("\\b(?:" + ar_in.uniq.map { |txt|\r
+        Regexp.escape(txt)\r
+      }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_in.empty?\r
+      @match[lang][:out] = Regexp.new("\\b(?:" + ar_out.uniq.map { |txt|\r
+        Regexp.escape(txt)\r
+      }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_out.empty?\r
+      @match[lang][:both] = Regexp.new("\\b(?:" + ar_both.uniq.map { |txt|\r
+        Regexp.escape(txt)\r
+      }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_both.empty?\r
+      @match[lang][:dest] = Regexp.new("\\b(?:" + ar_dest.uniq.map { |txt|\r
+        Regexp.escape(txt)\r
+      }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_dest.empty?\r
+    }\r
+    @punct = /\s*[.,:!;?]?\s*/ # Punctuation\r
+\r
+    # Languages to match for, in order\r
+    @match_langs.clear\r
+    @match_langs << @main_lang if @match.key?(@main_lang)\r
+    @match_langs << :english if @match.key?(:english)\r
+    @match.each_key { |key|\r
+      @match_langs << key\r
     }\r
-    @match[:in] = Regexp.new("\\b(?:" + ar_in.uniq.map { |txt|\r
-      Regexp.escape(txt)\r
-    }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_in.empty?\r
-    @match[:out] = Regexp.new("\\b(?:" + ar_out.uniq.map { |txt|\r
-      Regexp.escape(txt)\r
-    }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_out.empty?\r
-    @match[:both] = Regexp.new("\\b(?:" + ar_both.uniq.map { |txt|\r
-      Regexp.escape(txt)\r
-    }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_both.empty?\r
-    debug "Matches: #{@match.inspect}"\r
+    @match_langs.uniq!\r
   end\r
 \r
   def listen(m)\r
+    return if @match.empty?\r
+    return unless m.kind_of?(PrivMessage)\r
+    return if m.address? and m.plugin == 'config'\r
+    to_me = m.address? || m.message =~ /#{Regexp.escape(@bot.nick)}/i\r
+    if @bot.config['salut.address_only']\r
+      return unless to_me\r
+    end\r
     salut = nil\r
-    [:both, :in, :out].each { |k|\r
-      next unless @match[k]\r
-      debug "Checking salutations #{k} (#{@match[k].inspect})"\r
-      if m.message =~ /^#{@match[k]}/\r
-        salut = k\r
-        break\r
-      end\r
+    @match_langs.each { |lang|\r
+      [:both, :in, :out].each { |k|\r
+        next unless @match[lang][k]\r
+        if m.message =~ @match[lang][k]\r
+          salut = [@match[lang][k], lang, k]\r
+          break\r
+        end\r
+      }\r
+      break if salut\r
     }\r
     return unless salut\r
+    # If the bot wasn't addressed, we continue only if the match was exact\r
+    # (apart from space and punctuation) or if @match[:dest] matches too\r
+    return unless to_me or m.message =~ /^#{@punct}#{salut.first}#{@punct}$/ or m.message =~ @match[salut[1]][:dest] \r
     h = Time.new.hour\r
     case h\r
     when 4...12\r
@@ -84,8 +125,12 @@ class SalutPlugin < Plugin
     end\r
   end\r
 \r
-  def salut_reply(m, k, time)\r
-    debug "Replying to #{k} in the #{time}"\r
+  def salut_reply(m, salut, time)\r
+    lang = salut[1]\r
+    k = salut[2]\r
+    debug "Replying to #{salut.first} (#{lang} #{k}) in the #{time}"\r
+    # salut_ar = @salutations[@main_lang].update @salutations[:english].update @salutations[lang]\r
+    salut_ar = @salutations[lang]\r
     case k\r
     when :both\r
       sfx = ""\r
@@ -94,13 +139,13 @@ class SalutPlugin < Plugin
     end\r
     debug "Building array ..."\r
     rep_ar = Array.new\r
-    rep_ar += @salutations[@main_lang].fetch("#{time}#{sfx}".to_sym, [])\r
-    rep_ar += @salutations[@main_lang].fetch("#{time}".to_sym, []) unless sfx.empty?\r
-    rep_ar += @salutations[@main_lang].fetch("generic#{sfx}".to_sym, [])\r
-    rep_ar += @salutations[@main_lang].fetch("generic".to_sym, []) unless sfx.empty?\r
+    rep_ar += salut_ar.fetch("#{time}#{sfx}".to_sym, [])\r
+    rep_ar += salut_ar.fetch("#{time}".to_sym, []) unless sfx.empty?\r
+    rep_ar += salut_ar.fetch("generic#{sfx}".to_sym, [])\r
+    rep_ar += salut_ar.fetch("generic".to_sym, []) unless sfx.empty?\r
     debug "Choosing reply in #{rep_ar.inspect} ..."\r
     if rep_ar.empty?\r
-      if m.public? and (m.address? or m =~ /#{Regexp.escape(@bot.nick)}/)\r
+      if m.public? and (m.address? or m =~ /#{Regexp.escape(@bot.nick)}/)\r
         choice = @bot.lang.get("hello_X") % m.sourcenick\r
       else\r
         choice = @bot.lang.get("hello") % m.sourcenick\r
@@ -134,9 +179,14 @@ class SalutPlugin < Plugin
       @salutations[@main_lang] = load_lang(@main_lang_str)\r
     end\r
     create_match\r
+    @changed = false\r
   end\r
 \r
   def load_lang(lang)\r
+    dir = "#{@bot.botclass}/salut"\r
+    if not File.exist?(dir)\r
+      Dir.mkdir(dir)\r
+    end\r
     file = "#{@bot.botclass}/salut/salut-#{lang}"\r
     if File.exist?(file)\r
       begin\r
@@ -155,15 +205,17 @@ class SalutPlugin < Plugin
 \r
   def save\r
     return if @salutations.empty?\r
+    return unless @changed\r
     @salutations.each { |lang, val|\r
       l = lang.to_s\r
       save_lang(lang, val)\r
     }\r
+    @changed = false\r
   end\r
 \r
   def save_lang(lang, val)\r
-    file = "#{@bot.botclass}/salut/salut-#{lang}"\r
-    Utils.safe_save(file) { |file|\r
+    fn = "#{@bot.botclass}/salut/salut-#{lang}"\r
+    Utils.safe_save(fn) { |file|\r
       file.puts val.to_yaml\r
     }\r
   end\r