From: Andy Spencer Date: Tue, 3 Nov 2015 05:52:43 +0000 (+0000) Subject: Add at daemon X-Git-Url: http://pileus.org/git/?p=~andy%2Frhawk;a=commitdiff_plain;h=8f635b1463fe6a559861fdccff705d09c2c577a8 Add at daemon --- diff --git a/json.awk b/json.awk index 6a8e96d..cfb8eac 100644 --- a/json.awk +++ b/json.awk @@ -305,6 +305,7 @@ function json_encode(var, pad) # File API function json_load(file, var, line, string) { + delete var while ((getline line < file) > 0) string = string line "\n" return json_decode(string, var) diff --git a/remind.awk b/remind.awk new file mode 100644 index 0000000..3be1d2f --- /dev/null +++ b/remind.awk @@ -0,0 +1,143 @@ +@include "json.awk" + +# Load saved at queue +BEGIN { + json_load("var/remind.json", remind); +} + +# Parse an at style time +function atp(now, time, cmd, iso, arr, month) { + # Remove quotes if needed + gsub(/["']/, "", time); + + # Normalize date + cmd = "atp " now " " time " 2>/dev/null"; + cmd | getline iso; + close(cmd); + + # Parse date + gsub(/^\w+ |:/, " ", iso); + if (!match(iso, /(\w+) +([0-9]+ [0-9]+ [0-9]+ [0-9]+) +([0-9]+)/, arr)) + return -1; + month = (index("JanFebMarAprMayJunJulAugSepOctNovDec", arr[1])-1)/3+1; + return mktime(arr[3] " " month " " arr[2]) +} + +# Queue a new job +function at(from, text, prefix, now, arr, desc, time, mesg, cmd) { + now = systime(); + + # Check input + if (!match(text, /^.(at|in) +([a-zA-Z0-9:+-]+|"[ a-zA-Z0-9:+-]+") +(.*)/, arr)) + return reply("invalid time"); + if (!arr[3]) + return reply("no message"); + desc = arr[2]; + mesg = arr[3]; + + # Parse date + time = atp(now, prefix desc); + if (time < 0) + return reply("unparsable time: " desc); + if (time < now) + return reply("time is in the past"); + if (time == now) + return reply("date is right now"); + + # Log message + id = length(remind); + remind[id]["time"] = time; + remind[id]["from"] = from; + remind[id]["mesg"] = mesg; + remind[id]["done"] = "pending"; + json_save("var/remind.json", remind); + + say("queued job " id ": " \ + strftime("%Y-%m-%d %H:%M", time)); +} + +# Print the at queue +function atq(all, i, from, time, done, desc, line) { + for (i = 0; i < length(remind); i++) { + from = remind[i]["from"]; + time = remind[i]["time"]; + done = remind[i]["done"]; + if (!all && done != "pending") + continue; + desc = strftime("%Y-%m-%d %H:%M", time); + line = sprintf("%-3d %s %s (%s)", i, desc, from, done); + say(line); + } +} + +# Print an at job +function atc(id) { + if (id >= length(remind)) + return reply("invalid job id"); + say("job " id ": " remind[id]["mesg"]); +} + +# Remove job from the queue +function atrm(id) { + if (id >= length(remind)) + return reply("invalid job id"); + if (remind[id]["done"] != "pending") + return reply("job is not pending"); + remind[id]["done"] = "canceled"; + json_save("var/remind.json", remind); + say("canceled job " id); +} + +# Run the at daemon +function atd(now) { + now = systime(); + for (i = 0; i < length(remind); i++) { + if (remind[i]["done"] != "pending") + continue; + if (remind[i]["time"] > now) + continue; + remind[i]["done"] = "finished"; + say(CHANNEL, remind[i]["from"] ": " remind[i]["mesg"]); + } + json_save("var/remind.json", remind); +} + + +# At handlers +/^\.at / { + at(FROM, $0, ""); +} + +/^\.in / { + at(FROM, $0, "now+"); +} + +/^\.atq/ { + atq($0 ~ /!/); +} + +/^\.atc +[0-9]+$/ { + atc($2); +} + +/^\.atrm +[0-9]+$/ { + atrm($2); +} + +/^\.help$/ { + say(".help at -- queue reminders for later") +} + +/^\.help at/ { + say(".at [time] [msg] -- record a message for the given time") + say(".in [len] [msg] -- same as .at \"now + len\"") + say(".atq -- list any pending job") + say(".atq! -- list all jobs in the queue") + say(".atc [n] -- print the given job") + say(".atrm [n] -- delete the given job") + next +} + +// { + atd(); +} diff --git a/remind.sh b/remind.sh new file mode 100755 index 0000000..6ef6d8f --- /dev/null +++ b/remind.sh @@ -0,0 +1,45 @@ +# Testing +cat < /tmp/test.awk + BEGIN { + offset = 0; + FROM = "andy"; + } + + function reply(msg) { + print "\t" FROM ": " msg + } + + function say(msg) { + print "\t" msg + } + + // { + printf("%s", \$1) + } + + /^\.wait +[0-9]+\$/ { + offset += \$2; + } + + /^\.atclr\$/ { + delete remind; + json_save("var/remind.json", remind); + say("all jobs cleared"); + } +EOF + +awk -f /tmp/test.awk -f remind.awk <<-EOF + .atclr + .in "1 min" hello october + .in "2 min" hello november + .atq + .wait 60 + .atq + .atq! + .atc 3 + .atc 1 + .atrm 1 + .atrm 1 + .atq + .atq! +EOF diff --git a/rhawk b/rhawk index 8811273..66b2e06 100755 --- a/rhawk +++ b/rhawk @@ -4,6 +4,7 @@ @include "json.awk" @include "spades.awk" @include "email.awk" +@include "remind.awk" @include "sfvlug.awk" # Initialization