diff options
author | metamuffin <metamuffin@disroot.org> | 2024-11-04 20:05:04 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-11-04 20:06:25 +0100 |
commit | c78ca2592dd35703d4f61f4c0b78481135e029eb (patch) | |
tree | bff207ffc5aacc357f475f561d083dacf89828ad /abrechenbarkeit.lua | |
parent | 7dc2354e497c472fca0ebf6e75abe672dd9278b4 (diff) | |
download | abrechenbarkeit-c78ca2592dd35703d4f61f4c0b78481135e029eb.tar abrechenbarkeit-c78ca2592dd35703d4f61f4c0b78481135e029eb.tar.bz2 abrechenbarkeit-c78ca2592dd35703d4f61f4c0b78481135e029eb.tar.zst |
a
Diffstat (limited to 'abrechenbarkeit.lua')
-rwxr-xr-x | abrechenbarkeit.lua | 152 |
1 files changed, 89 insertions, 63 deletions
diff --git a/abrechenbarkeit.lua b/abrechenbarkeit.lua index deaaf34..d29cf20 100755 --- a/abrechenbarkeit.lua +++ b/abrechenbarkeit.lua @@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. -]]-- +]] -- local function escape(s) return s:gsub("<", "<"):gsub("<", "<") @@ -63,17 +63,50 @@ local function load_config() return config end +local function load_translations(langs) + local t = {} + for _, lcode in ipairs(langs) do + local file = io.open(string.format("locale/%s.ini", lcode), "r") + if file ~= nil then + for l in file:lines("l") do + if l ~= "" then + local key, value = string.match(l, "^([^=]+)=([^=]*)") + if key ~= nil and value ~= nil then + t[key] = value + end + end + end + end + end + return t +end + local config = load_config() local path = os.getenv("PATH_INFO") local method = os.getenv("REQUEST_METHOD") local query = parse_query(os.getenv("QUERY_STRING")) +local translations = load_translations({ "en", config.language }) local stylesheet = io.open("style.css"):read("a") local script = io.open("script.js"):read("a") +local function format(template, params) + return string.gsub(template, "{([%w\\.!]+)}", function(n) + local raw = n:sub(1,1) ~= "!" + if raw then n = n:sub(2) end + local s = format(params[n] or translations[n] or "NIL TEMPLATE", params) + return raw and s or escape(s) + end) +end + +local function format_amount(amount, tag, classes) + local s = string.format("%.02f%s", amount / 100, config.unit or "€") + if tag == nil then return s end + return string.format([[<%s class="amount-%s %s">%s</%s>"]], tag, amount >= 0 and "pos" or "neg", s, tag, classes or "") +end + local function get_user_theme(username) local c = "" - local js = "" if username == "_jeb" then c = "html { animation: 2s jeb infinite; }" c = c .. "@keyframes jeb {\n" @@ -84,24 +117,29 @@ local function get_user_theme(username) elseif username == "Dinnerbone" then c = "html { transform: scale(-1); } " end - return c, js + return c end -local function respond(status, title, body) - local themecss, themejs = get_user_theme(path and path:sub(2)) +local function format_duration(t) + if t > 86400 then return string.format("%d day%s", t / 86400, math.floor(t / 86400) ~= 1 and "s" or "") end + if t > 3600 then return string.format("%d hour%s", t / 3600, math.floor(t / 3600) ~= 1 and "s" or "") end + if t > 60 then return string.format("%d minute%s", t / 60, math.floor(t / 60) ~= 1 and "s" or "") end + return string.format("%d seconds", t) +end +local function respond(status, title, body) print(string.format("Status: %d", status)) print("Content-Type: text/html") print("") - print(string.format([[ + print(format([[ <!DOCTYPE html> <html><head> - <title>%s</title> + <title>{title}</title> <meta charset="utf-8" /> - <style>%s</style> - <style>%s</style> - <script>%s</script> - %s + <style>{style}</style> + <style>{user_style}</style> + <script>{script}</script> + {head_extra} </head> <body> <nav> @@ -110,23 +148,21 @@ local function respond(status, title, body) <path d="M3 4.5a.5.5 0 0 1 .5-.5h6a.5.5 0 1 1 0 1h-6a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 1 1 0 1h-6a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 1 1 0 1h-6a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5M11.5 4a.5.5 0 0 0 0 1h1a.5.5 0 0 0 0-1zm0 2a.5.5 0 0 0 0 1h1a.5.5 0 0 0 0-1zm0 2a.5.5 0 0 0 0 1h1a.5.5 0 0 0 0-1zm0 2a.5.5 0 0 0 0 1h1a.5.5 0 0 0 0-1zm0 2a.5.5 0 0 0 0 1h1a.5.5 0 0 0 0-1z"/> <path d="M2.354.646a.5.5 0 0 0-.801.13l-.5 1A.5.5 0 0 0 1 2v13H.5a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1H15V2a.5.5 0 0 0-.053-.224l-.5-1a.5.5 0 0 0-.8-.13L13 1.293l-.646-.647a.5.5 0 0 0-.708 0L11 1.293l-.646-.647a.5.5 0 0 0-.708 0L9 1.293 8.354.646a.5.5 0 0 0-.708 0L7 1.293 6.354.646a.5.5 0 0 0-.708 0L5 1.293 4.354.646a.5.5 0 0 0-.708 0L3 1.293zm-.217 1.198.51.51a.5.5 0 0 0 .707 0L4 1.707l.646.647a.5.5 0 0 0 .708 0L6 1.707l.646.647a.5.5 0 0 0 .708 0L8 1.707l.646.647a.5.5 0 0 0 .708 0L10 1.707l.646.647a.5.5 0 0 0 .708 0L12 1.707l.646.647a.5.5 0 0 0 .708 0l.509-.51.137.274V15H2V2.118z"/> </svg> - Abrechenbarkeit</a> - <a href="/?log">Log</a> - <a href="/?products">Products</a> - <a href="/?about">About</a> + {appname} + </a> + <a href="/?log">{log}</a> + <a href="/?products">{products}</a> + <a href="/?about">{about}</a> </nav> - ]], - escape(title), - stylesheet, -- style.css - themecss, -- theme for user - script, -- script.js - config.head_extra or "" - )) + ]], { + title = escape(title), + style = stylesheet, + user_style = get_user_theme(path and path:sub(2)), + script = script, + head_extra = config.head_extra or "" + })) body() - print(string.format( - "<script>%s</script></body></html>", - themejs - )) + print("</body></html>") end local function error_box(message) @@ -149,13 +185,6 @@ local function form_data() return parse_query(io.read()) end -local function format_duration(t) - if t > 86400 then return string.format("%d day%s", t / 86400, math.floor(t / 86400) ~= 1 and "s" or "") end - if t > 3600 then return string.format("%d hour%s", t / 3600, math.floor(t / 3600) ~= 1 and "s" or "") end - if t > 60 then return string.format("%d minute%s", t / 60, math.floor(t / 60) ~= 1 and "s" or "") end - return string.format("%d seconds", t) -end - local function read_log() local log = io.open("log", "r") if log == nil then @@ -285,14 +314,15 @@ local function r_user_post(username) end log:flush() log:close() - return string.format([[ - <div class="notif"><p>Transaction successful: <strong class="amount-%s">%.02f€</strong> (%s)</p></div> - <audio src="%s" autoplay></audio> - ]], - amount >= 0 and "pos" or "neg", amount / 100, - escape(comment), - config.transaction_sound or "" - ) + return format([[ + <div class="notif"><p>Transaction successful: {amount} ({!comment})</p></div> + <audio src="{sound}" autoplay></audio> + ]], { + sign = amount >= 0 and "pos" or "neg", + amount = format_amount(amount, "strong"), + comment = escape(comment), + sound = config.transaction_sound or "" + }) end local function r_user(username) @@ -301,24 +331,20 @@ local function r_user(username) notif = r_user_post(username) end return respond(200, string.format("Abrechenbarheit: %s", username), function() - print(string.format("<h1>%s</h1>", username)) + print(format("<h1>{username}</h1>", { username = username })) local balance = balances()[username] local last_txn = last_txns()[username] local new_user = balance == nil balance = balance or 0 if notif then print(notif) end if new_user then - print([[ - <div class="notif"><p><i>This user account does not exist yet. It will only be created after the first transaction.</i></p></div> - ]]) + print([[<div class="notif"><p><i>{user.lazy_creation}</i></p></div>]]) else print([[<div class="backgroundbox userinfo">]]) - print(string.format([[ - Current balance:<br><span class="amount-%s balance-value">%.02f€</span><br> - ]], balance >= 0 and "pos" or "neg", balance / 100)) - print(string.format([[ - Last transaction added %s ago. <a href="/%s?log">View user log</a> - ]], format_duration(os.time() - last_txn), username)) + print(format([[{user.balance}: <br>{amount}<br>]], + { sign = balance >= 0 and "pos" or "neg", amount = format_amount(balance, "span", "balance-value") })) + print(format([[{user.last_txn} <a href="/{username}?log">{user.view_log}</a>]], + { time = format_duration(os.time() - last_txn), username = urlencode(username) })) print([[</div>]]) end print([[<div class="transactions container firstchildlarge">]]) @@ -336,35 +362,35 @@ local function r_user(username) end end print("</div>") - print([[ + print(format([[ <form class="transaction box backgroundbox" action="" method="POST"> - <h3>Create Transaction</h3> + <h3>{user.form.transaction}</h3> <label for="amount">Amount (ct): </label> <input type="number" name="amount" id="amount" /> <label for="comment">Comment: </label> <input type="text" name="comment" id="comment" /> - <input type="submit" value="Update" class="amount-ntr button" /> + <input type="submit" value="{user.form.transaction.submit}" class="amount-ntr button" /> </form> <form class="transaction box backgroundbox" action="" method="POST" id="buy_product"> - <h3>Buy Product</h3> + <h3>{user.form.buy}</h3> <input type="text" name="negate_pcount" value="1" hidden /> <label for="pcount">Count: </label> <input type="number" name="pcount" id="pcount" value="1" /> - <label for="pcode">Product Barcode: </label> + <label for="pcode">{field.barcode}: </label> <input type="text" name="pcode" id="pcode" /> - <input class="amount-neg button" type="submit" value="Buy" /> + <input class="amount-neg button" type="submit" value="{user.form.buy.submit}" /> </form> <form class="transaction box backgroundbox" action="" method="POST" id="buy_product"> - <h3>Restock Product</h3> - <label for="pcount">Count: </label> + <h3>{user.form.restock}</h3> + <label for="pcount">{field.count}: </label> <input type="number" name="pcount" id="pcount" value="1" /> - <label for="amount">Upstream price: </label> + <label for="amount">{field.upstream_price}: </label> <input type="number" name="amount" id="amount" /> - <label for="pcode">Product Barcode: </label> + <label for="pcode">{field.barcode}: </label> <input type="text" name="pcode" id="pcode" /> - <input type="submit" value="Restock" class="button amount-pos" /> + <input type="submit" value="{user.form.restock.submit}" class="button amount-pos" /> </form> - ]]) + ]])) print("</div>") end) end |