class Irc::Server
An IRC Server
represents the Server
the client is connected to.
Attributes
Public Class Methods
Source
# File lib/rbot/irc.rb, line 1563 def initialize @hostname = @version = @usermodes = @chanmodes = nil @channels = ChannelList.new @users = UserList.new reset_capabilities end
Create a new Server
, with all instance variables reset to nil (for scalar variables), empty channel and user lists and @supports initialized to the default values for all known supported features.
Public Instance Methods
Source
# File lib/rbot/irc.rb, line 1786 def casemap @supports[:casemapping] end
Returns the casemap of the server.
Source
# File lib/rbot/irc.rb, line 1912 def channel(str) new_channel(str,nil,[],false) end
Returns the Channel
with the given name on the server, creating it if necessary. This is a short form for new_channel
(str, nil, [], false
)
Source
# File lib/rbot/irc.rb, line 1534 def channel_names @channels.map { |ch| ch.downcase } end
TODO Ho
Source
# File lib/rbot/irc.rb, line 1637 def clear reset_lists reset_capabilities @hostname = @version = @usermodes = @chanmodes = nil end
Clears the server
Source
Source
# File lib/rbot/irc.rb, line 1993 def delete_user(someuser) idx = has_user?(someuser) raise "Tried to remove unmanaged user #{user}" unless idx have = self.user(someuser) @channels.each { |ch| delete_user_from_channel(have, ch) } @users.delete_at(idx) end
Remove User
someuser from the list of User
s. someuser must be specified with the full Netmask
.
Source
Source
# File lib/rbot/irc.rb, line 2011 def find_users(mask) nm = new_netmask(mask) @users.inject(UserList.new) { |list, user| if user.user == "*" or user.host == "*" list << user if user.nick.irc_downcase(casemap) =~ nm.nick.irc_downcase(casemap).to_irc_regexp else list << user if user.matches?(nm) end list } end
Source
# File lib/rbot/irc.rb, line 1821 def get_channel(name) return nil if name.nil_or_empty? idx = has_channel?(name) channels[idx] if idx end
Returns the channel with name name, if available
Source
# File lib/rbot/irc.rb, line 1933 def get_user(nick) idx = has_user?(nick) @users[idx] if idx end
Returns the user with nick nick, if available
Source
# File lib/rbot/irc.rb, line 1813 def has_channel?(name) return false if name.nil_or_empty? channel_names.index(name.irc_downcase(casemap)) end
Checks if the receiver already has a channel with the given name
Source
# File lib/rbot/irc.rb, line 1926 def has_user?(nick) return false if nick.nil_or_empty? user_nicks.index(nick.irc_downcase(casemap)) end
Checks if the receiver already has a user with the given nick
Source
# File lib/rbot/irc.rb, line 1543 def inspect chans, users = [@channels, @users].map {|d| d.sort { |a, b| a.downcase <=> b.downcase }.map { |x| x.inspect } } str = self.__to_s__[0..-2] str << " @hostname=#{hostname}" str << " @channels=#{chans}" str << " @users=#{users}" str << ">" end
Source
# File lib/rbot/irc.rb, line 1618 def mode_for_prefix(pfx) return @supports[:prefix][:modes][ @supports[:prefix][:prefixes].index(pfx.to_sym) ] end
Convert a prefix (@, +, %, …) to the corresponding mode (o, v, h, …). See also prefix_for_mode
Source
# File lib/rbot/irc.rb, line 1835 def new_channel(name, topic=nil, users=[], fails=true) if name.nil_or_empty? raise "Tried to look for empty or nil channel name #{name.inspect}" if fails return nil end ex = get_chan(name) if ex raise "Channel #{name} already exists on server #{self}" if fails return ex else prefix = name[0,1] # Give a warning if the new Channel goes over some server limits. # # FIXME might need to raise an exception # warn "#{self} doesn't support channel prefix #{prefix}" unless @supports[:chantypes].include?(prefix) warn "#{self} doesn't support channel names this long (#{name.length} > #{@supports[:channellen]})" unless name.length <= @supports[:channellen] # Next, we check if we hit the limit for channels of type +prefix+ # if the server supports +chanlimit+ # @supports[:chanlimit].keys.each { |k| next unless k.include?(prefix) count = 0 channel_names.each { |n| count += 1 if k.include?(n[0]) } # raise IndexError, "Already joined #{count} channels with prefix #{k}" if count == @supports[:chanlimit][k] warn "Already joined #{count}/#{@supports[:chanlimit][k]} channels with prefix #{k}, we may be going over server limits" if count >= @supports[:chanlimit][k] } # So far, everything is fine. Now create the actual Channel # chan = Channel.new(name, topic, users, :server => self) # We wade through +prefix+ and +chanmodes+ to create appropriate # lists and flags for this channel @supports[:prefix][:modes].each { |mode| chan.create_mode(mode, Channel::UserMode) } if @supports[:prefix][:modes] @supports[:chanmodes].each { |k, val| if val case k when :typea val.each { |mode| chan.create_mode(mode, Channel::ModeTypeA) } when :typeb val.each { |mode| chan.create_mode(mode, Channel::ModeTypeB) } when :typec val.each { |mode| chan.create_mode(mode, Channel::ModeTypeC) } when :typed val.each { |mode| chan.create_mode(mode, Channel::ModeTypeD) } end end } @channels << chan # debug "Created channel #{chan.inspect}" return chan end end
Create a new Channel
object bound to the receiver and add it to the list of Channel
s on the receiver, unless the channel was present already. In this case, the default action is to raise an exception, unless fails is set to false. An exception can also be raised if str is nil or empty, again only if fails is set to true; otherwise, the method just returns nil
Source
# File lib/rbot/irc.rb, line 2005 def new_netmask(str) str.to_irc_netmask(:server => self) end
Create a new Netmask
object with the appropriate casemap
Source
# File lib/rbot/irc.rb, line 1945 def new_user(str, fails=true) if str.nil_or_empty? raise "Tried to look for empty or nil user name #{str.inspect}" if fails return nil end tmp = str.to_irc_user(:server => self) old = get_user(tmp.nick) # debug "Tmp: #{tmp.inspect}" # debug "Old: #{old.inspect}" if old # debug "User already existed as #{old.inspect}" if tmp.known? if old.known? # debug "Both were known" # Do not raise an error: things like Freenode change the hostname after identification warning "User #{tmp.nick} has inconsistent Netmasks! #{self} knows #{old.inspect} but access was tried with #{tmp.inspect}" if old != tmp raise "User #{tmp} already exists on server #{self}" if fails end if old.fullform.downcase != tmp.fullform.downcase old.replace(tmp) # debug "Known user now #{old.inspect}" end end return old else warn "#{self} doesn't support nicknames this long (#{tmp.nick.length} > #{@supports[:nicklen]})" unless tmp.nick.length <= @supports[:nicklen] @users << tmp return @users.last end end
Create a new User
object bound to the receiver and add it to the list of User
s on the receiver, unless the User
was present already. In this case, the default action is to raise an exception, unless fails is set to false. An exception can also be raised if str is nil or empty, again only if fails is set to true; otherwise, the method just returns nil
Source
# File lib/rbot/irc.rb, line 1674 def parse_isupport(line) debug "Parsing ISUPPORT #{line.inspect}" ar = line.split(' ') reparse = [] ar.each { |en| prekey, val = en.split('=', 2) if prekey =~ /^-(.*)/ key = $1.downcase.to_sym val = false else key = prekey.downcase.to_sym end case key when :casemapping noval_warn(key, val) { if val == 'charset' reparse << "CASEMAPPING=(charset)" else # TODO some servers offer non-standard CASEMAPPINGs in the form # locale.charset[-options], which indicate an extended set of # allowed characters (mostly for nicks). This might be supported # with hooks for the unicode core module @supports[key] = val.to_irc_casemap end } when :chanlimit, :idchan, :maxlist, :targmax noval_warn(key, val) { groups = val.split(',') groups.each { |g| k, v = g.split(':') @supports[key][k] = v.to_i || 0 if @supports[key][k] == 0 warn "Deleting #{key} limit of 0 for #{k}" @supports[key].delete(k) end } } when :chanmodes noval_warn(key, val) { groups = val.split(',') @supports[key][:typea] = groups[0].scan(/./).map { |x| x.to_sym} @supports[key][:typeb] = groups[1].scan(/./).map { |x| x.to_sym} @supports[key][:typec] = groups[2].scan(/./).map { |x| x.to_sym} @supports[key][:typed] = groups[3].scan(/./).map { |x| x.to_sym} } when :channellen, :kicklen, :modes, :topiclen if val @supports[key] = val.to_i else @supports[key] = nil end when :chantypes @supports[key] = val # can also be nil when :excepts val ||= 'e' @supports[key] = val when :invex val ||= 'I' @supports[key] = val when :maxchannels noval_warn(key, val) { reparse << "CHANLIMIT=(chantypes):#{val} " } when :maxtargets noval_warn(key, val) { @supports[:targmax]['PRIVMSG'] = val.to_i @supports[:targmax]['NOTICE'] = val.to_i } when :network noval_warn(key, val) { @supports[key] = val } when :nicklen noval_warn(key, val) { @supports[key] = val.to_i } when :prefix if val val.scan(/\((.*)\)(.*)/) { |m, p| @supports[key][:modes] = m.scan(/./).map { |x| x.to_sym} @supports[key][:prefixes] = p.scan(/./).map { |x| x.to_sym} } else @supports[key][:modes] = nil @supports[key][:prefixes] = nil end when :safelist val_warn(key, val) { @supports[key] = val.nil? ? true : val } when :statusmsg noval_warn(key, val) { @supports[key] = val.scan(/./) } when :std noval_warn(key, val) { @supports[key] = val.split(',') } else @supports[key] = val.nil? ? true : val end } unless reparse.empty? reparse_str = reparse.join(" ") reparse_str.gsub!("(chantypes)",@supports[:chantypes]) reparse_str.gsub!("(charset)",@supports[:charset] || 'rfc1459') parse_isupport(reparse_str) end end
This method is used to parse a 005 RPL_ISUPPORT line
See the RPL_ISUPPORT draft
Source
# File lib/rbot/irc.rb, line 1645 def parse_my_info(line) ar = line.split(' ') @hostname = ar[0] @version = ar[1] @usermodes = ar[2] @chanmodes = ar[3] end
This method is used to parse a 004 RPL_MY_INFO line
Source
# File lib/rbot/irc.rb, line 1610 def prefix_for_mode(mode) return @supports[:prefix][:prefixes][ @supports[:prefix][:modes].index(mode.to_sym) ] end
Convert a mode (o, v, h, …) to the corresponding prefix (@, +, %, …). See also mode_for_prefix
Source
# File lib/rbot/irc.rb, line 1575 def reset_capabilities @supports = { :casemapping => 'rfc1459'.to_irc_casemap, :chanlimit => {}, :chanmodes => { :typea => nil, # Type A: address lists :typeb => nil, # Type B: needs a parameter :typec => nil, # Type C: needs a parameter when set :typed => nil # Type D: must not have a parameter }, :channellen => 50, :chantypes => "#&!+", :excepts => nil, :idchan => {}, :invex => nil, :kicklen => nil, :maxlist => {}, :modes => 3, :network => nil, :nicklen => 9, :prefix => { :modes => [:o, :v], :prefixes => [:"@", :+] }, :safelist => nil, :statusmsg => nil, :std => nil, :targmax => {}, :topiclen => nil } @capabilities = {} end
Resets the server capabilities
Source
Source
Source
# File lib/rbot/irc.rb, line 1539 def user_nicks @users.map { |u| u.downcase } end
TODO Ho
Source
Source
Private Instance Methods
Source
# File lib/rbot/irc.rb, line 1653 def noval_warn(key, val, &block) if val yield if block_given? else warn "No #{key.to_s.upcase} value" end end
Source
# File lib/rbot/irc.rb, line 1661 def val_warn(key, val, &block) if val == true or val == false or val.nil? yield if block_given? else warn "No #{key.to_s.upcase} value must be specified, got #{val}" end end