# Channels is the User on (of those the client is on too)?\r
# We may want this so that when a User leaves all Channels and he hasn't\r
# sent us privmsgs, we know remove him from the Server @users list\r
+# * Maybe ChannelList and UserList should be HashesOf instead of ArrayOf?\r
+# See items marked as TODO Ho\r
#++\r
# :title: IRC module\r
#\r
\r
# Channel modes of type A manipulate lists\r
#\r
+ # Example: b (banlist)\r
+ #\r
class ModeTypeA < Mode\r
def initialize(ch)\r
super\r
\r
# Channel modes of type B need an argument\r
#\r
+ # Example: k (key)\r
+ #\r
class ModeTypeB < Mode\r
def initialize(ch)\r
super\r
# Channel modes of type C need an argument when set,\r
# but not when they get reset\r
#\r
+ # Example: l (limit)\r
+ #\r
class ModeTypeC < Mode\r
def initialize(ch)\r
super\r
\r
# Channel modes of type D are basically booleans\r
#\r
+ # Example: m (moderate)\r
+ #\r
class ModeTypeD < Mode\r
def initialize(ch)\r
super\r
str = "<#{self.class}:#{'0x%x' % self.object_id}:"\r
str << " on server #{server}" if server\r
str << " @name=#{@name.inspect} @topic=#{@topic.text.inspect}"\r
- str << " @users=[#{@users.sort.join(', ')}]"\r
+ str << " @users=[#{user_nicks.sort.join(', ')}]"\r
str << ">"\r
end\r
\r
self\r
end\r
\r
+ # TODO Ho\r
+ def user_nicks\r
+ @users.map { |u| u.downcase }\r
+ end\r
+\r
+ # Checks if the receiver already has a user with the given _nick_\r
+ #\r
+ def has_user?(nick)\r
+ user_nicks.index(nick.irc_downcase(casemap))\r
+ end\r
+\r
+ # Returns the user with nick _nick_, if available\r
+ #\r
+ def get_user(nick)\r
+ idx = has_user?(nick)\r
+ @users[idx] if idx\r
+ end\r
+\r
+ # Adds a user to the channel\r
+ #\r
+ def add_user(user, opts={})\r
+ silent = opts.fetch(:silent, false) \r
+ if has_user?(user) && !silent\r
+ warn "Trying to add user #{user} to channel #{self} again"\r
+ else\r
+ @users << user.to_irc_user(server_and_casemap)\r
+ end\r
+ end\r
+\r
# Creates a new channel with the given name, optionally setting the topic\r
# and an initial users list.\r
#\r
@users = UserList.new\r
\r
users.each { |u|\r
- @users << u.to_irc_user(server_and_casemap)\r
+ add_user(u)\r
}\r
\r
# Flags\r
# A channel is local to a server if it has the '&' prefix\r
#\r
def local?\r
- name[0] = 0x26\r
+ name[0] == 0x26\r
end\r
\r
# A channel is modeless if it has the '+' prefix\r
#\r
def modeless?\r
- name[0] = 0x2b\r
+ name[0] == 0x2b\r
end\r
\r
# A channel is safe if it has the '!' prefix\r
#\r
def safe?\r
- name[0] = 0x21\r
+ name[0] == 0x21\r
end\r
\r
# A channel is normal if it has the '#' prefix\r
#\r
def normal?\r
- name[0] = 0x23\r
+ name[0] == 0x23\r
end\r
\r
# Create a new mode\r
\r
attr_reader :channels, :users\r
\r
+ # TODO Ho\r
def channel_names\r
@channels.map { |ch| ch.downcase }\r
end\r
\r
+ # TODO Ho\r
def user_nicks\r
@users.map { |u| u.downcase }\r
end\r
# Checks if the receiver already has a channel with the given _name_\r
#\r
def has_channel?(name)\r
- channel_names.index(name.downcase)\r
+ channel_names.index(name.irc_downcase(casemap))\r
end\r
alias :has_chan? :has_channel?\r
\r
# Checks if the receiver already has a user with the given _nick_\r
#\r
def has_user?(nick)\r
- user_nicks.index(nick.downcase)\r
+ user_nicks.index(nick.irc_downcase(casemap))\r
end\r
\r
# Returns the user with nick _nick_, if available\r
@users.inject(UserList.new) {\r
|list, user|\r
if user.user == "*" or user.host == "*"\r
- list << user if user.nick.downcase =~ nm.nick.downcase.to_irc_regexp\r
+ list << user if user.nick.irc_downcase(casemap) =~ nm.nick.irc_downcase(casemap).to_irc_regexp\r
else\r
list << user if user.matches?(nm)\r
end\r
users = []
argv[3].scan(/\S+/).each { |u|
# FIXME beware of servers that allow multiple prefixes
- if(u =~ /^(#{@server.supports[:prefix][:prefixes].join})?(.*)$/)
+ if(u =~ /^([#{@server.supports[:prefix][:prefixes].join}])?(.*)$/)
umode = $1
user = $2
users << [user, umode]
users.each { |ar|
u = @server.user(ar[0])
- chan.users << u unless chan.users.include?(u)
+ chan.add_user(u, :silent => true)
+ debug "Adding user #{u}"
if ar[1]
m = @server.supports[:prefix][:prefixes].index(ar[1].to_sym)
- m = @server.supports[:prefix][:modes][m]
- chan.mode[m.to_sym].set(u)
+ ms = @server.supports[:prefix][:modes][m]
+ debug "\twith mode #{ar[1]} (#{ms})"
+ chan.mode[ms].set(u)
end
}
@tmpusers += users
when 'QUIT'
data[:message] = argv[0]
data[:was_on] = @server.channels.inject(ChannelList.new) { |list, ch|
- list << ch if ch.users.include?(data[:source])
- list
+ list << ch if ch.has_user?(data[:source])
+ list
}
@server.delete_user(data[:source])
handle(:quit, data)
when 'JOIN'
data[:channel] = @server.channel(argv[0])
- data[:channel].users << data[:source]
+ data[:channel].add_user(data[:source])
handle(:join, data)
when 'TOPIC'
handle(:invite, data)
when 'NICK'
data[:is_on] = @server.channels.inject(ChannelList.new) { |list, ch|
- list << ch if ch.users.include?(data[:source])
+ list << ch if ch.has_user?(data[:source])
list
}
case data[:channel]
when User
# TODO
+ warn "Unhandled user mode message '#{serverstring}'"
else
# data[:modes] is an array where each element
# is either a flag which doesn't need parameters
data[:modes] << [setting + m]
who_wants_params << data[:modes].length - 1
else
- warn "Unknown mode #{m} in #{serverstring}"
+ warn "Unknown mode #{m} in #{serverstring.inspect}"
end
}
else
idx = who_wants_params.shift
if idx.nil?
- warn "Oops, problems parsing #{serverstring}"
+ warn "Oops, problems parsing #{serverstring.inspect}"
break
end
data[:modes][idx] << arg
handle(:mode, data)
else
+ warn "Unknown message #{serverstring.inspect}"
handle(:unknown, data)
end
end