# :title: RFC 2821 Client Protocol module
#
# This module defines the Irc::Client class, a class that can handle and
-# dispatch messages based on RFC 2821i (Internet Relay Chat: Client Protocol)
+# dispatch messages based on RFC 2821 (Internet Relay Chat: Client Protocol)
module Irc
# - The server sends Replies 001 to 004 to a user upon
# Clear the server and reset the user
def reset
@server.clear
- @user = @server.user("")
+ @user = @server.user("*!*@*")
end
# key:: server event to handle
num=command.to_i
case num
when RPL_WELCOME
+ data[:message] = argv[1]
# "Welcome to the Internet Relay Network
# <nick>!<user>@<host>"
if not_us
warning "Server thinks client (#{@user.inspect}) has a different nick"
@user.nick = data[:target]
end
- if argv[1] =~ /([^@!\s]+)(?:!([^@!\s]+?))?@(\S+)/
+ if data[:message] =~ /([^@!\s]+)(?:!([^@!\s]+?))?@(\S+)/
nick = $1
user = $2
host = $3
# be able to consume parameters for all
# but Type D modes
- data[:channel] = @server.user_or_channel(argv[0])
+ data[:target] = @server.user_or_channel(argv[0])
data[:modestring] = argv[1..-1].join(" ")
- case data[:channel]
+ # data[:modes] is an array where each element
+ # is an array with two elements, the first of which
+ # is either :set or :reset, and the second symbol
+ # is the mode letter. An optional third element
+ # is present e.g. for channel modes that need
+ # a parameter
+ data[:modes] = []
+ case data[:target]
when User
- # TODO
+ # User modes aren't currently handled internally,
+ # but we still parse them and delegate to the client
warning "Unhandled user mode message '#{serverstring}'"
+ argv[1..-1].each { |arg|
+ setting = arg[0].chr
+ if "+-".include?(setting)
+ setting = setting == "+" ? :set : :reset
+ arg[1..-1].each_byte { |b|
+ m = b.chr.intern
+ data[:modes] << [setting, m]
+ }
+ else
+ # Although typically User modes don't take an argument,
+ # this is not true for all modes on all servers. Since
+ # we have no knowledge of which modes take parameters
+ # and which don't we just assign it to the last
+ # mode. This is not going to do strange things often,
+ # as usually User modes are only set one at a time
+ warning "Unhandled user mode parameter #{arg} found"
+ data[:modes].last << arg
+ end
+ }
else
- # data[:modes] is an array where each element
- # is either a flag which doesn't need parameters
- # or an array with a flag which needs parameters
- # and the corresponding parameter
- data[:modes] = []
# array of indices in data[:modes] where parameters
# are needed
who_wants_params = []
argv[1..-1].each { |arg|
setting = arg[0].chr
if "+-".include?(setting)
+ setting = setting == "+" ? :set : :reset
arg[1..-1].each_byte { |b|
- m = b.chr
- case m.to_sym
+ m = b.chr.intern
+ if m == :+
+ setting = :set
+ next
+ elsif m == :-
+ setting = :reset
+ next
+ end
+ data[:modes] << [setting, m]
+ case m
when *@server.supports[:chanmodes][:typea]
- data[:modes] << [setting + m]
who_wants_params << data[:modes].length - 1
when *@server.supports[:chanmodes][:typeb]
- data[:modes] << [setting + m]
who_wants_params << data[:modes].length - 1
when *@server.supports[:chanmodes][:typec]
- if setting == "+"
- data[:modes] << [setting + m]
+ if setting == :set
who_wants_params << data[:modes].length - 1
- else
- data[:modes] << setting + m
end
when *@server.supports[:chanmodes][:typed]
- data[:modes] << setting + m
+ # Nothing to do
when *@server.supports[:prefix][:modes]
- data[:modes] << [setting + m]
who_wants_params << data[:modes].length - 1
else
warning "Unknown mode #{m} in #{serverstring.inspect}"
data[:modes][idx] << arg
end
}
- end
- data[:modes].each { |mode|
- case mode
- when Array
- set = mode[0][0].chr == "+" ? :set : :reset
- key = mode[0][1].chr.to_sym
- val = mode[1]
- data[:channel].mode[key].send(set, val)
- else
- set = mode[0].chr == "+" ? :set : :reset
- key = mode[1].chr.to_sym
- data[:channel].mode[key].send(set)
- end
- } if data[:modes]
+ data[:modes].each { |mode|
+ set, key, val = mode
+ if val
+ data[:target].mode[key].send(set, val)
+ else
+ data[:target].mode[key].send(set)
+ end
+ }
+ end
handle(:mode, data)
else