2018-01-12 16:08:51 -08:00
|
|
|
|
-- chat3/init.lua
|
2018-01-12 18:20:52 -08:00
|
|
|
|
-- implemented chat_anticurse by SaKeL:
|
|
|
|
|
-- Minetest 0.4.10+ mod: chat_anticurse
|
|
|
|
|
-- punish player for cursing by disconnecting them
|
|
|
|
|
--
|
|
|
|
|
-- Created in 2015 by Andrey.
|
|
|
|
|
-- This mod is Free and Open Source Software, released under the LGPL 2.1 or later.
|
|
|
|
|
--
|
|
|
|
|
-- See README.txt for more information.
|
|
|
|
|
|
|
|
|
|
chat_anticurse = {}
|
|
|
|
|
chat_anticurse.simplemask = {}
|
2018-01-12 16:08:51 -08:00
|
|
|
|
|
|
|
|
|
chat3 = {}
|
|
|
|
|
|
|
|
|
|
chat3.settings = {}
|
|
|
|
|
chat3.storage = minetest.get_mod_storage()
|
|
|
|
|
|
|
|
|
|
local modpath = minetest.get_modpath("chat3")
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
--- Handle Settings
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
-- [function] Get float setting
|
|
|
|
|
function chat3.settings.get_int(key)
|
|
|
|
|
local res = minetest.settings:get(key)
|
|
|
|
|
if res then
|
|
|
|
|
return tonumber(res)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- [function] Get boolean setting
|
|
|
|
|
function chat3.settings.get_bool(key, default)
|
|
|
|
|
local retval = minetest.settings:get_bool(key)
|
|
|
|
|
|
|
|
|
|
if default and retval == nil then
|
|
|
|
|
retval = default
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return retval
|
|
|
|
|
end
|
|
|
|
|
|
2018-01-12 18:20:52 -08:00
|
|
|
|
local prot = {} -- Table of protocol versions - to be used later
|
|
|
|
|
|
2018-01-12 16:08:51 -08:00
|
|
|
|
local bell = chat3.settings.get_bool("chat3.bell")
|
|
|
|
|
local shout = chat3.settings.get_bool("chat3.shout")
|
|
|
|
|
local prefix = minetest.settings:get("chat3.shout_prefix") or "!"
|
|
|
|
|
local near = chat3.settings.get_int("chat3.near") or 12
|
|
|
|
|
local ignore = chat3.settings.get_bool("chat3.ignore", true)
|
|
|
|
|
local alt = chat3.settings.get_bool("chat3.alt_support", true)
|
|
|
|
|
|
|
|
|
|
if prefix:len() > 1 then
|
|
|
|
|
prefix = "!"
|
|
|
|
|
end
|
|
|
|
|
|
2018-01-12 18:20:52 -08:00
|
|
|
|
-- some english and some russian curse words
|
|
|
|
|
-- i don't want to keep these words as cleartext in code, so they are stored like this.
|
|
|
|
|
local x1="a"
|
|
|
|
|
local x2="i"
|
|
|
|
|
local x3="u"
|
|
|
|
|
local x4="e"
|
|
|
|
|
local x5="o"
|
|
|
|
|
local y1="y"
|
|
|
|
|
local y2="и"
|
|
|
|
|
local y3="о"
|
|
|
|
|
local y4="е"
|
|
|
|
|
local y5="я"
|
|
|
|
|
|
2018-01-16 07:24:53 -08:00
|
|
|
|
chat_anticurse.simplemask[1] = " c"..x3.."nt "
|
2018-01-12 18:20:52 -08:00
|
|
|
|
chat_anticurse.simplemask[2] = " d" .. ""..x2.."ck"
|
|
|
|
|
chat_anticurse.simplemask[3] = " p"..x4.."n" .. "is"
|
|
|
|
|
chat_anticurse.simplemask[4] = " p" .. ""..x3.."ssy"
|
|
|
|
|
chat_anticurse.simplemask[5] = " h"..x5.."" .. "r".."ny "
|
|
|
|
|
chat_anticurse.simplemask[6] = " b"..x2.."" .. "tch "
|
|
|
|
|
chat_anticurse.simplemask[7] = " b"..x2.."" .. "tche"
|
|
|
|
|
chat_anticurse.simplemask[8] = " s"..x4.."" .. "x"
|
|
|
|
|
chat_anticurse.simplemask[9] = " "..y4.."б" .. "а"
|
|
|
|
|
chat_anticurse.simplemask[10] = " бл"..y5.."" .. " "
|
|
|
|
|
chat_anticurse.simplemask[11] = " ж" .. ""..y3.."п"
|
|
|
|
|
chat_anticurse.simplemask[12] = " х" .. ""..y1.."й"
|
|
|
|
|
chat_anticurse.simplemask[13] = " ч" .. "л"..y4.."н"
|
|
|
|
|
chat_anticurse.simplemask[14] = " п"..y2.."" .. "зд"
|
|
|
|
|
chat_anticurse.simplemask[15] = " в"..y3.."" .. "збуд"
|
|
|
|
|
chat_anticurse.simplemask[16] = " в"..y3.."з" .. "б"..y1.."ж"
|
|
|
|
|
chat_anticurse.simplemask[17] = " сп"..y4.."" .. "рм"
|
|
|
|
|
chat_anticurse.simplemask[18] = " бл"..y5.."" .. "д"
|
|
|
|
|
chat_anticurse.simplemask[19] = " бл"..y5.."" .. "ть"
|
|
|
|
|
chat_anticurse.simplemask[20] = " с" .. ""..y4.."кс"
|
|
|
|
|
chat_anticurse.simplemask[21] = " f" .. ""..x3.."ck"
|
|
|
|
|
chat_anticurse.simplemask[22] = ""..x1.."rs"..x4.."h"..x5.."l"..x4..""
|
2018-01-16 07:24:53 -08:00
|
|
|
|
-- chat_anticurse.simplemask[23] = " "..x1.."s" .. "s "
|
2018-01-12 18:20:52 -08:00
|
|
|
|
|
|
|
|
|
chat_anticurse.check_message = function(name, message)
|
|
|
|
|
local checkingmessage = string.lower( name.." "..message .." " )
|
|
|
|
|
local uncensored = 0
|
|
|
|
|
|
|
|
|
|
-- check for any swear occurance from simplemask
|
|
|
|
|
for i=1, #chat_anticurse.simplemask do
|
|
|
|
|
-- split sentence in to words and check every word
|
|
|
|
|
-- print("find mask: ", chat_anticurse.simplemask[i]:gsub("%s+", ""))
|
|
|
|
|
|
|
|
|
|
for j in string.gmatch(checkingmessage, "%S+") do
|
|
|
|
|
-- remove any remaining spaces from chat word and simplemask word and check for any swear occurance
|
|
|
|
|
-- print("in chat word: ", j:gsub("%s+", ""))
|
|
|
|
|
if string.find(j:gsub("%s+", ""), chat_anticurse.simplemask[i]:gsub("%s+", ""), 1, true) ~= nil then
|
|
|
|
|
-- print("found: ", j:gsub("%s+", ""))
|
|
|
|
|
uncensored = 2
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if uncensored == 2 then break end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--additional checks
|
|
|
|
|
if string.find(checkingmessage, " c"..x3.."" .. "m ", 1, true) ~=nil and
|
|
|
|
|
not (string.find(checkingmessage, " c"..x3.."" .. "m " .. "se", 1, true) ~=nil) and
|
|
|
|
|
not (string.find(checkingmessage, " c"..x3.."" .. "m " .. "to", 1, true) ~=nil) then
|
|
|
|
|
uncensored = 2
|
|
|
|
|
end
|
|
|
|
|
return uncensored
|
|
|
|
|
end
|
|
|
|
|
|
2018-01-12 16:08:51 -08:00
|
|
|
|
---
|
|
|
|
|
--- Load Features
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
if ignore then dofile(modpath.."/ignore.lua") end -- Load ignore
|
|
|
|
|
if alt then dofile(modpath.."/alt.lua") end -- Load alt
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
--- Exposed Functions (API)
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
-- [function] Colorize
|
|
|
|
|
function chat3.colorize(name, colour, msg)
|
|
|
|
|
local vers = prot[name]
|
|
|
|
|
if vers and vers >= 27 then
|
|
|
|
|
return minetest.colorize(colour, msg)
|
|
|
|
|
else
|
|
|
|
|
return msg
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- [function] Check if mentioned (should highlight or not)
|
|
|
|
|
function chat3.is_mentioned(name, msg)
|
|
|
|
|
name, msg = name:lower(), msg:lower()
|
|
|
|
|
|
|
|
|
|
-- Direct mentions
|
|
|
|
|
local direct_mention = msg:find(name, 1, true)
|
|
|
|
|
|
|
|
|
|
-- Alt mentions
|
|
|
|
|
local alt_mention
|
|
|
|
|
if alt then
|
|
|
|
|
local list = chat3.alt.get(name)
|
|
|
|
|
for alt, i in pairs(list) do
|
|
|
|
|
alt_mention = msg:find(alt, 1, true) or alt_mention
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return direct_mention or alt_mention
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- [function] Process
|
|
|
|
|
function chat3.send(name, msg, prefix, source)
|
|
|
|
|
if minetest.get_modpath("ranks") and source ~= "ranks" then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local sender = minetest.get_player_by_name(name)
|
2018-11-10 18:38:15 -08:00
|
|
|
|
local privs = minetest.get_player_privs(name)
|
|
|
|
|
|
|
|
|
|
if not privs.shout then
|
|
|
|
|
return
|
|
|
|
|
end
|
2018-01-12 16:08:51 -08:00
|
|
|
|
|
|
|
|
|
for _, player in pairs(minetest.get_connected_players()) do
|
|
|
|
|
local rname = player:get_player_name()
|
|
|
|
|
local colour = "#ffffff"
|
|
|
|
|
|
|
|
|
|
local vers = prot[rname]
|
|
|
|
|
if (not vers or (vers and (vers >= 29 or (vers < 29 and name ~= rname))))
|
|
|
|
|
and (not ignore or not chat3.ignore.is(rname, name)) then
|
|
|
|
|
-- Check for near
|
|
|
|
|
if near ~= 0 then -- and name ~= rname then
|
|
|
|
|
if vector.distance(sender:getpos(), player:getpos()) <= near then
|
|
|
|
|
colour = "#88ffff"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Check for mentions
|
|
|
|
|
if chat3.is_mentioned(rname, msg) then
|
|
|
|
|
colour = "#00ff00"
|
|
|
|
|
|
|
|
|
|
-- Chat bell
|
|
|
|
|
if bell and name ~= rname then
|
|
|
|
|
local pbell = player:get_attribute("chat3:bell")
|
|
|
|
|
if pbell ~= "false" then
|
|
|
|
|
minetest.sound_play("chat3_bell", {
|
|
|
|
|
gain = 4,
|
|
|
|
|
to_player = rname,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Check for shout
|
|
|
|
|
if shout and msg:sub(1, 1) == prefix then
|
|
|
|
|
colour = "#ff0000"
|
|
|
|
|
|
|
|
|
|
-- Chat bell
|
|
|
|
|
if bell and name ~= rname then
|
|
|
|
|
local pbell = player:get_attribute("chat3:bell")
|
|
|
|
|
if pbell ~= "false" then
|
|
|
|
|
minetest.sound_play("chat3_bell", {
|
|
|
|
|
gain = 4,
|
|
|
|
|
to_player = rname,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-01-13 09:21:41 -08:00
|
|
|
|
elseif name == rname then
|
|
|
|
|
-- if same player, set to white (not for shouting)
|
|
|
|
|
colour = "#ffffff"
|
2018-01-12 16:08:51 -08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Send message
|
|
|
|
|
local send = chat3.colorize(rname, colour, "<"..name.."> "..msg)
|
|
|
|
|
-- if prefix then
|
|
|
|
|
-- send = prefix..send
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
minetest.chat_send_player(rname, send)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Log message
|
|
|
|
|
minetest.log("action", "CHAT: ".."<"..name.."> "..msg)
|
|
|
|
|
|
|
|
|
|
-- Prevent from sending normally
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
--- Events/Definitions
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
-- [event] On join player
|
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
|
|
|
local name = player:get_player_name()
|
|
|
|
|
local info = minetest.get_player_information(name)
|
2018-01-13 09:14:57 -08:00
|
|
|
|
|
|
|
|
|
if not info then
|
|
|
|
|
minetest.log("warning", "[chat3] Didn't found player_information for player: "..name..". Falling back to old chat.")
|
|
|
|
|
prot[name] = 0
|
|
|
|
|
else
|
|
|
|
|
prot[name] = info.protocol_version
|
|
|
|
|
end
|
|
|
|
|
|
2018-01-12 16:08:51 -08:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
-- [event] On chat message
|
|
|
|
|
minetest.register_on_chat_message(function(name, msg)
|
2018-01-12 18:20:52 -08:00
|
|
|
|
local uncensored = chat_anticurse.check_message(name, msg)
|
2018-01-16 07:24:53 -08:00
|
|
|
|
local privs = minetest.get_player_privs(name)
|
2018-01-12 18:20:52 -08:00
|
|
|
|
|
|
|
|
|
if uncensored == 1 then
|
2018-01-16 07:24:53 -08:00
|
|
|
|
if privs.privs then return end
|
|
|
|
|
minetest.kick_player(name, "Hey! Was there a bad word?")
|
|
|
|
|
minetest.log("action", "Player "..name.." warned for cursing. Chat:"..msg)
|
|
|
|
|
return true
|
2018-01-12 18:20:52 -08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if uncensored == 2 then
|
2018-01-16 07:24:53 -08:00
|
|
|
|
if privs.privs then return end
|
|
|
|
|
minetest.kick_player(name, "Cursing or words, inappropriate to game server. Kids may be playing here!")
|
|
|
|
|
minetest.chat_send_all("Player <"..name.."> warned for cursing" )
|
|
|
|
|
minetest.log("action", "Player "..name.." warned for cursing. Chat:"..msg)
|
|
|
|
|
return true
|
2018-01-12 18:20:52 -08:00
|
|
|
|
end
|
|
|
|
|
|
2018-01-12 16:08:51 -08:00
|
|
|
|
return chat3.send(name, msg, prefix)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
-- [redefine] /msg
|
|
|
|
|
if minetest.chatcommands["msg"] then
|
|
|
|
|
local old_command = minetest.chatcommands["msg"].func
|
|
|
|
|
minetest.override_chatcommand("msg", {
|
|
|
|
|
func = function(name, param)
|
2018-01-12 18:20:52 -08:00
|
|
|
|
local uncensored = chat_anticurse.check_message(name, param)
|
2018-01-16 07:24:53 -08:00
|
|
|
|
local privs = minetest.get_player_privs(name)
|
2018-01-12 18:20:52 -08:00
|
|
|
|
|
|
|
|
|
if uncensored == 1 then
|
2018-01-16 07:24:53 -08:00
|
|
|
|
if privs.privs then return end
|
|
|
|
|
minetest.kick_player(name, "Hey! Was there a bad word?")
|
|
|
|
|
minetest.log("action", "Player "..name.." warned for cursing. Msg:"..param)
|
|
|
|
|
return
|
2018-01-12 18:20:52 -08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if uncensored == 2 then
|
2018-01-16 07:24:53 -08:00
|
|
|
|
if privs.privs then return end
|
|
|
|
|
minetest.kick_player(name, "Cursing or words, inappropriate to game server. Kids may be playing here!")
|
|
|
|
|
minetest.chat_send_all("Player <"..name.."> warned for cursing" )
|
|
|
|
|
minetest.log("action", "Player "..name.." warned for cursing. Msg:"..param)
|
|
|
|
|
return
|
2018-01-12 18:20:52 -08:00
|
|
|
|
end
|
|
|
|
|
|
2018-01-12 16:08:51 -08:00
|
|
|
|
local sendto, message = param:match("^(%S+)%s(.+)$")
|
|
|
|
|
if not sendto then
|
|
|
|
|
return false, "Invalid usage, see /help msg."
|
|
|
|
|
end
|
|
|
|
|
if not minetest.get_player_by_name(sendto) then
|
|
|
|
|
return false, "The player " .. sendto
|
|
|
|
|
.. " is not online."
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if ignore and chat3.ignore.is(sendto, name) then
|
|
|
|
|
return false, chat3.colorize(name, "red",
|
|
|
|
|
"Could not send message, you are on "..sendto.."'s ignore list.")
|
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
minetest.log("action", "PM from " .. name .. " to " .. sendto
|
|
|
|
|
.. ": " .. message)
|
2018-01-12 16:19:02 -08:00
|
|
|
|
minetest.chat_send_player(sendto, chat3.colorize(sendto, '#ffff00',
|
2018-01-12 16:08:51 -08:00
|
|
|
|
"PM from " .. name .. ": ".. message))
|
|
|
|
|
|
|
|
|
|
if bell then
|
|
|
|
|
local player = minetest.get_player_by_name(sendto)
|
|
|
|
|
local pbell = player:get_attribute("chat3:bell")
|
|
|
|
|
if pbell ~= "false" then
|
|
|
|
|
minetest.sound_play("chat3_bell", {
|
|
|
|
|
gain = 4,
|
|
|
|
|
to_player = sendto,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if ignore and chat3.ignore.is(name, sendto) then
|
|
|
|
|
return true, "Message sent.\n"..chat3.colorize(name, "red",
|
|
|
|
|
"Warning: "..sendto.." will not be able to respond to this"
|
|
|
|
|
.." message unless you remove them from your ignore list.")
|
|
|
|
|
else
|
|
|
|
|
return true, "Message sent."
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- [redefine] /me
|
|
|
|
|
if minetest.chatcommands["me"] then
|
|
|
|
|
local old_command = minetest.chatcommands["me"]
|
|
|
|
|
minetest.override_chatcommand("me", {
|
|
|
|
|
func = function(name, param)
|
2018-01-12 18:20:52 -08:00
|
|
|
|
local uncensored = chat_anticurse.check_message(name, param)
|
2018-01-16 07:24:53 -08:00
|
|
|
|
local privs = minetest.get_player_privs(name)
|
2018-01-12 18:20:52 -08:00
|
|
|
|
|
|
|
|
|
if uncensored == 1 then
|
2018-01-16 07:24:53 -08:00
|
|
|
|
if privs.privs then return end
|
|
|
|
|
minetest.kick_player(name, "Hey! Was there a bad word?")
|
|
|
|
|
minetest.log("action", "Player "..name.." warned for cursing. Msg:"..param)
|
|
|
|
|
return
|
2018-01-12 18:20:52 -08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if uncensored == 2 then
|
2018-01-16 07:24:53 -08:00
|
|
|
|
if privs.privs then return end
|
|
|
|
|
minetest.kick_player(name, "Cursing or words, inappropriate to game server. Kids may be playing here!")
|
|
|
|
|
minetest.chat_send_all("Player <"..name.."> warned for cursing" )
|
|
|
|
|
minetest.log("action", "Player "..name.." warned for cursing. Me:"..param)
|
|
|
|
|
return
|
2018-01-12 18:20:52 -08:00
|
|
|
|
end
|
|
|
|
|
|
2018-01-12 16:08:51 -08:00
|
|
|
|
for _, player in pairs(minetest.get_connected_players()) do
|
|
|
|
|
local rname = player:get_player_name()
|
|
|
|
|
|
|
|
|
|
if not ignore or not chat3.ignore.is(rname, name) then
|
|
|
|
|
minetest.chat_send_player(rname, "* "..name.." "..param)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- [chatcommand] Chatbell
|
|
|
|
|
if bell then
|
|
|
|
|
minetest.register_chatcommand("chatbell", {
|
|
|
|
|
description = "Enable/disable chatbell when you are mentioned in the chat",
|
|
|
|
|
func = function(name)
|
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
|
|
|
if player then
|
|
|
|
|
local bell = player:get_attribute("chat3:bell")
|
|
|
|
|
if not bell or bell == "" or bell == "true" then
|
|
|
|
|
player:set_attribute("chat3:bell", "false")
|
|
|
|
|
return true, "Disabled Chatbell"
|
|
|
|
|
else
|
|
|
|
|
player:set_attribute("chat3:bell", "true")
|
|
|
|
|
return true, "Enabled Chatbell"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
end
|