Skip to content

Misc Additions and Cleanups #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions asyncoperations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -87,3 +85,5 @@ function meta:setMode(t)

self:send("MODE %s %s", verify(target, 3), mode)
end

return meta
6 changes: 3 additions & 3 deletions doc/irc.luadoc
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,10 @@ function irc:shutdown()
-- <li><code>OnChat(user, channel, message)</code></li>
-- <li><code>OnNotice(user, channel, message)</code></li>
-- <li><code>OnJoin(user, channel)</code>*</li>
-- <li><code>OnPart(user, channel)</code>*</li>
-- <li><code>OnPart(user, channel, reason)</code>*</li>
-- <li><code>OnQuit(user, message)</code></li>
-- <li><code>NickChange(user, newnick, channel)</code>*�</li>
-- <li><code>NameList(channel, names)</code></li>
-- <li><code>NameList(channel, names, message)</code></li>
-- <li><code>OnTopic(channel, topic)</code></li>
-- <li><code>OnTopicInfo(channel, creator, timeCreated)</code></li>
-- <li><code>OnKick(channel, nick, kicker, reason)</code>* (kicker is a <code>user</code> table)</li>
Expand All @@ -154,7 +154,7 @@ function irc:shutdown()
-- <li><code>username</code> - User username.</li>
-- <li><code>host</code> - User hostname.</li>
-- <li><code>realname</code> - User real name.</li>
-- <li><code>access</code> - User access, available in channel-oriented callbacks. A table containing the boolean fields 'op', 'halfop', and 'voice'.</li>
-- <li><code>access</code> - User access, available in channel-oriented callbacks. A table containing the boolean fields 'owner', 'admin', 'op', 'halfop', and 'voice'.</li>
-- </ul>
-- Apart from <code>nick</code>, fields may be missing. To fill them in, enable user tracking and use irc:whois.
-- @name User
Expand Down
39 changes: 26 additions & 13 deletions handlers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 = {}}
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -97,16 +97,19 @@ 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

--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

Expand All @@ -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
Expand Down Expand Up @@ -164,11 +175,13 @@ 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)
o:invoke("OnDisconnect", message, true)
o:shutdown()
error(message, 3)
end

return handlers
26 changes: 12 additions & 14 deletions init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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

Expand Down Expand Up @@ -172,16 +168,14 @@ 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
end
end
end

local handlers = handlers

function meta:handle(prefix, cmd, params)
local handler = handlers[cmd]
if handler then
Expand All @@ -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
Expand All @@ -231,3 +225,7 @@ function meta:topic(channel)
self:send("TOPIC %s", channel)
end

return {
_META = meta;
new = new;
}
64 changes: 41 additions & 23 deletions util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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;
}