Hi. Working on a script.
The above is the whole script, but that's unimportant probably as my error is specific.
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:
I really don't get what's going wrong here.
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.