]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/salut.rb
salut plugin: handles multi-lingual salutations (hello/goodbye)
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / salut.rb
1 # vim: set sw=2 et:\r
2 # Salutations plugin: respond to salutations\r
3 \r
4 unless Array.respond_to?(:pick_one)\r
5   debug "Defining the pick_one method for Array"\r
6   class ::Array\r
7     def pick_one\r
8       return nil if self.empty?\r
9       self[rand(self.length)]\r
10     end\r
11   end\r
12 end\r
13 \r
14 \r
15 class SalutPlugin < Plugin\r
16   BotConfig.register BotConfigBooleanValue.new('salut.all_languages',\r
17     :default => true, \r
18     :desc => "Check for a salutation in all languages and not just in the one defined by core.language",\r
19     :on_change => Proc.new {|bot, v| bot.plugins['salut'].reload}\r
20   )\r
21 \r
22   def initialize\r
23     @salutations = Hash.new\r
24     @match = nil\r
25     @main_lang_str = nil\r
26     @main_lang = nil\r
27     @all_langs = true\r
28     super\r
29     reload\r
30   end\r
31 \r
32   def set_language(what)\r
33     reload\r
34   end\r
35 \r
36   def create_match\r
37     @match = Hash.new\r
38     ar_in = Array.new\r
39     ar_out = Array.new\r
40     ar_both = Array.new\r
41     @salutations.each { |lang, hash|\r
42       hash.each { |situation, array|\r
43         case situation.to_s\r
44         when /in$/\r
45           ar_in += array\r
46         when /out$/\r
47           ar_out += array\r
48         else\r
49           ar_both += array\r
50         end\r
51       }\r
52     }\r
53     @match[:in] = Regexp.new("\\b(?:" + ar_in.uniq.map { |txt|\r
54       Regexp.escape(txt)\r
55     }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_in.empty?\r
56     @match[:out] = Regexp.new("\\b(?:" + ar_out.uniq.map { |txt|\r
57       Regexp.escape(txt)\r
58     }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_out.empty?\r
59     @match[:both] = Regexp.new("\\b(?:" + ar_both.uniq.map { |txt|\r
60       Regexp.escape(txt)\r
61     }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_both.empty?\r
62     debug "Matches: #{@match.inspect}"\r
63   end\r
64 \r
65   def listen(m)\r
66     salut = nil\r
67     [:both, :in, :out].each { |k|\r
68       next unless @match[k]\r
69       debug "Checking salutations #{k} (#{@match[k].inspect})"\r
70       if m.message =~ /^#{@match[k]}/\r
71         salut = k\r
72         break\r
73       end\r
74     }\r
75     return unless salut\r
76     h = Time.new.hour\r
77     case h\r
78     when 4...12\r
79       salut_reply(m, salut, :morning)\r
80     when 12...18\r
81       salut_reply(m, salut, :afternoon)\r
82     else\r
83       salut_reply(m, salut, :evening)\r
84     end\r
85   end\r
86 \r
87   def salut_reply(m, k, time)\r
88     debug "Replying to #{k} in the #{time}"\r
89     case k\r
90     when :both\r
91       sfx = ""\r
92     else\r
93       sfx = "-#{k}"\r
94     end\r
95     debug "Building array ..."\r
96     rep_ar = Array.new\r
97     rep_ar += @salutations[@main_lang].fetch("#{time}#{sfx}".to_sym, [])\r
98     rep_ar += @salutations[@main_lang].fetch("#{time}".to_sym, []) unless sfx.empty?\r
99     rep_ar += @salutations[@main_lang].fetch("generic#{sfx}".to_sym, [])\r
100     rep_ar += @salutations[@main_lang].fetch("generic".to_sym, []) unless sfx.empty?\r
101     debug "Choosing reply in #{rep_ar.inspect} ..."\r
102     if rep_ar.empty?\r
103       if m.public? and (m.address? or m =~ /#{Regexp.escape(@bot.nick)}/)\r
104         choice = @bot.lang.get("hello_X") % m.sourcenick\r
105       else\r
106         choice = @bot.lang.get("hello") % m.sourcenick\r
107       end\r
108     else\r
109       choice = rep_ar.pick_one\r
110       if m.public? and (m.address? or m.message =~ /#{Regexp.escape(@bot.nick)}/)\r
111         choice += "#{[',',''].pick_one} #{m.sourcenick}"\r
112         choice += [" :)", " :D", "!", "", "", ""].pick_one\r
113       end\r
114     end\r
115     debug "Replying #{choice}"\r
116     m.plainreply choice\r
117   end\r
118 \r
119   def reload\r
120     save\r
121     @main_lang_str = @bot.config['core.language']\r
122     @main_lang = @main_lang_str.to_sym\r
123     @all_langs = @bot.config['salut.all_languages']\r
124     if @all_langs\r
125       # Get all available languages\r
126       langs = Dir.new("#{@bot.botclass}/salut").collect {|f|\r
127         f =~ /salut-([^.]+)/ ? $1 : nil\r
128       }.compact\r
129       langs.each { |lang|\r
130         @salutations[lang.to_sym] = load_lang(lang)\r
131       }\r
132     else\r
133       @salutations.clear\r
134       @salutations[@main_lang] = load_lang(@main_lang_str)\r
135     end\r
136     create_match\r
137   end\r
138 \r
139   def load_lang(lang)\r
140     file = "#{@bot.botclass}/salut/salut-#{lang}"\r
141     if File.exist?(file)\r
142       begin\r
143         salutations = Hash.new\r
144         content = YAML::load_file(file)\r
145         content.each { |key, val|\r
146           salutations[key.to_sym] = val\r
147         }\r
148         return salutations\r
149       rescue\r
150         error "failed to read salutations in #{lang}: #{$!}"\r
151       end\r
152     end\r
153     return nil\r
154   end\r
155 \r
156   def save\r
157     return if @salutations.empty?\r
158     @salutations.each { |lang, val|\r
159       l = lang.to_s\r
160       save_lang(lang, val)\r
161     }\r
162   end\r
163 \r
164   def save_lang(lang, val)\r
165     file = "#{@bot.botclass}/salut/salut-#{lang}"\r
166     Utils.safe_save(file) { |file|\r
167       file.puts val.to_yaml\r
168     }\r
169   end\r
170 \r
171 end\r
172 \r
173 plugin = SalutPlugin.new\r
174 \r