diff options
Diffstat (limited to 'src/irc')
-rw-r--r-- | src/irc/channel.lua | 80 | ||||
-rw-r--r-- | src/irc/constants.lua | 10 | ||||
-rw-r--r-- | src/irc/ctcp.lua | 20 | ||||
-rw-r--r-- | src/irc/dcc.lua | 42 | ||||
-rw-r--r-- | src/irc/debug.lua | 32 | ||||
-rw-r--r-- | src/irc/message.lua | 23 | ||||
-rw-r--r-- | src/irc/misc.lua | 69 |
7 files changed, 134 insertions, 142 deletions
diff --git a/src/irc/channel.lua b/src/irc/channel.lua index 82bca71..64011a6 100644 --- a/src/irc/channel.lua +++ b/src/irc/channel.lua @@ -2,17 +2,15 @@ -- Implementation of the Channel class -- initialization {{{ -local base = _G -local irc = require 'irc' -local misc = require 'irc.misc' -local socket = require 'socket' -local table = require 'table' +local irc = libs.irc +local misc = libs.misc +local socket = libs.socket -- }}} --- -- This module implements a channel object representing a single channel we -- have joined. -module 'irc.channel' +local channel = {} -- object metatable {{{ -- TODO: this <br /> shouldn't be necessary - bug in luadoc @@ -37,7 +35,7 @@ local mt = { elseif key == "chanmode" then return self._chanmode else - return _M[key] + return channel[key] end end, -- }}} @@ -50,7 +48,7 @@ local mt = { elseif key == "chanmode" then return else - base.rawset(self, key, value) + rawset(self, key, value) end end, -- }}} @@ -58,12 +56,12 @@ local mt = { __concat = function(first, second) local first_str, second_str - if base.type(first) == "table" then + if type(first) == "table" then first_str = first._name else first_str = first end - if base.type(second) == "table" then + if type(second) == "table" then second_str = second._name else second_str = second @@ -88,7 +86,7 @@ local mt = { -- @param self Channel object -- @param set True to set the mode, false to unset it -- @param letter Letter of the mode -local function set_basic_mode(self, set, letter) +local function set_basic_mode(set, letter) if set then irc.send("MODE", self.name, "+" .. letter) else @@ -107,7 +105,7 @@ end -- @param self Channel object -- @param user Nick of the user to add -- @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 '' self._members[user] = mode .. user end @@ -118,7 +116,7 @@ end -- Remove a user from the channel's internal user list. -- @param self Channel object -- @param user Nick of the user to remove -function _remove_user(self, user) +function channel:_remove_user(user) self._members[user] = nil end -- }}} @@ -130,7 +128,7 @@ end -- @param user Nick of the user to affect -- @param on True if the mode is being set, false if it's being unset -- @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 mode == 'o' then self._members[user] = '@' .. user @@ -152,7 +150,7 @@ end -- @param self Channel object -- @param old_nick User's old 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 local member_nick = member:gsub('@+', '') if member_nick == old_nick then @@ -172,8 +170,8 @@ end -- Creates a new Channel object. -- @param chan Name of the new channel -- @return The new channel instance -function new(chan) - return base.setmetatable({_name = chan, _topic = {}, _chanmode = "", +function channel.new(chan) + return setmetatable({_name = chan, _topic = {}, _chanmode = "", _members = {}}, mt) end -- }}} @@ -184,7 +182,7 @@ end --- -- Iterator over the ops in the channel -- @param self Channel object -function each_op(self) +function channel:each_op() return function(state, arg) return misc._value_iter(state, arg, function(v) @@ -200,7 +198,7 @@ end --- -- Iterator over the voiced users in the channel -- @param self Channel object -function each_voice(self) +function channel:each_voice() return function(state, arg) return misc._value_iter(state, arg, function(v) @@ -216,7 +214,7 @@ end --- -- Iterator over the normal users in the channel -- @param self Channel object -function each_user(self) +function channel:each_user() return function(state, arg) return misc._value_iter(state, arg, function(v) @@ -233,7 +231,7 @@ end --- -- Iterator over all users in the channel -- @param self Channel object -function each_member(self) +function channel:each_member() return misc._value_iter, self._members, nil end -- }}} @@ -245,7 +243,7 @@ end -- Gets an array of all the ops in the channel. -- @param self Channel object -- @return Array of channel ops -function ops(self) +function channel:ops() local ret = {} for nick in self:each_op() do table.insert(ret, nick) @@ -259,7 +257,7 @@ end -- Gets an array of all the voiced users in the channel. -- @param self Channel object -- @return Array of channel voiced users -function voices(self) +function channel:voices() local ret = {} for nick in self:each_voice() do table.insert(ret, nick) @@ -273,7 +271,7 @@ end -- Gets an array of all the normal users in the channel. -- @param self Channel object -- @return Array of channel normal users -function users(self) +function channel:users() local ret = {} for nick in self:each_user() do table.insert(ret, nick) @@ -287,7 +285,7 @@ end -- Gets an array of all the users in the channel. -- @param self Channel object -- @return Array of channel users -function members(self) +function channel:members() local ret = {} -- not just returning self._members, since the return value shouldn't be -- modifiable @@ -306,7 +304,7 @@ end -- Ban a user from a channel. -- @param self Channel object -- @param name User to ban -function ban(self, name) +function channel:ban(name) irc.send("MODE", self.name, "+b", name) end -- }}} @@ -317,7 +315,7 @@ end -- Remove a ban on a user. -- @param self Channel object -- @param name User to unban -function unban(self, name) +function channel:unban(name) irc.send("MODE", self.name, "-b", name) end -- }}} @@ -327,7 +325,7 @@ end -- Give a user voice on a channel. -- @param self Channel object -- @param name User to give voice to -function voice(self, name) +function channel:voice(name) irc.send("MODE", self.name, "+v", name) end -- }}} @@ -337,7 +335,7 @@ end -- Remove voice from a user. -- @param self Channel object -- @param name User to remove voice from -function devoice(self, name) +function channel:devoice(name) irc.send("MODE", self.name, "-v", name) end -- }}} @@ -347,7 +345,7 @@ end -- Give a user ops on a channel. -- @param self Channel object -- @param name User to op -function op(self, name) +function channel:op(name) irc.send("MODE", self.name, "+o", name) end -- }}} @@ -357,7 +355,7 @@ end -- Remove ops from a user. -- @param self Channel object -- @param name User to remove ops from -function deop(self, name) +function channel:deop(name) irc.send("MODE", self.name, "-o", name) end -- }}} @@ -368,7 +366,7 @@ end -- @param self Channel object -- @param new_limit New value for the channel limit (optional; limit is unset -- if this argument isn't passed) -function set_limit(self, new_limit) +function channel:set_limit(new_limit) if new_limit then irc.send("MODE", self.name, "+l", new_limit) else @@ -383,7 +381,7 @@ end -- @param self Channel object -- @param key New channel password (optional; password is unset if this -- argument isn't passed) -function set_key(self, key) +function channel:set_key(key) if key then irc.send("MODE", self.name, "+k", key) else @@ -397,7 +395,7 @@ end -- Set the private state of a channel. -- @param self Channel object -- @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") end -- }}} @@ -407,7 +405,7 @@ end -- Set the secret state of a channel. -- @param self Channel object -- @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") end -- }}} @@ -417,7 +415,7 @@ end -- Set whether joining the channel requires an invite. -- @param self Channel object -- @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") end -- }}} @@ -427,7 +425,7 @@ end -- If true, the topic can only be changed by an op. -- @param self Channel object -- @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") end -- }}} @@ -438,7 +436,7 @@ end -- @param self Channel object -- @param set True to require users to be in the channel to send messages to -- 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") end -- }}} @@ -448,7 +446,7 @@ end -- Set whether voice is required to speak. -- @param self Channel object -- @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") end -- }}} @@ -461,7 +459,7 @@ end -- @param self Channel object -- @param nick Nick to search for -- @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 local member_nick = member:gsub('@+', '') if member_nick == nick then @@ -473,3 +471,5 @@ end -- }}} -- }}} -- }}} + +return channel diff --git a/src/irc/constants.lua b/src/irc/constants.lua index b26cecb..dfee506 100644 --- a/src/irc/constants.lua +++ b/src/irc/constants.lua @@ -1,13 +1,13 @@ --- -- This module holds various constants used by the IRC protocol. -module "irc.constants" +local constants = {} -- protocol constants {{{ -IRC_MAX_MSG = 512 +constants.IRC_MAX_MSG = 512 -- }}} -- server replies {{{ -replies = { +constants.replies = { -- Command responses {{{ [001] = "RPL_WELCOME", [002] = "RPL_YOURHOST", @@ -183,9 +183,11 @@ replies = { -- }}} -- chanmodes {{{ -chanmodes = { +constants.chanmodes = { ["@"] = "secret", ["*"] = "private", ["="] = "public" } -- }}} + +return constants diff --git a/src/irc/ctcp.lua b/src/irc/ctcp.lua index c77cae8..c229064 100644 --- a/src/irc/ctcp.lua +++ b/src/irc/ctcp.lua @@ -1,14 +1,10 @@ --- -- Implementation of the CTCP protocol --- initialization {{{ -local base = _G -local table = require "table" --- }}} --- -- This module implements the various quoting and escaping requirements of the -- CTCP protocol. -module "irc.ctcp" +local ctcp = {} -- internal functions {{{ -- _low_quote {{{ @@ -17,7 +13,7 @@ module "irc.ctcp" -- to appear in an IRC packet). -- @param ... Strings to quote together, space separated -- @return Quoted string -function _low_quote(...) +function ctcp._low_quote(...) local str = table.concat({...}, " ") return str:gsub("[%z\n\r\020]", {["\000"] = "\0200", ["\n"] = "\020n", @@ -31,7 +27,7 @@ end -- Removes low level quoting done by low_quote. -- @param str String with low level quoting applied to it -- @return String with those quoting methods stripped off -function _low_dequote(str) +function ctcp._low_dequote(str) return str:gsub("\020(.?)", function(s) if s == "0" then return "\000" end if s == "n" then return "\n" end @@ -48,7 +44,7 @@ end -- data (by the calling program). -- @param ... Strings to apply CTCP quoting to together, space separated -- @return String with CTCP quoting applied -function _ctcp_quote(...) +function ctcp._ctcp_quote(...) local str = table.concat({...}, " ") local ret = str:gsub("[\001\\]", {["\001"] = "\\a", ["\\"] = "\\\\"}) @@ -62,7 +58,7 @@ end -- data (likely by ctcp_split). -- @param str String with CTCP quoting -- @return String with all CTCP quoting stripped -function _ctcp_dequote(str) +function ctcp._ctcp_dequote(str) local ret = str:gsub("^\001", ""):gsub("\001$", "") return ret:gsub("\\(.?)", function(s) 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 -- otherwise</li> -- </ul> -function _ctcp_split(str) +function ctcp._ctcp_split(str) local ret = {} local iter = 1 while true do @@ -103,7 +99,7 @@ function _ctcp_split(str) end if not s then break end 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 iter = e + 1 @@ -113,3 +109,5 @@ function _ctcp_split(str) end -- }}} -- }}} + +return ctcp diff --git a/src/irc/dcc.lua b/src/irc/dcc.lua index 6e8537e..6d9b347 100644 --- a/src/irc/dcc.lua +++ b/src/irc/dcc.lua @@ -1,26 +1,22 @@ --- -- Implementation of the DCC protocol -- initialization {{{ -local base = _G -local irc = require 'irc' -local ctcp = require 'irc.ctcp' +local irc = libs.irc +local ctcp = libs.ctcp local c = ctcp._ctcp_quote -local irc_debug = require 'irc.debug' -local misc = require 'irc.misc' -local socket = require 'socket' -local coroutine = require 'coroutine' -local io = require 'io' -local string = require 'string' +local irc_debug = libs.debug +local misc = libs.misc +local socket = libs.socket -- }}} --- -- This module implements the DCC protocol. File transfers (DCC SEND) are -- handled, but DCC CHAT is not, as of yet. -module 'irc.dcc' +local dcc = {} -- defaults {{{ -FIRST_PORT = 1028 -LAST_PORT = 5000 +dcc.FIRST_PORT = 1028 +dcc.LAST_PORT = 5000 -- }}} -- private functions {{{ @@ -138,13 +134,13 @@ end -- @param address IP address of the remote user in low level int form -- @param port Port to connect to at the remote user -- @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) packet_size = packet_size or 1024 - local sock = base.assert(socket.tcp()) - base.assert(sock:connect(address, port)) + local sock = assert(socket.tcp()) + assert(sock:connect(address, port)) 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', coroutine.wrap(function(s) return accept_file(s, file, packet_size) @@ -162,17 +158,17 @@ end -- @param port Port to accept connections on (optional, defaults to -- choosing an available port between FIRST_PORT and LAST_PORT -- above) -function send(nick, filename, port) - port = port or FIRST_PORT +function dcc.send(nick, filename, port) + port = port or dcc.FIRST_PORT local sock repeat - sock = base.assert(socket.tcp()) + sock = assert(socket.tcp()) err, msg = sock:bind('*', port) 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 - base.assert(err, msg) - base.assert(sock:listen(1)) + assert(err, msg) + assert(sock:listen(1)) local ip = misc._ip_str_to_int(irc.get_ip()) local file, err = io.open(filename) if not file then @@ -194,3 +190,5 @@ function send(nick, filename, port) end -- }}} -- }}} + +return dcc diff --git a/src/irc/debug.lua b/src/irc/debug.lua index 414b49d..5bfbee6 100644 --- a/src/irc/debug.lua +++ b/src/irc/debug.lua @@ -1,17 +1,13 @@ --- -- Basic debug output --- initialization {{{ -local base = _G -local io = require 'io' --- }}} --- -- This module implements a few useful debug functions for use throughout the -- rest of the code. -module 'irc.debug' +local irc_debug = {} -- defaults {{{ -COLOR = true +irc_debug.COLOR = true -- }}} -- local variables {{{ @@ -27,10 +23,10 @@ local outfile = io.output() -- @param msg Message text -- @param color Which terminal code to use for color output (defaults to -- dark gray) -function _message(msg_type, msg, color) +function irc_debug._message(msg_type, msg, color) if ON then local endcolor = "" - if COLOR and outfile == io.stdout then + if irc_debug.COLOR and outfile == io.stdout then color = color or "\027[1;30m" endcolor = "\027[0m" else @@ -48,9 +44,9 @@ end -- error(). -- @param msg Error message -- @see error -function _err(msg) - _message("ERR", msg, "\027[0;31m") - base.error(msg, 2) +function irc_debug._err(msg) + irc_debug._message("ERR", msg, "\027[0;31m") + error(msg, 2) end -- }}} @@ -58,8 +54,8 @@ end -- -- Signal a warning. Writes the warning message to the screen in yellow. -- @param msg Warning message -function _warn(msg) - _message("WARN", msg, "\027[0;33m") +function irc_debug._warn(msg) + irc_debug._message("WARN", msg, "\027[0;33m") end -- }}} -- }}} @@ -68,7 +64,7 @@ end -- enable {{{ --- -- Turns on debug output. -function enable() +function irc_debug.enable() ON = true end -- }}} @@ -76,7 +72,7 @@ end -- disable {{{ --- -- Turns off debug output. -function disable() +function irc_debug.disable() ON = false end -- }}} @@ -85,8 +81,10 @@ end --- -- Redirects output to a file rather than stdout. -- @param file File to write debug output to -function set_output(file) - outfile = base.assert(io.open(file)) +function irc_debug.set_output(file) + outfile = assert(io.open(file)) end -- }}} -- }}} + +return irc_debug diff --git a/src/irc/message.lua b/src/irc/message.lua index e05e87e..4471ba8 100644 --- a/src/irc/message.lua +++ b/src/irc/message.lua @@ -1,19 +1,16 @@ --- -- Implementation of IRC server message parsing -- initialization {{{ -local base = _G -local constants = require 'irc.constants' -local ctcp = require 'irc.ctcp' -local irc_debug = require 'irc.debug' -local misc = require 'irc.misc' -local socket = require 'socket' -local string = require 'string' -local table = require 'table' +local constants = libs.constants +local ctcp = libs.ctcp +local irc_debug = libs.debug +local misc = libs.misc +local socket = libs.socket -- }}} --- -- This module contains parsing functions for IRC server messages. -module 'irc.message' +local message = {} -- internal functions {{{ -- _parse {{{ @@ -32,7 +29,7 @@ module 'irc.message' -- to the received command</li> -- -- </ul> -function _parse(str) +function message._parse(str) -- low-level ctcp quoting {{{ str = ctcp._low_dequote(str) -- }}} @@ -49,8 +46,8 @@ function _parse(str) local reply = false if command:find("^%d%d%d$") then reply = true - if constants.replies[base.tonumber(command)] then - command = constants.replies[base.tonumber(command)] + if constants.replies[tonumber(command)] then + command = constants.replies[tonumber(command)] else irc_debug._warn("Unknown server reply: " .. command) end @@ -67,3 +64,5 @@ function _parse(str) end -- }}} -- }}} + +return message diff --git a/src/irc/misc.lua b/src/irc/misc.lua index 92c3ac4..d708391 100644 --- a/src/irc/misc.lua +++ b/src/irc/misc.lua @@ -1,25 +1,20 @@ --- -- Various useful functions that didn't fit anywhere else -- initialization {{{ -local base = _G -local irc_debug = require 'irc.debug' -local socket = require 'socket' -local math = require 'math' -local os = require 'os' -local string = require 'string' -local table = require 'table' +local irc_debug = libs.debug +local socket = libs.socket -- }}} --- -- This module contains various useful functions which didn't fit in any of the -- other modules. -module 'irc.misc' +local misc = {} -- defaults {{{ -DELIM = ' ' -PATH_SEP = '/' -ENDIANNESS = "big" -INT_BYTES = 4 +misc.DELIM = ' ' +misc.PATH_SEP = '/' +misc.ENDIANNESS = "big" +misc.INT_BYTES = 4 -- }}} -- private functions {{{ @@ -49,9 +44,9 @@ end -- in str will be considered one substring) -- @param rquotes String of characters to use as closing quotes -- @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 {{{ - delim = "["..(delim or DELIM).."]" + delim = "["..(delim or misc.DELIM).."]" if end_delim then end_delim = "["..end_delim.."]" end if lquotes then lquotes = "["..lquotes.."]" end if rquotes then rquotes = "["..rquotes.."]" end @@ -111,8 +106,8 @@ end -- @param path Path to the file -- @param sep Directory separator (optional, defaults to PATH_SEP) -- @return The basename of the file -function _basename(path, sep) - sep = sep or PATH_SEP +function misc._basename(path, sep) + sep = sep or misc.PATH_SEP if not path:find(sep) then return path end return socket.skip(2, path:find(".*" .. sep .. "(.*)")) end @@ -124,8 +119,8 @@ end -- @param path Path to the file -- @param sep Directory separator (optional, defaults to PATH_SEP) -- @return The dirname of the file -function _dirname(path, sep) - sep = sep or PATH_SEP +function misc._dirname(path, sep) + sep = sep or misc.PATH_SEP if not path:find(sep) then return "." end return socket.skip(2, path:find("(.*)" .. sep .. ".*")) end @@ -139,9 +134,9 @@ end -- @param endian Which endianness to use (big, little, host, network) (defaultsi -- to ENDIANNESS) -- @return A string whose first INT_BYTES characters make a low-level int -function _str_to_int(str, bytes, endian) - bytes = bytes or INT_BYTES - endian = endian or ENDIANNESS +function misc._str_to_int(str, bytes, endian) + bytes = bytes or misc.INT_BYTES + endian = endian or misc.ENDIANNESS local ret = "" for i = 0, bytes - 1 do 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 endian Endianness of the int argument (defaults to ENDIANNESS) -- @return String representation of the low-level int argument -function _int_to_str(int, endian) - endian = endian or ENDIANNESS +function misc._int_to_str(int, endian) + endian = endian or misc.ENDIANNESS local ret = 0 for i = 1, int:len() do 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. -- @param ip_str String representation of an 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 ret = 0 for num in ip_str:gmatch("%d+") do @@ -195,7 +190,7 @@ end -- Converts an int to a string IP address. -- @param ip_int Low-level int representation of an 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 = {} for i = 3, 0, -1 do local new_num = math.floor(ip_int / 2^(i * 8)) @@ -212,7 +207,7 @@ end -- @param filename Filename to start with -- @return Filename (same as the one we started with, except possibly with some -- 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 local count = 1 @@ -231,8 +226,8 @@ end -- @param fn Function to try to call -- @param ... Arguments to fn -- @return The return values of fn, if it was successfully called -function _try_call(fn, ...) - if base.type(fn) == "function" then +function misc._try_call(fn, ...) + if type(fn) == "function" then return fn(...) end end @@ -245,8 +240,8 @@ end -- @param fn Function to try to call -- @param ... Arguments to fn -- @return The return values of fn, if it was successfully called -function _try_call_warn(msg, fn, ...) - if base.type(fn) == "function" then +function misc._try_call_warn(msg, fn, ...) + if type(fn) == "function" then return fn(...) else irc_debug._warn(msg) @@ -257,16 +252,16 @@ end -- _value_iter {{{ -- -- Iterator to iterate over just the values of a table. -function _value_iter(state, arg, pred) - for k, v in base.pairs(state) do +function misc._value_iter(state, arg, pred) + for k, v in pairs(state) do if arg == v then arg = k end end - local key, val = base.next(state, arg) + local key, val = next(state, arg) if not key then return end - if base.type(pred) == "function" then + if type(pred) == "function" then while not pred(val) do - key, val = base.next(state, key) + key, val = next(state, key) if not key then return end end end @@ -281,7 +276,7 @@ end -- @return nick -- @return username (if it exists) -- @return hostname (if it exists) -function _parse_user(user) +function misc._parse_user(user) local found, bang, nick = user:find("^([^!]*)!") if found then user = user:sub(bang + 1) @@ -301,3 +296,5 @@ function _parse_user(user) end -- }}} -- }}} + +return misc |