]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/factoids.rb
factoids plugin: fact command (get a random fact). Remove fact command from chucknorr...
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / factoids.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: Factoids pluing
5 #
6 # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
7 # Copyright:: (C) 2007 Giuseppe Bilotta
8 # License:: GPLv2
9 #
10 # Store (and retrieve) unstructured one-sentence factoids
11
12 class FactoidsPlugin < Plugin
13
14   class Factoid
15     def initialize(hash)
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]
20       end
21     end
22
23     def to_s
24       @hash[:fact]
25     end
26
27     def [](*args)
28       @hash[*args]
29     end
30
31     def to_hsh
32       return @hash
33     end
34   end
35
36   class FactoidList < ArrayOf
37     def initialize(ar=[])
38       super(Factoid, ar)
39     end
40
41     def index(f)
42       fact = f.to_s
43       return if fact.empty?
44       self.map { |f| f[:fact] }.index(fact)
45     end
46
47     def delete(f)
48       idx = index(f)
49       return unless idx
50       self.delete_at(idx)
51     end
52
53     def grep(x)
54       self.find_all { |f|
55         x === f[:fact]
56       }
57     end
58   end
59
60   def initialize
61     super
62
63     # TODO config
64     @dir = File.join(@bot.botclass,"factoids")
65     @filename = "factoids.rbot"
66     @factoids = FactoidList.new
67     read_factfile
68     @changed = false
69   end
70
71   def read_factfile(name=@filename,dir=@dir)
72     fname = File.join(dir,name)
73     if File.exist?(fname)
74       factoids = File.readlines(fname)
75       return if factoids.empty?
76       firstline = factoids.shift
77       pattern = firstline.chomp.split(" | ")
78       if pattern.length == 1 and pattern.first != "fact"
79         factoids.unshift(firstline)
80         factoids.each { |f|
81           @factoids << Factoid.new( :fact => f.chomp )
82         }
83       else
84         pattern.map! { |p| p.intern }
85         raise ArgumentError, "fact must be the last field" unless pattern.last == :fact
86         factoids.each { |f|
87           ar = f.chomp.split(" | ", pattern.length)
88           @factoids << Factoid.new(Hash[*([pattern, ar].transpose.flatten)])
89         }
90       end
91     end
92   end
93
94   def save
95     return unless @changed
96     Dir.mkdir(@dir) unless FileTest.directory?(@dir)
97     fname = File.join(@dir,@filename)
98     ar = ["when | who | where | fact"]
99     @factoids.each { |f|
100       ar << "%s | %s | %s | %s" % [ f[:when], f[:who], f[:where], f[:fact]]
101     }
102     Utils.safe_save(fname) do |file|
103       file.puts ar
104     end
105     @changed = false
106   end
107
108   def help(plugin, topic="")
109     _("factoids plugin: learn that <factoid>, forget that <factoids>, facts about <words>")
110   end
111
112   def learn(m, params)
113     factoid = Factoid.new(
114       :fact => params[:stuff].to_s,
115       :when => Time.now,
116       :who => m.source.fullform,
117       :where => m.channel.to_s
118     )
119     if @factoids.index(factoid)
120       m.reply _("I already know that %{factoid}" % { :factoid => factoid })
121     else
122       @factoids << factoid
123       @changed = true
124       m.okay
125     end
126   end
127
128   def forget(m, params)
129     factoid = params[:stuff].to_s
130     if @factoids.delete(factoid)
131       @changed = true
132       m.okay
133     else
134       m.reply _("I didn't know that %{factoid}" % { :factoid => factoid })
135     end
136   end
137
138   def facts(m, params)
139     if params[:words].empty?
140       m.reply _("I know %{count} facts" % { :count => @factoids.length })
141     else
142       rx = Regexp.new(params[:words].to_s, true)
143       known = @factoids.grep(rx)
144       if known.empty?
145         m.reply _("I know nothing about %{words}" % params)
146       else
147         m.reply known.join(" | "), :split_at => /\s+\|\s+/
148       end
149     end
150   end
151
152   def fact(m, params)
153     known = nil
154     if params[:words].empty?
155       if @factoids.empty?
156         m.reply _("I know nothing")
157         return
158       end
159       known = @factoids
160     else
161       rx = Regexp.new(params[:words].to_s, true)
162       known = @factoids.grep(rx)
163       if known.empty?
164         m.reply _("I know nothing about %{words}" % params)
165         return
166       end
167     end
168     fact = known.pick_one
169     idx = @factoids.index(fact)+1
170     m.reply _("fact %{idx}/%{total}: %{fact}" % {
171       :idx => idx,
172       :total => @factoids.length,
173       :fact => fact
174     })
175   end
176
177 end
178
179 plugin = FactoidsPlugin.new
180 plugin.map 'learn that *stuff'
181 plugin.map 'forget that *stuff'
182 plugin.map 'facts [about *words]'
183 plugin.map 'fact [about *words]'