name_restrictions/init.lua

232 lines
5.8 KiB
Lua
Raw Normal View History

2014-06-23 23:05:51 +02:00
-- name_restrictions mod by ShadowNinja
-- License: WTFPL
2014-06-25 22:25:35 +02:00
----------------------------
-- Restriction exemptions --
----------------------------
-- For legitimate player names that are caught by the filters.
local exemptions = {}
2014-10-14 20:36:58 +02:00
local temp = minetest.setting_get("name_restrictions.exemptions")
2014-06-25 22:25:35 +02:00
temp = temp and temp:split() or {}
for _, allowed_name in pairs(temp) do
exemptions[allowed_name] = true
end
temp = nil
2014-10-14 20:37:34 +02:00
-- Exempt server owner
exemptions[minetest.setting_get("name")] = true
exemptions["singleplayer"] = true
2014-06-25 22:25:35 +02:00
2014-06-23 23:05:51 +02:00
---------------------
-- Simple matching --
---------------------
2015-05-16 19:40:33 +02:00
local msg_guest = "Guest accounts are disallowed on this server. "..
"Please choose a proper name and try again."
local msg_misleading = "Your player name is misleading. "..
"Please choose a more appropriate name."
2014-06-23 23:05:51 +02:00
local disallowed = {
2015-05-16 19:40:33 +02:00
["^guest[0-9]+"] = msg_guest,
["^squeakecrafter[0-9]+"] = msg_guest,
["adm[1il]n"] = msg_misleading,
["[0o]wn[e3]r"] = msg_misleading,
["^[0-9]+$"] = "All-numeric usernames are disallowed on this server.",
2014-06-23 23:05:51 +02:00
}
minetest.register_on_prejoinplayer(function(name, ip)
if exemptions[name] then return end
-- Check for disallowed names
2014-06-23 23:05:51 +02:00
local lname = name:lower()
for re, reason in pairs(disallowed) do
if lname:find(re) then
return reason
end
end
end)
------------------------
-- Case-insensitivity --
------------------------
minetest.register_on_prejoinplayer(function(name, ip)
if exemptions[name] then return end
-- Check for used names
2014-06-23 23:05:51 +02:00
local lname = name:lower()
for iname, data in pairs(minetest.auth_table) do
if iname:lower() == lname and iname ~= name then
return "Sorry, someone else is already using this"
.." name. Please pick another name."
2014-10-14 23:52:29 +02:00
.." Annother possibility is that you used the"
2014-06-23 23:05:51 +02:00
.." wrong case for your name."
end
end
end)
-- Compatability, for old servers with conflicting players
minetest.register_chatcommand("choosecase", {
description = "Choose the casing that a player name should have.",
params = "<name>",
privs = {server=true},
func = function(name, params)
local lname = params:lower()
local worldpath = minetest.get_worldpath()
for iname, data in pairs(minetest.auth_table) do
if iname:lower() == lname and iname ~= params then
minetest.auth_table[iname] = nil
assert(not iname:find("[/\\]"))
os.remove(worldpath.."/players/"..iname)
end
end
return true, "Done."
end,
})
------------------------
-- Anti-impersonation --
------------------------
2014-10-14 23:52:29 +02:00
-- Prevents names that are too similar to another player's name.
2014-06-23 23:05:51 +02:00
local similar_chars = {
-- Only A-Z, a-z, 1-9, dash, and underscore are allowed in player names
2014-06-23 23:05:51 +02:00
"A4",
2014-06-25 22:25:35 +02:00
"B8",
2014-06-23 23:05:51 +02:00
"COco0",
"Ee3",
"Gg69",
"ILil1",
"S5",
"Tt7",
"Zz2",
}
-- Map of characters to a regex of similar characters
local char_map = {}
for _, str in pairs(similar_chars) do
for c in str:gmatch(".") do
if not char_map[c] then
char_map[c] = str
else
char_map[c] = char_map[c] .. str
end
end
end
for c, str in pairs(char_map) do
char_map[c] = "[" .. char_map[c] .."]"
end
-- Characters to match for, containing all characters
local all_chars = "["
for _, str in pairs(similar_chars) do
all_chars = all_chars .. str
end
all_chars = all_chars .. "]"
minetest.register_on_prejoinplayer(function(name, ip)
2014-06-25 22:25:35 +02:00
if exemptions[name] then return end
-- String off dashes and underscores from the start and end of the name.
local stripped_name = name:match("^[_-]*(.-)[_-]*$")
if not stripped_name or stripped_name == "" then
return "Your name is composed solely of whitespace-like characters."
end
-- Generate a regular expression to match all similar names
local re = stripped_name:gsub(all_chars, char_map)
2014-06-23 23:05:51 +02:00
re = "^[_-]*" .. re .. "[_-]*$"
2014-06-25 22:25:35 +02:00
2014-06-23 23:05:51 +02:00
for authName, _ in pairs(minetest.auth_table) do
if authName ~= name and authName:match(re) then
2014-10-14 23:52:29 +02:00
return "Your name is too similar to another player's name."
2014-06-23 23:05:51 +02:00
end
end
end)
2014-06-25 22:25:35 +02:00
-----------------
-- Name length --
-----------------
2014-10-14 20:36:58 +02:00
local min_name_len = tonumber(minetest.setting_get("name_restrictions.minimum_name_length")) or 3
2014-06-25 22:25:35 +02:00
minetest.register_on_prejoinplayer(function(name, ip)
if exemptions[name] then return end
if #name < min_name_len then
return "Your player name is too short, please try a longer name."
end
end)
----------------------
-- Pronounceability --
----------------------
-- Original implementation (in Python) by sfan5
local function pronounceable(pronounceability, text)
2014-06-25 22:25:35 +02:00
local pronounceable = 0
local nonpronounceable = 0
local cn = 0
local lastc = ""
for c in text:lower():gmatch(".") do
if c:find("[aeiou0-9_-]") then
if not c:find("[0-9]") then
if cn > 2 then
nonpronounceable = nonpronounceable + 1
else
pronounceable = pronounceable + 1
end
end
cn = 0
else
if cn == 1 and lastc == c and lastc ~= 's' then
nonpronounceable = nonpronounceable + 1
cn = 0
end
if cn > 2 then
nonpronounceable = nonpronounceable + 1
cn = 0
end
if lastc:find("[aeiou]") then
pronounceable = pronounceable + 1
cn = 0
end
if not (c == "r" and lastc:find("[aipfom]")) and
not (lastc == "c" and c == "h") then
cn = cn + 1
end
end
lastc = c
end
if cn > 0 then
nonpronounceable = nonpronounceable + 1
end
return pronounceable * pronounceability >= nonpronounceable
2014-06-25 22:25:35 +02:00
end
-- Pronounceability factor:
-- nil = Checking disabled.
-- 0 = Everything's unpronounceable.
-- 0.5 = Strict checking.
-- 1 = Normal checking.
-- 2 = Relaxed checking.
local pronounceability = tonumber(minetest.setting_get("name_restrictions.pronounceability"))
if pronounceability then
minetest.register_on_prejoinplayer(function(name, ip)
if exemptions[name] then return end
if not pronounceable(pronounceability, name) then
return "Your player name does not seem to be pronounceable."
.." Please choose a more pronounceable name."
end
end)
end
2014-06-25 22:25:35 +02:00