#!/usr/bin/env luajit
local path = os.getenv("PATH_INFO")
local method = os.getenv("REQUEST_METHOD")
local query = os.getenv("QUERY_STRING")
local function escape(s)
return s:gsub("<", "<"):gsub("<", "<")
end
local function respond(status, title, body)
print(string.format("Status: %d", status))
print("Content-Type: text/html")
print("")
print(string.format([[
%s
]], escape(title)))
body()
print("")
end
local function respond_error(message)
respond(400, "Error", function()
print(string.format("Error: %s
", escape(message)))
end)
end
local function form_data()
local data = {}
for pair in string.gmatch(io.read(), "([^&]+)") do
local key, value = string.match(pair, "([^=]+)=([^=]+)")
if key == nil or value == nil then
goto continue
end
data[key] = value
::continue::
end
return data
end
local function read_log()
local log = io.open("log", "r")
if log == nil then
return function() return nil end
end
local lines = log:lines("l")
return function()
local l = lines()
local time, username, amount, comment = string.match(l, "(%d+),([%w_-]+),(-?%d+),([%w_-]*)")
return tonumber(time), username, tonumber(amount), comment
end
end
local function balances()
local users = {}
for _, username, amount, _ in read_log() do
users[username] = (users[username] or 0) + amount
end
return users
end
if path == "/" then
if query == "?log" then
return respond(200, "Log", function()
print("")
print("Time | Username | Amount | Comment |
")
for time, username, amount, comment in read_log() do
print(string.format("%d | %s | %.02f€ | %s |
", time, escape(username),
amount / 100, escape(comment)))
end
print("
")
end)
end
return respond(200, "Users", function()
print("")
for username, balance in balances() do
print(string.format("- %s: %.02f€
", escape(username), escape(username),
balance / 100))
end
print("
")
end)
elseif path ~= nil then
local username = path:sub(2)
if username:match("^[%w_-]+$") == nil then
return respond_error("username invalid")
end
if method == "POST" then
local data = form_data()
local amount = tonumber(data.amount)
if amount == nil then
return respond_error("amount invalid")
end
local comment = data.comment or ""
if comment:match("^[%w_-]*$") == nil then
return respond_error("comment invalid")
end
local log = io.open("log", "a+")
if log == nil then
return respond_error("failed to open log")
end
local time = os.time()
log:write(string.format("%d,%s,%s,%s\n", time, username, amount, comment))
log:flush()
log:close()
end
respond(200, username, function()
print(string.format("%s
", username))
print([[
]])
for _, type in ipairs({ 1, -1 }) do
for _, amount in ipairs({ 50, 100, 150, 200, 500, 1000 }) do
print(string.format([[
]], amount * type, ({ [-1] = "-", [1] = "+" })[type], amount / 100))
end
end
end)
end