-- -- censor.lua: black out certain users' messages -- -- Copyright (c) 2016 - 2021, Přemysl Eric Janouch
-- -- Permission to use, copy, modify, and/or distribute this software for any -- purpose with or without fee is hereby granted. -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- local to_pattern = function (mask) if not mask:match ("!") then mask = mask .. "!*" end if not mask:match ("@") then mask = mask .. "@*" end -- That is, * acts like a wildcard, otherwise everything is escaped return "^" .. mask:gsub ("[%^%$%(%)%%%.%[%]%+%-%?]", "%%%0") :gsub ("%*", ".*") .. "$" end local patterns = {} local read_masks = function (v) patterns = {} local add = function (who, where) local channels = patterns[who] or {} table.insert (channels, where) patterns[who] = channels end for item in v:lower ():gmatch ("[^,]+") do local who, where = item:match ("^([^/]+)/*(.*)") if who then add (to_pattern (who), where == "" or where) end end end local quote degesch.setup_config { masks = { type = "string_array", default = "\"\"", comment = "user masks (optionally \"/#channel\") to censor", on_change = read_masks }, quote = { type = "string", default = "\"\\x0301,01\"", comment = "formatting prefix for censored messages", on_change = function (v) quote = v end }, } local decolor = function (text) local rebuilt, last = {""}, 1 for start in text:gmatch ('()\x03') do table.insert (rebuilt, text:sub (last, start - 1)) local sub = text:sub (start + 1) last = start + (sub:match ('^%d%d?,%d%d?()') or sub:match ('^%d?%d?()')) end return table.concat (rebuilt) .. text:sub (last) end local censor = function (line) -- Taking a shortcut to avoid lengthy message reassembly local start, text = line:match ("^(.- PRIVMSG .- :)(.*)$") local ctcp, rest = text:match ("^(\x01%g+ )(.*)") text = ctcp and ctcp .. quote .. decolor (rest) or quote .. decolor (text) return start .. text end degesch.hook_irc (function (hook, server, line) local msg = degesch.parse (line) if msg.command ~= "PRIVMSG" then return line end local channel = msg.params[1]:lower () for who, where in pairs (patterns) do if msg.prefix:lower ():match (who) then for _, x in pairs (where) do if x == true or x == channel then return censor (line) end end end end return line end)