#-- vim:sw=2:et #++ # # :title: Seen Plugin # # Keep a database of who last said/did what define_structure :Saw, :nick, :time, :type, :where, :message class SeenPlugin < Plugin Config.register Config::IntegerValue.new('seen.max_results', :default => 3, :validate => Proc.new{|v| v >= 0}, :desc => "Maximum number of seen users to return in search (0 = no limit).") def help(plugin, topic="") "seen => have you seen, or when did you last see " end def privmsg(m) unless(m.params =~ /^(\S)+$/) m.reply "incorrect usage: " + help(m.plugin) return end m.params.gsub!(/\?$/, "") if @registry.has_key?(m.params) m.reply seen(@registry[m.params]) else rx = Regexp.new(m.params, true) num_matched = 0 @registry.each {|nick, saw| if nick.match(rx) m.reply seen(saw) num_matched += 1 break if num_matched == @bot.config['seen.max_results'] end } m.reply "nope!" if num_matched.zero? end end def listen(m) return unless m.source # keep database up to date with who last said what now = Time.new case m when PrivMessage return if m.private? type = m.action? ? 'ACTION' : 'PUBLIC' store m, Saw.new(m.sourcenick.dup, now, type, m.target.to_s, m.message.dup) when QuitMessage return if m.address? store m, Saw.new(m.sourcenick.dup, now, "QUIT", nil, m.message.dup) when NickMessage return if m.address? store m, Saw.new(m.oldnick, now, "NICK", nil, m.newnick) when PartMessage return if m.address? store m, Saw.new(m.sourcenick.dup, Time.new, "PART", m.target.to_s, m.message.dup) when JoinMessage return if m.address? store m, Saw.new(m.sourcenick.dup, Time.new, "JOIN", m.target.to_s, m.message.dup) when TopicMessage return if m.address? or m.info_or_set == :info store m, Saw.new(m.sourcenick.dup, Time.new, "TOPIC", m.target.to_s, m.message.dup) end end def seen(reg) saw = case reg when Struct::Saw reg # for backwards compatibility when Array reg.last end ret = "#{saw.nick} was last seen " ago = Time.new - saw.time if (ago.to_i == 0) ret << "just now, " else ret << Utils.secs_to_string(ago) + " ago, " end case saw.type.to_sym when :PUBLIC ret << "saying \"#{saw.message}\"" when :ACTION ret << "doing #{saw.nick} #{saw.message}" when :NICK ret << "changing nick from #{saw.nick} to #{saw.message}" when :PART ret << "leaving #{saw.where}" ret << " (#{saw.message})" unless saw.message.empty? when :JOIN ret << "joining #{saw.where}" when :QUIT ret << "quitting IRC (#{saw.message})" when :TOPIC ret << "changing the topic of #{saw.where} to \"#{saw.message}\"" end case saw.type.to_sym when :PART, :QUIT before = reg.first if before.type == "PUBLIC" || before.type == "ACTION" time_diff = saw.time - before.time if time_diff < 300 time = "a moment" elsif time_diff < 3600 time = "a while" else return ret end ret << ' and %{time} before' % { :time => time } if before.type == "PUBLIC" ret << ' saying "%{message}"' % { :message => before.message } elsif before.type == "ACTION" ret << ' doing *%{message}*' % { :nick => saw.nick, :message => before.message } end end end return ret end def store(m, saw) reg = @registry[saw.nick] if reg && reg.is_a?(Array) reg.shift if reg.size > 1 reg.push(saw) else reg = [saw] end if m.is_a? NickMessage @registry[m.newnick] = reg end @registry[saw.nick] = reg end end plugin = SeenPlugin.new plugin.register("seen")