end
end
+ # TODO default should be language-specific
+ Config.register Config::ArrayValue.new('factoids.trigger_pattern',
+ :default => [
+ "(this|that|a|the|an|all|both)\\s+(.*)\\s+(is|are)\\s+.*:2",
+ "(this|that|a|the|an|all|both)\\s+(.*?)\\s+(is|are)\\s+.*:2",
+ "(.*)\\s+(is|are)\\s+.*",
+ "(.*?)\\s+(is|are)\\s+.*",
+ ],
+ :on_change => Proc.new { |bot, v| bot.plugins['factoids'].reset_triggers },
+ :desc => "A list of regular expressions matching factoids where keywords can be identified. append ':n' if the keyword is defined by the n-th group instead of the first. if the list is empty, any word will be considered a keyword")
+ Config.register Config::BooleanValue.new('factoids.address',
+ :default => true,
+ :desc => "Should the bot reply with relevant factoids only when addressed with a direct question? If not, the bot will attempt to lookup foo if someone says 'foo?' in channel")
+
def initialize
super
@dir = File.join(@bot.botclass,"factoids")
@filename = "factoids.rbot"
@factoids = FactoidList.new
+ @triggers = Set.new
begin
read_factfile
rescue
:fname => fname
})
end
+ reset_triggers
end
def save
@changed = false
end
+ def trigger_patterns_to_rx
+ return [] if @bot.config['factoids.trigger_pattern'].empty?
+ @bot.config['factoids.trigger_pattern'].inject([]) { |list, str|
+ s = str.dup
+ if s =~ /:(\d+)$/
+ idx = $1.to_i
+ s.sub!(/:\d+$/,'')
+ else
+ idx = 1
+ end
+ list << [/^#{s}$/iu, idx]
+ }
+ end
+
+ def parse_for_trigger(f, rx=nil)
+ if !rx
+ regs = trigger_patterns_to_rx
+ else
+ regs = rx
+ end
+ if regs.empty?
+ f.to_s.scan(/\w+/u)
+ else
+ regs.inject([]) { |list, a|
+ r = a.first
+ i = a.last
+ m = r.match(f.to_s)
+ if m
+ list << m[i].downcase
+ else
+ list
+ end
+ }
+ end
+ end
+
+ def reset_triggers
+ return unless @factoids
+ start_time = Time.now
+ rx = trigger_patterns_to_rx
+ triggers = @factoids.inject(Set.new) { |set, f|
+ found = parse_for_trigger(f, rx)
+ if found.empty?
+ set
+ else
+ set | found
+ end
+ }
+ debug "Triggers done in #{Time.now - start_time}"
+ @triggers.replace(triggers)
+ end
+
def help(plugin, topic="")
_("factoids plugin: learn that <factoid>, forget that <factoids>, facts about <words>")
end
:who => m.source.fullform,
:where => m.channel.to_s
)
- if @factoids.index(factoid)
- m.reply _("I already know that %{factoid}" % { :factoid => factoid })
+ if idx = @factoids.index(factoid)
+ m.reply _("I already know that %{factoid} [#%{idx}]" % {
+ :factoid => factoid,
+ :idx => idx
+ })
else
@factoids << factoid
@changed = true
m.okay
+ fact(m, :index => @factoids.length.to_s)
+ parse_for_trigger(factoid)
end
end
end
end
+ def unreplied(m)
+ return if @bot.config['factoids.address'] and !m.address?
+ return if @factoids.empty?
+ return if @triggers.empty?
+ return unless m.message =~ /^(.*)\?\s*$/
+ query = $1.strip.downcase
+ if @triggers.include?(query)
+ facts(m, :words => query)
+ end
+ end
+
def fact(m, params)
fact = nil
idx = 0