diff options
Diffstat (limited to 'plugins/zyklonb/seen')
-rwxr-xr-x | plugins/zyklonb/seen | 160 |
1 files changed, 0 insertions, 160 deletions
diff --git a/plugins/zyklonb/seen b/plugins/zyklonb/seen deleted file mode 100755 index 8fc9c82..0000000 --- a/plugins/zyklonb/seen +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env lua --- --- ZyklonB seen plugin --- --- Copyright 2016 Přemysl Eric Janouch <p@janouch.name> --- See the file LICENSE for licensing information. --- - -function parse (line) - local msg = { params = {} } - line = line:match ("[^\r]*") - for start, word in line:gmatch ("()([^ ]+)") do - local colon = word:match ("^:(.*)") - if start == 1 and colon then - msg.prefix = colon - elseif not msg.command then - msg.command = word - elseif colon then - table.insert (msg.params, line:sub (start + 1)) - break - elseif start ~= #line then - table.insert (msg.params, word) - end - end - return msg -end - -function get_config (name) - io.write ("ZYKLONB get_config :", name, "\r\n") - return parse (io.read ()).params[1] -end - --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -io.output ():setvbuf ('line') -local prefix = get_config ('prefix') -io.write ("ZYKLONB register\r\n") - -local db = {} -local db_filename = "seen.db" -local db_garbage = 0 - -function remember (who, where, when, what) - if not db[who] then db[who] = {} end - if db[who][where] then db_garbage = db_garbage + 1 end - db[who][where] = { tonumber (when), what } -end - --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -local db_file, e = io.open (db_filename, "a+") -if not db_file then error ("cannot open database: " .. e, 0) end - -function db_store (who, where, when, what) - db_file:write (string.format - (":%s %s %s %s :%s\n", who, "PRIVMSG", where, when, what)) -end - -function db_compact () - db_file:close () - - -- Unfortunately, default Lua doesn't have anything like mkstemp() - local db_tmpname = db_filename .. "." .. os.time () - db_file, e = io.open (db_tmpname, "a+") - if not db_file then error ("cannot save database: " .. e, 0) end - - for who, places in pairs (db) do - for where, data in pairs (places) do - db_store (who, where, data[1], data[2]) - end - end - db_file:flush () - - local ok, e = os.rename (db_tmpname, db_filename) - if not ok then error ("cannot save database: " .. e, 0) end - db_garbage = 0 -end - -for line in db_file:lines () do - local msg = parse (line) - remember (msg.prefix, table.unpack (msg.params)) -end - --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -function seen (who, where, args) - local respond = function (...) - local privmsg = function (target, ...) - io.write ("PRIVMSG ", target, " :", table.concat { ... }, "\r\n") - end - if where:match ("^[#&!+]") then - privmsg (where, who, ": ", ...) - else - privmsg (who, ...) - end - end - - local whom, e, garbage = args:match ("^(%S+)()%s*(.*)") - if not whom or #garbage ~= 0 then - return respond ("usage: <name>") - elseif who:lower () == whom:lower () then - return respond ("I can see you right now.") - end - - local top = {} - -- That is, * acts like a wildcard, otherwise everything is escaped - local pattern = "^" .. whom:gsub ("[%^%$%(%)%%%.%[%]%+%-%?]", "%%%0") - :gsub ("%*", ".*"):lower () .. "$" - for name, places in pairs (db) do - if places[where] and name:lower ():match (pattern) then - local when, what = table.unpack (places[where]) - table.insert (top, { name = name, when = when, what = what }) - end - end - if #top == 0 then - return respond ("I have not seen \x02" .. whom .. "\x02 here.") - end - - -- Get all matching nicknames ordered from the most recently active - -- and make the list case insensitive (remove older duplicates) - table.sort (top, function (a, b) return a.when > b.when end) - for i = #top, 2, -1 do - if top[i - 1].name:lower () == top[i].name:lower () then - table.remove (top, i) - end - end - - -- Hopefully the formatting mess will disrupt highlights in clients - for i = 1, math.min (#top, 3) do - local name = top[i].name:gsub ("^.", "%0\x02\x02") - respond (string.format ("\x02%s\x02 -> %s -> %s", - name, os.date ("%c", top[i].when), top[i].what)) - end -end - -function handle (msg) - local who = msg.prefix:match ("^[^!@]*") - local where, what = table.unpack (msg.params) - local when = os.time () - - local what_log = what:gsub ("^\x01ACTION", "*"):gsub ("\x01$", "") - remember (who, where, when, what_log) - db_store (who, where, when, what_log) - - -- Comment out to reduce both disk load and reliability - db_file:flush () - - if db_garbage > 5000 then db_compact () end - - if what:sub (1, #prefix) == prefix then - local command = what:sub (#prefix + 1) - local name, e = command:match ("^(%S+)%s*()") - if name == 'seen' then seen (who, where, command:sub (e)) end - end -end - -for line in io.lines () do - local msg = parse (line) - if msg.command == "PRIVMSG" then handle (msg) end -end |