Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Strange nomethod error

Hi. Working on a script.

Code:
class IRC

  def initialize(server, port, nick)

    @server = server

    @port = port

    @nick = nick

    @channel = ""

    @quitmessage = "Disconnecting..."     

  end

  def main

    loop do

      ready = select([@irc],nil, nil,1)                    

      next if !ready

           

      for rs in ready[0]

        if rs == @irc then

          return if @irc.eof                    

          lock.synchronize do          

            s = @irc.readline.chomp

            handleservermessage(s)

          end

        end

      end

    end

  end

  def connect()    

    @irc = TCPSocket.open(@server, @port)

    send "USER #{@nick} server #{@server} :#{@nick} user"        

    send "Nick #{@nick}"        

  end

  def send msg

    p msg

    @irc.send(msg)

  end

  def puts msg

    $environment.put msg

  end

  def handleservermessage(s)        

    $environment.put s

    case s.strip                    

    when /^PING :(.+)$/i

    # makes no point puts "[ Server ping ]"

    send "PONG :#{$1}"

    when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s.+\s:[\001]PING (.+)[\001]$/i

      puts "[ CTCP PING from #{$1}!#{$2}@#{$3} ]"

      send "NOTICE #{$1} :\001PING #{$4}\001"

    when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s.+\s:[\001]VERSION[\001]$/i

      puts "[ CTCP VERSION from #{$1}!#{$2}@#{$3} ]"

      send "NOTICE #{$1} :\001VERSION Ruby-IRCClient "+version+"\001"            

    when /^:(\S*)!(.)* PRIVMSG #{@nick} :(.*)$/                

      puts "\033[21m"+$1+"\033[24m >>*>> "+$3

      sendername = $1.strip

      sendermsg = $3.strip

    when /^:(\S*)!(.)* PRIVMSG (\S+) :(.*)$/                

      puts "\033[21m"+$1+"@"+$3+"\033[24m >> "+$4

    when /^:(\S*)!(.)* NOTICE (.*)$/                

      puts "\033[21m#{$1} NOTICE\033[24m >> #{$3}"                

    when  /^:(\S*)!(.*) JOIN (\S+)/

      puts $1+" (#{$2}) joined "+$3

    when  /^:(\S*)!(.*) PART (\S*)/

      puts "#{$1} (#{$2}) left #{$3}"

    when  /^:(\S*)!(.*) QUIT(.*)/

      user = $1

      address = $2

      tail = $3

      if (tail =~ /:(.*)/)

        puts "#{user} (#{address}) quit - #{$1}"

      else

        puts "#{user} (#{address}) quit"

      end    

    when /^:(\S+) (\d+) (\S+) (\S) (\S+) (.*):(.*)$/i                

      puts "USERS@#{$5} >> #{$6} : #{$7}"                     

    when /^:(\S+) (\d+) (\S+) (\S+) (.*):(.*)$/i                

      puts "MSG >> #{$4} >> #{$5} : #{$6}"                 

    end

  end

end

The above is the whole script, but that's unimportant probably as my error is specific.

Code:
def connect()    

    @irc = TCPSocket.open(@server, @port)

    send "USER #{@nick} server #{@server} :#{@nick} user"        

    send "Nick #{@nick}"        

  end

 

  def send msg

    p msg

    @irc.send(msg)

  end

 
 
The problem is on the send "x" line.
 
I do the following:
 
p @irc.methods
 
The first method is "send".
 
So @irc.send("message") should work.
 
But I get a really strange error, the following:
 
Undefined method 'USER wyatt server irc.slacked.org :wyatt user' for nil:NilClass

for line: send "USER #{@nick} server #{@server} :#{@nick} user"

also happens for: @irc.send("USER #{@nick} server #{@server} :#{@nick} user")

 
I.e. it's trying to run the string as a method?
 
The socket class is here:
 
Code:
    #===============================================================================

    # ** Module Win32 - Handles numerical based data.

    #-------------------------------------------------------------------------------

    # Author    Ruby

    # Version   1.8.1

    #===============================================================================

 

 

    module Win32

 

      #--------------------------------------------------------------------------

      # ● Retrieves data from a pointer.

      #--------------------------------------------------------------------------

      def copymem(len)

        buf = "\0" * len

        Win32API.new("kernel32", "RtlMoveMemory", "ppl", "").call(buf, self, len)

        buf

      end

 

    end

 

    # Extends the numeric class.

    class Numeric

      include Win32

    end

 

    # Extends the string class.

    class String

      include Win32

    end

 

 

    #===============================================================================

    # ** Module Winsock - Maps out the functions held in the Winsock DLL.

    #-------------------------------------------------------------------------------

    # Author    Ruby

    # Version   1.8.1

    #===============================================================================

 

    module Winsock

 

      DLL = "ws2_32"

 

      #--------------------------------------------------------------------------

      # * Accept Connection

      #--------------------------------------------------------------------------

      def self.accept(*args)

        Win32API.new(DLL, "accept", "ppl", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Bind

      #--------------------------------------------------------------------------

      def self.bind(*args)

        Win32API.new(DLL, "bind", "ppl", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Close Socket

      #--------------------------------------------------------------------------

      def self.closesocket(*args)

        Win32API.new(DLL, "closesocket", "p", "l").call(*args)

      end 

 

      #--------------------------------------------------------------------------

      # * Connect

      #--------------------------------------------------------------------------

      def self.connect(*args)

        Win32API.new(DLL, "connect", "ppl", "l").call(*args)

      end   

 

      #--------------------------------------------------------------------------

      # * Get host (Using Adress)

      #--------------------------------------------------------------------------

      def self.gethostbyaddr(*args)

        Win32API.new(DLL, "gethostbyaddr", "pll", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Get host (Using Name)

      #--------------------------------------------------------------------------

      def self.gethostbyname(*args)

        Win32API.new(DLL, "gethostbyname", "p", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Get host's Name

      #--------------------------------------------------------------------------

      def self.gethostname(*args)

        Win32API.new(DLL, "gethostname", "pl", "").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Get Server (Using Name)

      #--------------------------------------------------------------------------

      def self.getservbyname(*args)

        Win32API.new(DLL, "getservbyname", "pp", "p").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * HT OnL

      #--------------------------------------------------------------------------

      def self.htonl(*args)

        Win32API.new(DLL, "htonl", "l", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * HT OnS

      #--------------------------------------------------------------------------

      def self.htons(*args)

        Win32API.new(DLL, "htons", "l", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Inet Adress

      #--------------------------------------------------------------------------

      def self.inet_addr(*args)

        Win32API.new(DLL, "inet_addr", "p", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Inet NtOA

      #--------------------------------------------------------------------------

      def self.inet_ntoa(*args)

        Win32API.new(DLL, "inet_ntoa", "l", "p").call(*args)

      end 

 

      #--------------------------------------------------------------------------

      # * Listen

      #--------------------------------------------------------------------------

      def self.listen(*args)

        Win32API.new(DLL, "listen", "pl", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Recieve

      #--------------------------------------------------------------------------

      def self.recv(*args)

        Win32API.new(DLL, "recv", "ppll", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Select

      #--------------------------------------------------------------------------

      def self.select(*args)

        Win32API.new(DLL, "select", "lpppp", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Send

      #--------------------------------------------------------------------------

      def self.send(*args)

        Win32API.new(DLL, "send", "ppll", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Set Socket Options

      #--------------------------------------------------------------------------

      def self.setsockopt(*args)

        Win32API.new(DLL, "setsockopt", "pllpl", "l").call(*args)

      end 

 

      #--------------------------------------------------------------------------

      # * Shutdown

      #--------------------------------------------------------------------------

      def self.shutdown(*args)

        Win32API.new(DLL, "shutdown", "pl", "l").call(*args)

      end

 

      #--------------------------------------------------------------------------

      # * Socket

      #--------------------------------------------------------------------------

      def self.socket(*args)

        Win32API.new(DLL, "socket", "lll", "l").call(*args) 

      end

 

      #--------------------------------------------------------------------------

      # * Get Last Error

      #--------------------------------------------------------------------------

      def self.WSAGetLastError(*args)

        Win32API.new(DLL, "WSAGetLastError", "", "l").call(*args)

      end

 

    end

 

    #===============================================================================

    # ** Socket - Creates and manages sockets.

    #-------------------------------------------------------------------------------

    # Author    Ruby

    # Version   1.8.1

    #===============================================================================

 

    class Socket

 

      #--------------------------------------------------------------------------

      # ● Constants

      #--------------------------------------------------------------------------

      AF_UNSPEC                 = 0 

      AF_UNIX                   = 1

      AF_INET                   = 2

      AF_IPX                    = 6

      AF_APPLETALK              = 16

 

      PF_UNSPEC                 = 0 

      PF_UNIX                   = 1

      PF_INET                   = 2

      PF_IPX                    = 6

      PF_APPLETALK              = 16

 

      SOCK_STREAM               = 1

      SOCK_DGRAM                = 2

      SOCK_RAW                  = 3

      SOCK_RDM                  = 4

      SOCK_SEQPACKET            = 5

 

      IPPROTO_IP                = 0

      IPPROTO_ICMP              = 1

      IPPROTO_IGMP              = 2

      IPPROTO_GGP               = 3

      IPPROTO_TCP               = 6

      IPPROTO_PUP               = 12

      IPPROTO_UDP               = 17

      IPPROTO_IDP               = 22

      IPPROTO_ND                = 77

      IPPROTO_RAW               = 255

      IPPROTO_MAX               = 256

 

      SOL_SOCKET                = 65535

 

      SO_DEBUG                  = 1

      SO_REUSEADDR              = 4

      SO_KEEPALIVE              = 8

      SO_DONTROUTE              = 16

      SO_BROADCAST              = 32

      SO_LINGER                 = 128

      SO_OOBINLINE              = 256

      SO_RCVLOWAT               = 4100

      SO_SNDTIMEO               = 4101

      SO_RCVTIMEO               = 4102

      SO_ERROR                  = 4103

      SO_TYPE                   = 4104

      SO_SNDBUF                 = 4097

      SO_RCVBUF                 = 4098

      SO_SNDLOWAT               = 4099

 

      TCP_NODELAY               =   1

 

      MSG_OOB                   = 1

      MSG_PEEK                  = 2

      MSG_DONTROUTE             = 4

 

      IP_OPTIONS                =   1

      IP_DEFAULT_MULTICAST_LOOP =   1

      IP_DEFAULT_MULTICAST_TTL  =   1

      IP_MULTICAST_IF           =   2

      IP_MULTICAST_TTL          =   3

      IP_MULTICAST_LOOP         =   4

      IP_ADD_MEMBERSHIP         =   5

      IP_DROP_MEMBERSHIP        =   6

      IP_TTL                    =   7

      IP_TOS                    =   8

      IP_MAX_MEMBERSHIPS        =   20

 

      EAI_ADDRFAMILY            = 1

      EAI_AGAIN                 = 2

      EAI_BADFLAGS              = 3

      EAI_FAIL                  = 4

      EAI_FAMILY                = 5

      EAI_MEMORY                = 6

      EAI_NODATA                = 7

      EAI_NONAME                = 8

      EAI_SERVICE               = 9

      EAI_SOCKTYPE              = 10

      EAI_SYSTEM                = 11

      EAI_BADHINTS              = 12

      EAI_PROTOCOL              = 13

      EAI_MAX                   = 14

 

      AI_PASSIVE                = 1

      AI_CANONNAME              = 2

      AI_NUMERICHOST            = 4

      AI_MASK                   = 7

      AI_ALL                    = 256

      AI_V4MAPPED_CFG           = 512

      AI_ADDRCONFIG             = 1024

      AI_DEFAULT                = 1536

      AI_V4MAPPED               = 2048

 

      #--------------------------------------------------------------------------

      # ● Returns the associated IP address for the given hostname.

      #-------------------------------------------------------------------------- 

      def self.getaddress(host)

        gethostbyname(host)[3].unpack("C4").join(".")

      end

 

      #--------------------------------------------------------------------------

      # ● Returns the associated IP address for the given hostname.

      #-------------------------------------------------------------------------- 

      def self.getservice(serv)

        case serv

        when Numeric

          return serv

        when String

          return getservbyname(serv)

        else

          raise "Please us an interger or string for services."

        end

      end

 

      #--------------------------------------------------------------------------

      # ● Returns information about the given hostname.

      #--------------------------------------------------------------------------

      def self.gethostbyname(name)

        raise SocketError::ENOASSOCHOST if (ptr = Winsock.gethostbyname(name)) == 0

        host = ptr.copymem(16).unpack("iissi")

        [host[0].copymem(64).split("\0")[0], [], host[2], host[4].copymem(4).unpack("l")[0].copymem(4)]

      end

 

      #--------------------------------------------------------------------------

      # ● Returns the user's hostname.

      #-------------------------------------------------------------------------- 

      def self.gethostname

        buf = "\0" * 256

        Winsock.gethostname(buf, 256)

        buf.strip

      end

 

      #--------------------------------------------------------------------------

      # ● Returns information about the given service.

      #--------------------------------------------------------------------------

      def self.getservbyname(name)

        case name

        when /echo/i

          return 7

        when /daytime/i

          return 13

        when /ftp/i

          return 21

        when /telnet/i

          return 23

        when /smtp/i

          return 25

        when /time/i

          return 37

        when /http/i

          return 80

        when /pop/i

          return 110

        else

          raise "Service not recognized."

        end

      end

 

      #--------------------------------------------------------------------------

      # ● Creates an INET-sockaddr struct.

      #-------------------------------------------------------------------------- 

      def self.sockaddr_in(port, host)

        begin

          [AF_INET, getservice(port)].pack("sn") + gethostbyname(host)[3] + [].pack("x8")

        rescue

          nil

        end

      end

 

      #--------------------------------------------------------------------------

      # ● Creates a new socket and connects it to the given host and port.

      #-------------------------------------------------------------------------- 

      def self.open(*args)

        socket = new(*args)

        if block_given?

          begin

            yield socket

          ensure

            socket.close

          end

        end

        nil

      end

 

      #--------------------------------------------------------------------------

      # ● Creates a new socket.

      #-------------------------------------------------------------------------- 

      def initialize(domain, type, protocol)

        SocketError.check if (@fd = Winsock.socket(domain, type, protocol)) == -1

        @fd

      end

 

      #--------------------------------------------------------------------------

      # ● Accepts incoming connections.

      #-------------------------------------------------------------------------- 

      def accept(flags = 0)

        buf = "\0" * 16

        SocketError.check if Winsock.accept(@fd, buf, flags) == -1

        buf

      end

 

      #--------------------------------------------------------------------------

      # ● Binds a socket to the given sockaddr.

      #-------------------------------------------------------------------------- 

      def bind(sockaddr)

        SocketError.check if (ret = Winsock.bind(@fd, sockaddr, sockaddr.size)) == -1

        ret

      end

 

      #--------------------------------------------------------------------------

      # ● Closes a socket.

      #-------------------------------------------------------------------------- 

      def close

        SocketError.check if (ret = Winsock.closesocket(@fd)) == -1

        ret

      end

 

      #--------------------------------------------------------------------------

      # ● Connects a socket to the given sockaddr.

      #-------------------------------------------------------------------------- 

      def connect(sockaddr)

        ret = Winsock.connect(@fd, sockaddr, sockaddr.size)

        SocketError.check if ret == -1

        ret

      end

 

      #--------------------------------------------------------------------------

      # ● Listens for incoming connections.

      #-------------------------------------------------------------------------- 

      def listen(backlog)

        SocketError.check if (ret = Winsock.listen(@fd, backlog)) == -1

        ret

      end

 

      #--------------------------------------------------------------------------

      # ● Checks waiting data's status.

      #-------------------------------------------------------------------------- 

      def select(timeout)

        SocketError.check if (ret = Winsock.select(1, [1, @fd].pack("ll"), 0, 0, [timeout, timeout * 1000000].pack("ll"))) == -1

        ret

      end

 

      #--------------------------------------------------------------------------

      # ● Checks if data is waiting.

      #-------------------------------------------------------------------------- 

      def ready?

        not select(0) == 0

      end 

 

      #--------------------------------------------------------------------------

      # ● Reads data from socket.

      #-------------------------------------------------------------------------- 

      def read(len)

        buf = "\0" * len

        Win32API.new("msvcrt", "_read", "lpl", "l").call(@fd, buf, len)

        buf

      end

 

      #--------------------------------------------------------------------------

      # ● Returns recieved data.

      #-------------------------------------------------------------------------- 

      def recv(len, flags = 0)

        buf = "\0" * len

        SocketError.check if Winsock.recv(@fd, buf, buf.size, flags) == -1

        buf

      end

 

      #--------------------------------------------------------------------------

      # ● Sends data to a host.

      #-------------------------------------------------------------------------- 

      def send(data, flags = 0)

        SocketError.check if (ret = Winsock.send(@fd, data, data.size, flags)) == -1

        ret

      end

 

      #--------------------------------------------------------------------------

      # * Gets

      #--------------------------------------------------------------------------

      def gets

        # Create buffer

        buffer = ""

        # Loop Until "end of line"

        while (char = recv(1)) != "\n"

          buffer += char

        end

        # Return recieved data

        return buffer

      end

 

      #--------------------------------------------------------------------------

      # ● Writes data to socket.

      #-------------------------------------------------------------------------- 

      def write(data)

        Win32API.new("msvcrt", "_write", "lpl", "l").call(@fd, data, 1)

      end

 

    end

 

 

    #===============================================================================

    # ** TCPSocket - Creates and manages TCP sockets.

    #-------------------------------------------------------------------------------

    # Author    Ruby

    # Version   1.8.1

    #===============================================================================

 

    class TCPSocket < Socket

 

      #--------------------------------------------------------------------------

      # ● Creates a new socket and connects it to the given host and port.

      #-------------------------------------------------------------------------- 

      def self.open(*args)

        socket = new(*args)

        if block_given?

          begin

            yield socket

          ensure

            socket.close

          end

        end

        nil

      end

 

      #--------------------------------------------------------------------------

      # ● Creates a new socket and connects it to the given host and port.

      #-------------------------------------------------------------------------- 

      def initialize(host, port)

        super(AF_INET, SOCK_STREAM, IPPROTO_TCP)

        connect(Socket.sockaddr_in(port, host))

      end

 

    end

 

    #==============================================================================

    # ■ SocketError

    #------------------------------------------------------------------------------

    #  Default exception class for sockets.

    #==============================================================================

    class SocketError < StandardError

      ENOASSOCHOST = "getaddrinfo: no address associated with hostname."

      def self.check

        errno = Winsock.WSAGetLastError

        errno = Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno }

        if errno != nil

          raise Errno.const_get(errno)

        end

      end

    end

 

I really don't get what's going wrong here.
 
There is nothing wrong with the send method, it works for me. I can't test it all, because I can't find a server and port for connecting with... But the send method works well.
How are you using the IRC class? And, how are you calling the connect method?

Edit: I reproduced the error now. The problem is that Object has a method called "send", which invokes a method of Object. And when you do: "@irc.send(msg)" you are calling the method called "USER #{@nick} server #{@server} :#{@nick} user" for @irc.
When it says: "Undefined method 'USER wyatt server irc.slacked.org :wyatt user' for nil:NilClass" you are invoking the "send" method for a nilclass object, and that send method is also invoking the method called 'USER wyatt server irc.slacked.org :wyatt user', which is not defined.

You should try changing the name of the method send to something else, or doing self.send and ensuring that it is calling the "send" method of IRC and not of Object or a NilClass.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top