]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/commitdiff
+ handle WHOIS queries
authorGiuseppe Bilotta <giuseppe.bilotta@gmail.com>
Sat, 9 Aug 2008 23:43:32 +0000 (01:43 +0200)
committerGiuseppe Bilotta <giuseppe.bilotta@gmail.com>
Sat, 9 Aug 2008 23:47:13 +0000 (01:47 +0200)
The bot now exposes a whois(nick) method to make WHOIS queries to the
server. The extended syntax whois(nick, server) is also supported,
allowing another server to be queried (this is useful to retrieve info
which is only available on nick's server, such as idle time and signon
date).

Most if not all RFC-compliant replies are handled, although some of the
data received is currently ignored. Non-RFC extended replies such as
nickserv identification status are not hanlded yet, since they are
highly server-specific, both in numeric reply choice (e.g. 307 vs 320)
and in reply message syntax and meaning.

A new WhoisMessage is also introduced, for plugin delegation. The source
is the originating server, the target is the user for which information
was requested. A #whois() method is provided holding all retrieved
information.

lib/rbot/irc.rb
lib/rbot/ircbot.rb
lib/rbot/message.rb
lib/rbot/rfc2812.rb

index 23bd9e0da2b922df16ea8b3fdb5104da321fab1e..2eb676e2ed0506ce465f59f492884044b5241362 100644 (file)
@@ -922,7 +922,7 @@ module Irc
   class User < Netmask
     alias :to_s :nick
 
-    attr_accessor :real_name
+    attr_accessor :real_name, :idle_since, :signon
 
     # Create a new IRC User from a given Netmask (or anything that can be converted
     # into a Netmask) provided that the given Netmask does not have globs.
@@ -934,6 +934,8 @@ module Irc
       raise ArgumentError, "#{str.inspect} must not have globs (unescaped * or ?)" if host.has_irc_glob? && host != "*"
       @away = false
       @real_name = String.new
+      @idle_since = nil
+      @signon = nil
     end
 
     # The nick of a User may be changed freely, but it must not contain glob patterns.
index 0d934e33f0621430fc36e5ee09cedb7344bc43ec..4f5018e30758a04b73a27d164f2cfb34945385bb 100644 (file)
@@ -698,6 +698,12 @@ class Bot
       m.modes = data[:modes]
       @plugins.delegate "modechange", m
     }
+    @client[:whois] = proc {|data|
+      source = data[:source]
+      target = server.get_user(data[:whois][:nick])
+      m = WhoisMessage.new(self, server, source, target, data[:whois])
+      @plugins.delegate "whois", m
+    }
     @client[:join] = proc {|data|
       m = JoinMessage.new(self, server, data[:source], data[:channel], data[:message])
       sendq("MODE #{data[:channel]}", nil, 0) if m.address?
@@ -1209,6 +1215,11 @@ class Bot
     sendq "MODE #{channel} #{mode} #{target}", channel, 2
   end
 
+  # asking whois
+  def whois(nick, target=nil)
+    sendq "WHOIS #{target} #{nick}", nil, 0
+  end
+
   # kicking a user
   def kick(channel, user, msg)
     sendq "KICK #{channel} #{user} :#{msg}", channel, 2
index 5d6ea60f28e10c89d07e42163407c92e3bd7845e..6d14b2137c8007d6fb519c94d28119e204e8428b 100644 (file)
@@ -553,6 +553,21 @@ module Irc
     end
   end
 
+  # class to manage WHOIS replies
+  class WhoisMessage < BasicUserMessage
+    attr_reader :whois
+    def initialize(bot, server, source, target, whois)
+      super(bot, server, source, target, "")
+      @address = (target == @bot.myself)
+      @whois = whois
+    end
+
+    def inspect
+      fields = ' whois=' << whois.inspect
+      super(fields)
+    end
+  end
+
   # class to manage NAME replies
   class NamesMessage < BasicUserMessage
     attr_accessor :users
index 758f574e0bde8a5ca076708196e6bffdfdd327ed..d781c0f1f7e9bb0a805e081d4c5a5954e1cd4eb1 100644 (file)
@@ -1288,6 +1288,62 @@ module Irc
           handle(:who, data)
         when RPL_ENDOFWHO
           handle(:eowho, data)
+        when RPL_WHOISUSER
+          @whois ||= Hash.new
+          @whois[:nick] = argv[1]
+          @whois[:user] = argv[2]
+          @whois[:host] = argv[3]
+          @whois[:real_name] = argv[-1]
+
+          user = @server.get_user(@whois[:nick])
+          user.user = @whois[:user]
+          user.host = @whois[:host]
+          user.real_name = @whois[:real_name]
+        when RPL_WHOISSERVER
+          @whois ||= Hash.new
+          @whois[:nick] = argv[1]
+          @whois[:server] = argv[2]
+          @whois[:server_info] = argv[-1]
+          # TODO update user info
+        when RPL_WHOISOPERATOR
+          @whois ||= Hash.new
+          @whois[:nick] = argv[1]
+          @whois[:operator] = argv[-1]
+          # TODO update user info
+        when RPL_WHOISIDLE
+          @whois ||= Hash.new
+          @whois[:nick] = argv[1]
+          user = @server.get_user(@whois[:nick])
+          @whois[:idle] = argv[2].to_i
+          user.idle_since = Time.now - @whois[:idle]
+          if argv[-1] == 'seconds idle, signon time'
+            @whois[:signon] = Time.at(argv[3].to_i)
+            user.signon = @whois[:signon]
+          end
+        when RPL_ENDOFWHOIS
+          @whois ||= Hash.new
+          @whois[:nick] = argv[1]
+          data[:whois] = @whois.dup
+          @whois.clear
+          handle(:whois, data)
+        when RPL_WHOISCHANNELS
+          @whois ||= Hash.new
+          @whois[:nick] = argv[1]
+          @whois[:channels] = []
+          user = @server.get_user(@whois[:nick])
+          argv[-1].split.each do |prechan|
+            pfx = prechan.scan(/[#{@server.supports[:prefix][:prefixes].join}]/)
+            modes = pfx.map { |p| @server.mode_for_prefix p }
+            chan = prechan[pfx.length..prechan.length]
+
+            channel = @server.get_channel(chan)
+            if channel
+              channel.add_user(user, :silent => true)
+              modes.map { |mode| channel.mode[mode].set(user) }
+            end
+
+            @whois[:channels] << [chan, modes]
+          end
         when RPL_CHANNELMODEIS
           parse_mode(serverstring, argv[1..-1], data)
           handle(:mode, data)