@ -251,16 +251,31 @@ function itte.get_commands(svr)
resp = " QUIT : " ,
} ,
target_private = {
-- Like privmsg but targets bot nick in a direct message without a
-- service code.
-- Escape magic character "-"
check = " PRIVMSG(.*) " .. string.gsub ( svr.nick , " - " , " %%- " ) .. " (.*): " ,
resp = nil ,
} ,
target_private_code = {
-- Like privmsg but targets bot nick in a direct message
-- Escape magic character "-"
check = " PRIVMSG(.*) " .. string.gsub ( svr.nick , " - " , " %%- " ) .. " : " ,
resp = " PRIVMSG " ,
check = " PRIVMSG(.*) " .. string.gsub ( svr.nick , " - " , " %%- " ) .. " (.*): " ..
string.gsub ( svr.nick , " - " , " %%- " ) .. " (.*) " .. svr.code_prefix ,
resp = nil ,
} ,
target_public = {
-- Like privmsg but targets bot nick in a channel
-- Like privmsg but targets bot nick in a channel without a service code.
-- Escape magic character "-"
check = " PRIVMSG(.*)#(.*): " .. string.gsub ( svr.nick , " - " , " %%- " ) ,
resp = " PRIVMSG " ,
resp = nil ,
} ,
target_public_code = {
-- Like privmsg but targets bot nick in a channel
-- Escape magic character "-"
check = " PRIVMSG(.*)#(.*): " .. string.gsub ( svr.nick , " - " , " %%- " ) ..
" (.*) " .. svr.code_prefix ,
resp = nil ,
} ,
user = {
check = " NOTICE " ,
@ -610,18 +625,16 @@ function itte.parse_privmsg(cxt, str, mode)
-- Separator marks the start of the message body
body_sep , _ = string.find ( str , " : " , 2 )
-- Message in the format `[nick]: [body]`
-- Message in the format `[body]` (private message) or `[ nick]: [body]`
if mode == " target " then
msg = {
sender = string.sub ( str , string.find ( str , " ! " ) + 2 ,
string.find ( str , " @ " ) - 1 ) ,
-- Escape magic character "-" in the nick
recipient = string.sub ( str , string.find ( str , " PRIVMSG " ) + 8 ,
string.find ( str , " : " .. string.gsub ( cxt.nick , " - " , " %%- " ) ) - 2 ) ,
string.find ( str , " :" ) - 1 ) ,
reply_to = string.sub ( str , string.find ( str , " ! " ) + 2 ,
string.find ( str , " @ " ) - 1 ) ,
body = string.gsub ( string.sub ( str , body_sep + 2 +
string.len ( cxt.nick ) ) , " ^%s " , " " ) ,
body = string.sub ( str , body_sep + 1 ) ,
}
-- Reply to sender by default (private message), or reply in a channel if
-- original message recipient is a channel.
@ -635,19 +648,31 @@ function itte.parse_privmsg(cxt, str, mode)
" , " .. itte.config . debugs.privmsg [ 7 ] .. " : " .. msg.body ..
" } " , itte.config . debug )
-- Message in the format `[code] [params]`
-- Message in the format `[code] [params]` or `[nick] [code] [params]`
else
-- Set the code prefix position variable to a number out of range of the
-- service code parsing buffer, then get the position. Check for the colon
-- separator at exactly the start of the message body, i.e. `[code]`, or
-- the space char for `[nick] [code]`.
local code_full = " "
-- Service code found with specified prefix
if util.is_substr ( str , " : " .. cxt.code_prefix ) then
code_full = string.sub ( str , string.find ( str , " : " ..
cxt.code_prefix ) + 1 + string.len ( cxt.code_prefix ) )
local cp_pos = body_sep + string.len ( cxt.nick ) + 4
local co_sep , _ = string.find ( str , " : " .. cxt.code_prefix )
if co_sep == body_sep then
cp_pos = string.find ( str , " : " .. cxt.code_prefix )
elseif string.find ( str , " " .. cxt.code_prefix ) ~= nil then
cp_pos = string.find ( str , " " .. cxt.code_prefix )
end
-- Only parse service code if it is near the start of the message body,
-- within a small buffer in position to allow some variation in style, e.g.
-- `[nick]: [code]`, `[nick] [code]`, etc.
if cp_pos <= body_sep + string.len ( cxt.nick ) + 3 then
code_full = string.sub ( str , cp_pos + 1 + string.len ( cxt.code_prefix ) )
end
msg = {
sender = string.sub ( str , string.find ( str , " ! " ) + 2 ,
string.find ( str , " @ " ) - 1 ) ,
recipient = string.sub ( str , string.find ( str , " PRIVMSG " ) + 8 ,
string.find ( str , " : " .. cxt.code_prefix ) - 2 ) ,
string.find ( str , " :" ) - 1 ) ,
reply_to = string.sub ( str , string.find ( str , " ! " ) + 2 ,
string.find ( str , " @ " ) - 1 ) ,
body = string.sub ( str , body_sep + 1 ) ,
@ -656,7 +681,6 @@ function itte.parse_privmsg(cxt, str, mode)
msg.code = string.sub ( code_full , 0 , string.find ( code_full , " " ) - 1 )
msg.code_params = util.split_str ( string.sub ( code_full ,
string.find ( code_full , " " ) + 1 ) )
else
msg.code = code_full
msg.code_params = { }
@ -666,7 +690,6 @@ function itte.parse_privmsg(cxt, str, mode)
if util.is_substr ( msg.recipient , " # " ) then
msg.reply_to = msg.recipient
end
-- Redact debug output for admin-only handlers to avoid logging passwords.
local body = msg.body
local code_params = table.concat ( msg.code_params , " " )
@ -937,8 +960,12 @@ function itte.listen(name, str)
local channel , names = itte.parse_names ( cxt , str )
cxt.chan_meta [ channel : sub ( 2 ) ] = { users = names }
-- Respond to service code
elseif util.is_substr ( str , cxt.cmds . privmsg.check ) then
-- Respond to service code, checking for `[code]` and `[nick]: [code]`.
-- Code prefix cannot be the last character in the data string.
elseif ( util.is_substr ( str , cxt.cmds . privmsg.check ) or
( util.is_substr ( str , cxt.cmds . target_public_code.check ) ) or
( util.is_substr ( str , cxt.cmds . target_private_code.check ) ) ) and
( str : sub ( string.len ( str ) ) ~= cxt.code_prefix ) then
local msg = itte.parse_privmsg ( cxt , str )
-- Check for the service in the admin handlers table and redact the debug
-- output for admin handlers.
@ -960,6 +987,12 @@ function itte.listen(name, str)
-- Check the handlers table
elseif util.has_key ( itte.handlers , msg.code ) then
itte.handlers [ msg.code ] ( cxt , msg )
-- If there is no service code found near the start of the message body,
-- respond as a direct address and pass the message to the target handler
-- if it exists.
elseif ( util.has_key ( itte.handlers , itte.config . target_handler ) ) and
( msg.code == " " ) then
itte.handlers [ itte.config . target_handler ] ( cxt , msg )
else
-- Only hint with unknown code error in private messages as there may be
-- prefix collision in channels.