]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/seen.rb
seen: cyclically store two of the users' latest actions in the registry
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / seen.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: Seen Plugin
5 #
6 # Keep a database of who last said/did what
7
8 define_structure :Saw, :nick, :time, :type, :where, :message
9
10 class SeenPlugin < Plugin
11   Config.register Config::IntegerValue.new('seen.max_results',
12     :default => 3, :validate => Proc.new{|v| v >= 0},
13     :desc => "Maximum number of seen users to return in search (0 = no limit).")
14
15   def help(plugin, topic="")
16     "seen <nick> => have you seen, or when did you last see <nick>"
17   end
18
19   def privmsg(m)
20     unless(m.params =~ /^(\S)+$/)
21       m.reply "incorrect usage: " + help(m.plugin)
22       return
23     end
24
25     m.params.gsub!(/\?$/, "")
26
27     if @registry.has_key?(m.params)
28       m.reply seen(@registry[m.params])
29     else
30       rx = Regexp.new(m.params, true)
31       num_matched = 0
32       @registry.each {|nick, saw|
33         if nick.match(rx)
34           m.reply seen(saw)
35           num_matched += 1
36           break if num_matched == @bot.config['seen.max_results']
37         end
38       }
39
40       m.reply "nope!" if num_matched.zero?
41     end
42   end
43
44   def listen(m)
45     return unless m.source
46     # keep database up to date with who last said what
47     now = Time.new
48     case m
49     when PrivMessage
50       return if m.private?
51       type = m.action? ? 'ACTION' : 'PUBLIC'
52       store m, Saw.new(m.sourcenick.dup, now, type,
53                        m.target.to_s, m.message.dup)
54     when QuitMessage
55       return if m.address?
56       store m, Saw.new(m.sourcenick.dup, now, "QUIT",
57                        nil, m.message.dup)
58     when NickMessage
59       return if m.address?
60       store m, Saw.new(m.oldnick, now, "NICK", nil, m.newnick)
61     when PartMessage
62       return if m.address?
63       store m, Saw.new(m.sourcenick.dup, Time.new, "PART",
64                        m.target.to_s, m.message.dup)
65     when JoinMessage
66       return if m.address?
67       store m, Saw.new(m.sourcenick.dup, Time.new, "JOIN",
68                        m.target.to_s, m.message.dup)
69     when TopicMessage
70       return if m.address? or m.info_or_set == :info
71       store m, Saw.new(m.sourcenick.dup, Time.new, "TOPIC",
72                        m.target.to_s, m.message.dup)
73     end
74   end
75
76   def seen(reg)
77     saw = case reg
78     when Struct::Saw
79       reg # for backwards compatibility
80     when Array
81       reg.last
82     end
83
84     ret = "#{saw.nick} was last seen "
85     ago = Time.new - saw.time
86
87     if (ago.to_i == 0)
88       ret << "just now, "
89     else
90       ret << Utils.secs_to_string(ago) + " ago, "
91     end
92
93     case saw.type.to_sym
94     when :PUBLIC
95       ret << "saying #{saw.message}"
96     when :ACTION
97       ret << "doing #{saw.nick} #{saw.message}"
98     when :NICK
99       ret << "changing nick from #{saw.nick} to #{saw.message}"
100     when :PART
101       ret << "leaving #{saw.where}"
102     when :JOIN
103       ret << "joining #{saw.where}"
104     when :QUIT
105       ret << "quitting IRC (#{saw.message})"
106     when :TOPIC
107       ret << "changing the topic of #{saw.where} to #{saw.message}"
108     end
109   end
110
111   def store(m, saw)
112     reg = @registry[saw.nick]
113
114     if reg && reg.is_a?(Array)
115       reg.shift if reg.size > 1
116       reg.push(saw)
117     else
118       reg = [saw]
119     end
120
121     if m.is_a? NickMessage
122       @registry[m.newnick] = reg
123     end
124
125     @registry[saw.nick] = reg
126   end
127 end
128 plugin = SeenPlugin.new
129 plugin.register("seen")