summaryrefslogtreecommitdiff
path: root/lib/rbot
diff options
context:
space:
mode:
authorGiuseppe Bilotta <giuseppe.bilotta@gmail.com>2008-08-10 01:43:32 +0200
committerGiuseppe Bilotta <giuseppe.bilotta@gmail.com>2008-08-10 01:47:13 +0200
commiteebdc6973a6ab1089ed18c0ea02e72cd6e656120 (patch)
tree714e77316f6015ce19d371534a41819d342acbb1 /lib/rbot
parentfa4a71c43227669b42b4b1c0a68be796091f3d1d (diff)
+ handle WHOIS queries
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.
Diffstat (limited to 'lib/rbot')
-rw-r--r--lib/rbot/irc.rb4
-rw-r--r--lib/rbot/ircbot.rb11
-rw-r--r--lib/rbot/message.rb15
-rw-r--r--lib/rbot/rfc2812.rb56
4 files changed, 85 insertions, 1 deletions
diff --git a/lib/rbot/irc.rb b/lib/rbot/irc.rb
index 23bd9e0d..2eb676e2 100644
--- a/lib/rbot/irc.rb
+++ b/lib/rbot/irc.rb
@@ -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.
diff --git a/lib/rbot/ircbot.rb b/lib/rbot/ircbot.rb
index 0d934e33..4f5018e3 100644
--- a/lib/rbot/ircbot.rb
+++ b/lib/rbot/ircbot.rb
@@ -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
diff --git a/lib/rbot/message.rb b/lib/rbot/message.rb
index 5d6ea60f..6d14b213 100644
--- a/lib/rbot/message.rb
+++ b/lib/rbot/message.rb
@@ -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
diff --git a/lib/rbot/rfc2812.rb b/lib/rbot/rfc2812.rb
index 758f574e..d781c0f1 100644
--- a/lib/rbot/rfc2812.rb
+++ b/lib/rbot/rfc2812.rb
@@ -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)