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