Add kick above certain number of violations (#2)

Keep track of muted players, prevents players without shout being shown wrong message
Add kick after 3 mutes in 5 minutes (ish)
Split chat message callback in to functions, this would allow other mods to use the functions to check for spam and write their own violation mechanisms (although I'd like to add a callback)
Add word count to chat command
Add support for words.txt file in mod, to avoid having to manually enter loads of items. In future support for reading from world files using /filter import words.txt could be added.
Make filter case insensitive
Add gitignore
This commit is contained in:
Andrew Ward 2018-02-02 17:07:41 +00:00 committed by sofar
parent da43e4aabd
commit fea7973687
2 changed files with 197 additions and 26 deletions

113
.gitignore vendored Normal file
View File

@ -0,0 +1,113 @@
words*.txt
# Created by https://www.gitignore.io/api/lua,linux,macos,windows
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Lua ###
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.gitignore.io/api/lua,linux,macos,windows

110
init.lua
View File

@ -24,43 +24,99 @@
]]--
filter = {}
local words = {}
local muted = {}
local violations = {}
local s = minetest.get_mod_storage()
assert(s, "minetest version too old")
local words
local sw = s:get_string("words")
function filter.init()
local sw = s:get_string("words")
if sw and sw ~= "" then
words = minetest.parse_json(sw)
end
if sw and sw ~= "" then
words = minetest.parse_json(sw)
else
words = {}
if #words == 0 then
filter.import_file(minetest.get_modpath("filter") .. "/words.txt")
end
end
minetest.register_on_chat_message(function(name, message)
function filter.import_file(filepath)
local file = io.open(filepath, "r")
if file then
for line in file:lines() do
line = line:trim()
if line ~= "" then
words[#words + 1] = line:trim()
end
end
return true
else
return false
end
end
function filter.check_message(name, message)
for _, w in ipairs(words) do
if string.find(message:lower(), "%f[%a]" .. w .. "%f[%A]") then
return false
end
end
return true
end
function filter.on_violation(name, message)
violations[name] = (violations[name] or 0) + 1
local resolution
if violations[name] >= 3 then
resolution = "kicked"
minetest.kick_player(name, "Please mind your language!")
else
resolution = "muted"
local privs = minetest.get_player_privs(name)
privs.shout = nil
minetest.set_player_privs(name, privs)
minetest.chat_send_player(name, "Watch your language! You have been temporarily muted")
muted[name] = true
minetest.after(60, function()
muted[name] = nil
minetest.chat_send_player(name, "Chat privilege reinstated. Please do not abuse chat.")
privs.shout = true
minetest.set_player_privs(name, privs)
end)
end
minetest.log("action", "VIOLATION (" .. resolution .. "): <" .. name .. "> ".. message)
end
table.insert(minetest.registered_on_chat_messages, 1, function(name, message)
local privs = minetest.get_player_privs(name)
if not privs.shout then
if not privs.shout and muted[name] then
minetest.chat_send_player(name, "You are temporarily muted.")
return true
end
for _, w in ipairs(words) do
if string.find(message, "%f[%a]" .. w .. "%f[%A]") then
privs.shout = nil
minetest.set_player_privs(name, privs)
minetest.chat_send_player(name, "Chat temporarily disabled due to language.")
if not filter.check_message(name, message) then
filter.on_violation(name, message)
return true
end
end)
minetest.after(60, function()
minetest.chat_send_player(name, "Chat privilege reinstated. Please do not abuse chat.")
privs.shout = true
minetest.set_player_privs(name, privs)
end)
return true
local function step()
for name, v in pairs(violations) do
violations[name] = math.floor(v * 0.5)
if violations[name] < 1 then
violations[name] = nil
end
end
return false
end)
minetest.after(2*60, step)
end
minetest.after(2*60, step)
minetest.register_chatcommand("filter", {
params = "filter server",
@ -69,7 +125,7 @@ minetest.register_chatcommand("filter", {
func = function(name, param)
local cmd, val = param:match("(%w+) (.+)")
if param == "list" then
return true, table.concat(words, ", ")
return true, #words .. " words: " .. table.concat(words, ", ")
elseif cmd == "add" then
table.insert(words, val)
s:set_string("words", minetest.write_json(words))
@ -84,7 +140,9 @@ minetest.register_chatcommand("filter", {
end
return true, "\"" .. val .. "\" not found in list."
else
return true, "Usage: /filter <add|remove|list> [<word>]"
return true, "I know " .. #words .. " words.\nUsage: /filter <add|remove|list> [<word>]"
end
end,
})
filter.init()