2014-03-17 19:52:09 +01:00
|
|
|
local assert = assert
|
|
|
|
local setmetatable = setmetatable
|
|
|
|
local unpack = unpack
|
2014-03-18 09:36:02 +01:00
|
|
|
local pairs = pairs
|
2014-03-17 19:52:09 +01:00
|
|
|
|
|
|
|
module "irc"
|
|
|
|
|
|
|
|
msgs = {}
|
|
|
|
|
|
|
|
local msg_meta = {}
|
|
|
|
msg_meta.__index = msg_meta
|
|
|
|
|
|
|
|
function Message(cmd, args)
|
|
|
|
return setmetatable({
|
|
|
|
command = cmd,
|
|
|
|
args = args or {},
|
|
|
|
}, msg_meta)
|
|
|
|
end
|
|
|
|
|
|
|
|
function msg_meta:toRFC1459()
|
2014-03-18 09:36:02 +01:00
|
|
|
s = ""
|
|
|
|
|
|
|
|
if self.tags then
|
|
|
|
s = s.."@"
|
|
|
|
for key, value in pairs(self.tags) do
|
|
|
|
s = s..key
|
|
|
|
if value ~= true then
|
|
|
|
assert(not value:find("[%z\07\r\n; ]"),
|
|
|
|
"NUL, BELL, CR, LF, semicolon, and"
|
|
|
|
.." space are not allowed in RFC1459"
|
|
|
|
.." formated tag values.")
|
|
|
|
s = s.."="..value
|
|
|
|
end
|
|
|
|
s = s..";"
|
|
|
|
end
|
|
|
|
-- Strip trailing semicolon
|
|
|
|
s = s:sub(1, -2)
|
|
|
|
s = s.." "
|
|
|
|
end
|
|
|
|
|
|
|
|
s = s..self.command
|
|
|
|
|
2014-03-17 19:52:09 +01:00
|
|
|
argnum = #self.args
|
|
|
|
for i = 1, argnum do
|
|
|
|
local arg = self.args[i]
|
|
|
|
local startsWithColon = (arg:sub(1, 1) == ":")
|
|
|
|
local hasSpace = arg:find(" ")
|
|
|
|
if i == argnum and (hasSpace or startsWithColon) then
|
|
|
|
s = s.." :"
|
|
|
|
else
|
|
|
|
assert(not hasSpace and not startsWithColon,
|
|
|
|
"Message arguments can not be "
|
|
|
|
.."serialized to RFC1459 format")
|
|
|
|
s = s.." "
|
|
|
|
end
|
|
|
|
s = s..arg
|
|
|
|
end
|
2014-03-18 09:36:02 +01:00
|
|
|
|
2014-03-17 19:52:09 +01:00
|
|
|
return s
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.privmsg(to, text)
|
|
|
|
return Message("PRIVMSG", {to, text})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.notice(to, text)
|
|
|
|
return Message("NOTICE", {to, text})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.action(to, text)
|
|
|
|
return Message("PRIVMSG", {to, ("\x01ACTION %s\x01"):format(text)})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.ctcp(command, to, args)
|
|
|
|
s = "\x01"..command
|
|
|
|
if args then
|
|
|
|
s = ' '..args
|
|
|
|
end
|
|
|
|
s = s..'\x01'
|
|
|
|
return Message("PRIVMSG", {to, s})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.kick(channel, target, reason)
|
|
|
|
return Message("KICK", {channel, target, reason})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.join(channel, key)
|
|
|
|
return Message("JOIN", {channel, key})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.part(channel, reason)
|
|
|
|
return Message("PART", {channel, reason})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.quit(reason)
|
|
|
|
return Message("QUIT", {reason})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.kill(target, reason)
|
|
|
|
return Message("KILL", {target, reason})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.kline(time, mask, reason, operreason)
|
|
|
|
local args = nil
|
|
|
|
if time then
|
|
|
|
args = {time, mask, reason..'|'..operreason}
|
|
|
|
else
|
|
|
|
args = {mask, reason..'|'..operreason}
|
|
|
|
end
|
|
|
|
return Message("KLINE", args)
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.whois(nick, server)
|
|
|
|
local args = nil
|
|
|
|
if server then
|
|
|
|
args = {server, nick}
|
|
|
|
else
|
|
|
|
args = {nick}
|
|
|
|
end
|
|
|
|
return Message("WHOIS", args)
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.topic(channel, text)
|
|
|
|
return Message("TOPIC", {channel, text})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.invite(channel, target)
|
|
|
|
return Message("INVITE", {channel, target})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.nick(nick)
|
|
|
|
return Message("NICK", {nick})
|
|
|
|
end
|
|
|
|
|
|
|
|
function msgs.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 :+ov Nick1 Nick2
|
|
|
|
-- MODE +ov Nick1 Nick2
|
|
|
|
mt = split(modes)
|
|
|
|
return Message("MODE", {target, unpack(mt)})
|
|
|
|
end
|
|
|
|
|