diff --git a/asyncoperations.lua b/asyncoperations.lua index 3a6bf7b..7531b28 100644 --- a/asyncoperations.lua +++ b/asyncoperations.lua @@ -1,13 +1,6 @@ -local table = table -local assert = assert -local error = error -local select = select -local pairs = pairs -local type = type +local msgs = require("irc.messages") -module "irc" - -local meta = _META +local meta = {} function meta:send(msg, ...) if type(msg) == "table" then @@ -95,3 +88,5 @@ function meta:setMode(t) self:queue(msgs.mode(verify(target, 3), mode)) end +return meta + diff --git a/handlers.lua b/handlers.lua index e832529..46e900e 100644 --- a/handlers.lua +++ b/handlers.lua @@ -1,15 +1,11 @@ -local pairs = pairs -local error = error -local tonumber = tonumber -local table = table -local unpack = unpack +local util = require("irc.util") +local msgs = require("irc.messages") +local Message = msgs.Message -module "irc" - -handlers = {} +local handlers = {} handlers["PING"] = function(conn, msg) - conn:send(Message("PONG", msg.args)) + conn:send(Message({command="PONG", args=msg.args})) end handlers["001"] = function(conn, msg) @@ -127,7 +123,7 @@ handlers["353"] = function(conn, msg) local users = conn.channels[channel].users for nick in names:gmatch("(%S+)") do - local access, name = parseNick(conn, nick) + local access, name = util.parseNick(conn, nick) users[name] = {access = access} end end @@ -184,15 +180,17 @@ handlers["MODE"] = function(conn, msg) if conn.track_users and target ~= conn.nick then local add = true local argNum = 1 - updatePrefixModes(conn) + util.updatePrefixModes(conn) for c in modes:gmatch(".") do if c == "+" then add = true elseif c == "-" then add = false elseif conn.modeprefix[c] then local nick = optList[argNum] argNum = argNum + 1 - local access = conn.channels[target].users[nick].access - access[conn.modeprefix[c]] = add + local user = conn.channels[target].users[nick] + user.access = user.access or {} + local access = user.access + access[c] = add if c == "o" then access.op = add elseif c == "v" then access.voice = add end @@ -208,3 +206,5 @@ handlers["ERROR"] = function(conn, msg) error(msg.args[1], 3) end +return handlers + diff --git a/init.lua b/init.lua index b695c22..24a5ff8 100644 --- a/init.lua +++ b/init.lua @@ -1,27 +1,15 @@ -local socket = require "socket" - -local error = error -local setmetatable = setmetatable -local rawget = rawget -local unpack = unpack -local pairs = pairs -local assert = assert -local require = require -local tonumber = tonumber -local type = type -local pcall = pcall -local remove = table.remove - -module "irc" +local socket = require("socket") +local util = require("irc.util") +local handlers = require("irc.handlers") +local msgs = require("irc.messages") +local Message = msgs.Message local meta = {} meta.__index = meta -_META = meta -require "irc.util" -require "irc.asyncoperations" -require "irc.handlers" -require "irc.messages" +for k, v in pairs(require("irc.asyncoperations")) do + meta[k] = v +end local meta_preconnect = {} function meta_preconnect.__index(o, k) @@ -38,7 +26,7 @@ function new(data) nick = assert(data.nick, "Field 'nick' is required"); username = data.username or "lua"; realname = data.realname or "Lua owns"; - nickGenerator = data.nickGenerator or defaultNickGenerator; + nickGenerator = data.nickGenerator or util.defaultNickGenerator; hooks = {}; track_users = true; supports = {}; @@ -46,7 +34,7 @@ function new(data) lastThought = 0; recentMessages = 0; } - assert(checkNick(o.nick), "Erroneous nickname passed to irc.new") + assert(util.checkNick(o.nick), "Erroneous nickname passed to irc.new") return setmetatable(o, meta_preconnect) end @@ -116,7 +104,7 @@ function meta_preconnect:connect(_host, _port) end s = ssl.wrap(s, params) - success, errmsg = s:dohandshake() + local success, errmsg = s:dohandshake() if not success then error(("could not make secure connection: %s"):format(errmsg), 2) end @@ -195,20 +183,18 @@ function meta:think() if self.recentMessages > 4 then break end - self:send(remove(self.messageQueue, 1)) + self:send(table.remove(self.messageQueue, 1)) self.recentMessages = self.recentMessages + 1 end self.lastThought = socket.gettime() end -local handlers = handlers - function meta:handle(msg) local handler = handlers[msg.command] if handler then handler(self, msg) end - self:invoke("Do"..capitalize(msg.command), msg) + self:invoke("Do" .. util.capitalize(msg.command), msg) end local whoisHandlers = { @@ -232,7 +218,7 @@ function meta:whois(nick) local handler = whoisHandlers[msg.command] if handler then result[handler] = msg.args - elseif cmd == "318" then + elseif msg.command == "318" then break else self:handle(msg) @@ -253,3 +239,14 @@ function meta:topic(channel) self:queue(msgs.topic(channel)) end +return { + new = new; + + Message = Message; + msgs = msgs; + + color = util.color; + bold = util.bold; + underline = util.underline; +} + diff --git a/messages.lua b/messages.lua index cd64c51..46cf8c0 100644 --- a/messages.lua +++ b/messages.lua @@ -1,17 +1,11 @@ -local assert = assert -local setmetatable = setmetatable -local unpack = unpack -local pairs = pairs -local insert = table.insert -module "irc" - -msgs = {} +-- Module table +local m = {} local msg_meta = {} msg_meta.__index = msg_meta -function Message(opts) +local function Message(opts) opts = opts or {} setmetatable(opts, msg_meta) if opts.raw then @@ -20,6 +14,8 @@ function Message(opts) return opts end +m.Message = Message + local tag_escapes = { [";"] = "\\:", [" "] = "\\s", @@ -33,7 +29,7 @@ local tag_unescapes = {} for x, y in pairs(tag_escapes) do tag_unescapes[y] = x end function msg_meta:toRFC1459() - s = "" + local s = "" if self.tags then s = s.."@" @@ -52,7 +48,7 @@ function msg_meta:toRFC1459() s = s..self.command - argnum = #self.args + local argnum = #self.args for i = 1, argnum do local arg = self.args[i] local startsWithColon = (arg:sub(1, 1) == ":") @@ -114,26 +110,26 @@ function msg_meta:fromRFC1459(line) for pos, param in line:gmatch("()(%S+)") do if param:sub(1, 1) == ":" then param = line:sub(pos + 1) - insert(self.args, param) + table.insert(self.args, param) break end - insert(self.args, param) + table.insert(self.args, param) end end -function msgs.privmsg(to, text) +function m.privmsg(to, text) return Message({command="PRIVMSG", args={to, text}}) end -function msgs.notice(to, text) +function m.notice(to, text) return Message({command="NOTICE", args={to, text}}) end -function msgs.action(to, text) +function m.action(to, text) return Message({command="PRIVMSG", args={to, ("\x01ACTION %s\x01"):format(text)}}) end -function msgs.ctcp(command, to, args) +function m.ctcp(command, to, args) s = "\x01"..command if args then s = ' '..args @@ -142,27 +138,27 @@ function msgs.ctcp(command, to, args) return Message({command="PRIVMSG", args={to, s}}) end -function msgs.kick(channel, target, reason) +function m.kick(channel, target, reason) return Message({command="KICK", args={channel, target, reason}}) end -function msgs.join(channel, key) +function m.join(channel, key) return Message({command="JOIN", args={channel, key}}) end -function msgs.part(channel, reason) +function m.part(channel, reason) return Message({command="PART", args={channel, reason}}) end -function msgs.quit(reason) +function m.quit(reason) return Message({command="QUIT", args={reason}}) end -function msgs.kill(target, reason) +function m.kill(target, reason) return Message({command="KILL", args={target, reason}}) end -function msgs.kline(time, mask, reason, operreason) +function m.kline(time, mask, reason, operreason) local args = nil if time then args = {time, mask, reason..'|'..operreason} @@ -172,7 +168,7 @@ function msgs.kline(time, mask, reason, operreason) return Message({command="KLINE", args=args}) end -function msgs.whois(nick, server) +function m.whois(nick, server) local args = nil if server then args = {server, nick} @@ -182,24 +178,26 @@ function msgs.whois(nick, server) return Message({command="WHOIS", args=args}) end -function msgs.topic(channel, text) +function m.topic(channel, text) return Message({command="TOPIC", args={channel, text}}) end -function msgs.invite(channel, target) +function m.invite(channel, target) return Message({command="INVITE", args={channel, target}}) end -function msgs.nick(nick) +function m.nick(nick) return Message({command="NICK", args={nick}}) end -function msgs.mode(target, modes) +function m.mode(target, modes) -- We have to split the modes parameter because the mode string and -- each parameter are seperate arguments (The first command is incorrect) -- MODE foo :+ov Nick1 Nick2 -- MODE foo +ov Nick1 Nick2 - local mt = split(modes) + local mt = util.split(modes) return Message({command="MODE", args={target, unpack(mt)}}) end +return m + diff --git a/set.lua b/set.lua index 13952c3..a4c6881 100644 --- a/set.lua +++ b/set.lua @@ -1,17 +1,10 @@ -local select = require "socket".select - -local setmetatable = setmetatable -local insert = table.insert -local remove = table.remove -local ipairs = ipairs -local error = error - -module "irc.set" +local select = require("socket").select +local m = {} local set = {} set.__index = set -function new(t) +function m.new(t) t.connections = {} t.sockets = {} return setmetatable(t, set) @@ -54,3 +47,6 @@ function set:poll() local read, err = self:select() return err == "timeout" and self.connections or read end + +return m + diff --git a/util.lua b/util.lua index 3baab8e..5916857 100644 --- a/util.lua +++ b/util.lua @@ -1,36 +1,8 @@ -local setmetatable = setmetatable -local sub = string.sub -local byte = string.byte -local char = string.char -local table = table -local assert = assert -local tostring = tostring -local type = type -local random = math.random -module "irc" +-- Module table +local m = {} - -function parseNick(conn, nick) - local access = {} - updatePrefixModes(conn) - local namestart = 1 - for i = 1, #nick - 1 do - local c = nick:sub(i, i) - if conn.prefixmode[c] then - access[conn.prefixmode[c]] = true - else - namestart = i - break - end - end - access.op = access.o - access.voice = access.v - local name = nick:sub(namestart) - return access, name -end - -function updatePrefixModes(conn) +function m.updatePrefixModes(conn) if conn.prefixmode and conn.modeprefix then return end @@ -50,8 +22,27 @@ function updatePrefixModes(conn) end end ---mIRC markup scheme (de-facto standard) -color = { +function m.parseNick(conn, nick) + local access = {} + m.updatePrefixModes(conn) + local namestart = 1 + for i = 1, #nick - 1 do + local c = nick:sub(i, i) + if conn.prefixmode[c] then + access[conn.prefixmode[c]] = true + else + namestart = i + break + end + end + access.op = access.o + access.voice = access.v + local name = nick:sub(namestart) + return access, name +end + +-- mIRC markup scheme (de-facto standard) +m.color = { black = 1, blue = 2, green = 3, @@ -70,52 +61,54 @@ color = { white = 16 } -local colByte = char(3) -setmetatable(color, {__call = function(_, text, colornum) - colornum = type(colornum) == "string" and assert(color[colornum], "Invalid color '"..colornum.."'") or colornum +local colByte = string.char(3) +setmetatable(m.color, {__call = function(_, text, colornum) + colornum = (type(colornum) == "string" and + assert(color[colornum], "Invalid color '"..colornum.."'") or + colornum) return table.concat{colByte, tostring(colornum), text, colByte} end}) -local boldByte = char(2) -function bold(text) +local boldByte = string.char(2) +function m.bold(text) return boldByte..text..boldByte end -local underlineByte = char(31) -function underline(text) +local underlineByte = string.char(31) +function m.underline(text) return underlineByte..text..underlineByte end -function checkNick(nick) +function m.checkNick(nick) return nick:find("^[a-zA-Z_%-%[|%]%^{|}`][a-zA-Z0-9_%-%[|%]%^{|}`]*$") ~= nil end -function defaultNickGenerator(nick) +function m.defaultNickGenerator(nick) -- LuaBot -> LuaCot -> LuaCou -> ... -- We change a random character rather than appending to the -- nickname as otherwise the new nick could exceed the ircd's -- maximum nickname length. - local randindex = random(1, #nick) - local randchar = sub(nick, randindex, randindex) - local b = byte(randchar) + local randindex = math.random(1, #nick) + local randchar = string.sub(nick, randindex, randindex) + local b = string.byte(randchar) b = b + 1 if b < 65 or b > 125 then b = 65 end -- Get the halves before and after the changed character - local first = sub(nick, 1, randindex - 1) - local last = sub(nick, randindex + 1, #nick) - nick = first..char(b)..last -- Insert the new charachter + local first = string.sub(nick, 1, randindex - 1) + local last = string.sub(nick, randindex + 1, #nick) + nick = first .. string.char(b) .. last -- Insert the new charachter return nick end -function capitalize(text) +function m.capitalize(text) -- Converts first character to upercase and the rest to lowercase. -- "PING" -> "Ping" | "hello" -> "Hello" | "123" -> "123" return text:sub(1, 1):upper()..text:sub(2):lower() end -function split(str, sep) +function m.split(str, sep) local t = {} for s in str:gmatch("%S+") do table.insert(t, s) @@ -123,3 +116,5 @@ function split(str, sep) return t end +return m +