raise "Unexpected match #{m} when converting #{self}"\r
end\r
}\r
- Regexp.new(regmask)\r
+ Regexp.new("^#{regmask}$")\r
end\r
\r
end\r
end\r
end\r
\r
- # A Netmask is easily converted to a String for the usual representation\r
+ # A Netmask is easily converted to a String for the usual representation.\r
+ # We skip the user or host parts if they are "*", unless we've been asked\r
+ # for the full form\r
#\r
+ def to_s\r
+ ret = nick.dup\r
+ ret << "!" << user unless user == "*"\r
+ ret << "@" << host unless host == "*"\r
+ return ret\r
+ end\r
+\r
def fullform\r
"#{nick}!#{user}@#{host}"\r
end\r
- alias :to_s :fullform\r
+\r
+ # This method downcases the fullform of the netmask. While this may not be\r
+ # significantly different from the #downcase() method provided by the\r
+ # ServerOrCasemap mixin, it's significantly different for Netmask\r
+ # subclasses such as User whose simple downcasing uses the nick only.\r
+ #\r
+ def full_irc_downcase(cmap=casemap)\r
+ self.fullform.irc_downcase(cmap)\r
+ end\r
+\r
+ # full_downcase() will return the fullform downcased according to the\r
+ # User's own casemap\r
+ #\r
+ def full_downcase\r
+ self.full_irc_downcase\r
+ end\r
\r
# Converts the receiver into a Netmask with the given (optional)\r
# server/casemap association. We return self unless a conversion\r
# is needed (different casemap/server)\r
#\r
- # Subclasses of Netmask will return a new Netmask\r
+ # Subclasses of Netmask will return a new Netmask, using full_downcase\r
#\r
def to_irc_netmask(opts={})\r
if self.class == Netmask\r
return self if fits_with_server_and_casemap?(opts)\r
end\r
- return self.downcase.to_irc_netmask(opts)\r
+ return self.full_downcase.to_irc_netmask(opts)\r
end\r
\r
# Converts the receiver into a User with the given (optional)\r
class User < Netmask\r
alias :to_s :nick\r
\r
+ attr_accessor :real_name\r
+\r
# Create a new IRC User from a given Netmask (or anything that can be converted\r
# into a Netmask) provided that the given Netmask does not have globs.\r
#\r
raise ArgumentError, "#{str.inspect} must not have globs (unescaped * or ?)" if user.has_irc_glob? && user != "*"\r
raise ArgumentError, "#{str.inspect} must not have globs (unescaped * or ?)" if host.has_irc_glob? && host != "*"\r
@away = false\r
+ @real_name = String.new\r
end\r
\r
# The nick of a User may be changed freely, but it must not contain glob patterns.\r
# Checks if a User is well-known or not by looking at the hostname and user\r
#\r
def known?\r
- return nick!= "*" && user!="*" && host!="*"\r
+ return nick != "*" && user != "*" && host != "*"\r
end\r
\r
# Is the user away?\r
end\r
end\r
\r
- # Users can be either simply downcased (their nick only)\r
- # or fully downcased: this will return the fullform downcased\r
- # according to the given casemap.\r
- #\r
- def full_irc_downcase(cmap=casemap)\r
- self.fullform.irc_downcase(cmap)\r
- end\r
-\r
- # full_downcase() will return the fullform downcased according to the\r
- # User's own casemap\r
- #\r
- def full_downcase\r
- self.full_irc_downcase\r
- end\r
-\r
# Since to_irc_user runs the same checks on server and channel as\r
# to_irc_netmask, we just try that and return self if it works.\r
#\r
end\r
end\r
\r
+ def modes_on(channel)\r
+ case channel\r
+ when Channel\r
+ channel.modes_of(self)\r
+ else\r
+ return @server.channel(channel).modes_of(self) if @server\r
+ raise "Can't resolve channel #{channel}"\r
+ end\r
+ end\r
+\r
+ def is_op?(channel)\r
+ case channel\r
+ when Channel\r
+ channel.has_op?(self)\r
+ else\r
+ return @server.channel(channel).has_op?(self) if @server\r
+ raise "Can't resolve channel #{channel}"\r
+ end\r
+ end\r
+\r
+ def is_voice?(channel)\r
+ case channel\r
+ when Channel\r
+ channel.has_voice?(self)\r
+ else\r
+ return @server.channel(channel).has_voice?(self) if @server\r
+ raise "Can't resolve channel #{channel}"\r
+ end\r
+ end\r
end\r
\r
\r
#\r
def initialize(text="", set_by="", set_on=Time.new)\r
@text = text\r
- @set_by = set_by.to_irc_user\r
+ @set_by = set_by.to_irc_netmask\r
@set_on = set_on\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
+ @users.index(nick.to_irc_user(server_and_casemap))\r
end\r
\r
# Returns the user with nick _nick_, if available\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
+ if has_user?(user)\r
+ warn "Trying to add user #{user} to channel #{self} again" unless silent\r
else\r
@users << user.to_irc_user(server_and_casemap)\r
end\r
@mode[sym.to_sym] = kl.new(self)\r
end\r
\r
+ def modes_of(user)\r
+ l = []\r
+ @mode.map { |s, m|\r
+ l << s if (m.class <= UserMode and m.list[user])\r
+ }\r
+ l\r
+ end\r
+\r
+ def has_op?(user)\r
+ @mode.has_key?(:o) and @mode[:o].list[user]\r
+ end\r
+\r
+ def has_voice?(user)\r
+ @mode.has_key?(:v) and @mode[:v].list[user]\r
+ end\r
end\r
\r
\r
# Resets the Channel and User list\r
#\r
def reset_lists\r
- @users.each { |u|\r
+ @users.reverse_each { |u|\r
delete_user(u)\r
}\r
- @channels.each { |u|\r
+ @channels.reverse_each { |u|\r
delete_channel(u)\r
}\r
end\r
groups.each { |g|\r
k, v = g.split(':')\r
@supports[key][k] = v.to_i || 0\r
+ if @supports[key][k] == 0\r
+ warn "Deleting #{key} limit of 0 for #{k}"\r
+ @supports[key].delete(k)\r
+ end\r
}\r
}\r
when :chanmodes\r
channel_names.each { |n|\r
count += 1 if k.include?(n[0])\r
}\r
- raise IndexError, "Already joined #{count} channels with prefix #{k}" if count == @supports[:chanlimit][k]\r
+ # raise IndexError, "Already joined #{count} channels with prefix #{k}" if count == @supports[:chanlimit][k]\r
+ warn "Already joined #{count}/#{@supports[:chanlimit][k]} channels with prefix #{k}, we may be going over server limits" if count >= @supports[:chanlimit][k]\r
}\r
\r
# So far, everything is fine. Now create the actual Channel\r