]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - lib/rbot/irc.rb
Saner treatment for connect errors
[user/henk/code/ruby/rbot.git] / lib / rbot / irc.rb
index 4c462bb3cb6486fb5cbcf688e7db9a466a4f5518..c57b252f58973801f7f5b8a6e234a56903c1185e 100644 (file)
 
 require 'singleton'
 
+# The following monkeypatch is to fix a bug in Singleton where marshaling would
+# fail when trying to restore a marshaled Singleton due to _load being declared
+# private.
+if RUBY_VERSION < '1.9'
+module ::Singleton
+  public :_dump
+end
+
+class << Singleton
+  module SingletonClassMethods
+    public :_load
+  end
+end
+end
+
 class Object
 
   # We extend the Object class with a method that
@@ -258,7 +273,13 @@ class String
   # This method returns the Irc::Casemap whose name is the receiver
   #
   def to_irc_casemap
-    Irc::Casemap.get(self) rescue raise TypeError, "Unkown Irc::Casemap #{self.inspect}"
+    begin
+      Irc::Casemap.get(self)
+    rescue
+      # raise TypeError, "Unkown Irc::Casemap #{self.inspect}"
+      error "Unkown Irc::Casemap #{self.inspect} requested, defaulting to rfc1459"
+      Irc::Casemap.get('rfc1459')
+    end
   end
 
   # This method returns a string which is the downcased version of the
@@ -1308,6 +1329,13 @@ module Irc
   #
   class Channel
 
+    # Return the non-prefixed part of a channel name.
+    # Also works with ## channels found on some networks
+    # (e.g. FreeNode)
+    def self.npname(str)
+      return str.to_s.sub(/^[&#+!]+/,'')
+    end
+
     include ServerOrCasemap
     attr_reader :name, :topic, :mode, :users
     alias :to_s :name
@@ -1366,7 +1394,7 @@ module Irc
     #
     def initialize(name, topic=nil, users=[], opts={})
       raise ArgumentError, "Channel name cannot be empty" if name.to_s.empty?
-      warn "Unknown channel prefix #{name[0].chr}" if name !~ /^[&#+!]/
+      warn "Unknown channel prefix #{name[0,1]}" if name !~ /^[&#+!]/
       raise ArgumentError, "Invalid character in #{name.inspect}" if name =~ /[ \x07,]/
 
       init_server_or_casemap(opts)
@@ -1403,31 +1431,31 @@ module Irc
     # The channel prefix
     #
     def prefix
-      name[0].chr
+      name[0,1]
     end
 
     # A channel is local to a server if it has the '&' prefix
     #
     def local?
-      name[0] == 0x26
+      name[0,1] == '&'
     end
 
     # A channel is modeless if it has the '+' prefix
     #
     def modeless?
-      name[0] == 0x2b
+      name[0,1] == '+'
     end
 
     # A channel is safe if it has the '!' prefix
     #
     def safe?
-      name[0] == 0x21
+      name[0,1] == '!'
     end
 
     # A channel is normal if it has the '#' prefix
     #
     def normal?
-      name[0] == 0x23
+      name[0,1] == '#'
     end
 
     # Create a new mode
@@ -1497,7 +1525,6 @@ module Irc
   class Server
 
     attr_reader :hostname, :version, :usermodes, :chanmodes
-    alias :to_s :hostname
     attr_reader :supports, :capabilities
 
     attr_reader :channels, :users
@@ -1528,6 +1555,10 @@ module Irc
       str << ">"
     end
 
+    def to_s
+      hostname.nil? ? "<no hostname>" : hostname
+    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.
@@ -1646,7 +1677,7 @@ module Irc
     def parse_isupport(line)
       debug "Parsing ISUPPORT #{line.inspect}"
       ar = line.split(' ')
-      reparse = ""
+      reparse = []
       ar.each { |en|
         prekey, val = en.split('=', 2)
         if prekey =~ /^-(.*)/
@@ -1658,7 +1689,15 @@ module Irc
         case key
         when :casemapping
           noval_warn(key, val) {
-            @supports[key] = val.to_irc_casemap
+            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) {
@@ -1696,7 +1735,7 @@ module Irc
           @supports[key] = val
         when :maxchannels
           noval_warn(key, val) {
-            reparse += "CHANLIMIT=(chantypes):#{val} "
+            reparse << "CHANLIMIT=(chantypes):#{val} "
           }
         when :maxtargets
           noval_warn(key, val) {
@@ -1737,8 +1776,12 @@ module Irc
           @supports[key] =  val.nil? ? true : val
         end
       }
-      reparse.gsub!("(chantypes)",@supports[:chantypes])
-      parse_isupport(reparse) unless reparse.empty?
+      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
 
     # Returns the casemap of the server.
@@ -1803,7 +1846,7 @@ module Irc
         return ex
       else
 
-        prefix = name[0].chr
+        prefix = name[0,1]
 
         # Give a warning if the new Channel goes over some server limits.
         #