# File lib/rbot/rfc2812.rb, line 868
    def process(serverstring)
      data = Hash.new
      data[:serverstring] = serverstring

      unless serverstring =~ /^(:(\S+)\s)?(\S+)(\s(.*))?/
        raise "Unparseable Server Message!!!: #{serverstring}"
      end

      prefix, command, params = $2, $3, $5

      if prefix != nil
        data[:source] = prefix
        if prefix =~ /^(\S+)!(\S+)$/
          data[:sourcenick] = $1
          data[:sourceaddress] = $2
        end
      end

      # split parameters in an array
      argv = []
      params.scan(/(?!:)(\S+)|:(.*)/) { argv << ($1 || $2) } if params

      case command
      when 'PING'
        data[:pingid] = argv[0]
        handle(:ping, data)
      when 'PONG'
        data[:pingid] = argv[0]
        handle(:pong, data)
      when /^(\d+)$/            # numeric server message
        num=command.to_i
        case num
        when RPL_YOURHOST
          # "Your host is <servername>, running version <ver>"
          # TODO how standard is this "version <ver>? should i parse it?
          data[:message] = argv[1]
          handle(:yourhost, data)
        when RPL_CREATED
          # "This server was created <date>"
          data[:message] = argv[1]
          handle(:created, data)
        when RPL_MYINFO
          # "<servername> <version> <available user modes>
          # <available channel modes>"
          data[:servername] = argv[1]
          data[:version] = argv[2]
          data[:usermodes] = argv[3]
          data[:chanmodes] = argv[4]
        when ERR_NICKNAMEINUSE
          # "* <nick> :Nickname is already in use"
          data[:nick] = argv[1]
          data[:message] = argv[2]
          handle(:nicktaken, data)
        when ERR_ERRONEUSNICKNAME
          # "* <nick> :Erroneous nickname"
          data[:nick] = argv[1]
          data[:message] = argv[2]
          handle(:badnick, data)
        when RPL_TOPIC
          data[:channel] = argv[1]
          data[:topic] = argv[2]
          handle(:topic, data)
        when RPL_TOPIC_INFO
          data[:nick] = argv[0]
          data[:channel] = argv[1]
          data[:source] = argv[2]
          data[:unixtime] = argv[3]
          handle(:topicinfo, data)
        when RPL_NAMREPLY
          # "( "=" / "*" / "@" ) <channel>
          # :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
          # - "@" is used for secret channels, "*" for private
          # channels, and "=" for others (public channels).
          argv[3].scan(/\S+/).each { |u|
            if(u =~ /^([@+])?(.*)$/)
              umode = $1 || ""
              user = $2
              @users << [user, umode]
            end
          }
        when RPL_ENDOFNAMES
          data[:channel] = argv[1]
          data[:users] = @users
          handle(:names, data)
          @users = Array.new
        when RPL_ISUPPORT
          # "PREFIX=(ov)@+ CHANTYPES=#& :are supported by this server"
          # "MODES=4 CHANLIMIT=#:20 NICKLEN=16 USERLEN=10 HOSTLEN=63
          # TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=#
          # PREFIX=(ov)@+ CASEMAPPING=ascii CAPAB IRCD=dancer :are available
          # on this server"
          #
          argv[0,argv.length-1].each {|a|
            if a =~ /^(.*)=(.*)$/
              data[$1.downcase.to_sym] = $2
              debug "server's #{$1.downcase.to_sym} is #{$2}"
            else
              data[a.downcase.to_sym] = true
              debug "server supports #{a.downcase.to_sym}"
            end
          }
          handle(:isupport, data)
        when RPL_LUSERCLIENT
          # ":There are <integer> users and <integer>
          # services on <integer> servers"
          data[:message] = argv[1]
          handle(:luserclient, data)
        when RPL_LUSEROP
          # "<integer> :operator(s) online"
          data[:ops] = argv[1].to_i
          handle(:luserop, data)
        when RPL_LUSERUNKNOWN
          # "<integer> :unknown connection(s)"
          data[:unknown] = argv[1].to_i
          handle(:luserunknown, data)
        when RPL_LUSERCHANNELS
          # "<integer> :channels formed"
          data[:channels] = argv[1].to_i
          handle(:luserchannels, data)
        when RPL_LUSERME
          # ":I have <integer> clients and <integer> servers"
          data[:message] = argv[1]
          handle(:luserme, data)
        when ERR_NOMOTD
          # ":MOTD File is missing"
          data[:message] = argv[1]
          handle(:motd_missing, data)
        when RPL_LOCALUSERS
          # ":Current local  users: 3  Max: 4"
          data[:message] = argv[1]
          handle(:localusers, data)
        when RPL_GLOBALUSERS
          # ":Current global users: 3  Max: 4"
          data[:message] = argv[1]
          handle(:globalusers, data)
        when RPL_STATSCONN
          # ":Highest connection count: 4 (4 clients) (251 since server was
          # (re)started)"
          data[:message] = argv[1]
          handle(:statsconn, data)
        when RPL_WELCOME
          # "Welcome to the Internet Relay Network
          # <nick>!<user>@<host>"
          case argv[1]
          when /((\S+)!(\S+))/
            data[:netmask] = $1
            data[:nick] = $2
            data[:address] = $3
          when /Welcome to the Internet Relay Network\s(\S+)/
            data[:nick] = $1
          when /Welcome.*\s+(\S+)$/
            data[:nick] = $1
          when /^(\S+)$/
            data[:nick] = $1
          end
          handle(:welcome, data)
        when RPL_MOTDSTART
          # "<nick> :- <server> Message of the Day -"
          if argv[1] =~ /^-\s+(\S+)\s/
            server = $1
            @motd = ""
          end
        when RPL_MOTD
          if(argv[1] =~ /^-\s+(.*)$/)
            @motd << $1
            @motd << "\n"
          end
        when RPL_ENDOFMOTD
          data[:motd] = @motd
          handle(:motd, data)
        when RPL_DATASTR
          data[:text] = argv[1]
          handle(:datastr, data)
        else
          handle(:unknown, data)
        end
      # end of numeric replies
      when 'PRIVMSG'
        # you can either bind to 'PRIVMSG', to get every one and
        # parse it yourself, or you can bind to 'MSG', 'PUBLIC',
        # etc and get it all nicely split up for you.
        data[:target] = argv[0]
        data[:message] = argv[1]
        handle(:privmsg, data)

        # Now we split it
        if(data[:target] =~ /^[#&!+].*/)
          handle(:public, data)
        else
          handle(:msg, data)
        end
      when 'KICK'
        data[:channel] = argv[0]
        data[:target] = argv[1]
        data[:message] = argv[2]
        handle(:kick, data)
      when 'PART'
        data[:channel] = argv[0]
        data[:message] = argv[1]
        handle(:part, data)
      when 'QUIT'
        data[:message] = argv[0]
        handle(:quit, data)
      when 'JOIN'
        data[:channel] = argv[0]
        handle(:join, data)
      when 'TOPIC'
        data[:channel] = argv[0]
        data[:topic] = argv[1]
        handle(:changetopic, data)
      when 'INVITE'
        data[:target] = argv[0]
        data[:channel] = argv[1]
        handle(:invite, data)
      when 'NICK'
        data[:nick] = argv[0]
        handle(:nick, data)
      when 'MODE'
        data[:channel] = argv[0]
        data[:modestring] = argv[1]
        data[:targets] = argv[2]
        handle(:mode, data)
      when 'NOTICE'
        data[:target] = argv[0]
        data[:message] = argv[1]
        if data[:sourcenick]
          handle(:notice, data)
        else
          # "server notice" (not from user, noone to reply to
          handle(:snotice, data)
        end
      else
        handle(:unknown, data)
      end
    end