1
0
mirror of https://github.com/sys4-fr/server-nalc.git synced 2024-12-27 03:00:38 +01:00
server-nalc/mods/wiki/wikilib.lua

223 lines
5.4 KiB
Lua
Raw Normal View History

2014-10-28 18:01:32 +01:00
local WP = minetest.get_worldpath().."/wiki"
wikilib.path = WP
local WIKI_FORMNAME = "wiki:wiki"
os.mkdir(WP)
os.mkdir(WP.."/users")
local function name_to_filename(name)
name = name:gsub("[^A-Za-z0-9-]", function(c)
if c == " " then
return "_"
else
return ("%%%02X"):format(c:byte(1))
end
end)
return name:lower()
end
wikilib.name_to_filename = name_to_filename
local function get_page_path(name, player) --> path, is_file, allow_save
local allow_save = minetest.check_player_privs(player, {wiki=true})
if name:sub(1, 1) == "." then
local text = wikilib.internal_pages[name] or wikilib.internal_pages[".NotFound_Internal"]
return text, false, false
elseif name:sub(1, 1) == ":" then
if name:match("^:[0-9]?$") then
local n = tonumber(name:sub(2,2)) or 0
path = "users/"..player.."/page"..n
os.mkdir(WP.."/users/"..player)
elseif name == ":profile" then
path = "users/"..player.."/profile"
os.mkdir(WP.."/users/"..player)
elseif name:match("^:.-:[0-9]$") then
local user, n = name:match("^:(.-):([0-9])$")
if user:find("..[/\\]") then
return wikilib.internal_pages[".BadPageName"], false, false
end
if (n == "0") and (not minetest.check_player_privs(player, {wiki_admin=true})) then
return wikilib.internal_pages[".Forbidden"], false, false
end
path = "users/"..user.."/page"..n
os.mkdir(WP.."/users/"..user)
allow_save = false
elseif name:match("^:.-:profile$") then
local user = name:match("^:(.-):.*$")
if user:find("..[/\\]") then
return wikilib.internal_pages[".BadPageName"], false, false
end
path = "users/"..user.."/profile"
os.mkdir(WP.."/users/"..user)
allow_save = false
else
return wikilib.internal_pages[".BadPageName"], false, false
end
else
path = name_to_filename(name)
end
return WP.."/"..path, true, allow_save
end
local function find_links(lines) --> links
local links = { }
local links_n = 0
for _,line in ipairs(lines) do
for link in line:gmatch("%[(.-)%]") do
links_n = links_n + 1
links[links_n] = link
end
end
return links
end
local function load_page(name, player) --> text, links, allow_save
local text, allow_save = wikilib.plugin_handle_load(name, player)
if text then
return text, find_links(text:split("\n")), allow_save
end
local path, is_file, allow_save = get_page_path(name, player)
local f
if is_file then
f = io.open(path)
if not f then
f = strfile.open(wikilib.internal_pages[".NotFound"])
end
else
f = strfile.open(path)
end
local lines = { }
local lines_n = 0
for line in f:lines() do
lines_n = lines_n + 1
lines[lines_n] = line
end
f:close()
local text = table.concat(lines, "\n")
local links = find_links(lines)
return text, links, allow_save
end
local function save_page(name, player, text)
local ok = wikilib.plugin_handle_save(name, player, text)
if ok then return ok end
local path, is_file, allow_save = get_page_path(name, player)
if (not is_file) or (not allow_save) then return end
local f = io.open(path, "w")
if not f then return end
f:write(text)
f:close()
end
local esc = minetest.formspec_escape
function wikilib.show_wiki_page(player, name)
if name == "" then name = "Main" end
local text, links, allow_save = load_page(name, player)
local buttons = ""
local bx = 0
local by = 7.5
for i, link in ipairs(links) do
if ((i - 1) % 5) == 0 then
bx = 0
by = by + 0.5
end
link = esc(link)
buttons = buttons..(("button[%f,%f;2.4,0.3;page_%s;%s]"):format(bx, by, link, link))
bx = bx + 2.4
end
local toolbar
if allow_save then
toolbar = "button[0,9;2.4,1;save;Save]"
else
toolbar = "label[0,9;You are not authorized to edit this page.]"
end
minetest.show_formspec(player, WIKI_FORMNAME, ("size[12,10]"
.. "field[0,1;11,1;page;Page;"..esc(name).."]"
.. "button[11,1;1,0.5;go;Go]"
.. "textarea[0,2;12,6;text;"..esc(name)..";"..esc(text).."]"
.. buttons
.. toolbar
))
end
minetest.register_node("wiki:wiki", {
description = "Wiki",
tiles = { "default_wood.png", "default_wood.png", "default_bookshelf.png" },
groups = { choppy=3, oddly_breakable_by_hand=2, flammable=3 },
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", "Wiki")
end,
on_rightclick = function(pos, node, clicker, itemstack)
if clicker then
wikilib.show_wiki_page(clicker:get_player_name(), "Main")
end
end,
})
minetest.register_privilege("wiki", {
description = "Allow editing wiki pages in the global space",
give_to_singleplayer = false,
})
minetest.register_privilege("wiki_admin", {
description = "Allow editing wiki pages in any space",
give_to_singleplayer = false,
})
local BS = "default:bookshelf"
local BSL = { BS, BS, BS }
minetest.register_craft({
output = "wiki:wiki",
recipe = { BSL, BSL, BSL },
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if (not formname) or (formname ~= WIKI_FORMNAME) then return end
local plname = player:get_player_name()
if fields.save then
local r = save_page(fields.page, plname, fields.text)
if type(r) == "string" then
wikilib.show_wiki_page(plname, r)
else
wikilib.show_wiki_page(plname, fields.page)
end
elseif fields.go then
wikilib.show_wiki_page(plname, fields.page)
else
for k in pairs(fields) do
if type(k) == "string" then
local name = k:match("^page_(.*)")
if name then
wikilib.show_wiki_page(plname, name)
end
end
end
end
end)