144 lines
3.7 KiB
Lua
Raw Normal View History

-- LUALOCALS < ---------------------------------------------------------
local ipairs, math, minetest, os, string, tonumber
= ipairs, math, minetest, os, string, tonumber
local math_random, os_time, string_format
= math.random, os.time, string.format
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local modstore = minetest.get_mod_storage()
local scaninterval = tonumber(minetest.settings:get(modname .. "_interval")) or 3600
local maxdays = tonumber(minetest.settings:get(modname .. "_maxdays")) or 90
local keepauth = minetest.settings:get_bool(modname .. "_keepauth")
local protectnames = {
singleplayer = true,
[minetest.settings:get("name")] = true,
}
local noprune = "noprune"
minetest.register_privilege(noprune, {
description = "Do not automatically prune player for unuse",
give_to_admin = false,
give_to_singleplayer = false,
})
------------------------------------------------------------------------
local queue_current
local queue_next
local queue_pos = 1
local function processqueue()
if queue_current then
local act = queue_current[queue_pos]
act()
queue_pos = queue_pos + 1
if queue_pos > #queue_current then
queue_current = nil
queue_pos = 1
end
end
if not queue_current then
queue_current = queue_next
queue_next = nil
end
if queue_current then
minetest.after(0, processqueue)
end
end
local function enqueue(act)
queue_next = queue_next or {}
queue_next[#queue_next + 1] = act
if not queue_current then
queue_current = queue_next
queue_next = nil
minetest.after(0, processqueue)
end
end
------------------------------------------------------------------------
do
local function bump(pname)
modstore:set_string(pname, string_format("%d", os_time()))
end
minetest.register_on_authplayer(function(pname, _, success)
if success then bump(pname) end
end)
minetest.register_on_joinplayer(function(player)
bump(player:get_player_name())
end)
minetest.register_on_leaveplayer(function(player)
bump(player:get_player_name())
end)
local function scanall()
for _, player in ipairs(minetest.get_connected_players()) do
bump(player:get_player_name())
end
end
minetest.register_on_shutdown(scanall)
local function bgscan()
minetest.after(1, bgscan)
return scanall()
end
minetest.after(0, bgscan)
end
------------------------------------------------------------------------
local function check(pname)
if protectnames[pname] or minetest.get_player_by_name(pname) then return end
local handler = minetest.get_auth_handler()
local data = handler.get_auth(pname)
if not data then return end
if data.privileges[noprune] then return end
local logintime = data.last_login
local seentime = tonumber(modstore:get_string(pname)) or 0
local seen = (logintime > seentime) and logintime or seentime
local now = os_time()
local daysago = (now - seen) / 86400
if daysago <= maxdays then return end
modstore:set_string(pname, "")
minetest.log("warning", string_format(
"Deleting player %q last seen %0.1f day(s) ago",
pname, daysago))
minetest.remove_player(pname)
if not keepauth then
minetest.log("warning", string_format(
"Purging player %q auth", pname))
return minetest.remove_player_auth(pname)
end
end
local function runscan()
local handler = minetest.get_auth_handler()
local names = {}
for name in handler.iterate() do
names[#names + 1] = name
end
for i = #names, 2, -1 do
local j = math_random(1, i)
local x = names[i]
names[i] = names[j]
names[j] = x
end
for i = 1, #names do
local pname = names[i]
enqueue(function() return check(pname) end)
end
end
local function startscan()
enqueue(runscan)
minetest.after(scaninterval, startscan)
end
minetest.after(0, startscan)