~ecs/awkbot

awk IRC bot
_sql: fix utf8 support
parsetime(): return times in UTC
Simplify handle() by only calling __onmsg__

refs

master
browse  log 

clone

read-only
https://git.d2evs.net/~ecs/awkbot
read/write
git@git.d2evs.net:~ecs/awkbot

You can also use your local clone with git send-email.

#awkbot

#Bootstrapping

Since awkbot's interface is written in awk, you'll need to bootstrap it by manually adding something along these lines to the snippet database:

fn_add: function add(name, cmd, args) { eval_excl(cmd, name); args[1] = name; args[2] = cmd; sql("INSERT INTO snippets (name, cmd) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET cmd = $2", args) }
fn_cron: function cron(time, zone, period, cmd, id) { id = get("cron.id"); set("cron.id", id + 1); set("cron." id, "{ id = " id "; at(\"" period "\", \"" zone "\", \"{ print eval(get(\\\"cron." id "\\\")) }\"); set(\"cron." nick() "\", id); " cmd " }"); return at(time, zone, "{ print eval(get(\"cron." id "\")) }") }
fn_del: function del(key, args) { args[1] = key; sql("DELETE FROM storage WHERE key = $1", args) }
fn_escape: function escape(s) { gsub(/\\/, "\\\\", s); gsub(/"/, "\\\"", s); return s }
fn_eval: function eval(c, r, i) { r = sql("SELECT cmd FROM snippets WHERE name ~ '^fn_' ORDER BY NAME"); for (i = 1; i <= r; i++) { c = c "\n" query[i, "cmd"] }; return _eval(c) }
fn_eval_excl: function eval_excl(c, name, args, r, i) { args[1] = name; r = sql("SELECT cmd FROM snippets WHERE name ~ '^fn_' AND name != $1 ORDER BY NAME", args); for (i = 1; i <= r; i++) { c = c "\n" query[i, "cmd"] }; return _eval(c) }
fn_get: function get(key, args) { args[0] = key; sql("SELECT value FROM storage WHERE key = $1", args); return query[1, "value"] }
fn_rmatch: function rmatch(s, ere, idx) { idx = 0; RLENGTH = 0; while (RLENGTH != -1) idx += match(substr(s, idx), ere); return idx }
fn_sched_reminder: function sched_reminder(time, who, msg) { msg = "\"" escape(msg) "\""; return "reminding you at " at(time, get("tz." who), "{ print " msg "; set(\"prev." who "\", " msg ") }") }
fn_set: function set(key, value, args) { args[1] = key; args[2] = value; sql("INSERT INTO storage (key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = $2", args) }
fn_sql: function sql(q, args, _args, i, j, res, res2, r) { _args = sql_escape(args); split("", query); r = split(_sql(q, _args), res, /b/); split(res[1], cols, /a/); for (i in cols) { cols[i] = sql_unescape(cols[i]) }; for (i in res) { split(res[i], res2, /a/); for (j in res2) { query[i - 1, cols[j]] = sql_unescape(res2[j])}}; return r - 2}
fn_sql_escape: function sql_escape(args, _args, arg, i) { for (i in args) { arg = args[i]; gsub(/\\/, "\\\\", arg); gsub(/a/, "\\A", arg); gsub(/b/, "\\B", arg); _args = _args arg "a" }; sub(/a$/, "", _args); return _args }
fn_sql_unescape: function sql_unescape(s, i, r) { for (i = 1; i <= length(s); i++) { if (substr(s, i, 1) == "\\") { i++; si = substr(s, i, 1); if (si == "\\") { r = r "\\" } else if (si == "A") { r = r "a" } else if (si == "B") { r = r "b" } else { r = r "\\" si } } else r = r substr(s, i, 1) }; return r }
add: /^\.add / { sub(/^\.add /, ""); idx = index($0, " "); if (idx == 0) { print "usage: .add <name> <awk script>"; exit }; name = substr($0, 1, idx - 1); cmd = substr($0, idx + 1); f = substr(name, 1, 1); if (f == "/" || f == "{") { print "script name must not start wth / or {"; exit }; add(name, cmd); print "success" }
rm: /\.rm / { if (argc() != 2) { print "usage: .rm <name>"; exit }; args[1] = argv(1); sql("DELETE FROM snippets WHERE name = $1", args); print "success" }
ls: /^\.ls/ { if (argc() > 2) { print "usage: .ls [<regex>]"; exit }; if (argc() == 1) r = sql("SELECT name, cmd FROM snippets ORDER BY name"); else { args[1] = argv(1); r = sql("SELECT name, cmd FROM snippets WHERE name ~ $1 ORDER BY name", args) }; for (i = 1; i <= r; i++ ) print query[i, "name"] ": " query[i, "cmd"] }

If you have any trouble setting up awkbot, feel free to reach out to me at ecs@d2evs.net or ecs on most IRC networks.