]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - lib/rbot/rfc2812.rb
+ support channel URL and creation time
[user/henk/code/ruby/rbot.git] / lib / rbot / rfc2812.rb
index f4487bdb8eaf5576454c8f4af2828c7e79013546..ac44888330d6b10726fa11be5a2eba04ff464d15 100644 (file)
@@ -144,6 +144,12 @@ module Irc
   # "<channel> <mode> <mode params>"
   RPL_CHANNELMODEIS=324
 
+  # "<channel> <unixtime>"
+  RPL_CREATIONTIME=329
+
+  # "<channel> <url>"
+  RPL_CHANNEL_URL=328
+
   # "<channel> :No topic is set"
   RPL_NOTOPIC=331
 
@@ -1122,19 +1128,14 @@ module Irc
           data[:message] = argv[2]
           handle(:badnick, data)
         when RPL_TOPIC
-          data[:channel] = @server.get_channel(argv[1])
+          data[:channel] = @server.channel(argv[1])
           data[:topic] = argv[2]
-
-          if data[:channel]
-            data[:channel].topic.text = data[:topic]
-          else
-            warning "Received topic #{data[:topic].inspect} for channel #{data[:channel].inspect} I was not on"
-          end
+          data[:channel].topic.text = data[:topic]
 
           handle(:topic, data)
         when RPL_TOPIC_INFO
           data[:nick] = @server.user(argv[0])
-          data[:channel] = @server.get_channel(argv[1])
+          data[:channel] = @server.channel(argv[1])
 
           # This must not be an IRC::User because it might not be an actual User,
           # and we risk overwriting valid User data
@@ -1142,12 +1143,8 @@ module Irc
 
           data[:time] = Time.at(argv[3].to_i)
 
-          if data[:channel]
-            data[:channel].topic.set_by = data[:source]
-            data[:channel].topic.set_on = data[:time]
-          else
-            warning "Received topic #{data[:topic].inspect} for channel #{data[:channel].inspect} I was not on"
-          end
+          data[:channel].topic.set_by = data[:source]
+          data[:channel].topic.set_on = data[:time]
 
           handle(:topicinfo, data)
         when RPL_NAMREPLY
@@ -1285,7 +1282,21 @@ module Irc
           handle(:who, data)
         when RPL_ENDOFWHO
           handle(:eowho, data)
+        when RPL_CHANNELMODEIS
+          parse_mode(serverstring, argv[1..-1], data)
+          handle(:mode, data)
+        when RPL_CREATIONTIME
+          data[:channel] = argv[1]
+          data[:time] = Time.at(argv[2].to_i)
+          @server.get_channel(data[:channel]).creation_time=data[:time]
+          handle(:creationtime, data)
+        when RPL_CHANNEL_URL
+          data[:channel] = argv[1]
+          data[:url] = argv[2]
+          @server.get_channel(data[:channel]).url=data[:url].dup
+          handle(:channel_url, data)
         else
+          warning "Unknown message #{serverstring.inspect}"
           handle(:unknown, data)
         end
        return # We've processed the numeric reply
@@ -1401,108 +1412,7 @@ module Irc
 
         handle(:nick, data)
       when :MODE
-        # MODE ([+-]<modes> (<params>)*)*
-        # When a MODE message is received by a server,
-        # Type C will have parameters too, so we must
-        # be able to consume parameters for all
-        # but Type D modes
-
-        data[:target] = @server.user_or_channel(argv[0])
-        data[:modestring] = argv[1..-1].join(" ")
-        # data[:modes] is an array where each element
-        # is an array with two elements, the first of which
-        # is either :set or :reset, and the second symbol
-        # is the mode letter. An optional third element
-        # is present e.g. for channel modes that need
-        # a parameter
-        data[:modes] = []
-        case data[:target]
-        when User
-          # User modes aren't currently handled internally,
-          # but we still parse them and delegate to the client
-          warning "Unhandled user mode message '#{serverstring}'"
-          argv[1..-1].each { |arg|
-            setting = arg[0].chr
-            if "+-".include?(setting)
-              setting = setting == "+" ? :set : :reset
-              arg[1..-1].each_byte { |b|
-                m = b.chr.intern
-                data[:modes] << [setting, m]
-              }
-            else
-              # Although typically User modes don't take an argument,
-              # this is not true for all modes on all servers. Since
-              # we have no knowledge of which modes take parameters
-              # and which don't we just assign it to the last
-              # mode. This is not going to do strange things often,
-              # as usually User modes are only set one at a time
-              warning "Unhandled user mode parameter #{arg} found"
-              data[:modes].last << arg
-            end
-          }
-        else
-          # array of indices in data[:modes] where parameters
-          # are needed
-          who_wants_params = []
-
-          modes = argv[1..-1].dup
-          debug modes
-          getting_args = false
-          while arg = modes.shift
-            debug arg
-            if getting_args
-              # getting args for previously set modes
-              idx = who_wants_params.shift
-              if idx.nil?
-                warning "Oops, problems parsing #{serverstring.inspect}"
-                break
-              end
-              data[:modes][idx] << arg
-              getting_args = false if who_wants_params.empty?
-            else
-              debug @server.supports[:chanmodes]
-              setting = :set
-              arg.each_byte do |c|
-                m = c.chr.intern
-                case m
-                when :+
-                  setting = :set
-                when :-
-                  setting = :reset
-                else
-                  data[:modes] << [setting, m]
-                  case m
-                  when *@server.supports[:chanmodes][:typea]
-                    who_wants_params << data[:modes].length - 1
-                  when *@server.supports[:chanmodes][:typeb]
-                    who_wants_params << data[:modes].length - 1
-                  when *@server.supports[:chanmodes][:typec]
-                    if setting == :set
-                      who_wants_params << data[:modes].length - 1
-                    end
-                  when *@server.supports[:chanmodes][:typed]
-                    # Nothing to do
-                  when *@server.supports[:prefix][:modes]
-                    who_wants_params << data[:modes].length - 1
-                  else
-                    warning "Unknown mode #{m} in #{serverstring.inspect}"
-                  end
-                end
-              end
-              getting_args = true unless who_wants_params.empty?
-            end
-          end
-
-          data[:modes].each { |mode|
-            set, key, val = mode
-            if val
-              data[:target].mode[key].send(set, val)
-            else
-              data[:target].mode[key].send(set)
-            end
-          }
-        end
-
+        parse_mode(serverstring, argv, data)
         handle(:mode, data)
       else
         warning "Unknown message #{serverstring.inspect}"
@@ -1520,5 +1430,110 @@ module Irc
         @handlers[key].call(data)
       end
     end
+
+    # RPL_CHANNELMODEIS
+    # MODE ([+-]<modes> (<params>)*)*
+    # When a MODE message is received by a server,
+    # Type C will have parameters too, so we must
+    # be able to consume parameters for all
+    # but Type D modes
+    def parse_mode(serverstring, argv, data)
+      data[:target] = @server.user_or_channel(argv[0])
+      data[:modestring] = argv[1..-1].join(" ")
+      # data[:modes] is an array where each element
+      # is an array with two elements, the first of which
+      # is either :set or :reset, and the second symbol
+      # is the mode letter. An optional third element
+      # is present e.g. for channel modes that need
+      # a parameter
+      data[:modes] = []
+      case data[:target]
+      when User
+        # User modes aren't currently handled internally,
+        # but we still parse them and delegate to the client
+        warning "Unhandled user mode message '#{serverstring}'"
+        argv[1..-1].each { |arg|
+          setting = arg[0].chr
+          if "+-".include?(setting)
+            setting = setting == "+" ? :set : :reset
+            arg[1..-1].each_byte { |b|
+              m = b.chr.intern
+              data[:modes] << [setting, m]
+            }
+          else
+            # Although typically User modes don't take an argument,
+            # this is not true for all modes on all servers. Since
+            # we have no knowledge of which modes take parameters
+            # and which don't we just assign it to the last
+            # mode. This is not going to do strange things often,
+            # as usually User modes are only set one at a time
+            warning "Unhandled user mode parameter #{arg} found"
+            data[:modes].last << arg
+          end
+        }
+      else
+        # array of indices in data[:modes] where parameters
+        # are needed
+        who_wants_params = []
+
+        modes = argv[1..-1].dup
+        debug modes
+        getting_args = false
+        while arg = modes.shift
+          debug arg
+          if getting_args
+            # getting args for previously set modes
+            idx = who_wants_params.shift
+            if idx.nil?
+              warning "Oops, problems parsing #{serverstring.inspect}"
+              break
+            end
+            data[:modes][idx] << arg
+            getting_args = false if who_wants_params.empty?
+          else
+            debug @server.supports[:chanmodes]
+            setting = :set
+            arg.each_byte do |c|
+              m = c.chr.intern
+              case m
+              when :+
+                setting = :set
+              when :-
+                setting = :reset
+              else
+                data[:modes] << [setting, m]
+                case m
+                when *@server.supports[:chanmodes][:typea]
+                  who_wants_params << data[:modes].length - 1
+                when *@server.supports[:chanmodes][:typeb]
+                  who_wants_params << data[:modes].length - 1
+                when *@server.supports[:chanmodes][:typec]
+                  if setting == :set
+                    who_wants_params << data[:modes].length - 1
+                  end
+                when *@server.supports[:chanmodes][:typed]
+                  # Nothing to do
+                when *@server.supports[:prefix][:modes]
+                  who_wants_params << data[:modes].length - 1
+                else
+                  warning "Ignoring unknown mode #{m} in #{serverstring.inspect}"
+                  data[:modes].pop
+                end
+              end
+            end
+            getting_args = true unless who_wants_params.empty?
+          end
+        end
+
+        data[:modes].each { |mode|
+          set, key, val = mode
+          if val
+            data[:target].mode[key].send(set, val)
+          else
+            data[:target].mode[key].send(set)
+          end
+        }
+      end
+    end
   end
 end