]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/seen.rb
nickserv: add 'ghosted' to nickserv.nick_avail
[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     if reg.kind_of? Array
85       before = reg.first
86     end
87
88     formats = {
89       :normal      => _("%{nick} was last seen %{when}, %{doing}"),
90       :with_before => _("%{nick} was last seen %{when}, %{doing} and %{time} before %{did_before}")
91     }
92
93     if before && [:PART, :QUIT].include?(saw.type.to_sym) &&
94        [:PUBLIC, :ACTION].include?(before.type.to_sym)
95       did_before = case before.type.to_sym
96       when :PUBLIC
97         _("saying \"%{message}\"")
98       when :ACTION
99         _("doing *%{nick} %{message}*")
100       end % {
101         :nick => saw.nick,
102         :message => before.message
103       }
104
105       format = :with_before
106
107       time_diff = saw.time - before.time
108       if time_diff < 300
109         time_before = _("a moment")
110       elsif time_diff < 3600
111         time_before = _("a while")
112       else
113         format = :normal
114       end
115     else
116       format = :normal
117     end
118
119     nick = saw.nick
120     ago = Time.new - saw.time
121
122     if (ago.to_i == 0)
123       time = _("just now")
124     else
125       time = _("%{time} ago") % { :time => Utils.secs_to_string(ago) }
126     end
127
128     doing = case saw.type.to_sym
129     when :PUBLIC
130       _("saying \"%{message}\"")
131     when :ACTION
132       _("doing *%{message}*")
133     when :NICK
134       _("changing nick from %{nick} to %{message}")
135     when :PART
136       if saw.message.empty?
137         _("leaving %{where}")
138       else
139         _("leaving %{where} (%{message})")
140       end
141     when :JOIN
142       _("joining %{where}")
143     when :QUIT
144       _("quitting IRC (%{message})")
145     when :TOPIC
146       _("changing the topic of %{where} to \"%{message}\"")
147     end % { :message => saw.message, :where => saw.where, :nick => saw.nick }
148
149     case format
150     when :normal
151       formats[:normal] % {
152         :nick  => saw.nick,
153         :when  => time,
154         :doing => doing,
155       }
156     when :with_before
157       formats[:with_before] % {
158         :nick  => saw.nick,
159         :when  => time,
160         :doing => doing,
161         :time  => time_before,
162         :did_before => did_before
163       }
164     end
165   end
166
167   def store(m, saw)
168     reg = @registry[saw.nick]
169
170     if reg && reg.is_a?(Array)
171       reg.shift if reg.size > 1
172       reg.push(saw)
173     else
174       reg = [saw]
175     end
176
177     if m.is_a? NickMessage
178       @registry[m.newnick] = reg
179     end
180
181     @registry[saw.nick] = reg
182   end
183 end
184 plugin = SeenPlugin.new
185 plugin.register("seen")