diff --git a/asyncoperations.lua b/asyncoperations.lua index 9e9ba13..7e65e46 100644 --- a/asyncoperations.lua +++ b/asyncoperations.lua @@ -4,9 +4,7 @@ local error = error local select = select local pairs = pairs -module "irc" - -local meta = _META +local meta = {} function meta:send(msg, ...) if select("#", ...) > 0 then @@ -87,3 +85,5 @@ function meta:setMode(t) self:send("MODE %s %s", verify(target, 3), mode) end + +return meta diff --git a/doc/irc.luadoc b/doc/irc.luadoc index 111de8e..7c175cd 100644 --- a/doc/irc.luadoc +++ b/doc/irc.luadoc @@ -132,10 +132,10 @@ function irc:shutdown() --
OnChat(user, channel, message)OnNotice(user, channel, message)OnJoin(user, channel)*OnPart(user, channel)*OnPart(user, channel, reason)*OnQuit(user, message)NickChange(user, newnick, channel)*†NameList(channel, names)NameList(channel, names, message)OnTopic(channel, topic)OnTopicInfo(channel, creator, timeCreated)OnKick(channel, nick, kicker, reason)* (kicker is a user table)username - User username.host - User hostname.realname - User real name.access - User access, available in channel-oriented callbacks. A table containing the boolean fields 'op', 'halfop', and 'voice'.access - User access, available in channel-oriented callbacks. A table containing the boolean fields 'owner', 'admin', 'op', 'halfop', and 'voice'.nick, fields may be missing. To fill them in, enable user tracking and use irc:whois.
-- @name User
diff --git a/handlers.lua b/handlers.lua
index cbd1c9e..dc71bb2 100644
--- a/handlers.lua
+++ b/handlers.lua
@@ -3,9 +3,9 @@ local error = error
local tonumber = tonumber
local table = table
-module "irc"
+local util = require "irc.util"
-handlers = {}
+local handlers = {}
handlers["PING"] = function(o, prefix, query)
o:send("PONG :%s", query)
@@ -17,15 +17,15 @@ handlers["001"] = function(o, prefix, me)
end
handlers["PRIVMSG"] = function(o, prefix, channel, message)
- o:invoke("OnChat", parsePrefix(prefix), channel, message)
+ o:invoke("OnChat", util.parsePrefix(prefix), channel, message)
end
handlers["NOTICE"] = function(o, prefix, channel, message)
- o:invoke("OnNotice", parsePrefix(prefix), channel, message)
+ o:invoke("OnNotice", util.parsePrefix(prefix), channel, message)
end
handlers["JOIN"] = function(o, prefix, channel)
- local user = parsePrefix(prefix)
+ local user = util.parsePrefix(prefix)
if o.track_users then
if user.nick == o.nick then
o.channels[channel] = {users = {}}
@@ -38,7 +38,7 @@ handlers["JOIN"] = function(o, prefix, channel)
end
handlers["PART"] = function(o, prefix, channel, reason)
- local user = parsePrefix(prefix)
+ local user = util.parsePrefix(prefix)
if o.track_users then
if user.nick == o.nick then
o.channels[channel] = nil
@@ -50,7 +50,7 @@ handlers["PART"] = function(o, prefix, channel, reason)
end
handlers["QUIT"] = function(o, prefix, msg)
- local user = parsePrefix(prefix)
+ local user = util.parsePrefix(prefix)
if o.track_users then
for channel, v in pairs(o.channels) do
v.users[user.nick] = nil
@@ -60,7 +60,7 @@ handlers["QUIT"] = function(o, prefix, msg)
end
handlers["NICK"] = function(o, prefix, newnick)
- local user = parsePrefix(prefix)
+ local user = util.parsePrefix(prefix)
if o.track_users then
for channel, v in pairs(o.channels) do
local users = v.users
@@ -97,8 +97,11 @@ handlers["353"] = function(o, prefix, me, chanType, channel, names)
local users = o.channels[channel].users
for nick in names:gmatch("(%S+)") do
- local access, name = parseNick(nick)
- users[name] = {access = access}
+ local access, name = util.parseNick(nick)
+ users[name] = {
+ nick = name;
+ access = access;
+ }
end
end
end
@@ -106,7 +109,7 @@ end
--end of NAMES
handlers["366"] = function(o, prefix, me, channel, msg)
if o.track_users then
- o:invoke("NameList", channel, msg)
+ o:invoke("NameList", channel, o.channels[channel].users, msg)
end
end
@@ -130,7 +133,15 @@ handlers["333"] = function(o, prefix, me, channel, nick, time)
end
handlers["KICK"] = function(o, prefix, channel, kicked, reason)
- o:invoke("OnKick", channel, kicked, parsePrefix(prefix), reason)
+ local user = util.parsePrefix(prefix)
+ if o.track_users then
+ if user.nick == o.nick then
+ o.channels[channel] = nil
+ else
+ o.channels[channel].users[user.nick] = nil
+ end
+ end
+ o:invoke("OnKick", channel, kicked, user, reason)
end
--RPL_UMODEIS
@@ -164,7 +175,7 @@ handlers["MODE"] = function(o, prefix, target, modes, ...)
end
end
end
- o:invoke("OnModeChange", parsePrefix(prefix), target, modes, ...)
+ o:invoke("OnModeChange", util.parsePrefix(prefix), target, modes, ...)
end
handlers["ERROR"] = function(o, prefix, message)
@@ -172,3 +183,5 @@ handlers["ERROR"] = function(o, prefix, message)
o:shutdown()
error(message, 3)
end
+
+return handlers
diff --git a/init.lua b/init.lua
index 99ae7f5..53fabc3 100644
--- a/init.lua
+++ b/init.lua
@@ -7,19 +7,15 @@ local unpack = unpack
local pairs = pairs
local assert = assert
local require = require
-local tonumber = tonumber
local type = type
local pcall = pcall
-module "irc"
-
local meta = {}
meta.__index = meta
-_META = meta
-require "irc.util"
-require "irc.asyncoperations"
-require "irc.handlers"
+local util = require "irc.util"
+for k, v in pairs(require "irc.asyncoperations") do meta[k] = v end
+local handlers = require "irc.handlers"
local meta_preconnect = {}
function meta_preconnect.__index(o, k)
@@ -31,16 +27,16 @@ function meta_preconnect.__index(o, k)
return v
end
-function new(data)
+local function new(data)
local o = {
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;
}
- 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
@@ -172,7 +168,7 @@ function meta:think()
local line = getline(self, 3)
if line and #line > 0 then
if not self:invoke("OnRaw", line) then
- self:handle(parse(line))
+ self:handle(util.parse(line))
end
else
break
@@ -180,8 +176,6 @@ function meta:think()
end
end
-local handlers = handlers
-
function meta:handle(prefix, cmd, params)
local handler = handlers[cmd]
if handler then
@@ -205,7 +199,7 @@ function meta:whois(nick)
while true do
local line = getline(self, 3)
if line then
- local prefix, cmd, args = parse(line)
+ local prefix, cmd, args = util.parse(line)
local handler = whoisHandlers[cmd]
if handler then
@@ -231,3 +225,7 @@ function meta:topic(channel)
self:send("TOPIC %s", channel)
end
+return {
+ _META = meta;
+ new = new;
+}
diff --git a/util.lua b/util.lua
index 2bdb222..ca262f6 100644
--- a/util.lua
+++ b/util.lua
@@ -8,10 +8,8 @@ local tostring = tostring
local type = type
local random = math.random
-module "irc"
-
--protocol parsing
-function parse(line)
+local function parse(line)
local prefix
local lineStart = 1
if line:sub(1,1) == ":" then
@@ -50,33 +48,41 @@ function parse(line)
return prefix, cmd, params
end
-function parseNick(nick)
- local access, name = nick:match("^([%+@]*)(.+)$")
+local function parseAccess(accessString)
+ local access = {
+ owner = false;
+ admin = false;
+ op = false;
+ halfop = false;
+ voice = false;
+ }
+ for c in accessString:gmatch(".") do
+ if c == "~" then access.owner = true
+ elseif c == "&" then access.admin = true
+ elseif c == "@" then access.op = true
+ elseif c == "%" then access.halfop = true
+ elseif c == "+" then access.voice = true
+ end
+ end
+ return access
+end
+
+local function parseNick(nick)
+ local access, name = nick:match("^([%%+@&~]*)(.+)$")
return parseAccess(access or ""), name
end
-function parsePrefix(prefix)
+local function parsePrefix(prefix)
local user = {}
if prefix then
- user.access, user.nick, user.username, user.host = prefix:match("^([%+@]*)(.+)!(.+)@(.+)$")
+ user.access, user.nick, user.username, user.host = prefix:match("^([%%+@&~]*)(.+)!(.+)@(.+)$")
end
user.access = parseAccess(user.access or "")
return user
end
-function parseAccess(accessString)
- local access = {op = false, halfop = false, voice = false}
- for c in accessString:gmatch(".") do
- if c == "@" then access.op = true
- elseif c == "%" then access.halfop = true
- elseif c == "+" then access.voice = true
- end
- end
- return access
-end
-
--mIRC markup scheme (de-facto standard)
-color = {
+local color = {
black = 1,
blue = 2,
green = 3,
@@ -102,20 +108,20 @@ setmetatable(color, {__call = function(_, text, colornum)
end})
local boldByte = char(2)
-function bold(text)
+local function bold(text)
return boldByte..text..boldByte
end
local underlineByte = char(31)
-function underline(text)
+local function underline(text)
return underlineByte..text..underlineByte
end
-function checkNick(nick)
+local function checkNick(nick)
return nick:find("^[a-zA-Z_%-%[|%]%^{|}`][a-zA-Z0-9_%-%[|%]%^{|}`]*$") ~= nil
end
-function defaultNickGenerator(nick)
+local function defaultNickGenerator(nick)
-- LuaBot -> LuaCot -> LuaCou -> ...
-- We change a random charachter rather than appending to the
-- nickname as otherwise the new nick could exceed the ircd's
@@ -134,3 +140,15 @@ function defaultNickGenerator(nick)
return nick
end
+return {
+ parse = parse;
+ parseNick = parseNick;
+ parsePrefix = parsePrefix;
+ parseAccess = parseAccess;
+
+ color = color;
+ bold = bold;
+ underline = underline;
+ checkNick = checkNick;
+ defaultNickGenerator = defaultNickGenerator;
+}