212 lines
7.0 KiB
Lua
212 lines
7.0 KiB
Lua
local hexchat = hexchat
|
|
hexchat.register("rot13", "3.0.1", "rot13")
|
|
|
|
local rot13 = {}
|
|
|
|
for i = string.byte('a'), string.byte('m') do
|
|
local a, b = string.char(i), string.char(i+13)
|
|
local A, B = a:upper(), b:upper()
|
|
rot13[a] = b
|
|
rot13[b] = a
|
|
rot13[A] = B
|
|
rot13[B] = A
|
|
end
|
|
|
|
local function do_rot13(arg, arg_eol)
|
|
if not arg[3] then
|
|
hexchat.print("Usage: /" .. arg[1] .. " <reason> <content>")
|
|
return hexchat.EAT_ALL
|
|
end
|
|
hexchat.command("say " .. arg[2] .. "\x01CW1 " .. arg_eol[3]:gsub("[A-Za-z]", rot13) .. "\x01")
|
|
return hexchat.EAT_ALL
|
|
end
|
|
|
|
hexchat.hook_command("cw-rot13", do_rot13)
|
|
|
|
local function startswith(str1, str2)
|
|
return str1:sub(1, #str2) == str2
|
|
end
|
|
|
|
local function parsecw(msg)
|
|
local hidden = {}
|
|
msg = msg:gsub("()(\1([^\1]*)\1)()", function(start, ctcp, contents, finish)
|
|
if startswith(contents, "CW1 ") then
|
|
local cw = contents:sub(5)
|
|
hidden[#hidden + 1] = cw:gsub("[A-Za-z]", rot13)
|
|
return " [Hidden Text " .. #hidden .. "] "
|
|
end
|
|
return ctcp
|
|
end)
|
|
return msg, hidden
|
|
end
|
|
|
|
local invert_notice = false
|
|
local last_notice = false
|
|
|
|
local tunpack = unpack or table.unpack
|
|
|
|
local skip = false
|
|
local function mkparse(event, pos)
|
|
return function(word, attributes)
|
|
if skip then return end
|
|
if event:find("Notice$") then
|
|
if invert_notice then
|
|
word[pos] = '\1'.. word[pos]
|
|
if last_notice then
|
|
word[pos] = word[pos] .. '\1'
|
|
end
|
|
end
|
|
end
|
|
invert_notice = false
|
|
local old_msg = word[pos]
|
|
local hidden
|
|
word[pos], hidden = parsecw(word[pos])
|
|
if word[pos] ~= old_msg then
|
|
skip = true
|
|
hexchat.emit_print_attrs(attributes, event, tunpack(word))
|
|
for i, v in ipairs(hidden) do
|
|
hexchat.print("\00326*\tHidden Text " .. i .. "\3 > \8"..v.."\8 < (Copy and paste to expand)")
|
|
end
|
|
skip = false
|
|
return hexchat.EAT_ALL
|
|
end
|
|
end
|
|
end
|
|
|
|
local function hookparse(event, pos)
|
|
return hexchat.hook_print_attrs(event, mkparse(event, pos))
|
|
end
|
|
|
|
do
|
|
(function(f,...)return f(f,...) end)(function(f, a, b, ...)
|
|
if a then
|
|
hookparse(a, b)
|
|
return f(f, ...)
|
|
end
|
|
end,
|
|
"Channel Message", 2,
|
|
"Channel Msg Hilight", 2,
|
|
"Channel Notice", 3,
|
|
"Private Message", 2,
|
|
"Private Message to Dialog", 2,
|
|
"Notice", 2,
|
|
"Your Message", 2,
|
|
"Notice Send", 2,
|
|
"Message Send", 2,
|
|
nil)
|
|
end
|
|
|
|
-- from here on: 3.0.1 bugfix
|
|
|
|
-- TODO maybe move these to a separate plugin. (or integrate them in hexchat)
|
|
|
|
local function tooct(n)
|
|
return string.format("%o", n)
|
|
end
|
|
|
|
local function on_privmsg(word, word_eol, attrs)
|
|
-- fix up some PRIVMSGs, pass them on to our handlers above
|
|
local i_at = 0
|
|
for i,v in ipairs(word) do
|
|
if v == "PRIVMSG" then
|
|
i_at = i + 2
|
|
break
|
|
end
|
|
end
|
|
if i_at == 0 then return end
|
|
if word_eol[i_at]:sub(1, 2):find(":[-+]") and tooct(hexchat.props["flags"]):find("[4-7].$") then -- bleh
|
|
word_eol[i_at] = ":" .. word_eol[i_at]:sub(3)
|
|
end
|
|
if word_eol[i_at]:sub(1, 6) == ":\1CW1 " then
|
|
if not word_eol[i_at]:find("\1", 7, true) == #word_eol[i_at] then
|
|
return hexchat.EAT_NONE -- let hexchat handle it normally
|
|
end
|
|
local target = word[i_at - 1]
|
|
local source
|
|
if word[1]:sub(1,1) ~= "@" then
|
|
source = word[1]
|
|
else
|
|
source = word[2]
|
|
end
|
|
source = source:match("^:([^!]+)!") -- this seems easy, right?
|
|
local context = hexchat.find_context(hexchat.get_info("server"), target)
|
|
if context then
|
|
local old_ctx = hexchat.get_context()
|
|
local serv_id = hexchat.props["id"]
|
|
-- sanity check
|
|
if hexchat.set_context(context) and hexchat.props["id"] == serv_id then
|
|
if hexchat.props["type"] == 2 then
|
|
local prefix = ""
|
|
for user in hexchat.iterate("users") do
|
|
if user.nick == source then
|
|
prefix = user.prefix
|
|
end
|
|
end
|
|
-- TODO fix highlights
|
|
hexchat.emit_print_attrs(attrs, "Channel Message", source, word_eol[i_at]:sub(2), prefix)
|
|
return hexchat.EAT_HEXCHAT
|
|
elseif hexchat.props["type"] == 3 then
|
|
hexchat.emit_print_attrs(attrs, "Private Message to Dialog", source, word_eol[i_at]:sub(2))
|
|
return hexchat.EAT_HEXCHAT
|
|
end
|
|
end
|
|
-- assume it's a query, because usually you only get channel messages if you're in the channel
|
|
if not hexchat.set_context(old_ctx) then return end -- how did we get this far without segfaulting?
|
|
end
|
|
if hexchat.prefs["gui_autoopen_dialog"] then
|
|
hexchat.command("query -nofocus " .. target)
|
|
local context = hexchat.find_context(hexchat.get_info("server"), target)
|
|
if context then
|
|
local old_ctx = hexchat.get_context()
|
|
local serv_id = hexchat.props["id"]
|
|
-- sanity check
|
|
if hexchat.set_context(context) and hexchat.props["id"] == serv_id then
|
|
-- meh, go hardmode on this (this shouldn't happen unless find_context returns the server context for some reason)
|
|
if hexchat.props["type"] ~= 3 then
|
|
local found = false
|
|
for chan in hexchat.iterate("channels") do
|
|
if chan.id == serv_id and chan.type == 3 and chan.channel == source then
|
|
found = true
|
|
hexchat.set_context(chan.context)
|
|
end
|
|
end
|
|
-- still not found? ragequit!
|
|
if not found then return hexchat.EAT_HEXCHAT end
|
|
end
|
|
hexchat.emit_print_attrs(attrs, "Private Message to Dialog", source, word_eol[i_at]:sub(2))
|
|
end
|
|
end
|
|
return hexchat.EAT_HEXCHAT
|
|
end
|
|
hexchat.emit_print_attrs(attrs, "Private Message", source, word_eol[i_at]:sub(2))
|
|
return hexchat.EAT_HEXCHAT
|
|
end
|
|
end
|
|
|
|
local function on_notice(word, word_eol, attrs) -- this one is much simpler
|
|
local i_at = 0
|
|
for i,v in ipairs(word) do
|
|
if v == "NOTICE" then
|
|
i_at = i + 2
|
|
break
|
|
end
|
|
end
|
|
if i_at == 0 then return end
|
|
if word_eol[i_at]:sub(1, 2):find(":[-+]") and tooct(hexchat.props["flags"]):find("[4-7].$") then -- bleh
|
|
word_eol[i_at] = ":" .. word_eol[i_at]:sub(3)
|
|
end
|
|
if word_eol[i_at]:sub(1, 6) == ":\1CW1 " then
|
|
-- workaround
|
|
invert_notice = true
|
|
last_notice = word_eol[i_at]:sub(-1,-1) == "\1"
|
|
-- then just let hexchat handle it
|
|
end
|
|
end
|
|
|
|
|
|
hexchat.hook_server_attrs("PRIVMSG", on_privmsg)
|
|
|
|
hexchat.hook_server_attrs("NOTICE", on_notice)
|
|
|
|
hexchat.print("rot13 loaded") -- this was in 3.0.0 too
|