]> Pileus Git - ~andy/rhawk/commitdiff
Add at daemon
authorAndy Spencer <andy753421@gmail.com>
Tue, 3 Nov 2015 05:52:43 +0000 (05:52 +0000)
committerAndy Spencer <andy753421@gmail.com>
Tue, 3 Nov 2015 06:17:13 +0000 (06:17 +0000)
json.awk
remind.awk [new file with mode: 0644]
remind.sh [new file with mode: 0755]
rhawk

index 6a8e96d675d9d3f6a0c6c4c853c1cbf46b746e4e..cfb8eac56c680460b9e12d4c6d7a1e7c3f45a61c 100644 (file)
--- a/json.awk
+++ b/json.awk
@@ -305,6 +305,7 @@ function json_encode(var, pad)
 # File API
 function json_load(file, var,   line, string)
 {
 # 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)
        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 (file)
index 0000000..3be1d2f
--- /dev/null
@@ -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 (executable)
index 0000000..6ef6d8f
--- /dev/null
+++ b/remind.sh
@@ -0,0 +1,45 @@
+# Testing
+cat <<EOF > /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 88112734d6ffbd5d69fa873a6c58766870c68098..66b2e06155a1785592f424d9beac0fb68ffcebbe 100755 (executable)
--- a/rhawk
+++ b/rhawk
@@ -4,6 +4,7 @@
 @include "json.awk"
 @include "spades.awk"
 @include "email.awk"
 @include "json.awk"
 @include "spades.awk"
 @include "email.awk"
+@include "remind.awk"
 @include "sfvlug.awk"
 
 # Initialization
 @include "sfvlug.awk"
 
 # Initialization