local handlers = {}
local ctcp_handlers = {}
local serverinfo = {}
+local ip = nil
-- }}}
-- defaults {{{
local function main_loop_iter()
if #rsockets == 0 and #wsockets == 0 then return false end
local rready, wready, err = socket.select(rsockets, wsockets)
- if err then irc_debug.err(err); return false; end
+ if err then irc_debug._err(err); return false; end
for _, sock in base.ipairs(rready) do
local cb = socket.protect(rcallbacks[sock])
local ret, err = cb(sock)
if not ret then
- irc_debug.warn("socket error: " .. err)
+ irc_debug._warn("socket error: " .. err)
_unregister_socket(sock, 'r')
end
end
local cb = socket.protect(wcallbacks[sock])
local ret, err = cb(sock)
if not ret then
- irc_debug.warn("socket error: " .. err)
+ irc_debug._warn("socket error: " .. err)
_unregister_socket(sock, 'w')
end
end
-- incoming_message {{{
local function incoming_message(sock)
local raw_msg = socket.try(sock:receive())
- irc_debug.message("RECV", raw_msg)
- local msg = message.parse(raw_msg)
- misc.try_call_warn("Unhandled server message: " .. msg.command,
- handlers["on_" .. msg.command:lower()],
- (misc.parse_user(msg.from)), base.unpack(msg.args))
+ irc_debug._message("RECV", raw_msg)
+ local msg = message._parse(raw_msg)
+ misc._try_call_warn("Unhandled server message: " .. msg.command,
+ handlers["on_" .. msg.command:lower()],
+ (misc.parse_user(msg.from)), base.unpack(msg.args))
return true
end
-- }}}
-- on_nick {{{
function handlers.on_nick(from, new_nick)
for chan in channels() do
- chan:change_nick(from, new_nick)
+ chan:_change_nick(from, new_nick)
end
- misc.try_call(on_nick_change, new_nick, from)
+ misc._try_call(on_nick_change, new_nick, from)
end
-- }}}
base.assert(serverinfo.channels[chan],
"Received join message for unknown channel: " .. chan)
if serverinfo.channels[chan].join_complete then
- serverinfo.channels[chan]:add_user(from)
- misc.try_call(on_join, serverinfo.channels[chan], from)
+ serverinfo.channels[chan]:_add_user(from)
+ misc._try_call(on_join, serverinfo.channels[chan], from)
end
end
-- }}}
-- after we remove the channel from the channel list
if not serverinfo.channels[chan] then return end
if serverinfo.channels[chan].join_complete then
- serverinfo.channels[chan]:remove_user(from)
- misc.try_call(on_part, serverinfo.channels[chan], from, part_msg)
+ serverinfo.channels[chan]:_remove_user(from)
+ misc._try_call(on_part, serverinfo.channels[chan], from, part_msg)
end
end
-- }}}
-- channel modes other than op/voice will be implemented as
-- information request commands
if mode == "o" then -- channel op {{{
- chan:change_status(target, dir == "+", "o")
- misc.try_call(({["+"] = on_op, ["-"] = on_deop})[dir],
- chan, from, target)
+ chan:_change_status(target, dir == "+", "o")
+ misc._try_call(({["+"] = on_op, ["-"] = on_deop})[dir],
+ chan, from, target)
ind = ind + 1
-- }}}
elseif mode == "v" then -- voice {{{
- chan:change_status(target, dir == "+", "v")
- misc.try_call(({["+"] = on_voice, ["-"] = on_devoice})[dir],
- chan, from, target)
+ chan:_change_status(target, dir == "+", "v")
+ misc._try_call(({["+"] = on_voice, ["-"] = on_devoice})[dir],
+ chan, from, target)
ind = ind + 1
-- }}}
end
serverinfo.channels[chan]._topic.user = (misc.parse_user(from))
serverinfo.channels[chan]._topic.time = os.time()
if serverinfo.channels[chan].join_complete then
- misc.try_call(on_topic_change, serverinfo.channels[chan])
+ misc._try_call(on_topic_change, serverinfo.channels[chan])
end
end
-- }}}
-- on_invite {{{
function handlers.on_invite(from, to, chan)
- misc.try_call(on_invite, from, chan)
+ misc._try_call(on_invite, from, chan)
end
-- }}}
base.assert(serverinfo.channels[chan],
"Received kick message for unknown channel: " .. chan)
if serverinfo.channels[chan].join_complete then
- serverinfo.channels[chan]:remove_user(to)
- misc.try_call(on_kick, serverinfo.channels[chan], to, from)
+ serverinfo.channels[chan]:_remove_user(to)
+ misc._try_call(on_kick, serverinfo.channels[chan], to, from)
end
end
-- }}}
-- on_privmsg {{{
function handlers.on_privmsg(from, to, msg)
- local msgs = ctcp.ctcp_split(msg, true)
+ local msgs = ctcp._ctcp_split(msg, true)
for _, v in base.ipairs(msgs) do
if base.type(v) == "string" then
-- normal message {{{
if to:sub(1, 1) == "#" then
base.assert(serverinfo.channels[to],
"Received channel msg from unknown channel: " .. to)
- misc.try_call(on_channel_msg, serverinfo.channels[to], from, v)
+ misc._try_call(on_channel_msg, serverinfo.channels[to], from, v)
else
- misc.try_call(on_private_msg, from, v)
+ misc._try_call(on_private_msg, from, v)
end
-- }}}
elseif base.type(v) == "table" then
-- ctcp message {{{
- local words = misc.split(v[1])
+ local words = misc._split(v[1])
local received_command = words[1]
local cb = "on_" .. received_command:lower()
table.remove(words, 1)
-- on_notice {{{
function handlers.on_notice(from, to, msg)
- local msgs = ctcp.ctcp_split(msg, true)
+ local msgs = ctcp._ctcp_split(msg, true)
for _, v in base.ipairs(msgs) do
if base.type(v) == "string" then
-- normal message {{{
if to:sub(1, 1) == "#" then
base.assert(serverinfo.channels[to],
"Received channel msg from unknown channel: " .. to)
- misc.try_call(on_channel_notice, serverinfo.channels[to],
- from, v)
+ misc._try_call(on_channel_notice, serverinfo.channels[to],
+ from, v)
else
- misc.try_call(on_private_notice, from, v)
+ misc._try_call(on_private_notice, from, v)
end
-- }}}
elseif base.type(v) == "table" then
-- ctcp message {{{
- local words = misc.split(v[1])
+ local words = misc._split(v[1])
local command = words[1]:lower()
table.remove(words, 1)
- misc.try_call_warn("Unknown CTCP message: " .. command,
- ctcp_handlers["on_rpl_"..command], from, to,
- table.concat(words, ' '))
+ misc._try_call_warn("Unknown CTCP message: " .. command,
+ ctcp_handlers["on_rpl_"..command], from, to,
+ table.concat(words, ' '))
-- }}}
end
end
-- on_quit {{{
function handlers.on_quit(from, quit_msg)
for name, chan in base.pairs(serverinfo.channels) do
- chan:remove_user(from)
+ chan:_remove_user(from)
end
- misc.try_call(on_quit, from, quit_msg)
+ misc._try_call(on_quit, from, quit_msg)
end
-- }}}
base.assert(serverinfo.channels[chan],
"Received user information about unknown channel: " .. chan)
serverinfo.channels[chan]._chanmode = constants.chanmodes[chanmode]
- local users = misc.split(userlist)
+ local users = misc._split(userlist)
for k,v in base.ipairs(users) do
if v:sub(1, 1) == "@" or v:sub(1, 1) == "+" then
local nick = v:sub(2)
- serverinfo.channels[chan]:add_user(nick, v:sub(1, 1))
+ serverinfo.channels[chan]:_add_user(nick, v:sub(1, 1))
else
- serverinfo.channels[chan]:add_user(v)
+ serverinfo.channels[chan]:_add_user(v)
end
end
end
base.assert(serverinfo.channels[chan],
"Received user information about unknown channel: " .. chan)
if not serverinfo.channels[chan].join_complete then
- misc.try_call(on_me_join, serverinfo.channels[chan])
+ misc._try_call(on_me_join, serverinfo.channels[chan])
serverinfo.channels[chan].join_complete = true
end
end
if not serverinfo.connected then
serverinfo.connected = true
serverinfo.connecting = false
- misc.try_call(on_connect)
+ misc._try_call(on_connect)
end
end
-- }}}
-- on_rpl_whoisuser {{{
function handlers.on_rpl_whoisuser(from, nick, user, host, star, realname)
- nick = nick:lower()
- requestinfo.whois[nick].user = user
- requestinfo.whois[nick].host = host
- requestinfo.whois[nick].realname = realname
+ local lnick = nick:lower()
+ requestinfo.whois[lnick].nick = nick
+ requestinfo.whois[lnick].user = user
+ requestinfo.whois[lnick].host = host
+ requestinfo.whois[lnick].realname = realname
end
-- }}}
if not requestinfo.whois[nick].channels then
requestinfo.whois[nick].channels = {}
end
- for _, channel in base.ipairs(misc.split(channel_list)) do
+ for _, channel in base.ipairs(misc._split(channel_list)) do
table.insert(requestinfo.whois[nick].channels, channel)
end
end
if to:sub(1, 1) == "#" then
base.assert(serverinfo.channels[to],
"Received channel msg from unknown channel: " .. to)
- misc.try_call(on_channel_act, serverinfo.channels[to], from, message)
+ misc._try_call(on_channel_act, serverinfo.channels[to], from, message)
else
- misc.try_call(on_private_act, from, message)
+ misc._try_call(on_private_act, from, message)
end
end
-- }}}
-- TODO: can we not have this handler be registered unless the dcc module is
-- loaded?
function ctcp_handlers.on_dcc(from, to, message)
- local type, argument, address, port, size = base.unpack(misc.split(message, " ", nil, '"', '"'))
+ local type, argument, address, port, size = base.unpack(misc._split(message, " ", nil, '"', '"'))
if type == "SEND" then
- if misc.try_call(on_dcc, from, to, argument, address, port, size) then
- dcc.accept(argument, address, port, size)
+ if misc._try_call(on_dcc, from, to, argument, address, port, size) then
+ dcc._accept(argument, address, port)
end
elseif type == "CHAT" then
-- TODO: implement this? do people ever use this?
-- on_rpl_version {{{
function ctcp_handlers.on_rpl_version(from, to, version)
- local cb = table.remove(icallbacks.ctcp_version[from], 1)
+ local lfrom = from:lower()
+ local cb = table.remove(icallbacks.ctcp_version[lfrom], 1)
cb({version = version, nick = from})
- if #icallbacks.ctcp_version[from] > 0 then say(from, {"VERSION"})
- else icallbacks.ctcp_version[from] = nil
+ if #icallbacks.ctcp_version[lfrom] > 0 then say(from, {"VERSION"})
+ else icallbacks.ctcp_version[lfrom] = nil
end
end
-- }}}
-- on_rpl_ping {{{
function ctcp_handlers.on_rpl_ping(from, to, timestamp)
- local cb = table.remove(icallbacks.ctcp_ping[from], 1)
+ local lfrom = from:lower()
+ local cb = table.remove(icallbacks.ctcp_ping[lfrom], 1)
cb({time = os.time() - timestamp, nick = from})
- if #icallbacks.ctcp_ping[from] > 0 then say(from, {"PING " .. os.time()})
- else icallbacks.ctcp_ping[from] = nil
+ if #icallbacks.ctcp_ping[lfrom] > 0 then say(from, {"PING " .. os.time()})
+ else icallbacks.ctcp_ping[lfrom] = nil
end
end
-- }}}
-- on_rpl_time {{{
function ctcp_handlers.on_rpl_time(from, to, time)
- local cb = table.remove(icallbacks.ctcp_time[from], 1)
+ local lfrom = from:lower()
+ local cb = table.remove(icallbacks.ctcp_time[lfrom], 1)
cb({time = time, nick = from})
- if #icallbacks.ctcp_time[from] > 0 then say(from, {"TIME"})
- else icallbacks.ctcp_time[from] = nil
+ if #icallbacks.ctcp_time[lfrom] > 0 then say(from, {"TIME"})
+ else icallbacks.ctcp_time[lfrom] = nil
end
end
-- }}}
_register_socket(irc_sock, 'r', incoming_message)
if args.pass then send("PASS", args.pass) end
send("NICK", nick)
- send("USER", username, (irc_sock:getsockname()), network, realname)
+ send("USER", username, get_ip(), network, realname)
begin_main_loop()
end
-- }}}
-- @param nick User to request WHOIS information about
function whois(cb, nick)
nick = nick:lower()
- requestinfo.whois[nick] = {nick = nick}
+ requestinfo.whois[nick] = {}
if not icallbacks.whois[nick] then
icallbacks.whois[nick] = {cb}
send("WHOIS", nick)
if base.type(v) == "string" then
arg = v
elseif base.type(v) == "table" then
- arg = ctcp.ctcp_quote(table.concat(v, " "))
+ arg = ctcp._ctcp_quote(table.concat(v, " "))
end
if i == #{...} then
arg = ":" .. arg
end
message = message .. " " .. arg
end
- message = ctcp.low_quote(message)
+ message = ctcp._low_quote(message)
-- we just truncate for now. -2 to account for the \r\n
message = message:sub(1, constants.IRC_MAX_MSG - 2)
- irc_debug.message("SEND", message)
+ irc_debug._message("SEND", message)
irc_sock:send(message .. "\r\n")
end
-- }}}
-- @return A string representation of the local IP address that the IRC server
-- connection is communicating on
function get_ip()
- return (irc_sock:getsockname())
+ return (ip or irc_sock:getsockname())
+end
+-- }}}
+
+-- set_ip {{{
+---
+-- Set the local IP manually (to allow for NAT workarounds)
+-- @param new_ip IP address to set
+function set_ip(new_ip)
+ ip = new_ip
end
-- }}}
-- @see irc.channel
function channels()
return function(state, arg)
- return misc.value_iter(state, arg,
- function(v)
- return v.join_complete
- end)
+ return misc._value_iter(state, arg,
+ function(v)
+ return v.join_complete
+ end)
end,
serverinfo.channels,
nil