]> Pileus Git - ~andy/rhawk/commitdiff
Add json load/save and save email addresses
authorAndy Spencer <andy753421@gmail.com>
Mon, 11 Jun 2012 00:55:43 +0000 (00:55 +0000)
committerAndy Spencer <andy753421@gmail.com>
Mon, 11 Jun 2012 01:13:49 +0000 (01:13 +0000)
email.awk
json.awk [new file with mode: 0644]

index 270836e12dafe8153e0158c3239d9a20c0450d5d..a417f9e3bf659304511703496c43ae7bb450e580 100644 (file)
--- a/email.awk
+++ b/email.awk
@@ -1,3 +1,9 @@
+@include "json.awk"
+
+# Save email addresses
+BEGIN { json_load("var/mail.txt", mail_enable) }
+END   { json_save("var/mail.txt", mail_enable) }
+
 # Email notifications
 BEGIN {
        mail_hist  = 60 # Send 60 seconds of backlog
@@ -6,6 +12,9 @@ BEGIN {
        mail_from  = NICK "<andy753421@gmail.com>"
        mail_err   = "If you received this message in error,\n" \
                     "someone in #rhnoise is being a jerk"
+
+       for (_user in mail_enable) 
+               debug("watching " mail_enable[_user] " for " _user)
 }
 
 function mail_send(addr, subj, body,
@@ -67,7 +76,7 @@ FROM ~ OWNER &&
 }
 
 /^e?mail  *[^ ]*$/ {
-       reply("notifying " $2)
+       reply("notifying " $2 " for " FROM)
        mail_enable[FROM] = $2
 }
 
diff --git a/json.awk b/json.awk
new file mode 100644 (file)
index 0000000..2f735c4
--- /dev/null
+++ b/json.awk
@@ -0,0 +1,345 @@
+# value:
+#      object: { string : value, .. }
+#      array:  [ value, .. ]
+#      string: "char .."
+#      number: (builtin)
+#      true
+#      false
+#      null
+# 
+# chars:
+#      any-Unicode-character-except-"-or-\-or-control-character
+#      \"
+#      \\
+#      \/
+#      \b
+#      \f
+#      \n
+#      \r
+#      \t
+#      \u four-hex-digits
+
+
+# Helpers
+function json_gettype(value,   key, sort, n, i)
+{
+       if (isarray(value)) { 
+               for (key in value)
+                       if (isarray(key))
+                               return "error"
+               n = asorti(value, sort)
+               for (i = 0; i < n; i++)
+                       if (sort[i+1] != i)
+                               return "object"
+               return "array"
+       } else {
+               if (value == value + 0)
+                       return "number"
+               if (value == value "")
+                       return "string"
+               return "error"
+       }
+}
+
+function json_join(array, sep,   i, str)
+{
+       str = array[0]
+       for (i = 1; i < length(array); i++)
+               str = str sep array[i]
+       return str
+}
+
+function json_copy(dst, to, src,   key)
+{
+       if (isarray(src)) {
+               delete dst[to]
+               for (key in src) {
+                       dst[to][key]
+                       json_copy(dst[to], key, src[key])
+               }
+       } else {
+               dst[to] = src
+       }
+}
+
+
+# Write functions
+function json_write_value(value, pad)
+{
+       switch (json_gettype(value)) {
+               case "object": return json_write_object(value, pad)
+               case "array":  return json_write_array(value, pad)
+               case "number": return json_write_number(value)
+               case "string": return json_write_string(value)
+               default:       return "error"
+       }
+}
+
+function json_write_object(object, pad,   n, i, sort, key, val, data, len, max)
+{
+       n = asorti(object, sort)
+       for (i = 0; i < n; i++) {
+               key = json_write_string(sort[i+1])
+               if (length(key) > max)
+                       max = length(key)
+       }
+       for (i = 0; i < n; i++) {
+               key = json_write_string(sort[i+1])
+               val = json_write_value(object[sort[i+1]],
+                       sprintf("%s  %"max"s  ", pad, ""))
+               data[i] = sprintf("%-"(max+1)"s %s", key":", val)
+       }
+       return "{ " json_join(data, ",\n  " pad) " }"
+}
+
+function json_write_array(array, pad,   i, data)
+{
+       for (i = 0; i < length(array); i++)
+               data[i] = json_write_value(array[i], pad "  ")
+       return "[ " json_join(data, ",\n  " pad) " ]"
+}
+
+function json_write_number(number)
+{
+       return "" number ""
+}
+
+function json_write_string(string)
+{
+       # todo: special characters
+       return "\"" string "\""
+}
+
+
+# Read functions
+function json_tokenize(str, tokens,   i, items, table, type, found)
+{
+       table["term"]  = "^[\\[\\]{}:,]"
+       table["str"]   = "^\"[^\"]*\""
+       table["num"]   = "^[0-9]+"
+       table["var"]   = "^(true|false|null)"
+       table["space"] = "^[ \\t\\n]+"
+       i = 0
+       while (length(str) > 0) {
+               found = 0
+               for (type in table) {
+                       #print "match: str=["str"] type="type" regex=/"table[type]"/"
+                       if (match(str, table[type], items) > 0) {
+                               #print "       len="RLENGTH" item=["items[0]"]"
+                               if (type == "term")
+                                       type = items[0]
+                               if (type != "space") {
+                                       tokens[i]["type"] = type
+                                       tokens[i]["text"] = items[0]
+                                       i++
+                               }
+                               str = substr(str, RLENGTH+1)
+                               found = 1
+                               break
+                       }
+               }
+               if (!found) {
+                       debug("error tokenizing")
+                       return 0
+               }
+       }
+       return i
+
+       #for (i = 0; i < length(tokens); i++)
+       #       printf "%-3s %-5s [%s]\n", i":",
+       #               tokens[i]["type"], tokens[i]["text"]
+}
+
+function json_parse_value(tokens, i, value, key,   type, text)
+{
+       if (!i    ) i = 0;
+       if (!depth) depth = 0
+       depth++
+       type = tokens[i]["type"]
+       text = tokens[i]["text"]
+       #printf "parse %d: i=%-2d type=%-3s text=%s\n", depth, i, type, text
+       switch (type) {
+               case "{":   i = json_parse_object(tokens, i, value, key); break
+               case "[":   i = json_parse_array(tokens,  i, value, key); break
+               case "str": i = json_parse_string(tokens, i, value, key); break
+               case "num": i = json_parse_number(tokens, i, value, key); break
+               case "var": i = json_parse_var(tokens,    i, value, key); break
+               default:    debug("error: type="type" text="text); return 0
+       }
+       depth--
+       return i
+}
+
+function json_parse_object(tokens, i, value, key,   object, k, v)
+{
+       if (tokens[i++]["text"] != "{")
+               return 0;
+
+       do {
+               delete k
+               delete v
+               if (!(i=json_parse_value(tokens, i, k, 0)))
+                       return 0
+               if (tokens[i++]["text"] != ":")
+                       return 0
+               if (!(i=json_parse_value(tokens, i, v, 0)))
+                       return 0
+               json_copy(object, k[0], v[0]) 
+       } while (tokens[i++]["text"] == ",")
+       i--
+
+       if (tokens[i++]["text"] != "}")
+               return 0;
+
+       json_copy(value, key, object)
+       return i
+}
+
+function json_parse_array(tokens, i, value, key,   array, k, v)
+{
+       #print "parse_array: .."
+       if (tokens[i++]["text"] != "[")
+               return 0;
+
+       do {
+               delete v
+               if (!(i=json_parse_value(tokens, i, v, 0)))
+                       return 0
+               json_copy(array, k++, v[0]) 
+       } while (tokens[i++]["text"] == ",")
+       i--
+
+       if (tokens[i++]["text"] != "]")
+               return 0;
+
+       json_copy(value, key, array)
+       return i
+}
+
+function json_parse_number(tokens, i, value, key,   text)
+{
+       text = tokens[i++]["text"]
+       json_copy(value, key, text + 0)
+       #print "parse_number: " (text + 0)
+       return i
+}
+
+function json_parse_string(tokens, i, value, key,   text)
+{
+       text = tokens[i++]["text"]
+       text = substr(text, 2, length(text)-2)
+       json_copy(value, key, text)
+       #print "parse_string: " text
+       return i
+}
+
+function json_parse_var(tokens, i, value, key,   text)
+{
+       text = tokens[i++]["text"]
+       json_copy(value, key, text == "true")
+       #print "parse_var: " text " -> " text == "true"
+       return i
+}
+
+
+# Nice API?
+function json_load(file, var,   line, text, tokens, data, key)
+{
+       while ((getline line < file) > 0)
+               text = text line
+       close(file)
+       if (!json_tokenize(text, tokens))
+               return ""
+       if (!json_parse_value(tokens, 0, data, 0))
+               return ""
+       if (!isarray(data[0]))
+               return data[0]
+       for (key in data[0])
+               json_copy(var, key, data[0][key])
+}
+
+function json_save(file, var,   cmd, tmp)
+{
+       cmd = "mktemp ." file ".XXX"
+       cmd | getline tmp
+       close(cmd)
+       print json_write_value(var) > tmp
+       close(tmp)
+       system("mv " tmp " " file)
+}
+
+
+# Test functions
+function json_test_write()
+{
+       num      = 42
+       str      = "hello, world"
+       arr[0]   = "zero"
+       arr[1]   = "one"
+       arr[2]   = "two"
+       obj["A"] = "a!"
+       obj["B"] = "b!"
+       obj["C"] = "c!"
+       json_copy(mix, "number", num);
+       json_copy(mix, "str",    str);
+       json_copy(mix, "arr",    arr);
+       json_copy(mix, "obj",    obj);
+       json_copy(dub, "first",  mix);
+       json_copy(dub, "second", mix);
+       print json_write_value(num)
+       print json_write_value(str)
+       print json_write_value(arr)
+       print json_write_value(obj)
+       print json_write_value(mix)
+       print json_write_value(dub)
+}
+
+function json_test_read()
+{
+       json_tokenize("[8, \"abc\", 9]", tokens)
+       json_parse_value(tokens, 0, array, 0)
+       json_print write_value(array[0])
+
+       json_tokenize("{\"abc\": 1, \"def\": 2}", tokens)
+       json_parse_value(tokens, 0, array, 0)
+       json_print write_value(array[0])
+
+       json = "{ \"first\":  { \"arr\":    [ \"zero\",         " \
+              "                              \"one\",          " \
+              "                              \"two\" ],        " \
+              "                \"number\": 42,                 " \
+              "                \"obj\":    { \"A\": \"a!\",    " \
+              "                              \"B\": \"b!\",    " \
+              "                              \"C\": \"c!\" },  " \
+              "                \"str\":    \"hello, world\" }, " \
+              "  \"second\": { \"arr\":    [ \"zero\",         " \
+              "                              \"one\",          " \
+              "                              \"two\" ],        " \
+              "                \"number\": 42,                 " \
+              "                \"obj\":    { \"A\": \"a!\",    " \
+              "                              \"B\": \"b!\",    " \
+              "                              \"C\": \"c!\" },  " \
+              "                \"str\":    \"hello, world\" } }"
+
+       json_tokenize(json, tokens)
+       json_parse_value(tokens, 0, array, 0)
+       print json_write_value(array[0])
+}
+
+function json_test_files()
+{
+       print "load: [" json_load("email.txt", mail) "]"
+       print "mail: "  json_write_value(mail, "      ")
+       mail["andy753421"] = "andy753421@gmail.com"
+       mail["andy"]       = "andy@gmail.com"
+       mail["somebody"]   = "foo@example.com"
+       print "mail: "  json_write_value(mail, "      ")
+       print "save: [" json_save("email.txt", mail) "]"
+}
+
+# Main
+BEGIN {
+       #json_test_write()
+       #json_test_read()
+       #json_test_files()
+}