4 # :title: Factoids pluing
6 # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
7 # Copyright:: (C) 2007 Giuseppe Bilotta
10 # Store (and retrieve) unstructured one-sentence factoids
12 class FactoidsPlugin < Plugin
16 @hash = hash.reject { |k, val| val.nil? or val.empty? rescue false }
17 raise ArgumentError, "no fact!" unless @hash[:fact]
18 if String === @hash[:when]
19 @hash[:when] = Time.parse @hash[:when]
32 @hash.send(:[]=,*args)
38 alias :to_hash :to_hsh
41 class FactoidList < ArrayOf
49 self.map { |f| f[:fact] }.index(fact)
69 @dir = File.join(@bot.botclass,"factoids")
70 @filename = "factoids.rbot"
71 @factoids = FactoidList.new
76 def read_factfile(name=@filename,dir=@dir)
77 fname = File.join(dir,name)
79 factoids = File.readlines(fname)
80 return if factoids.empty?
81 firstline = factoids.shift
82 pattern = firstline.chomp.split(" | ")
83 if pattern.length == 1 and pattern.first != "fact"
84 factoids.unshift(firstline)
86 @factoids << Factoid.new( :fact => f.chomp )
89 pattern.map! { |p| p.intern }
90 raise ArgumentError, "fact must be the last field" unless pattern.last == :fact
92 ar = f.chomp.split(" | ", pattern.length)
93 @factoids << Factoid.new(Hash[*([pattern, ar].transpose.flatten)])
100 return unless @changed
101 Dir.mkdir(@dir) unless FileTest.directory?(@dir)
102 fname = File.join(@dir,@filename)
103 ar = ["when | who | where | fact"]
105 ar << "%s | %s | %s | %s" % [ f[:when], f[:who], f[:where], f[:fact]]
107 Utils.safe_save(fname) do |file|
113 def help(plugin, topic="")
114 _("factoids plugin: learn that <factoid>, forget that <factoids>, facts about <words>")
118 factoid = Factoid.new(
119 :fact => params[:stuff].to_s,
121 :who => m.source.fullform,
122 :where => m.channel.to_s
124 if @factoids.index(factoid)
125 m.reply _("I already know that %{factoid}" % { :factoid => factoid })
133 def forget(m, params)
134 factoid = params[:stuff].to_s
135 if @factoids.delete(factoid)
139 m.reply _("I didn't know that %{factoid}" % { :factoid => factoid })
144 if params[:words].empty?
145 m.reply _("I know %{count} facts" % { :count => @factoids.length })
147 rx = Regexp.new(params[:words].to_s, true)
148 known = @factoids.grep(rx)
150 m.reply _("I know nothing about %{words}" % params)
152 m.reply known.join(" | "), :split_at => /\s+\|\s+/
160 total = @factoids.length
162 idx = params[:index].scan(/\d+/).first.to_i
163 if idx <= 0 or idx > total
164 m.reply _("please select a fact number between 1 and %{total}" % { :total => total })
167 fact = @factoids[idx-1]
170 if params[:words].empty?
172 m.reply _("I know nothing")
177 rx = Regexp.new(params[:words].to_s, true)
178 known = @factoids.grep(rx)
180 m.reply _("I know nothing about %{words}" % params)
184 fact = known.pick_one
185 idx = @factoids.index(fact)+1
190 metadata << _("from %{who}" % fact.to_hash)
193 metadata << _("on %{when}" % fact.to_hash)
196 metadata << _("in %{where}" % fact.to_hash)
198 unless metadata.empty?
199 meta = _(" [learnt %{data}]" % {:data => metadata.join(" ")})
201 m.reply _("fact #%{idx} of %{total}: %{fact}%{meta}" % {
209 def edit_fact(m, params)
212 total = @factoids.length
213 idx = params[:index].scan(/\d+/).first.to_i
214 if idx <= 0 or idx > total
215 m.reply _("please select a fact number between 1 and %{total}" % { :total => total })
218 fact = @factoids[idx-1]
221 who = params[:who].to_s.sub(/^me$/, m.source.fullform)
226 fact[:when] = Time.parse(params[:when].to_s)
229 fact[:where] = params[:where].to_s
232 m.reply _("couldn't change learn data for fact %{fact}: %{err}" % {
243 plugin = FactoidsPlugin.new
245 plugin.default_auth('edit', false)
247 plugin.map 'learn that *stuff'
248 plugin.map 'forget that *stuff', :auth_path => 'edit'
249 plugin.map 'facts [about *words]'
250 plugin.map 'fact [about *words]'
251 plugin.map 'fact :index', :requirements => { :index => /^#?\d+$/ }
252 plugin.map 'fact :index :learn from *who', :action => :edit_fact, :requirements => { :learn => /^((?:is|was)\s+)?learn(ed|t)$/, :index => /^#?\d+$/ }, :auth_path => 'edit'
253 plugin.map 'fact :index :learn on *when', :action => :edit_fact, :requirements => { :learn => /^((?:is|was)\s+)?learn(ed|t)$/, :index => /^#?\d+$/ }, :auth_path => 'edit'
254 plugin.map 'fact :index :learn in *where', :action => :edit_fact, :requirements => { :learn => /^((?:is|was)\s+)?learn(ed|t)$/, :index => /^#?\d+$/ }, :auth_path => 'edit'