yl_scheduler/internal.lua
2024-04-08 21:38:34 +02:00

252 lines
7.1 KiB
Lua

-- The functions and variables in this file are only for use in the mod itself.
-- Those that do real work should be local and wrapped in public functions
local debug = yl_scheduler.settings.debug or true
local function say(text)
if debug then core.log("action", "[MOD] yl_scheduler : " .. text) end
end
-- Helpers
local function filename2uuid(filename) return filename:sub(1, -6) end
local function is_visible(filename) return (string.sub(filename, 1, 1) ~= ".") end
local function is_json(filename) return (filename:match("%.json$")) end
local function generate_uuid()
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
return string.gsub(template, '[xy]', function(c)
local v = (c == 'x') and math.random(0, 15) or math.random(8, 11)
return string.format('%x', v)
end)
end
local function sort_by_timestamp(tasks)
local function compare(task1, task2) return task1.at < task2.at end
table.sort(tasks, compare)
return tasks
end
function yl_scheduler.sort_by_timestamp(tasks)
return sort_by_timestamp(tasks)
end
local function split(str)
local parts = {}
for part in str:gmatch("[^,%s]+") do table.insert(parts, part) end
return parts
end
local function ends_with(str, suffix) return str:sub(-suffix:len()) == suffix end
-- Loading and Saving
local function get_savepath()
-- TODO: Can we assume the path exists?
local savepath = yl_scheduler.worldpath .. yl_scheduler.settings.save_path
say("savepath : " .. dump(savepath))
return savepath
end
local function get_filepath(UUID)
local path_to_file = yl_scheduler.worldpath ..
yl_scheduler.settings.save_path .. DIR_DELIM ..
UUID .. ".json"
say(UUID .. ":" .. dump(path_to_file))
return path_to_file
end
local function save_json(UUID, content)
if type(UUID) ~= "string" or type(content) ~= "table" then
return false
end
local savepath = get_filepath(UUID)
local savecontent = minetest.write_json(content)
return minetest.safe_file_write(savepath, savecontent)
end
local function load_json(path)
local file = io.open(path, "r")
if not file then return false, "Error opening file: " .. path end
local content = file:read("*all")
file:close()
if not content then return false, "Error reading file: " .. path end
return true, minetest.parse_json(content)
end
-- Public functions wrap the private ones, so they can be exchanged easily
function yl_scheduler.load_json(filename, ...) return load_json(filename, ...) end
function yl_scheduler.save_json(filename, content, ...)
return save_json(filename, content, ...)
end
-- ### yl_scheduler.load_all_tasks ###
local function load_all_tasks()
-- Get all json files from savepath
-- Excluding invisible
-- Excluding non-json files
local save_path = get_savepath()
local files = minetest.get_dir_list(save_path, false) or {}
local tasks = {}
local total = 0
local good = 0
local bad = 0
for key, filename in ipairs(files) do
total = total + 1
if is_visible(filename) and is_json(filename) then
local UUID = filename2uuid(filename)
local filepath = get_filepath(UUID)
local success, content = load_json(filepath)
if success then
good = good + 1
table.insert(tasks, content)
else
bad = bad + 1
end
end
end
-- Sort table for "at"
-- TODO: What's more efficient? Sort by at? use index with UUID?
yl_scheduler.tasks = sort_by_timestamp(tasks)
if bad == 0 then
core.log("action",
"[MOD] yl_scheduler : bad = " .. tostring(bad) .. ", good = " ..
tostring(good) .. ", total = " .. tostring(total))
return true, good, bad
else
core.log("warning",
"[MOD] yl_scheduler : bad = " .. tostring(bad) .. ", good = " ..
tostring(good) .. ", total = " .. tostring(total))
return false, good, bad
end
end
function yl_scheduler.load_all_tasks() return load_all_tasks() end
-- ### priv exists ###
local function priv_exists(priv)
return (minetest.registered_privileges[priv] ~= nil) or false
end
function yl_scheduler.priv_exists(priv) return priv_exists(priv) end
-- ### get_privs ###
-- {[yl_scheduler.settings.admin_priv] = true}
local cmds = {}
cmds["scheduler_add"] = "taskadd_privs"
cmds["scheduler_remove"] = "taskremove_privs"
cmds["scheduler_list"] = "tasklist_privs"
cmds["scheduler_clean"] = "taskclean_privs"
local function get_privs(chatcommand_cmd) -- scheduler_add -- taskadd_privs
local privs = split(yl_scheduler.settings[cmds[chatcommand_cmd]])
local ret = {}
for _,priv in ipairs(privs) do
ret[priv] = true
end
return ret
end
function yl_scheduler.get_privs(chatcommand_cmd)
return get_privs(chatcommand_cmd)
end
-- ### check privs ###
function check_privs()
for key, value in pairs(yl_scheduler.settings) do
if ends_with(key, "_privs") then
local parts = split(value)
for _, part in ipairs(parts) do
assert(priv_exists(part), "yl_scheduler : configured priv " ..
dump(part) .. " doesn not exist.")
end
end
end
say("PASS priv check")
end
function yl_scheduler.check_privs() return check_privs() end
-- Remove file
local function remove_file(UUID)
local path = yl_scheduler.get_filepath(UUID)
return os.remove(path)
end
function yl_scheduler.remove_file(UUID)
return remove_file(UUID)
end
-- ### Chatcommands ###
-- ### scheduler_add ###
local function cmd_scheduler_add(name, params)
-- Defense: Overlap with yl_scheduler.set_task(at, func, params, owner, notes)
-- Params
-- Time, required: translate various time formats into utc timestamp
-- Function, required: Should we check existence and that it's a function?
-- Params, optional
-- Notes, optional
-- Store
-- Re-sort tasks table
end
function yl_scheduler.cmd_scheduler_add(name, params)
return cmd_scheduler_add(name, params)
end
-- ### scheduler_remove ###
local function cmd_scheduler_remove(name, params)
-- Defense: Overlap with yl_scheduler.remove_task(UUID)
-- Store
-- Re-sort tasks table
end
function yl_scheduler.cmd_scheduler_remove(name, params)
return cmd_scheduler_remove(name, params)
end
-- ### scheduler_list ###
local function cmd_scheduler_list(name, params)
-- Defense: Overlap with yl_scheduler.list_all_tasks() and yl_scheduler.list_task(UUID)
-- Display nicely. Steal from ... I mean INSPIRE ... by yl_cinema list? Or formspec output?
end
function yl_scheduler.cmd_scheduler_list(name, params)
return cmd_scheduler_list(name, params)
end
-- ### scheduler_clean ###
local function cmd_scheduler_list(name, params)
-- Just do it and at best return how many were removed, how many remain and how many the list had before.
-- Use yl_scheduler.clean_executed_tasks() and yl_scheduler.clean_past_tasks()
end
function yl_scheduler.cmd_scheduler_list(name, params)
return cmd_scheduler_list(name, params)
end