Port to Lua 5.3
This commit is contained in:
parent
09628cded4
commit
783fefdcb3
@ -1,5 +1,5 @@
|
|||||||
# Path to your Lua library directory (LUA_PATH)
|
# Path to your Lua library directory (LUA_PATH)
|
||||||
LUA_DIR = /usr/local/share/lua/5.1
|
LUA_DIR = /usr/local/share/lua/5.3
|
||||||
|
|
||||||
# Set this to the path of your luadoc executable if you want to regenerate the
|
# Set this to the path of your luadoc executable if you want to regenerate the
|
||||||
# documentation and the luadoc script isn't in your PATH
|
# documentation and the luadoc script isn't in your PATH
|
||||||
|
9
README
9
README
@ -1,5 +1,6 @@
|
|||||||
LuaIRC v0.3
|
LuaIRC v0.3 (Lua 5.3 Port)
|
||||||
Jesse Luehrs (jluehrs2@uiuc.edu)
|
Jesse Luehrs (jluehrs2@uiuc.edu)
|
||||||
|
Elias Fleckenstein (fleckenstein@elidragon.com)
|
||||||
|
|
||||||
OVERVIEW
|
OVERVIEW
|
||||||
========
|
========
|
||||||
@ -7,16 +8,18 @@ LuaIRC is a fully featured IRC framework written entirely in Lua. It provides an
|
|||||||
|
|
||||||
INSTALL
|
INSTALL
|
||||||
=======
|
=======
|
||||||
This module requires LuaSocket (http://www.cs.princeton.edu/~diego/professional/luasocket/) and Lua 5.1. To install, modify the Make.config file with paths appropriate to your system and run 'make install'.
|
This module requires LuaSocket (http://www.cs.princeton.edu/~diego/professional/luasocket/) and Lua 5.3. To install, modify the Make.config file with paths appropriate to your system and run 'make install'.
|
||||||
|
|
||||||
DOCUMENTATION
|
DOCUMENTATION
|
||||||
=============
|
=============
|
||||||
Documentation of the API can be found in the doc/ directory. It was autogenerated from the source files by LuaDoc (http://luadoc.luaforge.net/).
|
Documentation of the API can be found in the doc/ directory. It was autogenerated from the source files by LuaDoc (http://luadoc.luaforge.net/).
|
||||||
|
|
||||||
LuaIRC has only been tested on Freenode so far, but I plan to expand this to other servers in the future. It's quite possible that it works on other servers anyway, however, so feel free to try it out, and send in bug reports for things that break.
|
LuaIRC has only been tested on Freenode and Libera.chat so far, but I plan to expand this to other servers in the future. It's quite possible that it works on other servers anyway, however, so feel free to try it out, and send in bug reports for things that break.
|
||||||
|
|
||||||
CHANGES
|
CHANGES
|
||||||
=======
|
=======
|
||||||
|
0.3 (Lua 5.3 Port)
|
||||||
|
- Unofficial port to work with Lua 5.3
|
||||||
0.3
|
0.3
|
||||||
- Major cleanup and restructuring again, documentation added, first public release
|
- Major cleanup and restructuring again, documentation added, first public release
|
||||||
0.2
|
0.2
|
||||||
|
239
src/irc.lua
239
src/irc.lua
@ -1,31 +1,46 @@
|
|||||||
---
|
---
|
||||||
-- Implementation of the main LuaIRC module
|
-- Implementation of the main LuaIRC module
|
||||||
|
|
||||||
-- initialization {{{
|
|
||||||
local base = _G
|
|
||||||
local constants = require 'irc.constants'
|
|
||||||
local ctcp = require 'irc.ctcp'
|
|
||||||
local c = ctcp._ctcp_quote
|
|
||||||
local irc_debug = require 'irc.debug'
|
|
||||||
local message = require 'irc.message'
|
|
||||||
local misc = require 'irc.misc'
|
|
||||||
local socket = require 'socket'
|
|
||||||
local os = require 'os'
|
|
||||||
local string = require 'string'
|
|
||||||
local table = require 'table'
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- LuaIRC - IRC framework written in Lua
|
-- LuaIRC - IRC framework written in Lua
|
||||||
-- @release 0.3
|
-- @release 0.3
|
||||||
module 'irc'
|
local irc = {}
|
||||||
|
|
||||||
-- constants {{{
|
-- constants {{{
|
||||||
_VERSION = 'LuaIRC 0.3'
|
irc._VERSION = 'LuaIRC 0.3 (Lua 5.3 Port)'
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- libraries {{{
|
||||||
|
local libs = {}
|
||||||
|
|
||||||
|
libs.irc = irc
|
||||||
|
libs.socket = require 'socket'
|
||||||
|
|
||||||
|
local old_libs = _G.libs
|
||||||
|
_G.libs = libs
|
||||||
|
|
||||||
|
libs.constants = require 'irc.constants'
|
||||||
|
libs.ctcp = require 'irc.ctcp'
|
||||||
|
libs.debug = require 'irc.debug'
|
||||||
|
libs.misc = require 'irc.misc'
|
||||||
|
libs.channel = require 'irc.channel'
|
||||||
|
libs.dcc = require 'irc.dcc'
|
||||||
|
libs.message = require 'irc.message'
|
||||||
|
|
||||||
|
_G.libs = old_libs
|
||||||
|
|
||||||
|
-- localize modules {{{
|
||||||
|
local constants = libs.constants
|
||||||
|
local ctcp = libs.ctcp
|
||||||
|
local c = ctcp._ctcp_quote
|
||||||
|
local irc_debug = libs.debug
|
||||||
|
local message = libs.message
|
||||||
|
local misc = libs.misc
|
||||||
|
local socket = libs.socket
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- classes {{{
|
-- classes {{{
|
||||||
local Channel = base.require 'irc.channel'
|
local Channel = libs.channel
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- local variables {{{
|
-- local variables {{{
|
||||||
@ -51,14 +66,14 @@ local ip = nil
|
|||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- defaults {{{
|
-- defaults {{{
|
||||||
TIMEOUT = 60 -- connection timeout
|
irc.TIMEOUT = 60 -- connection timeout
|
||||||
NETWORK = "localhost" -- default network
|
irc.NETWORK = "localhost" -- default network
|
||||||
PORT = 6667 -- default port
|
irc.PORT = 6667 -- default port
|
||||||
NICK = "luabot" -- default nick
|
irc.NICK = "luabot" -- default nick
|
||||||
USERNAME = "LuaIRC" -- default username
|
irc.USERNAME = "LuaIRC" -- default username
|
||||||
REALNAME = "LuaIRC" -- default realname
|
irc.REALNAME = "LuaIRC" -- default realname
|
||||||
DEBUG = false -- whether we want extra debug information
|
irc.DEBUG = false -- whether we want extra debug information
|
||||||
OUTFILE = nil -- file to send debug output to - nil is stdout
|
irc.OUTFILE = nil -- file to send debug output to - nil is stdout
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- private functions {{{
|
-- private functions {{{
|
||||||
@ -68,21 +83,21 @@ local function main_loop_iter()
|
|||||||
local rready, wready, err = socket.select(rsockets, wsockets)
|
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
|
for _, sock in ipairs(rready) do
|
||||||
local cb = socket.protect(rcallbacks[sock])
|
local cb = socket.protect(rcallbacks[sock])
|
||||||
local ret, err = cb(sock)
|
local ret, err = cb(sock)
|
||||||
if not ret then
|
if not ret then
|
||||||
irc_debug._warn("socket error: " .. err)
|
irc_debug._warn("socket error: " .. err)
|
||||||
_unregister_socket(sock, 'r')
|
irc._unregister_socket(sock, 'r')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, sock in base.ipairs(wready) do
|
for _, sock in ipairs(wready) do
|
||||||
local cb = socket.protect(wcallbacks[sock])
|
local cb = socket.protect(wcallbacks[sock])
|
||||||
local ret, err = cb(sock)
|
local ret, err = cb(sock)
|
||||||
if not ret then
|
if not ret then
|
||||||
irc_debug._warn("socket error: " .. err)
|
irc_debug._warn("socket error: " .. err)
|
||||||
_unregister_socket(sock, 'w')
|
irc._unregister_socket(sock, 'w')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -103,7 +118,7 @@ local function incoming_message(sock)
|
|||||||
local msg = message._parse(raw_msg)
|
local msg = message._parse(raw_msg)
|
||||||
misc._try_call_warn("Unhandled server message: " .. msg.command,
|
misc._try_call_warn("Unhandled server message: " .. msg.command,
|
||||||
handlers["on_" .. msg.command:lower()],
|
handlers["on_" .. msg.command:lower()],
|
||||||
(misc._parse_user(msg.from)), base.unpack(msg.args))
|
(misc._parse_user(msg.from)), table.unpack(msg.args))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -119,7 +134,7 @@ end
|
|||||||
-- command handlers {{{
|
-- command handlers {{{
|
||||||
-- on_nick {{{
|
-- on_nick {{{
|
||||||
function handlers.on_nick(from, new_nick)
|
function handlers.on_nick(from, new_nick)
|
||||||
for chan in channels() do
|
for chan in irc.channels() do
|
||||||
chan:_change_nick(from, new_nick)
|
chan:_change_nick(from, new_nick)
|
||||||
end
|
end
|
||||||
callback("nick_change", new_nick, from)
|
callback("nick_change", new_nick, from)
|
||||||
@ -128,7 +143,7 @@ end
|
|||||||
|
|
||||||
-- on_join {{{
|
-- on_join {{{
|
||||||
function handlers.on_join(from, chan)
|
function handlers.on_join(from, chan)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received join message for unknown channel: " .. chan)
|
"Received join message for unknown channel: " .. chan)
|
||||||
if serverinfo.channels[chan].join_complete then
|
if serverinfo.channels[chan].join_complete then
|
||||||
serverinfo.channels[chan]:_add_user(from)
|
serverinfo.channels[chan]:_add_user(from)
|
||||||
@ -157,7 +172,7 @@ function handlers.on_mode(from, to, mode_string, ...)
|
|||||||
|
|
||||||
if to:sub(1, 1) == "#" then
|
if to:sub(1, 1) == "#" then
|
||||||
-- handle channel mode requests {{{
|
-- handle channel mode requests {{{
|
||||||
base.assert(serverinfo.channels[to],
|
assert(serverinfo.channels[to],
|
||||||
"Received mode change for unknown channel: " .. to)
|
"Received mode change for unknown channel: " .. to)
|
||||||
local chan = serverinfo.channels[to]
|
local chan = serverinfo.channels[to]
|
||||||
local ind = 1
|
local ind = 1
|
||||||
@ -204,7 +219,7 @@ end
|
|||||||
|
|
||||||
-- on_topic {{{
|
-- on_topic {{{
|
||||||
function handlers.on_topic(from, chan, new_topic)
|
function handlers.on_topic(from, chan, new_topic)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received topic message for unknown channel: " .. chan)
|
"Received topic message for unknown channel: " .. chan)
|
||||||
serverinfo.channels[chan]._topic.text = new_topic
|
serverinfo.channels[chan]._topic.text = new_topic
|
||||||
serverinfo.channels[chan]._topic.user = from
|
serverinfo.channels[chan]._topic.user = from
|
||||||
@ -223,7 +238,7 @@ end
|
|||||||
|
|
||||||
-- on_kick {{{
|
-- on_kick {{{
|
||||||
function handlers.on_kick(from, chan, to)
|
function handlers.on_kick(from, chan, to)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received kick message for unknown channel: " .. chan)
|
"Received kick message for unknown channel: " .. chan)
|
||||||
if serverinfo.channels[chan].join_complete then
|
if serverinfo.channels[chan].join_complete then
|
||||||
serverinfo.channels[chan]:_remove_user(to)
|
serverinfo.channels[chan]:_remove_user(to)
|
||||||
@ -235,7 +250,7 @@ end
|
|||||||
-- on_privmsg {{{
|
-- on_privmsg {{{
|
||||||
function handlers.on_privmsg(from, to, msg)
|
function handlers.on_privmsg(from, to, msg)
|
||||||
local msgs = ctcp._ctcp_split(msg)
|
local msgs = ctcp._ctcp_split(msg)
|
||||||
for _, v in base.ipairs(msgs) do
|
for _, v in ipairs(msgs) do
|
||||||
local msg = v.str
|
local msg = v.str
|
||||||
if v.ctcp then
|
if v.ctcp then
|
||||||
-- ctcp message {{{
|
-- ctcp message {{{
|
||||||
@ -245,16 +260,16 @@ function handlers.on_privmsg(from, to, msg)
|
|||||||
table.remove(words, 1)
|
table.remove(words, 1)
|
||||||
-- not using try_call here because the ctcp specification requires
|
-- not using try_call here because the ctcp specification requires
|
||||||
-- an error response to nonexistant commands
|
-- an error response to nonexistant commands
|
||||||
if base.type(ctcp_handlers[cb]) == "function" then
|
if type(ctcp_handlers[cb]) == "function" then
|
||||||
ctcp_handlers[cb](from, to, table.concat(words, " "))
|
ctcp_handlers[cb](from, to, table.concat(words, " "))
|
||||||
else
|
else
|
||||||
notice(from, c("ERRMSG", received_command, ":Unknown query"))
|
irc.notice(from, c("ERRMSG", received_command, ":Unknown query"))
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
else
|
else
|
||||||
-- normal message {{{
|
-- normal message {{{
|
||||||
if to:sub(1, 1) == "#" then
|
if to:sub(1, 1) == "#" then
|
||||||
base.assert(serverinfo.channels[to],
|
assert(serverinfo.channels[to],
|
||||||
"Received channel msg from unknown channel: " .. to)
|
"Received channel msg from unknown channel: " .. to)
|
||||||
callback("channel_msg", serverinfo.channels[to], from, msg)
|
callback("channel_msg", serverinfo.channels[to], from, msg)
|
||||||
else
|
else
|
||||||
@ -269,7 +284,7 @@ end
|
|||||||
-- on_notice {{{
|
-- on_notice {{{
|
||||||
function handlers.on_notice(from, to, msg)
|
function handlers.on_notice(from, to, msg)
|
||||||
local msgs = ctcp._ctcp_split(msg)
|
local msgs = ctcp._ctcp_split(msg)
|
||||||
for _, v in base.ipairs(msgs) do
|
for _, v in ipairs(msgs) do
|
||||||
local msg = v.str
|
local msg = v.str
|
||||||
if v.ctcp then
|
if v.ctcp then
|
||||||
-- ctcp message {{{
|
-- ctcp message {{{
|
||||||
@ -283,7 +298,7 @@ function handlers.on_notice(from, to, msg)
|
|||||||
else
|
else
|
||||||
-- normal message {{{
|
-- normal message {{{
|
||||||
if to:sub(1, 1) == "#" then
|
if to:sub(1, 1) == "#" then
|
||||||
base.assert(serverinfo.channels[to],
|
assert(serverinfo.channels[to],
|
||||||
"Received channel msg from unknown channel: " .. to)
|
"Received channel msg from unknown channel: " .. to)
|
||||||
callback("channel_notice", serverinfo.channels[to], from, msg)
|
callback("channel_notice", serverinfo.channels[to], from, msg)
|
||||||
else
|
else
|
||||||
@ -297,7 +312,7 @@ end
|
|||||||
|
|
||||||
-- on_quit {{{
|
-- on_quit {{{
|
||||||
function handlers.on_quit(from, quit_msg)
|
function handlers.on_quit(from, quit_msg)
|
||||||
for name, chan in base.pairs(serverinfo.channels) do
|
for name, chan in pairs(serverinfo.channels) do
|
||||||
chan:_remove_user(from)
|
chan:_remove_user(from)
|
||||||
end
|
end
|
||||||
callback("quit", from, quit_msg)
|
callback("quit", from, quit_msg)
|
||||||
@ -307,7 +322,7 @@ end
|
|||||||
-- on_ping {{{
|
-- on_ping {{{
|
||||||
-- respond to server pings to make sure it knows we are alive
|
-- respond to server pings to make sure it knows we are alive
|
||||||
function handlers.on_ping(from, respond_to)
|
function handlers.on_ping(from, respond_to)
|
||||||
send("PONG", respond_to)
|
irc.send("PONG", respond_to)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -316,7 +331,7 @@ end
|
|||||||
-- on_rpl_topic {{{
|
-- on_rpl_topic {{{
|
||||||
-- catch topic changes
|
-- catch topic changes
|
||||||
function handlers.on_rpl_topic(from, chan, topic)
|
function handlers.on_rpl_topic(from, chan, topic)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received topic information about unknown channel: " .. chan)
|
"Received topic information about unknown channel: " .. chan)
|
||||||
serverinfo.channels[chan]._topic.text = topic
|
serverinfo.channels[chan]._topic.text = topic
|
||||||
end
|
end
|
||||||
@ -324,7 +339,7 @@ end
|
|||||||
|
|
||||||
-- on_rpl_notopic {{{
|
-- on_rpl_notopic {{{
|
||||||
function handlers.on_rpl_notopic(from, chan)
|
function handlers.on_rpl_notopic(from, chan)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received topic information about unknown channel: " .. chan)
|
"Received topic information about unknown channel: " .. chan)
|
||||||
serverinfo.channels[chan]._topic.text = ""
|
serverinfo.channels[chan]._topic.text = ""
|
||||||
end
|
end
|
||||||
@ -333,21 +348,21 @@ end
|
|||||||
-- on_rpl_topicdate {{{
|
-- on_rpl_topicdate {{{
|
||||||
-- "topic was set by <user> at <time>"
|
-- "topic was set by <user> at <time>"
|
||||||
function handlers.on_rpl_topicdate(from, chan, user, time)
|
function handlers.on_rpl_topicdate(from, chan, user, time)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received topic information about unknown channel: " .. chan)
|
"Received topic information about unknown channel: " .. chan)
|
||||||
serverinfo.channels[chan]._topic.user = user
|
serverinfo.channels[chan]._topic.user = user
|
||||||
serverinfo.channels[chan]._topic.time = base.tonumber(time)
|
serverinfo.channels[chan]._topic.time = tonumber(time)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- on_rpl_namreply {{{
|
-- on_rpl_namreply {{{
|
||||||
-- handles a NAMES reply
|
-- handles a NAMES reply
|
||||||
function handlers.on_rpl_namreply(from, chanmode, chan, userlist)
|
function handlers.on_rpl_namreply(from, chanmode, chan, userlist)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received user information about unknown channel: " .. chan)
|
"Received user information about unknown channel: " .. chan)
|
||||||
serverinfo.channels[chan]._chanmode = constants.chanmodes[chanmode]
|
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
|
for k,v in ipairs(users) do
|
||||||
if v:sub(1, 1) == "@" or v:sub(1, 1) == "+" then
|
if v:sub(1, 1) == "@" or v:sub(1, 1) == "+" then
|
||||||
local nick = v:sub(2)
|
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))
|
||||||
@ -362,7 +377,7 @@ end
|
|||||||
-- when we get this message, the channel join has completed, so call the
|
-- when we get this message, the channel join has completed, so call the
|
||||||
-- external cb
|
-- external cb
|
||||||
function handlers.on_rpl_endofnames(from, chan)
|
function handlers.on_rpl_endofnames(from, chan)
|
||||||
base.assert(serverinfo.channels[chan],
|
assert(serverinfo.channels[chan],
|
||||||
"Received user information about unknown channel: " .. chan)
|
"Received user information about unknown channel: " .. chan)
|
||||||
if not serverinfo.channels[chan].join_complete then
|
if not serverinfo.channels[chan].join_complete then
|
||||||
callback("me_join", serverinfo.channels[chan])
|
callback("me_join", serverinfo.channels[chan])
|
||||||
@ -425,7 +440,7 @@ function handlers.on_rpl_whoischannels(from, nick, channel_list)
|
|||||||
if not requestinfo.whois[nick].channels then
|
if not requestinfo.whois[nick].channels then
|
||||||
requestinfo.whois[nick].channels = {}
|
requestinfo.whois[nick].channels = {}
|
||||||
end
|
end
|
||||||
for _, channel in base.ipairs(misc._split(channel_list)) do
|
for _, channel in ipairs(misc._split(channel_list)) do
|
||||||
table.insert(requestinfo.whois[nick].channels, channel)
|
table.insert(requestinfo.whois[nick].channels, channel)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -466,7 +481,7 @@ function handlers.on_rpl_endofwhois(from, nick)
|
|||||||
local cb = table.remove(icallbacks.whois[nick], 1)
|
local cb = table.remove(icallbacks.whois[nick], 1)
|
||||||
cb(requestinfo.whois[nick])
|
cb(requestinfo.whois[nick])
|
||||||
requestinfo.whois[nick] = nil
|
requestinfo.whois[nick] = nil
|
||||||
if #icallbacks.whois[nick] > 0 then send("WHOIS", nick)
|
if #icallbacks.whois[nick] > 0 then irc.send("WHOIS", nick)
|
||||||
else icallbacks.whois[nick] = nil
|
else icallbacks.whois[nick] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -476,7 +491,7 @@ end
|
|||||||
function handlers.on_rpl_version(from, version, server, comments)
|
function handlers.on_rpl_version(from, version, server, comments)
|
||||||
local cb = table.remove(icallbacks.serverversion[server], 1)
|
local cb = table.remove(icallbacks.serverversion[server], 1)
|
||||||
cb({version = version, server = server, comments = comments})
|
cb({version = version, server = server, comments = comments})
|
||||||
if #icallbacks.serverversion[server] > 0 then send("VERSION", server)
|
if #icallbacks.serverversion[server] > 0 then irc.send("VERSION", server)
|
||||||
else icallbacks.serverversion[server] = nil
|
else icallbacks.serverversion[server] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -486,7 +501,7 @@ end
|
|||||||
function on_rpl_time(from, server, time)
|
function on_rpl_time(from, server, time)
|
||||||
local cb = table.remove(icallbacks.servertime[server], 1)
|
local cb = table.remove(icallbacks.servertime[server], 1)
|
||||||
cb({time = time, server = server})
|
cb({time = time, server = server})
|
||||||
if #icallbacks.servertime[server] > 0 then send("TIME", server)
|
if #icallbacks.servertime[server] > 0 then irc.send("TIME", server)
|
||||||
else icallbacks.servertime[server] = nil
|
else icallbacks.servertime[server] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -498,7 +513,7 @@ end
|
|||||||
-- on_action {{{
|
-- on_action {{{
|
||||||
function ctcp_handlers.on_action(from, to, message)
|
function ctcp_handlers.on_action(from, to, message)
|
||||||
if to:sub(1, 1) == "#" then
|
if to:sub(1, 1) == "#" then
|
||||||
base.assert(serverinfo.channels[to],
|
assert(serverinfo.channels[to],
|
||||||
"Received channel msg from unknown channel: " .. to)
|
"Received channel msg from unknown channel: " .. to)
|
||||||
callback("channel_act", serverinfo.channels[to], from, message)
|
callback("channel_act", serverinfo.channels[to], from, message)
|
||||||
else
|
else
|
||||||
@ -511,7 +526,7 @@ end
|
|||||||
-- TODO: can we not have this handler be registered unless the dcc module is
|
-- TODO: can we not have this handler be registered unless the dcc module is
|
||||||
-- loaded?
|
-- loaded?
|
||||||
function ctcp_handlers.on_dcc(from, to, message)
|
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 = table.unpack(misc._split(message, " ", nil, '"', '"'))
|
||||||
address = misc._ip_int_to_str(address)
|
address = misc._ip_int_to_str(address)
|
||||||
if type == "SEND" then
|
if type == "SEND" then
|
||||||
if callback("dcc_send", from, to, argument, address, port, size) then
|
if callback("dcc_send", from, to, argument, address, port, size) then
|
||||||
@ -525,25 +540,25 @@ end
|
|||||||
|
|
||||||
-- on_version {{{
|
-- on_version {{{
|
||||||
function ctcp_handlers.on_version(from, to)
|
function ctcp_handlers.on_version(from, to)
|
||||||
notice(from, c("VERSION", _VERSION .. " running under " .. base._VERSION .. " with " .. socket._VERSION))
|
irc.notice(from, c("VERSION", irc._VERSION .. " running under " .. _VERSION .. " with " .. socket._VERSION))
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- on_errmsg {{{
|
-- on_errmsg {{{
|
||||||
function ctcp_handlers.on_errmsg(from, to, message)
|
function ctcp_handlers.on_errmsg(from, to, message)
|
||||||
notice(from, c("ERRMSG", message, ":No error has occurred"))
|
irc.notice(from, c("ERRMSG", message, ":No error has occurred"))
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- on_ping {{{
|
-- on_ping {{{
|
||||||
function ctcp_handlers.on_ping(from, to, timestamp)
|
function ctcp_handlers.on_ping(from, to, timestamp)
|
||||||
notice(from, c("PING", timestamp))
|
irc.notice(from, c("PING", timestamp))
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- on_time {{{
|
-- on_time {{{
|
||||||
function ctcp_handlers.on_time(from, to)
|
function ctcp_handlers.on_time(from, to)
|
||||||
notice(from, c("TIME", os.date()))
|
irc.notice(from, c("TIME", os.date()))
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -559,7 +574,7 @@ function ctcp_handlers.on_rpl_version(from, to, version)
|
|||||||
local lfrom = from:lower()
|
local lfrom = from:lower()
|
||||||
local cb = table.remove(icallbacks.ctcp_version[lfrom], 1)
|
local cb = table.remove(icallbacks.ctcp_version[lfrom], 1)
|
||||||
cb({version = version, nick = from})
|
cb({version = version, nick = from})
|
||||||
if #icallbacks.ctcp_version[lfrom] > 0 then say(from, c("VERSION"))
|
if #icallbacks.ctcp_version[lfrom] > 0 then irc.say(from, c("VERSION"))
|
||||||
else icallbacks.ctcp_version[lfrom] = nil
|
else icallbacks.ctcp_version[lfrom] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -576,7 +591,7 @@ function ctcp_handlers.on_rpl_ping(from, to, timestamp)
|
|||||||
local lfrom = from:lower()
|
local lfrom = from:lower()
|
||||||
local cb = table.remove(icallbacks.ctcp_ping[lfrom], 1)
|
local cb = table.remove(icallbacks.ctcp_ping[lfrom], 1)
|
||||||
cb({time = os.time() - timestamp, nick = from})
|
cb({time = os.time() - timestamp, nick = from})
|
||||||
if #icallbacks.ctcp_ping[lfrom] > 0 then say(from, c("PING", os.time()))
|
if #icallbacks.ctcp_ping[lfrom] > 0 then irc.say(from, c("PING", os.time()))
|
||||||
else icallbacks.ctcp_ping[lfrom] = nil
|
else icallbacks.ctcp_ping[lfrom] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -587,7 +602,7 @@ function ctcp_handlers.on_rpl_time(from, to, time)
|
|||||||
local lfrom = from:lower()
|
local lfrom = from:lower()
|
||||||
local cb = table.remove(icallbacks.ctcp_time[lfrom], 1)
|
local cb = table.remove(icallbacks.ctcp_time[lfrom], 1)
|
||||||
cb({time = time, nick = from})
|
cb({time = time, nick = from})
|
||||||
if #icallbacks.ctcp_time[lfrom] > 0 then say(from, c("TIME"))
|
if #icallbacks.ctcp_time[lfrom] > 0 then irc.say(from, c("TIME"))
|
||||||
else icallbacks.ctcp_time[lfrom] = nil
|
else icallbacks.ctcp_time[lfrom] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -605,7 +620,7 @@ end
|
|||||||
-- @param mode 'r' if the socket is for reading, 'w' if for writing
|
-- @param mode 'r' if the socket is for reading, 'w' if for writing
|
||||||
-- @param cb Callback to call when the socket is ready for reading/writing.
|
-- @param cb Callback to call when the socket is ready for reading/writing.
|
||||||
-- It will be called with the socket as the single argument.
|
-- It will be called with the socket as the single argument.
|
||||||
function _register_socket(sock, mode, cb)
|
function irc._register_socket(sock, mode, cb)
|
||||||
local socks, cbs
|
local socks, cbs
|
||||||
if mode == 'r' then
|
if mode == 'r' then
|
||||||
socks = rsockets
|
socks = rsockets
|
||||||
@ -614,7 +629,7 @@ function _register_socket(sock, mode, cb)
|
|||||||
socks = wsockets
|
socks = wsockets
|
||||||
cbs = wcallbacks
|
cbs = wcallbacks
|
||||||
end
|
end
|
||||||
base.assert(not cbs[sock], "socket already registered")
|
assert(not cbs[sock], "socket already registered")
|
||||||
table.insert(socks, sock)
|
table.insert(socks, sock)
|
||||||
cbs[sock] = cb
|
cbs[sock] = cb
|
||||||
end
|
end
|
||||||
@ -625,7 +640,7 @@ end
|
|||||||
-- Remove a previously registered socket.
|
-- Remove a previously registered socket.
|
||||||
-- @param sock Socket to unregister
|
-- @param sock Socket to unregister
|
||||||
-- @param mode 'r' to unregister it for reading, 'w' for writing
|
-- @param mode 'r' to unregister it for reading, 'w' for writing
|
||||||
function _unregister_socket(sock, mode)
|
function irc._unregister_socket(sock, mode)
|
||||||
local socks, cbs
|
local socks, cbs
|
||||||
if mode == 'r' then
|
if mode == 'r' then
|
||||||
socks = rsockets
|
socks = rsockets
|
||||||
@ -634,7 +649,7 @@ function _unregister_socket(sock, mode)
|
|||||||
socks = wsockets
|
socks = wsockets
|
||||||
cbs = wcallbacks
|
cbs = wcallbacks
|
||||||
end
|
end
|
||||||
for i, v in base.ipairs(socks) do
|
for i, v in ipairs(socks) do
|
||||||
if v == sock then table.remove(socks, i); break; end
|
if v == sock then table.remove(socks, i); break; end
|
||||||
end
|
end
|
||||||
cbs[sock] = nil
|
cbs[sock] = nil
|
||||||
@ -670,22 +685,22 @@ end
|
|||||||
-- dropping an idle connection
|
-- dropping an idle connection
|
||||||
-- (default: '60')</li>
|
-- (default: '60')</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
function connect(args)
|
function irc.connect(args)
|
||||||
local network = args.network or NETWORK
|
local network = args.network or irc.NETWORK
|
||||||
local port = args.port or PORT
|
local port = args.port or irc.PORT
|
||||||
local nick = args.nick or NICK
|
local nick = args.nick or irc.NICK
|
||||||
local username = args.username or USERNAME
|
local username = args.username or irc.USERNAME
|
||||||
local realname = args.realname or REALNAME
|
local realname = args.realname or irc.REALNAME
|
||||||
local timeout = args.timeout or TIMEOUT
|
local timeout = args.timeout or irc.TIMEOUT
|
||||||
serverinfo.connecting = true
|
serverinfo.connecting = true
|
||||||
if OUTFILE then irc_debug.set_output(OUTFILE) end
|
if irc.OUTFILE then irc_debug.set_output(irc.OUTFILE) end
|
||||||
if DEBUG then irc_debug.enable() end
|
if irc.DEBUG then irc_debug.enable() end
|
||||||
irc_sock = base.assert(socket.connect(network, port))
|
irc_sock = assert(socket.connect(network, port))
|
||||||
irc_sock:settimeout(timeout)
|
irc_sock:settimeout(timeout)
|
||||||
_register_socket(irc_sock, 'r', incoming_message)
|
irc._register_socket(irc_sock, 'r', incoming_message)
|
||||||
if args.pass then send("PASS", args.pass) end
|
if args.pass then irc.send("PASS", args.pass) end
|
||||||
send("NICK", nick)
|
irc.send("NICK", nick)
|
||||||
send("USER", username, get_ip(), network, realname)
|
irc.send("USER", username, irc.get_ip(), network, realname)
|
||||||
begin_main_loop()
|
begin_main_loop()
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -694,9 +709,9 @@ end
|
|||||||
---
|
---
|
||||||
-- Close the connection to the irc server.
|
-- Close the connection to the irc server.
|
||||||
-- @param message Quit message (optional, defaults to 'Leaving')
|
-- @param message Quit message (optional, defaults to 'Leaving')
|
||||||
function quit(message)
|
function irc.quit(message)
|
||||||
message = message or "Leaving"
|
message = message or "Leaving"
|
||||||
send("QUIT", message)
|
irc.send("QUIT", message)
|
||||||
serverinfo.connected = false
|
serverinfo.connected = false
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -705,10 +720,10 @@ end
|
|||||||
---
|
---
|
||||||
-- Join a channel.
|
-- Join a channel.
|
||||||
-- @param channel Channel to join
|
-- @param channel Channel to join
|
||||||
function join(channel)
|
function irc.join(channel)
|
||||||
if not channel then return end
|
if not channel then return end
|
||||||
serverinfo.channels[channel] = Channel.new(channel)
|
serverinfo.channels[channel] = Channel.new(channel)
|
||||||
send("JOIN", channel)
|
irc.send("JOIN", channel)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
@ -716,10 +731,10 @@ end
|
|||||||
---
|
---
|
||||||
-- Leave a channel.
|
-- Leave a channel.
|
||||||
-- @param channel Channel to leave
|
-- @param channel Channel to leave
|
||||||
function part(channel)
|
function irc.part(channel)
|
||||||
if not channel then return end
|
if not channel then return end
|
||||||
serverinfo.channels[channel] = nil
|
serverinfo.channels[channel] = nil
|
||||||
send("PART", channel)
|
irc.send("PART", channel)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
@ -728,10 +743,10 @@ end
|
|||||||
-- Send a message to a user or channel.
|
-- Send a message to a user or channel.
|
||||||
-- @param name User or channel to send the message to
|
-- @param name User or channel to send the message to
|
||||||
-- @param message Message to send
|
-- @param message Message to send
|
||||||
function say(name, message)
|
function irc.say(name, message)
|
||||||
if not name then return end
|
if not name then return end
|
||||||
message = message or ""
|
message = message or ""
|
||||||
send("PRIVMSG", name, message)
|
irc.send("PRIVMSG", name, message)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
@ -740,10 +755,10 @@ end
|
|||||||
-- Send a notice to a user or channel.
|
-- Send a notice to a user or channel.
|
||||||
-- @param name User or channel to send the notice to
|
-- @param name User or channel to send the notice to
|
||||||
-- @param message Message to send
|
-- @param message Message to send
|
||||||
function notice(name, message)
|
function irc.notice(name, message)
|
||||||
if not name then return end
|
if not name then return end
|
||||||
message = message or ""
|
message = message or ""
|
||||||
send("NOTICE", name, message)
|
irc.send("NOTICE", name, message)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
@ -752,10 +767,10 @@ end
|
|||||||
-- Perform a /me action.
|
-- Perform a /me action.
|
||||||
-- @param name User or channel to send the action to
|
-- @param name User or channel to send the action to
|
||||||
-- @param action Action to send
|
-- @param action Action to send
|
||||||
function act(name, action)
|
function irc.act(name, action)
|
||||||
if not name then return end
|
if not name then return end
|
||||||
action = action or ""
|
action = action or ""
|
||||||
send("PRIVMSG", name, c("ACTION", action))
|
irc.send("PRIVMSG", name, c("ACTION", action))
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -771,13 +786,13 @@ end
|
|||||||
-- <li><i>version:</i> the server version</li>
|
-- <li><i>version:</i> the server version</li>
|
||||||
-- <li><i>comments:</i> other data provided by the server</li>
|
-- <li><i>comments:</i> other data provided by the server</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
function server_version(cb)
|
function irc.server_version(cb)
|
||||||
-- apparently the optional server parameter isn't supported for servers
|
-- apparently the optional server parameter isn't supported for servers
|
||||||
-- which you are not directly connected to (freenode specific?)
|
-- which you are not directly connected to (freenode specific?)
|
||||||
local server = serverinfo.host
|
local server = serverinfo.host
|
||||||
if not icallbacks.serverversion[server] then
|
if not icallbacks.serverversion[server] then
|
||||||
icallbacks.serverversion[server] = {cb}
|
icallbacks.serverversion[server] = {cb}
|
||||||
send("VERSION", server)
|
irc.send("VERSION", server)
|
||||||
else
|
else
|
||||||
table.insert(icallbacks.serverversion[server], cb)
|
table.insert(icallbacks.serverversion[server], cb)
|
||||||
end
|
end
|
||||||
@ -808,12 +823,12 @@ end
|
|||||||
-- joined</li>
|
-- joined</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
-- @param nick User to request WHOIS information about
|
-- @param nick User to request WHOIS information about
|
||||||
function whois(cb, nick)
|
function irc.whois(cb, nick)
|
||||||
nick = nick:lower()
|
nick = nick:lower()
|
||||||
requestinfo.whois[nick] = {}
|
requestinfo.whois[nick] = {}
|
||||||
if not icallbacks.whois[nick] then
|
if not icallbacks.whois[nick] then
|
||||||
icallbacks.whois[nick] = {cb}
|
icallbacks.whois[nick] = {cb}
|
||||||
send("WHOIS", nick)
|
irc.send("WHOIS", nick)
|
||||||
else
|
else
|
||||||
table.insert(icallbacks.whois[nick], cb)
|
table.insert(icallbacks.whois[nick], cb)
|
||||||
end
|
end
|
||||||
@ -829,13 +844,13 @@ end
|
|||||||
-- <li><i>server:</i> the server which responded to the request</li>
|
-- <li><i>server:</i> the server which responded to the request</li>
|
||||||
-- <li><i>time:</i> the time reported by the server</li>
|
-- <li><i>time:</i> the time reported by the server</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
function server_time(cb)
|
function irc.server_time(cb)
|
||||||
-- apparently the optional server parameter isn't supported for servers
|
-- apparently the optional server parameter isn't supported for servers
|
||||||
-- which you are not directly connected to (freenode specific?)
|
-- which you are not directly connected to (freenode specific?)
|
||||||
local server = serverinfo.host
|
local server = serverinfo.host
|
||||||
if not icallbacks.servertime[server] then
|
if not icallbacks.servertime[server] then
|
||||||
icallbacks.servertime[server] = {cb}
|
icallbacks.servertime[server] = {cb}
|
||||||
send("TIME", server)
|
irc.send("TIME", server)
|
||||||
else
|
else
|
||||||
table.insert(icallbacks.servertime[server], cb)
|
table.insert(icallbacks.servertime[server], cb)
|
||||||
end
|
end
|
||||||
@ -854,11 +869,11 @@ end
|
|||||||
-- <li><i>time:</i> the roundtrip ping time, in seconds</li>
|
-- <li><i>time:</i> the roundtrip ping time, in seconds</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
-- @param nick User to ping
|
-- @param nick User to ping
|
||||||
function ctcp_ping(cb, nick)
|
function irc.ctcp_ping(cb, nick)
|
||||||
nick = nick:lower()
|
nick = nick:lower()
|
||||||
if not icallbacks.ctcp_ping[nick] then
|
if not icallbacks.ctcp_ping[nick] then
|
||||||
icallbacks.ctcp_ping[nick] = {cb}
|
icallbacks.ctcp_ping[nick] = {cb}
|
||||||
say(nick, c("PING", os.time()))
|
irc.say(nick, c("PING", os.time()))
|
||||||
else
|
else
|
||||||
table.insert(icallbacks.ctcp_ping[nick], cb)
|
table.insert(icallbacks.ctcp_ping[nick], cb)
|
||||||
end
|
end
|
||||||
@ -875,11 +890,11 @@ end
|
|||||||
-- <li><i>time:</i> the localtime reported by the remote client</li>
|
-- <li><i>time:</i> the localtime reported by the remote client</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
-- @param nick User to request the localtime from
|
-- @param nick User to request the localtime from
|
||||||
function ctcp_time(cb, nick)
|
function irc.ctcp_time(cb, nick)
|
||||||
nick = nick:lower()
|
nick = nick:lower()
|
||||||
if not icallbacks.ctcp_time[nick] then
|
if not icallbacks.ctcp_time[nick] then
|
||||||
icallbacks.ctcp_time[nick] = {cb}
|
icallbacks.ctcp_time[nick] = {cb}
|
||||||
say(nick, c("TIME"))
|
irc.say(nick, c("TIME"))
|
||||||
else
|
else
|
||||||
table.insert(icallbacks.ctcp_time[nick], cb)
|
table.insert(icallbacks.ctcp_time[nick], cb)
|
||||||
end
|
end
|
||||||
@ -896,11 +911,11 @@ end
|
|||||||
-- <li><i>version:</i> the version reported by the remote client</li>
|
-- <li><i>version:</i> the version reported by the remote client</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
-- @param nick User to request the client version from
|
-- @param nick User to request the client version from
|
||||||
function ctcp_version(cb, nick)
|
function irc.ctcp_version(cb, nick)
|
||||||
nick = nick:lower()
|
nick = nick:lower()
|
||||||
if not icallbacks.ctcp_version[nick] then
|
if not icallbacks.ctcp_version[nick] then
|
||||||
icallbacks.ctcp_version[nick] = {cb}
|
icallbacks.ctcp_version[nick] = {cb}
|
||||||
say(nick, c("VERSION"))
|
irc.say(nick, c("VERSION"))
|
||||||
else
|
else
|
||||||
table.insert(icallbacks.ctcp_version[nick], cb)
|
table.insert(icallbacks.ctcp_version[nick], cb)
|
||||||
end
|
end
|
||||||
@ -917,7 +932,7 @@ end
|
|||||||
-- callback for this event
|
-- callback for this event
|
||||||
-- @return Value of the original callback for this event (or nil if no previous
|
-- @return Value of the original callback for this event (or nil if no previous
|
||||||
-- callback had been set)
|
-- callback had been set)
|
||||||
function register_callback(name, fn)
|
function irc.register_callback(name, fn)
|
||||||
local old_handler = user_handlers[name]
|
local old_handler = user_handlers[name]
|
||||||
user_handlers[name] = fn
|
user_handlers[name] = fn
|
||||||
return old_handler
|
return old_handler
|
||||||
@ -936,10 +951,10 @@ end
|
|||||||
-- an array. Strings are sent literally, arrays are CTCP quoted
|
-- an array. Strings are sent literally, arrays are CTCP quoted
|
||||||
-- as a group. The last argument (if it exists) is preceded by
|
-- as a group. The last argument (if it exists) is preceded by
|
||||||
-- a : (so it may contain spaces).
|
-- a : (so it may contain spaces).
|
||||||
function send(command, ...)
|
function irc.send(command, ...)
|
||||||
if not serverinfo.connected and not serverinfo.connecting then return end
|
if not serverinfo.connected and not serverinfo.connecting then return end
|
||||||
local message = command
|
local message = command
|
||||||
for i, v in base.ipairs({...}) do
|
for i, v in ipairs({...}) do
|
||||||
if i == #{...} then
|
if i == #{...} then
|
||||||
v = ":" .. v
|
v = ":" .. v
|
||||||
end
|
end
|
||||||
@ -958,7 +973,7 @@ end
|
|||||||
-- Get the local IP address for the server connection.
|
-- Get the local IP address for the server connection.
|
||||||
-- @return A string representation of the local IP address that the IRC server
|
-- @return A string representation of the local IP address that the IRC server
|
||||||
-- connection is communicating on
|
-- connection is communicating on
|
||||||
function get_ip()
|
function irc.get_ip()
|
||||||
return (ip or irc_sock:getsockname())
|
return (ip or irc_sock:getsockname())
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -967,7 +982,7 @@ end
|
|||||||
---
|
---
|
||||||
-- Set the local IP manually (to allow for NAT workarounds)
|
-- Set the local IP manually (to allow for NAT workarounds)
|
||||||
-- @param new_ip IP address to set
|
-- @param new_ip IP address to set
|
||||||
function set_ip(new_ip)
|
function irc.set_ip(new_ip)
|
||||||
ip = new_ip
|
ip = new_ip
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -979,7 +994,7 @@ end
|
|||||||
-- channels() is an iterator function for use in for loops.
|
-- channels() is an iterator function for use in for loops.
|
||||||
-- For example, <pre>for chan in irc.channels() do print(chan:name) end</pre>
|
-- For example, <pre>for chan in irc.channels() do print(chan:name) end</pre>
|
||||||
-- @see irc.channel
|
-- @see irc.channel
|
||||||
function channels()
|
function irc.channels()
|
||||||
return function(state, arg)
|
return function(state, arg)
|
||||||
return misc._value_iter(state, arg,
|
return misc._value_iter(state, arg,
|
||||||
function(v)
|
function(v)
|
||||||
@ -992,3 +1007,5 @@ end
|
|||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return irc
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
-- Implementation of the Channel class
|
-- Implementation of the Channel class
|
||||||
|
|
||||||
-- initialization {{{
|
-- initialization {{{
|
||||||
local base = _G
|
local irc = libs.irc
|
||||||
local irc = require 'irc'
|
local misc = libs.misc
|
||||||
local misc = require 'irc.misc'
|
local socket = libs.socket
|
||||||
local socket = require 'socket'
|
|
||||||
local table = require 'table'
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This module implements a channel object representing a single channel we
|
-- This module implements a channel object representing a single channel we
|
||||||
-- have joined.
|
-- have joined.
|
||||||
module 'irc.channel'
|
local channel = {}
|
||||||
|
|
||||||
-- object metatable {{{
|
-- object metatable {{{
|
||||||
-- TODO: this <br /> shouldn't be necessary - bug in luadoc
|
-- TODO: this <br /> shouldn't be necessary - bug in luadoc
|
||||||
@ -37,7 +35,7 @@ local mt = {
|
|||||||
elseif key == "chanmode" then
|
elseif key == "chanmode" then
|
||||||
return self._chanmode
|
return self._chanmode
|
||||||
else
|
else
|
||||||
return _M[key]
|
return channel[key]
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -50,7 +48,7 @@ local mt = {
|
|||||||
elseif key == "chanmode" then
|
elseif key == "chanmode" then
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
base.rawset(self, key, value)
|
rawset(self, key, value)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -58,12 +56,12 @@ local mt = {
|
|||||||
__concat = function(first, second)
|
__concat = function(first, second)
|
||||||
local first_str, second_str
|
local first_str, second_str
|
||||||
|
|
||||||
if base.type(first) == "table" then
|
if type(first) == "table" then
|
||||||
first_str = first._name
|
first_str = first._name
|
||||||
else
|
else
|
||||||
first_str = first
|
first_str = first
|
||||||
end
|
end
|
||||||
if base.type(second) == "table" then
|
if type(second) == "table" then
|
||||||
second_str = second._name
|
second_str = second._name
|
||||||
else
|
else
|
||||||
second_str = second
|
second_str = second
|
||||||
@ -88,7 +86,7 @@ local mt = {
|
|||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param set True to set the mode, false to unset it
|
-- @param set True to set the mode, false to unset it
|
||||||
-- @param letter Letter of the mode
|
-- @param letter Letter of the mode
|
||||||
local function set_basic_mode(self, set, letter)
|
local function set_basic_mode(set, letter)
|
||||||
if set then
|
if set then
|
||||||
irc.send("MODE", self.name, "+" .. letter)
|
irc.send("MODE", self.name, "+" .. letter)
|
||||||
else
|
else
|
||||||
@ -107,7 +105,7 @@ end
|
|||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param user Nick of the user to add
|
-- @param user Nick of the user to add
|
||||||
-- @param mode Mode (op/voice) of the user, in symbolic form (@/+)
|
-- @param mode Mode (op/voice) of the user, in symbolic form (@/+)
|
||||||
function _add_user(self, user, mode)
|
function channel:_add_user(user, mode)
|
||||||
mode = mode or ''
|
mode = mode or ''
|
||||||
self._members[user] = mode .. user
|
self._members[user] = mode .. user
|
||||||
end
|
end
|
||||||
@ -118,7 +116,7 @@ end
|
|||||||
-- Remove a user from the channel's internal user list.
|
-- Remove a user from the channel's internal user list.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param user Nick of the user to remove
|
-- @param user Nick of the user to remove
|
||||||
function _remove_user(self, user)
|
function channel:_remove_user(user)
|
||||||
self._members[user] = nil
|
self._members[user] = nil
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -130,7 +128,7 @@ end
|
|||||||
-- @param user Nick of the user to affect
|
-- @param user Nick of the user to affect
|
||||||
-- @param on True if the mode is being set, false if it's being unset
|
-- @param on True if the mode is being set, false if it's being unset
|
||||||
-- @param mode 'o' for op, 'v' for voice
|
-- @param mode 'o' for op, 'v' for voice
|
||||||
function _change_status(self, user, on, mode)
|
function channel:_change_status(user, on, mode)
|
||||||
if on then
|
if on then
|
||||||
if mode == 'o' then
|
if mode == 'o' then
|
||||||
self._members[user] = '@' .. user
|
self._members[user] = '@' .. user
|
||||||
@ -152,7 +150,7 @@ end
|
|||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param old_nick User's old nick
|
-- @param old_nick User's old nick
|
||||||
-- @param new_nick User's new nick
|
-- @param new_nick User's new nick
|
||||||
function _change_nick(self, old_nick, new_nick)
|
function channel:_change_nick(old_nick, new_nick)
|
||||||
for member in self:each_member() do
|
for member in self:each_member() do
|
||||||
local member_nick = member:gsub('@+', '')
|
local member_nick = member:gsub('@+', '')
|
||||||
if member_nick == old_nick then
|
if member_nick == old_nick then
|
||||||
@ -172,8 +170,8 @@ end
|
|||||||
-- Creates a new Channel object.
|
-- Creates a new Channel object.
|
||||||
-- @param chan Name of the new channel
|
-- @param chan Name of the new channel
|
||||||
-- @return The new channel instance
|
-- @return The new channel instance
|
||||||
function new(chan)
|
function channel.new(chan)
|
||||||
return base.setmetatable({_name = chan, _topic = {}, _chanmode = "",
|
return setmetatable({_name = chan, _topic = {}, _chanmode = "",
|
||||||
_members = {}}, mt)
|
_members = {}}, mt)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -184,7 +182,7 @@ end
|
|||||||
---
|
---
|
||||||
-- Iterator over the ops in the channel
|
-- Iterator over the ops in the channel
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
function each_op(self)
|
function channel:each_op()
|
||||||
return function(state, arg)
|
return function(state, arg)
|
||||||
return misc._value_iter(state, arg,
|
return misc._value_iter(state, arg,
|
||||||
function(v)
|
function(v)
|
||||||
@ -200,7 +198,7 @@ end
|
|||||||
---
|
---
|
||||||
-- Iterator over the voiced users in the channel
|
-- Iterator over the voiced users in the channel
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
function each_voice(self)
|
function channel:each_voice()
|
||||||
return function(state, arg)
|
return function(state, arg)
|
||||||
return misc._value_iter(state, arg,
|
return misc._value_iter(state, arg,
|
||||||
function(v)
|
function(v)
|
||||||
@ -216,7 +214,7 @@ end
|
|||||||
---
|
---
|
||||||
-- Iterator over the normal users in the channel
|
-- Iterator over the normal users in the channel
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
function each_user(self)
|
function channel:each_user()
|
||||||
return function(state, arg)
|
return function(state, arg)
|
||||||
return misc._value_iter(state, arg,
|
return misc._value_iter(state, arg,
|
||||||
function(v)
|
function(v)
|
||||||
@ -233,7 +231,7 @@ end
|
|||||||
---
|
---
|
||||||
-- Iterator over all users in the channel
|
-- Iterator over all users in the channel
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
function each_member(self)
|
function channel:each_member()
|
||||||
return misc._value_iter, self._members, nil
|
return misc._value_iter, self._members, nil
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -245,7 +243,7 @@ end
|
|||||||
-- Gets an array of all the ops in the channel.
|
-- Gets an array of all the ops in the channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @return Array of channel ops
|
-- @return Array of channel ops
|
||||||
function ops(self)
|
function channel:ops()
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for nick in self:each_op() do
|
for nick in self:each_op() do
|
||||||
table.insert(ret, nick)
|
table.insert(ret, nick)
|
||||||
@ -259,7 +257,7 @@ end
|
|||||||
-- Gets an array of all the voiced users in the channel.
|
-- Gets an array of all the voiced users in the channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @return Array of channel voiced users
|
-- @return Array of channel voiced users
|
||||||
function voices(self)
|
function channel:voices()
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for nick in self:each_voice() do
|
for nick in self:each_voice() do
|
||||||
table.insert(ret, nick)
|
table.insert(ret, nick)
|
||||||
@ -273,7 +271,7 @@ end
|
|||||||
-- Gets an array of all the normal users in the channel.
|
-- Gets an array of all the normal users in the channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @return Array of channel normal users
|
-- @return Array of channel normal users
|
||||||
function users(self)
|
function channel:users()
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for nick in self:each_user() do
|
for nick in self:each_user() do
|
||||||
table.insert(ret, nick)
|
table.insert(ret, nick)
|
||||||
@ -287,7 +285,7 @@ end
|
|||||||
-- Gets an array of all the users in the channel.
|
-- Gets an array of all the users in the channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @return Array of channel users
|
-- @return Array of channel users
|
||||||
function members(self)
|
function channel:members()
|
||||||
local ret = {}
|
local ret = {}
|
||||||
-- not just returning self._members, since the return value shouldn't be
|
-- not just returning self._members, since the return value shouldn't be
|
||||||
-- modifiable
|
-- modifiable
|
||||||
@ -306,7 +304,7 @@ end
|
|||||||
-- Ban a user from a channel.
|
-- Ban a user from a channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param name User to ban
|
-- @param name User to ban
|
||||||
function ban(self, name)
|
function channel:ban(name)
|
||||||
irc.send("MODE", self.name, "+b", name)
|
irc.send("MODE", self.name, "+b", name)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -317,7 +315,7 @@ end
|
|||||||
-- Remove a ban on a user.
|
-- Remove a ban on a user.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param name User to unban
|
-- @param name User to unban
|
||||||
function unban(self, name)
|
function channel:unban(name)
|
||||||
irc.send("MODE", self.name, "-b", name)
|
irc.send("MODE", self.name, "-b", name)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -327,7 +325,7 @@ end
|
|||||||
-- Give a user voice on a channel.
|
-- Give a user voice on a channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param name User to give voice to
|
-- @param name User to give voice to
|
||||||
function voice(self, name)
|
function channel:voice(name)
|
||||||
irc.send("MODE", self.name, "+v", name)
|
irc.send("MODE", self.name, "+v", name)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -337,7 +335,7 @@ end
|
|||||||
-- Remove voice from a user.
|
-- Remove voice from a user.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param name User to remove voice from
|
-- @param name User to remove voice from
|
||||||
function devoice(self, name)
|
function channel:devoice(name)
|
||||||
irc.send("MODE", self.name, "-v", name)
|
irc.send("MODE", self.name, "-v", name)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -347,7 +345,7 @@ end
|
|||||||
-- Give a user ops on a channel.
|
-- Give a user ops on a channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param name User to op
|
-- @param name User to op
|
||||||
function op(self, name)
|
function channel:op(name)
|
||||||
irc.send("MODE", self.name, "+o", name)
|
irc.send("MODE", self.name, "+o", name)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -357,7 +355,7 @@ end
|
|||||||
-- Remove ops from a user.
|
-- Remove ops from a user.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param name User to remove ops from
|
-- @param name User to remove ops from
|
||||||
function deop(self, name)
|
function channel:deop(name)
|
||||||
irc.send("MODE", self.name, "-o", name)
|
irc.send("MODE", self.name, "-o", name)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -368,7 +366,7 @@ end
|
|||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param new_limit New value for the channel limit (optional; limit is unset
|
-- @param new_limit New value for the channel limit (optional; limit is unset
|
||||||
-- if this argument isn't passed)
|
-- if this argument isn't passed)
|
||||||
function set_limit(self, new_limit)
|
function channel:set_limit(new_limit)
|
||||||
if new_limit then
|
if new_limit then
|
||||||
irc.send("MODE", self.name, "+l", new_limit)
|
irc.send("MODE", self.name, "+l", new_limit)
|
||||||
else
|
else
|
||||||
@ -383,7 +381,7 @@ end
|
|||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param key New channel password (optional; password is unset if this
|
-- @param key New channel password (optional; password is unset if this
|
||||||
-- argument isn't passed)
|
-- argument isn't passed)
|
||||||
function set_key(self, key)
|
function channel:set_key(key)
|
||||||
if key then
|
if key then
|
||||||
irc.send("MODE", self.name, "+k", key)
|
irc.send("MODE", self.name, "+k", key)
|
||||||
else
|
else
|
||||||
@ -397,7 +395,7 @@ end
|
|||||||
-- Set the private state of a channel.
|
-- Set the private state of a channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param set True to set the channel as private, false to unset it
|
-- @param set True to set the channel as private, false to unset it
|
||||||
function set_private(self, set)
|
function channel:set_private(set)
|
||||||
set_basic_mode(self, set, "p")
|
set_basic_mode(self, set, "p")
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -407,7 +405,7 @@ end
|
|||||||
-- Set the secret state of a channel.
|
-- Set the secret state of a channel.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param set True to set the channel as secret, false to unset it
|
-- @param set True to set the channel as secret, false to unset it
|
||||||
function set_secret(self, set)
|
function channel:set_secret(set)
|
||||||
set_basic_mode(self, set, "s")
|
set_basic_mode(self, set, "s")
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -417,7 +415,7 @@ end
|
|||||||
-- Set whether joining the channel requires an invite.
|
-- Set whether joining the channel requires an invite.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param set True to set the channel invite only, false to unset it
|
-- @param set True to set the channel invite only, false to unset it
|
||||||
function set_invite_only(self, set)
|
function channel:set_invite_only(set)
|
||||||
set_basic_mode(self, set, "i")
|
set_basic_mode(self, set, "i")
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -427,7 +425,7 @@ end
|
|||||||
-- If true, the topic can only be changed by an op.
|
-- If true, the topic can only be changed by an op.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param set True to lock the topic, false to unlock it
|
-- @param set True to lock the topic, false to unlock it
|
||||||
function set_topic_lock(self, set)
|
function channel:set_topic_lock(set)
|
||||||
set_basic_mode(self, set, "t")
|
set_basic_mode(self, set, "t")
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -438,7 +436,7 @@ end
|
|||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param set True to require users to be in the channel to send messages to
|
-- @param set True to require users to be in the channel to send messages to
|
||||||
-- it, false to remove this restriction
|
-- it, false to remove this restriction
|
||||||
function set_no_outside_messages(self, set)
|
function channel:set_no_outside_messages(set)
|
||||||
set_basic_mode(self, set, "n")
|
set_basic_mode(self, set, "n")
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -448,7 +446,7 @@ end
|
|||||||
-- Set whether voice is required to speak.
|
-- Set whether voice is required to speak.
|
||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param set True to set the channel as moderated, false to unset it
|
-- @param set True to set the channel as moderated, false to unset it
|
||||||
function set_moderated(self, set)
|
function channel:set_moderated(set)
|
||||||
set_basic_mode(self, set, "m")
|
set_basic_mode(self, set, "m")
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -461,7 +459,7 @@ end
|
|||||||
-- @param self Channel object
|
-- @param self Channel object
|
||||||
-- @param nick Nick to search for
|
-- @param nick Nick to search for
|
||||||
-- @return True if the nick is in the channel, false otherwise
|
-- @return True if the nick is in the channel, false otherwise
|
||||||
function contains(self, nick)
|
function channel:contains(nick)
|
||||||
for member in self:each_member() do
|
for member in self:each_member() do
|
||||||
local member_nick = member:gsub('@+', '')
|
local member_nick = member:gsub('@+', '')
|
||||||
if member_nick == nick then
|
if member_nick == nick then
|
||||||
@ -473,3 +471,5 @@ end
|
|||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return channel
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
---
|
---
|
||||||
-- This module holds various constants used by the IRC protocol.
|
-- This module holds various constants used by the IRC protocol.
|
||||||
module "irc.constants"
|
local constants = {}
|
||||||
|
|
||||||
-- protocol constants {{{
|
-- protocol constants {{{
|
||||||
IRC_MAX_MSG = 512
|
constants.IRC_MAX_MSG = 512
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- server replies {{{
|
-- server replies {{{
|
||||||
replies = {
|
constants.replies = {
|
||||||
-- Command responses {{{
|
-- Command responses {{{
|
||||||
[001] = "RPL_WELCOME",
|
[001] = "RPL_WELCOME",
|
||||||
[002] = "RPL_YOURHOST",
|
[002] = "RPL_YOURHOST",
|
||||||
@ -183,9 +183,11 @@ replies = {
|
|||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- chanmodes {{{
|
-- chanmodes {{{
|
||||||
chanmodes = {
|
constants.chanmodes = {
|
||||||
["@"] = "secret",
|
["@"] = "secret",
|
||||||
["*"] = "private",
|
["*"] = "private",
|
||||||
["="] = "public"
|
["="] = "public"
|
||||||
}
|
}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return constants
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
---
|
---
|
||||||
-- Implementation of the CTCP protocol
|
-- Implementation of the CTCP protocol
|
||||||
-- initialization {{{
|
|
||||||
local base = _G
|
|
||||||
local table = require "table"
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This module implements the various quoting and escaping requirements of the
|
-- This module implements the various quoting and escaping requirements of the
|
||||||
-- CTCP protocol.
|
-- CTCP protocol.
|
||||||
module "irc.ctcp"
|
local ctcp = {}
|
||||||
|
|
||||||
-- internal functions {{{
|
-- internal functions {{{
|
||||||
-- _low_quote {{{
|
-- _low_quote {{{
|
||||||
@ -17,7 +13,7 @@ module "irc.ctcp"
|
|||||||
-- to appear in an IRC packet).
|
-- to appear in an IRC packet).
|
||||||
-- @param ... Strings to quote together, space separated
|
-- @param ... Strings to quote together, space separated
|
||||||
-- @return Quoted string
|
-- @return Quoted string
|
||||||
function _low_quote(...)
|
function ctcp._low_quote(...)
|
||||||
local str = table.concat({...}, " ")
|
local str = table.concat({...}, " ")
|
||||||
return str:gsub("[%z\n\r\020]", {["\000"] = "\0200",
|
return str:gsub("[%z\n\r\020]", {["\000"] = "\0200",
|
||||||
["\n"] = "\020n",
|
["\n"] = "\020n",
|
||||||
@ -31,7 +27,7 @@ end
|
|||||||
-- Removes low level quoting done by low_quote.
|
-- Removes low level quoting done by low_quote.
|
||||||
-- @param str String with low level quoting applied to it
|
-- @param str String with low level quoting applied to it
|
||||||
-- @return String with those quoting methods stripped off
|
-- @return String with those quoting methods stripped off
|
||||||
function _low_dequote(str)
|
function ctcp._low_dequote(str)
|
||||||
return str:gsub("\020(.?)", function(s)
|
return str:gsub("\020(.?)", function(s)
|
||||||
if s == "0" then return "\000" end
|
if s == "0" then return "\000" end
|
||||||
if s == "n" then return "\n" end
|
if s == "n" then return "\n" end
|
||||||
@ -48,7 +44,7 @@ end
|
|||||||
-- data (by the calling program).
|
-- data (by the calling program).
|
||||||
-- @param ... Strings to apply CTCP quoting to together, space separated
|
-- @param ... Strings to apply CTCP quoting to together, space separated
|
||||||
-- @return String with CTCP quoting applied
|
-- @return String with CTCP quoting applied
|
||||||
function _ctcp_quote(...)
|
function ctcp._ctcp_quote(...)
|
||||||
local str = table.concat({...}, " ")
|
local str = table.concat({...}, " ")
|
||||||
local ret = str:gsub("[\001\\]", {["\001"] = "\\a",
|
local ret = str:gsub("[\001\\]", {["\001"] = "\\a",
|
||||||
["\\"] = "\\\\"})
|
["\\"] = "\\\\"})
|
||||||
@ -62,7 +58,7 @@ end
|
|||||||
-- data (likely by ctcp_split).
|
-- data (likely by ctcp_split).
|
||||||
-- @param str String with CTCP quoting
|
-- @param str String with CTCP quoting
|
||||||
-- @return String with all CTCP quoting stripped
|
-- @return String with all CTCP quoting stripped
|
||||||
function _ctcp_dequote(str)
|
function ctcp._ctcp_dequote(str)
|
||||||
local ret = str:gsub("^\001", ""):gsub("\001$", "")
|
local ret = str:gsub("^\001", ""):gsub("\001$", "")
|
||||||
return ret:gsub("\\(.?)", function(s)
|
return ret:gsub("\\(.?)", function(s)
|
||||||
if s == "a" then return "\001" end
|
if s == "a" then return "\001" end
|
||||||
@ -84,7 +80,7 @@ end
|
|||||||
-- <li><i>ctcp:</i> True if the section was a CTCP message, false
|
-- <li><i>ctcp:</i> True if the section was a CTCP message, false
|
||||||
-- otherwise</li>
|
-- otherwise</li>
|
||||||
-- </ul>
|
-- </ul>
|
||||||
function _ctcp_split(str)
|
function ctcp._ctcp_split(str)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
local iter = 1
|
local iter = 1
|
||||||
while true do
|
while true do
|
||||||
@ -103,7 +99,7 @@ function _ctcp_split(str)
|
|||||||
end
|
end
|
||||||
if not s then break end
|
if not s then break end
|
||||||
if ctcp_string ~= "" then
|
if ctcp_string ~= "" then
|
||||||
table.insert(ret, {str = _ctcp_dequote(ctcp_string), ctcp = true})
|
table.insert(ret, {str = ctcp._ctcp_dequote(ctcp_string), ctcp = true})
|
||||||
end
|
end
|
||||||
|
|
||||||
iter = e + 1
|
iter = e + 1
|
||||||
@ -113,3 +109,5 @@ function _ctcp_split(str)
|
|||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return ctcp
|
||||||
|
@ -1,26 +1,22 @@
|
|||||||
---
|
---
|
||||||
-- Implementation of the DCC protocol
|
-- Implementation of the DCC protocol
|
||||||
-- initialization {{{
|
-- initialization {{{
|
||||||
local base = _G
|
local irc = libs.irc
|
||||||
local irc = require 'irc'
|
local ctcp = libs.ctcp
|
||||||
local ctcp = require 'irc.ctcp'
|
|
||||||
local c = ctcp._ctcp_quote
|
local c = ctcp._ctcp_quote
|
||||||
local irc_debug = require 'irc.debug'
|
local irc_debug = libs.debug
|
||||||
local misc = require 'irc.misc'
|
local misc = libs.misc
|
||||||
local socket = require 'socket'
|
local socket = libs.socket
|
||||||
local coroutine = require 'coroutine'
|
|
||||||
local io = require 'io'
|
|
||||||
local string = require 'string'
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This module implements the DCC protocol. File transfers (DCC SEND) are
|
-- This module implements the DCC protocol. File transfers (DCC SEND) are
|
||||||
-- handled, but DCC CHAT is not, as of yet.
|
-- handled, but DCC CHAT is not, as of yet.
|
||||||
module 'irc.dcc'
|
local dcc = {}
|
||||||
|
|
||||||
-- defaults {{{
|
-- defaults {{{
|
||||||
FIRST_PORT = 1028
|
dcc.FIRST_PORT = 1028
|
||||||
LAST_PORT = 5000
|
dcc.LAST_PORT = 5000
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- private functions {{{
|
-- private functions {{{
|
||||||
@ -138,13 +134,13 @@ end
|
|||||||
-- @param address IP address of the remote user in low level int form
|
-- @param address IP address of the remote user in low level int form
|
||||||
-- @param port Port to connect to at the remote user
|
-- @param port Port to connect to at the remote user
|
||||||
-- @param packet_size Size of the packets the remote user will be sending
|
-- @param packet_size Size of the packets the remote user will be sending
|
||||||
function _accept(filename, address, port, packet_size)
|
function dcc._accept(filename, address, port, packet_size)
|
||||||
debug_dcc("Accepting a DCC SEND request from " .. address .. ":" .. port)
|
debug_dcc("Accepting a DCC SEND request from " .. address .. ":" .. port)
|
||||||
packet_size = packet_size or 1024
|
packet_size = packet_size or 1024
|
||||||
local sock = base.assert(socket.tcp())
|
local sock = assert(socket.tcp())
|
||||||
base.assert(sock:connect(address, port))
|
assert(sock:connect(address, port))
|
||||||
sock:settimeout(0.1)
|
sock:settimeout(0.1)
|
||||||
local file = base.assert(io.open(misc._get_unique_filename(filename), "w"))
|
local file = assert(io.open(misc._get_unique_filename(filename), "w"))
|
||||||
irc._register_socket(sock, 'r',
|
irc._register_socket(sock, 'r',
|
||||||
coroutine.wrap(function(s)
|
coroutine.wrap(function(s)
|
||||||
return accept_file(s, file, packet_size)
|
return accept_file(s, file, packet_size)
|
||||||
@ -162,17 +158,17 @@ end
|
|||||||
-- @param port Port to accept connections on (optional, defaults to
|
-- @param port Port to accept connections on (optional, defaults to
|
||||||
-- choosing an available port between FIRST_PORT and LAST_PORT
|
-- choosing an available port between FIRST_PORT and LAST_PORT
|
||||||
-- above)
|
-- above)
|
||||||
function send(nick, filename, port)
|
function dcc.send(nick, filename, port)
|
||||||
port = port or FIRST_PORT
|
port = port or dcc.FIRST_PORT
|
||||||
local sock
|
local sock
|
||||||
repeat
|
repeat
|
||||||
sock = base.assert(socket.tcp())
|
sock = assert(socket.tcp())
|
||||||
err, msg = sock:bind('*', port)
|
err, msg = sock:bind('*', port)
|
||||||
port = port + 1
|
port = port + 1
|
||||||
until msg ~= "address already in use" and port <= LAST_PORT + 1
|
until msg ~= "address already in use" and port <= dcc.LAST_PORT + 1
|
||||||
port = port - 1
|
port = port - 1
|
||||||
base.assert(err, msg)
|
assert(err, msg)
|
||||||
base.assert(sock:listen(1))
|
assert(sock:listen(1))
|
||||||
local ip = misc._ip_str_to_int(irc.get_ip())
|
local ip = misc._ip_str_to_int(irc.get_ip())
|
||||||
local file, err = io.open(filename)
|
local file, err = io.open(filename)
|
||||||
if not file then
|
if not file then
|
||||||
@ -194,3 +190,5 @@ function send(nick, filename, port)
|
|||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return dcc
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
---
|
---
|
||||||
-- Basic debug output
|
-- Basic debug output
|
||||||
-- initialization {{{
|
|
||||||
local base = _G
|
|
||||||
local io = require 'io'
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This module implements a few useful debug functions for use throughout the
|
-- This module implements a few useful debug functions for use throughout the
|
||||||
-- rest of the code.
|
-- rest of the code.
|
||||||
module 'irc.debug'
|
local irc_debug = {}
|
||||||
|
|
||||||
-- defaults {{{
|
-- defaults {{{
|
||||||
COLOR = true
|
irc_debug.COLOR = true
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- local variables {{{
|
-- local variables {{{
|
||||||
@ -27,10 +23,10 @@ local outfile = io.output()
|
|||||||
-- @param msg Message text
|
-- @param msg Message text
|
||||||
-- @param color Which terminal code to use for color output (defaults to
|
-- @param color Which terminal code to use for color output (defaults to
|
||||||
-- dark gray)
|
-- dark gray)
|
||||||
function _message(msg_type, msg, color)
|
function irc_debug._message(msg_type, msg, color)
|
||||||
if ON then
|
if ON then
|
||||||
local endcolor = ""
|
local endcolor = ""
|
||||||
if COLOR and outfile == io.stdout then
|
if irc_debug.COLOR and outfile == io.stdout then
|
||||||
color = color or "\027[1;30m"
|
color = color or "\027[1;30m"
|
||||||
endcolor = "\027[0m"
|
endcolor = "\027[0m"
|
||||||
else
|
else
|
||||||
@ -48,9 +44,9 @@ end
|
|||||||
-- error().
|
-- error().
|
||||||
-- @param msg Error message
|
-- @param msg Error message
|
||||||
-- @see error
|
-- @see error
|
||||||
function _err(msg)
|
function irc_debug._err(msg)
|
||||||
_message("ERR", msg, "\027[0;31m")
|
irc_debug._message("ERR", msg, "\027[0;31m")
|
||||||
base.error(msg, 2)
|
error(msg, 2)
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
@ -58,8 +54,8 @@ end
|
|||||||
--
|
--
|
||||||
-- Signal a warning. Writes the warning message to the screen in yellow.
|
-- Signal a warning. Writes the warning message to the screen in yellow.
|
||||||
-- @param msg Warning message
|
-- @param msg Warning message
|
||||||
function _warn(msg)
|
function irc_debug._warn(msg)
|
||||||
_message("WARN", msg, "\027[0;33m")
|
irc_debug._message("WARN", msg, "\027[0;33m")
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -68,7 +64,7 @@ end
|
|||||||
-- enable {{{
|
-- enable {{{
|
||||||
---
|
---
|
||||||
-- Turns on debug output.
|
-- Turns on debug output.
|
||||||
function enable()
|
function irc_debug.enable()
|
||||||
ON = true
|
ON = true
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -76,7 +72,7 @@ end
|
|||||||
-- disable {{{
|
-- disable {{{
|
||||||
---
|
---
|
||||||
-- Turns off debug output.
|
-- Turns off debug output.
|
||||||
function disable()
|
function irc_debug.disable()
|
||||||
ON = false
|
ON = false
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -85,8 +81,10 @@ end
|
|||||||
---
|
---
|
||||||
-- Redirects output to a file rather than stdout.
|
-- Redirects output to a file rather than stdout.
|
||||||
-- @param file File to write debug output to
|
-- @param file File to write debug output to
|
||||||
function set_output(file)
|
function irc_debug.set_output(file)
|
||||||
outfile = base.assert(io.open(file))
|
outfile = assert(io.open(file))
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return irc_debug
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
---
|
---
|
||||||
-- Implementation of IRC server message parsing
|
-- Implementation of IRC server message parsing
|
||||||
-- initialization {{{
|
-- initialization {{{
|
||||||
local base = _G
|
local constants = libs.constants
|
||||||
local constants = require 'irc.constants'
|
local ctcp = libs.ctcp
|
||||||
local ctcp = require 'irc.ctcp'
|
local irc_debug = libs.debug
|
||||||
local irc_debug = require 'irc.debug'
|
local misc = libs.misc
|
||||||
local misc = require 'irc.misc'
|
local socket = libs.socket
|
||||||
local socket = require 'socket'
|
|
||||||
local string = require 'string'
|
|
||||||
local table = require 'table'
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This module contains parsing functions for IRC server messages.
|
-- This module contains parsing functions for IRC server messages.
|
||||||
module 'irc.message'
|
local message = {}
|
||||||
|
|
||||||
-- internal functions {{{
|
-- internal functions {{{
|
||||||
-- _parse {{{
|
-- _parse {{{
|
||||||
@ -32,7 +29,7 @@ module 'irc.message'
|
|||||||
-- to the received command</li>
|
-- to the received command</li>
|
||||||
--
|
--
|
||||||
-- </ul>
|
-- </ul>
|
||||||
function _parse(str)
|
function message._parse(str)
|
||||||
-- low-level ctcp quoting {{{
|
-- low-level ctcp quoting {{{
|
||||||
str = ctcp._low_dequote(str)
|
str = ctcp._low_dequote(str)
|
||||||
-- }}}
|
-- }}}
|
||||||
@ -49,8 +46,8 @@ function _parse(str)
|
|||||||
local reply = false
|
local reply = false
|
||||||
if command:find("^%d%d%d$") then
|
if command:find("^%d%d%d$") then
|
||||||
reply = true
|
reply = true
|
||||||
if constants.replies[base.tonumber(command)] then
|
if constants.replies[tonumber(command)] then
|
||||||
command = constants.replies[base.tonumber(command)]
|
command = constants.replies[tonumber(command)]
|
||||||
else
|
else
|
||||||
irc_debug._warn("Unknown server reply: " .. command)
|
irc_debug._warn("Unknown server reply: " .. command)
|
||||||
end
|
end
|
||||||
@ -67,3 +64,5 @@ function _parse(str)
|
|||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return message
|
||||||
|
@ -1,25 +1,20 @@
|
|||||||
---
|
---
|
||||||
-- Various useful functions that didn't fit anywhere else
|
-- Various useful functions that didn't fit anywhere else
|
||||||
-- initialization {{{
|
-- initialization {{{
|
||||||
local base = _G
|
local irc_debug = libs.debug
|
||||||
local irc_debug = require 'irc.debug'
|
local socket = libs.socket
|
||||||
local socket = require 'socket'
|
|
||||||
local math = require 'math'
|
|
||||||
local os = require 'os'
|
|
||||||
local string = require 'string'
|
|
||||||
local table = require 'table'
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This module contains various useful functions which didn't fit in any of the
|
-- This module contains various useful functions which didn't fit in any of the
|
||||||
-- other modules.
|
-- other modules.
|
||||||
module 'irc.misc'
|
local misc = {}
|
||||||
|
|
||||||
-- defaults {{{
|
-- defaults {{{
|
||||||
DELIM = ' '
|
misc.DELIM = ' '
|
||||||
PATH_SEP = '/'
|
misc.PATH_SEP = '/'
|
||||||
ENDIANNESS = "big"
|
misc.ENDIANNESS = "big"
|
||||||
INT_BYTES = 4
|
misc.INT_BYTES = 4
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- private functions {{{
|
-- private functions {{{
|
||||||
@ -49,9 +44,9 @@ end
|
|||||||
-- in str will be considered one substring)
|
-- in str will be considered one substring)
|
||||||
-- @param rquotes String of characters to use as closing quotes
|
-- @param rquotes String of characters to use as closing quotes
|
||||||
-- @return Array of strings, one for each substring that was separated out
|
-- @return Array of strings, one for each substring that was separated out
|
||||||
function _split(str, delim, end_delim, lquotes, rquotes)
|
function misc._split(str, delim, end_delim, lquotes, rquotes)
|
||||||
-- handle arguments {{{
|
-- handle arguments {{{
|
||||||
delim = "["..(delim or DELIM).."]"
|
delim = "["..(delim or misc.DELIM).."]"
|
||||||
if end_delim then end_delim = "["..end_delim.."]" end
|
if end_delim then end_delim = "["..end_delim.."]" end
|
||||||
if lquotes then lquotes = "["..lquotes.."]" end
|
if lquotes then lquotes = "["..lquotes.."]" end
|
||||||
if rquotes then rquotes = "["..rquotes.."]" end
|
if rquotes then rquotes = "["..rquotes.."]" end
|
||||||
@ -111,8 +106,8 @@ end
|
|||||||
-- @param path Path to the file
|
-- @param path Path to the file
|
||||||
-- @param sep Directory separator (optional, defaults to PATH_SEP)
|
-- @param sep Directory separator (optional, defaults to PATH_SEP)
|
||||||
-- @return The basename of the file
|
-- @return The basename of the file
|
||||||
function _basename(path, sep)
|
function misc._basename(path, sep)
|
||||||
sep = sep or PATH_SEP
|
sep = sep or misc.PATH_SEP
|
||||||
if not path:find(sep) then return path end
|
if not path:find(sep) then return path end
|
||||||
return socket.skip(2, path:find(".*" .. sep .. "(.*)"))
|
return socket.skip(2, path:find(".*" .. sep .. "(.*)"))
|
||||||
end
|
end
|
||||||
@ -124,8 +119,8 @@ end
|
|||||||
-- @param path Path to the file
|
-- @param path Path to the file
|
||||||
-- @param sep Directory separator (optional, defaults to PATH_SEP)
|
-- @param sep Directory separator (optional, defaults to PATH_SEP)
|
||||||
-- @return The dirname of the file
|
-- @return The dirname of the file
|
||||||
function _dirname(path, sep)
|
function misc._dirname(path, sep)
|
||||||
sep = sep or PATH_SEP
|
sep = sep or misc.PATH_SEP
|
||||||
if not path:find(sep) then return "." end
|
if not path:find(sep) then return "." end
|
||||||
return socket.skip(2, path:find("(.*)" .. sep .. ".*"))
|
return socket.skip(2, path:find("(.*)" .. sep .. ".*"))
|
||||||
end
|
end
|
||||||
@ -139,9 +134,9 @@ end
|
|||||||
-- @param endian Which endianness to use (big, little, host, network) (defaultsi
|
-- @param endian Which endianness to use (big, little, host, network) (defaultsi
|
||||||
-- to ENDIANNESS)
|
-- to ENDIANNESS)
|
||||||
-- @return A string whose first INT_BYTES characters make a low-level int
|
-- @return A string whose first INT_BYTES characters make a low-level int
|
||||||
function _str_to_int(str, bytes, endian)
|
function misc._str_to_int(str, bytes, endian)
|
||||||
bytes = bytes or INT_BYTES
|
bytes = bytes or misc.INT_BYTES
|
||||||
endian = endian or ENDIANNESS
|
endian = endian or misc.ENDIANNESS
|
||||||
local ret = ""
|
local ret = ""
|
||||||
for i = 0, bytes - 1 do
|
for i = 0, bytes - 1 do
|
||||||
local new_byte = string.char(math.fmod(str / (2^(8 * i)), 256))
|
local new_byte = string.char(math.fmod(str / (2^(8 * i)), 256))
|
||||||
@ -159,8 +154,8 @@ end
|
|||||||
-- @param int String whose bytes correspond to the bytes of a low-level int
|
-- @param int String whose bytes correspond to the bytes of a low-level int
|
||||||
-- @param endian Endianness of the int argument (defaults to ENDIANNESS)
|
-- @param endian Endianness of the int argument (defaults to ENDIANNESS)
|
||||||
-- @return String representation of the low-level int argument
|
-- @return String representation of the low-level int argument
|
||||||
function _int_to_str(int, endian)
|
function misc._int_to_str(int, endian)
|
||||||
endian = endian or ENDIANNESS
|
endian = endian or misc.ENDIANNESS
|
||||||
local ret = 0
|
local ret = 0
|
||||||
for i = 1, int:len() do
|
for i = 1, int:len() do
|
||||||
if endian == "big" or endian == "network" then ind = int:len() - i + 1
|
if endian == "big" or endian == "network" then ind = int:len() - i + 1
|
||||||
@ -178,7 +173,7 @@ end
|
|||||||
-- Converts a string IP address to a low-level int.
|
-- Converts a string IP address to a low-level int.
|
||||||
-- @param ip_str String representation of an IP address
|
-- @param ip_str String representation of an IP address
|
||||||
-- @return Low-level int representation of that IP address
|
-- @return Low-level int representation of that IP address
|
||||||
function _ip_str_to_int(ip_str)
|
function misc._ip_str_to_int(ip_str)
|
||||||
local i = 3
|
local i = 3
|
||||||
local ret = 0
|
local ret = 0
|
||||||
for num in ip_str:gmatch("%d+") do
|
for num in ip_str:gmatch("%d+") do
|
||||||
@ -195,7 +190,7 @@ end
|
|||||||
-- Converts an int to a string IP address.
|
-- Converts an int to a string IP address.
|
||||||
-- @param ip_int Low-level int representation of an IP address
|
-- @param ip_int Low-level int representation of an IP address
|
||||||
-- @return String representation of that IP address
|
-- @return String representation of that IP address
|
||||||
function _ip_int_to_str(ip_int)
|
function misc._ip_int_to_str(ip_int)
|
||||||
local ip = {}
|
local ip = {}
|
||||||
for i = 3, 0, -1 do
|
for i = 3, 0, -1 do
|
||||||
local new_num = math.floor(ip_int / 2^(i * 8))
|
local new_num = math.floor(ip_int / 2^(i * 8))
|
||||||
@ -212,7 +207,7 @@ end
|
|||||||
-- @param filename Filename to start with
|
-- @param filename Filename to start with
|
||||||
-- @return Filename (same as the one we started with, except possibly with some
|
-- @return Filename (same as the one we started with, except possibly with some
|
||||||
-- numbers appended) which does not currently exist on the filesystem
|
-- numbers appended) which does not currently exist on the filesystem
|
||||||
function _get_unique_filename(filename)
|
function misc._get_unique_filename(filename)
|
||||||
if not exists(filename) then return filename end
|
if not exists(filename) then return filename end
|
||||||
|
|
||||||
local count = 1
|
local count = 1
|
||||||
@ -231,8 +226,8 @@ end
|
|||||||
-- @param fn Function to try to call
|
-- @param fn Function to try to call
|
||||||
-- @param ... Arguments to fn
|
-- @param ... Arguments to fn
|
||||||
-- @return The return values of fn, if it was successfully called
|
-- @return The return values of fn, if it was successfully called
|
||||||
function _try_call(fn, ...)
|
function misc._try_call(fn, ...)
|
||||||
if base.type(fn) == "function" then
|
if type(fn) == "function" then
|
||||||
return fn(...)
|
return fn(...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -245,8 +240,8 @@ end
|
|||||||
-- @param fn Function to try to call
|
-- @param fn Function to try to call
|
||||||
-- @param ... Arguments to fn
|
-- @param ... Arguments to fn
|
||||||
-- @return The return values of fn, if it was successfully called
|
-- @return The return values of fn, if it was successfully called
|
||||||
function _try_call_warn(msg, fn, ...)
|
function misc._try_call_warn(msg, fn, ...)
|
||||||
if base.type(fn) == "function" then
|
if type(fn) == "function" then
|
||||||
return fn(...)
|
return fn(...)
|
||||||
else
|
else
|
||||||
irc_debug._warn(msg)
|
irc_debug._warn(msg)
|
||||||
@ -257,16 +252,16 @@ end
|
|||||||
-- _value_iter {{{
|
-- _value_iter {{{
|
||||||
--
|
--
|
||||||
-- Iterator to iterate over just the values of a table.
|
-- Iterator to iterate over just the values of a table.
|
||||||
function _value_iter(state, arg, pred)
|
function misc._value_iter(state, arg, pred)
|
||||||
for k, v in base.pairs(state) do
|
for k, v in pairs(state) do
|
||||||
if arg == v then arg = k end
|
if arg == v then arg = k end
|
||||||
end
|
end
|
||||||
local key, val = base.next(state, arg)
|
local key, val = next(state, arg)
|
||||||
if not key then return end
|
if not key then return end
|
||||||
|
|
||||||
if base.type(pred) == "function" then
|
if type(pred) == "function" then
|
||||||
while not pred(val) do
|
while not pred(val) do
|
||||||
key, val = base.next(state, key)
|
key, val = next(state, key)
|
||||||
if not key then return end
|
if not key then return end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -281,7 +276,7 @@ end
|
|||||||
-- @return nick
|
-- @return nick
|
||||||
-- @return username (if it exists)
|
-- @return username (if it exists)
|
||||||
-- @return hostname (if it exists)
|
-- @return hostname (if it exists)
|
||||||
function _parse_user(user)
|
function misc._parse_user(user)
|
||||||
local found, bang, nick = user:find("^([^!]*)!")
|
local found, bang, nick = user:find("^([^!]*)!")
|
||||||
if found then
|
if found then
|
||||||
user = user:sub(bang + 1)
|
user = user:sub(bang + 1)
|
||||||
@ -301,3 +296,5 @@ function _parse_user(user)
|
|||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
return misc
|
||||||
|
@ -225,4 +225,4 @@ local function on_dcc_send()
|
|||||||
end
|
end
|
||||||
irc.register_callback("dcc_send", on_dcc_send)
|
irc.register_callback("dcc_send", on_dcc_send)
|
||||||
|
|
||||||
irc.connect{network = "irc.freenode.net", nick = "doylua"}
|
irc.connect{network = "irc.libera.chat", nick = "doylua"}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user