commit 56f8d78f43b1a22eb1df09a6aa1a3ef1a509c096
parent 5628a86111a74db37573fb768d44f525f9728177
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date: Fri, 8 Sep 2023 12:24:58 -0300
Reorganize script and create libs
Diffstat:
| A | lib/registration.lua | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
| A | lib/report.lua | | | 9 | +++++++++ |
| A | lib/utils.lua | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | registrar | | | 158 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | registrar.lua | | | 182 | ------------------------------------------------------------------------------- |
5 files changed, 285 insertions(+), 182 deletions(-)
diff --git a/lib/registration.lua b/lib/registration.lua
@@ -0,0 +1,45 @@
+require "lib.utils"
+pprint = require "pprint"
+
+_M = {}
+
+function _M.deregister(args, players, log)
+ p = players[args.name]
+ if not p then
+ error(string.format("There's no player '%s'.", args.name))
+ end
+
+ h = table.query(p, function (c) return c.active end)
+
+ if not h then
+ error(string.format("Player '%s' is not active.", args.name))
+ end
+
+ ev = {when = args.date,
+ what = "deregister",
+ who = args.name,
+ where = args.m}
+
+ if not args.p then
+ h.active = nil
+ h.deregistration = os.date("%Y-%m-%d", args.date)
+ h.reason = "d"
+ h.latest = nil
+
+ table.insert(log, ev)
+ else
+ io.write(string.format("Deregister player %s.\n", args.name))
+ pprint.pprint(ev)
+ pprint.pprint(h)
+ io.write("active := nil\n")
+ io.write("latest := d\n")
+ io.write(string.format("deregistration := %s\n", os.date("%Y-%m-%d", args.date)))
+ io.write("reason := d\n")
+ end
+end
+
+function _M.register(args, players, log, ts)
+ return
+end
+
+return _M
diff --git a/lib/report.lua b/lib/report.lua
@@ -0,0 +1,9 @@
+_M = {}
+
+function _M.weekly()
+end
+
+function _M.monthly()
+end
+
+return _M
diff --git a/lib/utils.lua b/lib/utils.lua
@@ -0,0 +1,73 @@
+local path = require "path"
+
+function die(err, msg)
+ msg = tostring(msg or err)
+ if err then
+ io.stderr:write(msg .. "\n")
+ os.exit(1)
+ end
+end
+
+function yn(prompt)
+ meaning = {Y = true, y = true, n = false, N = false}
+ while meaning[ans] == nil do
+ io.write(prompt)
+ io.flush() -- For some reason, prompt doesn't show up without this
+ ans = io.read(1)
+ end
+ return ans
+end
+
+function decodewith(decoder, fn)
+ die(not path.exists(fn), fn.." does not exist.")
+ die(not path.isfile(fn), fn.." is not a file.")
+ local f, err = io.open(fn, "r")
+ die(err)
+ status, res = xpcall(decoder, die, f:read("a"))
+ f:close()
+ die(not status, res)
+ return res
+end
+
+function encodewith(encoder, fn, data)
+ local f, err = io.open(fn, "w")
+ die(not status, err)
+ status, err = f:write(encoder(data))
+ die(not status, err)
+end
+
+function format(fmt, dict, sett)
+ -- A identifier is
+ -- > any string of Latin letters, Arabic-Indic digits, and
+ -- > underscores, not beginning with a digit and not being a reserved
+ -- > word
+ res = fmt
+ for s in string.gmatch(fmt, "%{([_a-zA-Z][._a-zA-Z0-9]*)%}") do
+ local value = dict
+ local pref = sett
+ for k in string.gmatch(s, "([_a-zA-Z][_a-zA-Z0-9]*)") do
+ if type(value) == "table" then value = value[k] end
+ if type(pref) == "table" then pref = pref[k] end
+ end
+ if pref and value then string.format(pref, value) end
+ res = fmt.gsub(res, "{"..s.."}", value or "nil")
+ end
+ return res
+end
+
+function m4flags(d)
+ flags = ""
+ for k, v in pairs(d) do
+ flags = flags .. string.format(" -D %s='%s'", k, v)
+ end
+ return flags
+end
+
+function table.query(t, q)
+ for _,i in ipairs(t) do
+ if q(i) then
+ return i
+ end
+ end
+ return nil
+end
diff --git a/registrar b/registrar
@@ -0,0 +1,158 @@
+#!/usr/bin/lua5.4
+local argparse = require "argparse"
+local json = require "json"
+local path = require "path"
+
+require "lib.utils"
+registration = require "lib.registration"
+report = require "lib.report"
+
+local parser = argparse("registrar", "Manage Agora's registrar duties")
+parser:flag("-p", "Pretend: only show what would be done")
+
+parser:command_target("command")
+
+parser:command("monthly", "Generate and send registrar monthly report")
+parser:command("weekly", "Generate and send registrar weekly report")
+
+local birthday_cmd = parser:command("birthday", "Announce a player's birthday")
+birthday_cmd:flag("-p", "Pretent: generate and print only.")
+birthday_cmd:argument("name", "The name of the player")
+
+local deregister_cmd = parser:command("deregister", "Deregister player")
+deregister_cmd:argument("name", "The name of the player")
+deregister_cmd:argument("date", "Time stamp of deregistration (seconds after epoch)")
+ :convert(tonumber)
+deregister_cmd:option("-m", "Message ID of deregistration (without 'message://' prefix)")
+
+parser:command("register", "Register player")
+parser:command("activate", "Activate player")
+parser:command("deactivate", "Deactivate player")
+parser:command("rename", "Rename player")
+parser:command("readdress", "Change player's address")
+
+-- Deserialize
+local fns = {
+ players = "players.json",
+ log = "log.json",
+ tmp = ".tmp",
+ history = ".hist"
+}
+local args = parser:parse()
+local players = decodewith(json.decode, fns.players)
+local log = decodewith(json.decode, fns.log)
+
+-- Process
+
+-- commands[args.command](fns, args, players, log)
+
+if args.command == "monthly" then
+ local hist = io.open(fns.history, "w")
+
+ defs = {
+ YEAR = os.date("%Y"),
+ MONTH = os.date("%m"),
+ DAY = os.date("%d"),
+ MAILDATE = os.date("%a, %d %b %Y %T %z"),
+ PLAYERS = string.format("include(%s)", fns.history)
+ }
+ for n,h in pairs(players) do
+ hist:write("===============\n"..n.."\n")
+ for _,e in ipairs(h) do
+ if e.reason == "s" then
+ f = " ({reason}) {name} <{contact}> ({registration}--now)\n"
+ else
+ f = " ({reason}) {name} <{contact}> ({registration}--{deregistration})\n"
+ end
+ hist:write(format(f, e))
+ if e.observations then
+ hist:write(format(" {observations}\n", e))
+ end
+ end
+ hist:write("\n")
+ end
+ hist:close()
+
+ os.execute(string.format("m4 %s templates/monthly/monthly.m4 > %s", m4flags(defs), fns.tmp))
+
+ if args.p then
+ os.execute(string.format("cat %s", fns.tmp))
+ os.remove(fns.tmp)
+ else
+ os.execute(string.format("vis %s", fns.tmp))
+ os.execute(string.format("neomutt -H %s -E", fns.tmp))
+ if yn("Archive report? [Yn] ") then
+ table.insert(log, {
+ when = os.time(),
+ what = "monthly"
+ })
+ os.rename(tmpname, os.date("archive/%F-monthly.txt"))
+ else
+ os.remove(fns.tmp)
+ end
+ end
+ os.remove(fns.history)
+
+elseif args.command == "weekly" then
+ defs = {
+ YEAR = os.date("%Y"),
+ MONTH = os.date("%m"),
+ DAY = os.date("%d"),
+ MAILDATE = os.date("%a, %d %b %Y %T %z"),
+ }
+
+ os.execute(string.format("m4 %s templates/weekly/weekly.m4 > %s", m4flags(defs), fns.tmp))
+ if args.p then
+ os.execute(string.format("cat %s", fns.tmp))
+ os.remove(fns.tmp)
+ else
+ os.execute(string.format("vis %s", fns.tmp))
+ os.execute(string.format("neomutt -H %s -E", fns.tmp))
+ if yn("Archive report? [Yn] ") then
+ table.insert(log, {
+ when = os.time(),
+ what = "weekly",
+ height = height,
+ })
+ os.rename(tmpname, os.date("archive/%F-weekly.txt"))
+ else
+ os.remove(fns.tmp)
+ end
+ end
+ os.remove(fns.history)
+
+elseif args.command == "birthday" then
+ io.write("Birthdays not implemented. Use registrar.fish\n")
+
+elseif args.command == "register" then
+ local exists = false
+ -- Check if player name exists
+ for p, h in pairs(players) do
+ for _,e in ipairs(h) do
+ if e.name == args.name then
+ exists = true
+ break
+ end
+ end
+ end
+ -- If not, register
+ players[args.name] = players[args.name] or {}
+ table.insert(players[args.name], {{
+ name = args.name,
+ registration = args.date,
+ active = true,
+ reason = "s",
+ contact = args.contact
+ }})
+
+elseif args.command == "deregister" then
+ registration.deregister(args, players, log)
+else
+ io.write("Not implemented.")
+
+end
+
+-- Serialize
+encodewith(json.encode, fns.players, players)
+encodewith(json.encode, fns.log, log)
+encodewith(json.encode, fns.log, log)
diff --git a/registrar.lua b/registrar.lua
@@ -1,182 +0,0 @@
-#!/usr/bin/lua5.4
-local argparse = require "argparse"
-local json = require "json"
-local path = require "path"
--- local fs = require "path.fs"
-
-function die(err, msg)
- msg = tostring(msg or err)
- if err then
- io.stderr:write(msg .. "\n")
- os.exit(1)
- end
-end
-
-function yn(prompt)
- meaning = {Y = true, y = true, n = false, N = false}
- while meaning[ans] == nil do
- io.write(prompt)
- io.flush() -- For some reason, prompt doesn't show up without this
- ans = io.read(1)
- end
- return ans
-end
-
-function decodewith(decoder, fn)
- die(not path.exists(fn), fn.." does not exist.")
- die(not path.isfile(fn), fn.." is not a file.")
- local f, err = io.open(fn, "r")
- die(err)
- status, res = xpcall(decoder, die, f:read("a"))
- f:close()
- die(not status, res)
- return res
-end
-
-function encodewith(encoder, fn, data)
- local f, err = io.open(fn, "w")
- die(not status, err)
- status, err = f:write(encoder(data))
- die(not status, err)
-end
-
-function format(fmt, dict, sett)
- -- A identifier is
- -- > any string of Latin letters, Arabic-Indic digits, and
- -- > underscores, not beginning with a digit and not being a reserved
- -- > word
- res = fmt
- for s in string.gmatch(fmt, "%{([_a-zA-Z][._a-zA-Z0-9]*)%}") do
- local value = dict
- local pref = sett
- for k in string.gmatch(s, "([_a-zA-Z][_a-zA-Z0-9]*)") do
- if type(value) == "table" then value = value[k] end
- if type(pref) == "table" then pref = pref[k] end
- end
- if pref and value then string.format(pref, value) end
- res = fmt.gsub(res, "{"..s.."}", value or "nil")
- end
- return res
-end
-
-function m4flags(d)
- flags = ""
- for k, v in pairs(d) do
- flags = flags .. string.format(" -D %s='%s'", k, v)
- end
- return flags
-end
-
-local parser = argparse("registrar", "Manage Agora's registrar duties")
- :command_target("command")
-
-parser:command("monthly", "Generate and send registrar monthly report")
- :flag("-p", "Pretent: generate and print only.")
-parser:command("weekly", "Generate and send registrar weekly report")
- :flag("-p", "Pretent: generate and print only.")
-
-local birthday_cmd = parser:command("birthday", "Announce a player's birthday")
-birthday_cmd:flag("-p", "Pretent: generate and print only.")
-birthday_cmd:argument("name", "The name of the player")
-
-parser:command("register", "Register player")
-parser:command("deregister", "Deregister player")
-parser:command("activate", "Activate player")
-parser:command("deactivate", "Deactivate player")
-parser:command("rename", "Rename player")
-parser:command("readdress", "Change player's address")
-
--- Deserialize
-local fns = {
- players = "players.json",
- log = "log.json",
- tmp = ".tmp",
- history = ".hist"
-}
-local args = parser:parse()
-local players = decodewith(json.decode, fns.players)
-
--- Process
-
-if args.command == "monthly" then
- local hist = io.open(fns.history, "w")
-
- defs = {
- YEAR = os.date("%Y"),
- MONTH = os.date("%m"),
- DAY = os.date("%d"),
- MAILDATE = os.date("%a, %d %b %Y %T %z"),
- PLAYERS = string.format("include(%s)", fns.history)
- }
- for n,h in pairs(players) do
- hist:write("===============\n"..n.."\n")
- for _,e in ipairs(h) do
- if e.reason == "s" then
- f = " ({reason}) {name} <{contact}> ({registration}--now)\n"
- else
- f = " ({reason}) {name} <{contact}> ({registration}--{deregistration})\n"
- end
- hist:write(format(f, e))
- if e.observations then
- hist:write(format(" {observations}\n", e))
- end
- end
- hist:write("\n")
- end
- hist:close()
-
- os.execute(string.format("m4 %s templates/monthly/monthly.m4 > %s", m4flags(defs), fns.tmp))
-
- if args.p then
- os.execute(string.format("cat %s", fns.tmp))
- os.remove(fns.tmp)
- else
- os.execute(string.format("vis %s", fns.tmp))
- os.execute(string.format("neomutt -H %s -E", fns.tmp))
- if yn("Archive report? [Yn] ") then
- table.insert(log, {
- when = os.time(),
- what = "monthly"
- })
- os.rename(tmpname, os.date("archive/%F-monthly.txt"))
- else
- os.remove(fns.tmp)
- end
- end
- os.remove(fns.history)
-elseif args.command == "weekly" then
- defs = {
- YEAR = os.date("%Y"),
- MONTH = os.date("%m"),
- DAY = os.date("%d"),
- MAILDATE = os.date("%a, %d %b %Y %T %z"),
- }
-
- os.execute(string.format("m4 %s templates/weekly/weekly.m4 > %s", m4flags(defs), fns.tmp))
- if args.p then
- os.execute(string.format("cat %s", fns.tmp))
- os.remove(fns.tmp)
- else
- os.execute(string.format("vis %s", fns.tmp))
- os.execute(string.format("neomutt -H %s -E", fns.tmp))
- if yn("Archive report? [Yn] ") then
- table.insert(log, {
- when = os.time(),
- what = "weekly",
- height = height,
- })
- os.rename(tmpname, os.date("archive/%F-weekly.txt"))
- else
- os.remove(fns.tmp)
- end
- end
- os.remove(fns.history)
-elseif args.command == "birthday" then
- io.write("Birthdays not implemented. Use registrar.fish\n")
-else
- io.write("Not implemented.")
-end
-
--- Serialize
-encodewith(json.encode, fns.players, players)
-encodewith(json.encode, fns.log, log)