local cqueues = require("cqueues") local socket = require("cqueues.socket") local loop = cqueues.new() local host, port, socketpath = ... socketpath = socketpath or "./sock" -- irc session local irc = { callbacks = {} } function irc.new(nick, username, password, realname) local self = { nick = nick or "albotty", username = username or "albotty", password = password, realname = realname or "albotty" } return setmetatable(self, { __index = irc }) end function irc:connect(host, port) local hostname, password, tls, timeout if type(host) == "table" then hostname = host.host port = host.port password = host.password tls = host.tls timeout = host.timeout else hostname = host end self.conn = socket.connect(hostname, port) self.conn:settimeout(timeout or 30) self:send("NICK %s", self.nick) self:send("USER %s 0 * :%s", self.username, self.realname) local loop = cqueues.new() loop:wrap(function() for line in sess.conn:lines("*L") do if line and #line > 0 then sess:handle(line) end if self.authed then return end end end) while not loop:empty() and not self.authed do local ok, err = loop:step() if not ok then error("loop.step: "..err) end end return self end function irc:pollfd() return self.conn:pollfd() end function irc:events() return self.conn:events() end function irc:send(msg, ...) if select("#", ...) > 0 then msg = msg:format(...) end -- call send hook self.conn:write(msg.."\r\n") self.conn:flush() end local function irc_parse(line) local prefix local lineStart = 1 if line:sub(1,1) == ":" then local space = line:find(" ") prefix = line:sub(2, space-1) lineStart = space end local _, trailToken = line:find("%s+:", lineStart) local lineStop = line:len() local trailing if trailToken then trailing = line:sub(trailToken + 1) lineStop = trailToken - 2 end local params = {} local _, cmdEnd, cmd = line:find("(%S+)", lineStart) local pos = cmdEnd + 1 while true do local _, stop, param = line:find("(%S+)", pos) if not param or stop > lineStop then break end pos = stop + 1 params[#params + 1] = param end if trailing then params[#params + 1] = trailing end return prefix, cmd, params end local function parse_prefix(prefix) local user = {} if prefix then user.access, user.nick, user.username, user.host = prefix:match("^([%+@]*)(.+)!(.+)@(.+)$") end return user end irc.callbacks["001"] = function(self, prefix, me) self.authed = true self.nick = me end irc.callbacks["NOTICE"] = function(self, prefix, channel, msg) end irc.callbacks["NICK"] = function(self, prefix, newnick) local user = parse_prefix(prefix) if self.nick == user.nick then self.nick = newnick end end irc.callbacks["NICK"] = function(self, prefix, newnick) local user = parse_prefix(prefix) if self.nick == user.nick then self.nick = newnick end end irc.callbacks["PING"] = function(self, prefix, query) self:send("PONG :%", query) end function irc:handle(line) local prefix, cmd, params = irc_parse(line) callback = self.callbacks[cmd] if type(callback) == "function" then print("DEBUG: calling handler for:", cmd, prefix, table.unpack(params)) return callback(self, prefix, table.unpack(params)) else print("DEBUG no handler for:", cmd, "prefix:",prefix) end end function irc:step() local line, why, errmsg = self.conn:read("*L") if not line or #line == 0 then return nil end self:handle(line) return line end sess = irc.new() sess:connect("chat.freenode.net", "6667") print("CONNECTED!!!!!!!!!!!!!!!!!!!!!!!!!!!!11") loop:wrap(function() while sess:step() do print("witing for next") end end) while not loop:empty() do local ok, err = loop:step() if not ok then os.remove(socketpath) error("loop.step: "..err) end end os.remove(socketpath)