Class: Irc::Netmask

Inherits:
Object show all
Includes:
ServerOrCasemap
Defined in:
lib/rbot/irc.rb

Overview

A Netmask identifies each user by collecting its nick, username and hostname in the form nick!user@host

Netmasks can also contain glob patterns in any of their components; in this form they are used to refer to more than a user or to a user appearing under different forms.

Example:

  • *!*@* refers to everybody

  • *!someuser@somehost refers to user someuser on host somehost regardless of the nick used.

Direct Known Subclasses

User

Instance Attribute Summary collapse

Attributes included from ServerOrCasemap

#server

Instance Method Summary collapse

Methods included from ServerOrCasemap

#casemap, #downcase, #fits_with_server_and_casemap?, #init_server_or_casemap, #irc_downcase, #irc_upcase, #server_and_casemap, #upcase

Constructor Details

#initialize(str = "", opts = {}) ⇒ Netmask

Create a new Netmask from string str, which must be in the form nick!user@host

It is possible to specify a server or a casemap in the optional Hash: these are used to associate the Netmask with the given server and to set its casemap: if a server is specified and a casemap is not, the server’s casemap is used. If both a server and a casemap are specified, the casemap must match the server’s casemap or an exception will be raised.

Empty nick, user or host are converted to the generic glob pattern



639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
# File 'lib/rbot/irc.rb', line 639

def initialize(str="", opts={})
  # First of all, check for server/casemap option
  #
  init_server_or_casemap(opts)

  # Now we can see if the given string _str_ is an actual Netmask
  if str.respond_to?(:to_str)
    case str.to_str
      # We match a pretty generic string, to work around non-compliant
      # servers
    when /^(?:(\S+?)(?:(?:!(\S+?))?@(\S+))?)?$/
      # We do assignment using our internal methods
      self.nick = $1
      self.user = $2
      self.host = $3
    else
      raise ArgumentError, "#{str.to_str.inspect} does not represent a valid #{self.class}"
    end
  else
    raise TypeError, "#{str} cannot be converted to a #{self.class}"
  end
end

Instance Attribute Details

#hostObject

Returns the value of attribute host.



625
626
627
# File 'lib/rbot/irc.rb', line 625

def host
  @host
end

#nickObject

Returns the value of attribute nick.



625
626
627
# File 'lib/rbot/irc.rb', line 625

def nick
  @nick
end

#userObject Also known as: ident

Returns the value of attribute user.



625
626
627
# File 'lib/rbot/irc.rb', line 625

def user
  @user
end

Instance Method Details

#<=>(arg) ⇒ Object

Sorting is done via the fullform



853
854
855
856
857
858
859
860
# File 'lib/rbot/irc.rb', line 853

def <=>(arg)
  case arg
  when Netmask
    self.fullform.irc_downcase(casemap) <=> arg.fullform.irc_downcase(casemap)
  else
    self.downcase <=> arg.downcase
  end
end

#==(other) ⇒ Object

Equality: two Netmasks are equal if they downcase to the same thing

TODO we may want it to try other.to_irc_netmask



737
738
739
740
# File 'lib/rbot/irc.rb', line 737

def ==(other)
  return false unless other.kind_of?(self.class)
  self.downcase == other.downcase
end

#===(arg) ⇒ Object

Case equality. Checks if arg matches self



847
848
849
# File 'lib/rbot/irc.rb', line 847

def ===(arg)
  arg.to_irc_netmask(:casemap => casemap).matches?(self)
end

#downcasedObject

This method returns a new Netmask which is the fully downcased version of the receiver



697
698
699
# File 'lib/rbot/irc.rb', line 697

def downcased
  return self.full_downcase.to_irc_netmask(server_and_casemap)
end

#full_downcaseObject

full_downcase() will return the fullform downcased according to the User’s own casemap



691
692
693
# File 'lib/rbot/irc.rb', line 691

def full_downcase
  self.full_irc_downcase
end

#full_irc_downcase(cmap = casemap) ⇒ Object

This method downcases the fullform of the netmask. While this may not be significantly different from the #downcase() method provided by the ServerOrCasemap mixin, it’s significantly different for Netmask subclasses such as User whose simple downcasing uses the nick only.



684
685
686
# File 'lib/rbot/irc.rb', line 684

def full_irc_downcase(cmap=casemap)
  self.fullform.irc_downcase(cmap)
end

#fullformObject Also known as: to_str



673
674
675
# File 'lib/rbot/irc.rb', line 673

def fullform
  "#{nick}!#{user}@#{host}"
end

#generalizeObject



789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
# File 'lib/rbot/irc.rb', line 789

def generalize
  u = user.dup
  unless u.has_irc_glob?
    u.sub!(/^[in]=/, '=') or u.sub!(/^\W(\w+)/, '\1')
    u = '*' + u
  end

  h = host.dup
  unless h.has_irc_glob?
    if h.include? '/'
      h.sub!(/x-\w+$/, 'x-*')
    else
      h.match(/^[^\.]+\.[^\.]+$/) or
      h.sub!(/azzurra[=-][0-9a-f]+/i, '*') or # hello, azzurra, you suck!
      h.sub!(/^(\d+\.\d+\.\d+\.)\d+$/, '\1*') or
      h.sub!(/^[^\.]+\./, '*.')
    end
  end
  return Netmask.new("*!#{u}@#{h}", server_and_casemap)
end

#has_irc_glob?Boolean

This method checks if a Netmask is definite or not, by seeing if any of its components are defined by globs

Returns:

  • (Boolean)


785
786
787
# File 'lib/rbot/irc.rb', line 785

def has_irc_glob?
  return @nick.has_irc_glob? || @user.has_irc_glob? || @host.has_irc_glob?
end

#inspectObject

Inspection of a Netmask reveals the server it’s bound to (if there is one), its casemap and the nick, user and host part



725
726
727
728
729
730
731
# File 'lib/rbot/irc.rb', line 725

def inspect
  str = self.__to_s__[0..-2]
  str << " @server=#{@server}" if defined?(@server) and @server
  str << " @nick=#{@nick.inspect} @user=#{@user.inspect}"
  str << " @host=#{@host.inspect} casemap=#{casemap.inspect}"
  str << ">"
end

#matches?(arg) ⇒ Boolean

This method is used to match the current Netmask against another one

The method returns true if each component of the receiver matches the corresponding component of the argument. By matching here we mean that any netmask described by the receiver is also described by the argument.

In this sense, matching is rather simple to define in the case when the receiver has no globs: it is just necessary to check if the argument describes the receiver, which can be done by matching it against the argument converted into an IRC Regexp (see String#to_irc_regexp).

The situation is also easy when the receiver has globs and the argument doesn’t, since in this case the result is false.

The more complex case in which both the receiver and the argument have globs is not handled yet.

Returns:

  • (Boolean)


828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
# File 'lib/rbot/irc.rb', line 828

def matches?(arg)
  cmp = arg.to_irc_netmask(:casemap => casemap)
  debug "Matching #{self.fullform} against #{arg.inspect} (#{cmp.fullform})"
  [:nick, :user, :host].each { |component|
    us = self.send(component).irc_downcase(casemap)
    them = cmp.send(component).irc_downcase(casemap)
    if us.has_irc_glob? && them.has_irc_glob?
      next if us == them
      warn NotImplementedError
      return false
    end
    return false if us.has_irc_glob? && !them.has_irc_glob?
    return false unless us =~ them.to_irc_regexp
  }
  return true
end

#replace(other) ⇒ Object

We can replace everything at once with data from another Netmask



769
770
771
772
773
774
775
776
777
778
779
780
# File 'lib/rbot/irc.rb', line 769

def replace(other)
  case other
  when Netmask
    nick = other.nick
    user = other.user
    host = other.host
    @server = other.server
    @casemap = other.casemap unless @server
  else
    replace(other.to_irc_netmask(server_and_casemap))
  end
end

#to_irc_netmask(opts = {}) ⇒ Object

Converts the receiver into a Netmask with the given (optional) server/casemap association. We return self unless a conversion is needed (different casemap/server)

Subclasses of Netmask will return a new Netmask, using full_downcase



707
708
709
710
711
712
# File 'lib/rbot/irc.rb', line 707

def to_irc_netmask(opts={})
  if self.class == Netmask
    return self if fits_with_server_and_casemap?(opts)
  end
  return self.full_downcase.to_irc_netmask(server_and_casemap.merge(opts))
end

#to_irc_user(opts = {}) ⇒ Object

Converts the receiver into a User with the given (optional) server/casemap association. We return self unless a conversion is needed (different casemap/server)



718
719
720
# File 'lib/rbot/irc.rb', line 718

def to_irc_user(opts={})
  self.fullform.to_irc_user(server_and_casemap.merge(opts))
end

#to_sObject

A Netmask is easily converted to a String for the usual representation. We skip the user or host parts if they are “*”, unless we’ve been asked for the full form



666
667
668
669
670
671
# File 'lib/rbot/irc.rb', line 666

def to_s
  ret = nick.dup
  ret << "!" << user unless user == "*"
  ret << "@" << host unless host == "*"
  return ret
end