4 # :title: Salutations plugin for rbot
6 # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
7 # Copyright:: (C) 2006-2007 Giuseppe Bilotta
10 # Salutations plugin: respond to salutations
12 # TODO:: allow online editing of salutations
14 class SalutPlugin < Plugin
15 Config.register Config::BooleanValue.new('salut.all_languages',
17 :desc => "Check for a salutation in all languages and not just in the one defined by core.language",
18 :on_change => Proc.new {|bot, v| bot.plugins['salut'].reload})
20 Config.register Config::BooleanValue.new('salut.address_only',
22 :desc => "When set to true, the bot will only reply to salutations directed at him",
23 :on_change => Proc.new {|bot, v| bot.plugins['salut'].reload})
29 @match_langs = Array.new
34 def set_language(language)
38 def load_static_files(path)
39 debug "loading salutation rules from #{path}"
40 Dir.glob("#{path}/*").map { |filename|
41 language = filename[filename.rindex('-')+1..-1]
44 content = YAML::load_file(filename)
45 content.each { |key, val|
46 salutations[key.to_sym] = val
49 error "failed to read salutations in #{filename}: #{$!}"
51 [language, salutations]
56 @salutations = @registry[:salutations]
58 # migrate existing data files
59 if not @salutations and Dir.exists? datafile
60 log "migrate existing salutations from #{datafile}"
62 @salutations = load_static_files(datafile)
65 # load initial salutations from plugin directory
67 log "load initial salutations from #{plugin_path}"
69 initial_path = File.join(plugin_path, 'salut')
70 @salutations = load_static_files(initial_path)
73 debug @salutations.inspect
79 return unless @salutations
81 @registry[:salutations] = @salutations
87 use_all_languages = @bot.config['salut.all_languages']
94 @salutations.each { |lang, hash|
95 next if lang != @language and not use_all_languages
100 hash.each { |situation, array|
102 when /^generic-dest$/
112 @match[lang] = Hash.new
113 @match[lang][:in] = Regexp.new("\\b(?:" + ar_in.uniq.map { |txt|
115 }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_in.empty?
116 @match[lang][:out] = Regexp.new("\\b(?:" + ar_out.uniq.map { |txt|
118 }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_out.empty?
119 @match[lang][:both] = Regexp.new("\\b(?:" + ar_both.uniq.map { |txt|
121 }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_both.empty?
122 @match[lang][:dest] = Regexp.new("\\b(?:" + ar_dest.uniq.map { |txt|
124 }.join('|') + ")\\b", Regexp::IGNORECASE) unless ar_dest.empty?
126 @punct = /\s*[.,:!;?]?\s*/ # Punctuation
128 # Languages to match for, in order
130 @match_langs << @language if @match.key?(@language)
131 @match_langs << 'english' if @match.key?('english')
132 @match.each_key { |key|
139 return if @match.empty?
140 return unless m.kind_of?(PrivMessage)
141 return if m.address? and m.plugin == 'config'
142 to_me = m.address? || m.message =~ /#{Regexp.escape(@bot.nick)}/i
143 if @bot.config['salut.address_only']
147 @match_langs.each { |lang|
148 [:both, :in, :out].each { |k|
149 next unless @match[lang][k]
150 if m.message =~ @match[lang][k]
151 salut = [@match[lang][k], lang, k]
158 # If the bot wasn't addressed, we continue only if the match was exact
159 # (apart from space and punctuation) or if @match[:dest] matches too
160 return unless to_me or m.message =~ /^#{@punct}#{salut.first}#{@punct}$/ or m.message =~ @match[salut[1]][:dest]
164 salut_reply(m, salut, :morning)
166 salut_reply(m, salut, :afternoon)
168 salut_reply(m, salut, :evening)
172 def salut_reply(m, salut, time)
175 debug "Replying to #{salut.first} (#{lang} #{k}) in the #{time}"
176 salut_ar = @salutations[lang]
183 debug "Building array ..."
185 rep_ar += salut_ar.fetch("#{time}#{sfx}".to_sym, [])
186 rep_ar += salut_ar.fetch("#{time}".to_sym, []) unless sfx.empty?
187 rep_ar += salut_ar.fetch("generic#{sfx}".to_sym, [])
188 rep_ar += salut_ar.fetch("generic".to_sym, []) unless sfx.empty?
189 debug "Choosing reply in #{rep_ar.inspect} ..."
191 if m.public? # and (m.address? or m =~ /#{Regexp.escape(@bot.nick)}/)
192 choice = @bot.lang.get("hello_X") % m.sourcenick
194 choice = @bot.lang.get("hello") % m.sourcenick
197 choice = rep_ar.pick_one
198 if m.public? and (m.address? or m.message =~ /#{Regexp.escape(@bot.nick)}/)
199 choice += "#{[',',''].pick_one} #{m.sourcenick}"
200 choice += [" :)", " :D", "!", "", "", ""].pick_one
203 debug "Replying #{choice}"
204 m.reply choice, :nick => false, :to => :public