-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Channel based bans Write storage, restructure, add info messages Fix all bugs Fix all documentation Add crash prevention feature dos2unix * Basic tests for channel ban Load auth for tests Disable invalid player name smoke test
- Loading branch information
Showing
4 changed files
with
233 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
--luacheck: no_unused_args | ||
|
||
-- | ||
-- Data storage and helpers to persist channel bans through server restarts | ||
-- | ||
|
||
local channels = setmetatable(minetest.deserialize(beerchat.mod_storage:get("ban.channels")) or {}, { | ||
__index = function(p,k) | ||
return setmetatable({}, { | ||
__newindex = function(t, n, v) | ||
if not rawget(p,k) then rawset(p,k,{}) end | ||
p[k][n] = v | ||
end | ||
}) | ||
end | ||
}) | ||
|
||
local function write_storage() | ||
local data = minetest.serialize(channels) | ||
beerchat.mod_storage:set_string("ban.channels", data) | ||
end | ||
|
||
-- | ||
-- Register basic API for channel bans | ||
-- | ||
|
||
beerchat.ban = { | ||
priv = minetest.settings:get("beerchat.ban.priv") or "ban" | ||
} | ||
|
||
beerchat.ban.is_player_banned = function(channel, player_name) | ||
return not not channels[channel][player_name] | ||
end | ||
|
||
beerchat.ban.ban_player = function(channel, player_name) | ||
-- Can store timestamp or table for temporary ban or extended ban configuration | ||
channels[channel][player_name] = true | ||
end | ||
|
||
beerchat.ban.unban_player = function(channel, player_name) | ||
channels[channel][player_name] = nil | ||
end | ||
|
||
-- | ||
-- Register beerchat event handlers for channel bans | ||
-- | ||
|
||
beerchat.register_callback('before_send', function(name, message, channel) | ||
if beerchat.ban.is_player_banned(channel, name) then | ||
return false, "Sorry but you are banned on #"..channel..", you are not allowed to send messages there." | ||
end | ||
end) | ||
|
||
beerchat.register_callback('before_send_me', function(name, message, channel) | ||
if beerchat.ban.is_player_banned(channel, name) then | ||
return false, "Sorry but you are banned on #"..channel..", you are not allowed to send messages there." | ||
end | ||
end) | ||
|
||
-- | ||
-- Register chat commands for channel bans | ||
-- | ||
|
||
local function channel_ban(name, param) | ||
if not param or param == "" then | ||
return false, "ERROR: Invalid number of arguments. Please supply the player name(s)." | ||
end | ||
|
||
local channel = beerchat.get_player_channel(name) | ||
if not channel then | ||
beerchat.fix_player_channel(name, true) | ||
return true | ||
end | ||
|
||
local player_names = string.gmatch(param, "[^%s,]+") | ||
for player_name in player_names do | ||
if not beerchat.ban.is_player_banned(channel, player_name) then | ||
if not minetest.player_exists(player_name) then | ||
-- Inform that player does not exist in database but add record anyway to allow banning external users | ||
minetest.chat_send_player(name, "WARNING: " .. player_name .. " is external user or does not exist.") | ||
end | ||
beerchat.ban.ban_player(channel, player_name) | ||
else | ||
minetest.chat_send_player(name, "Channel ban: " .. player_name .. " is already banned on #"..channel) | ||
end | ||
end | ||
write_storage() | ||
return true | ||
end | ||
|
||
minetest.register_chatcommand("channel_ban", { | ||
params = "<Player Name> [<Player Name> ...]", | ||
description = ("Ban players <Player Name> on current channel. Requires %s privilege."):format(beerchat.ban.priv), | ||
privs = { [beerchat.ban.priv] = true }, | ||
func = channel_ban | ||
}) | ||
|
||
local function channel_unban(name, param) | ||
local channel = beerchat.get_player_channel(name) | ||
if not channel then | ||
beerchat.fix_player_channel(name, true) | ||
return true | ||
end | ||
|
||
if not param or param == "" then | ||
-- List banned names | ||
local names = {} | ||
for player_name,_ in pairs(channels[channel]) do | ||
table.insert(names, player_name) | ||
end | ||
if #names > 0 then | ||
minetest.chat_send_player(name, "Players banned on #"..channel..": " .. table.concat(names, ", ")) | ||
else | ||
minetest.chat_send_player(name, "Nobody is banned on #"..channel) | ||
end | ||
else | ||
-- Unban players | ||
local player_names = string.gmatch(param, "[^%s,]+") | ||
for player_name in player_names do | ||
if beerchat.ban.is_player_banned(channel, player_name) then | ||
beerchat.ban.unban_player(channel, player_name) | ||
else | ||
minetest.chat_send_player(name, "WARNING: " .. player_name .. " is not banned on #"..channel) | ||
end | ||
end | ||
end | ||
write_storage() | ||
return true | ||
end | ||
|
||
minetest.register_chatcommand("channel_unban", { | ||
params = "[<Player Name> [<Player Name> ...]]", | ||
description = ("Unban players <Player Name> on current channel. Requires %s privilege."):format(beerchat.ban.priv), | ||
privs = { [beerchat.ban.priv] = true }, | ||
func = channel_unban | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
require("mineunit") | ||
|
||
mineunit("core") | ||
mineunit("player") | ||
mineunit("server") | ||
mineunit("auth") | ||
|
||
sourcefile("init") | ||
|
||
-- Players, initialized in test environment setup functions | ||
local SX, XX, XX_channel, XX_name | ||
local XX_count = 0 | ||
|
||
local function do_setup() | ||
SX = Player("SX", { shout = 1, ban = 1 }) | ||
mineunit:execute_on_joinplayer(SX) | ||
assert.equals("main", beerchat.get_player_channel("SX")) | ||
end | ||
|
||
local function do_teardown() | ||
mineunit:execute_on_leaveplayer(SX) | ||
end | ||
|
||
local function do_before_each() | ||
XX_count = XX_count + 1 | ||
XX_name = "XX"..XX_count | ||
XX = Player(XX_name, { shout = 1 }) | ||
mineunit:execute_on_joinplayer(XX) | ||
XX_channel = beerchat.get_player_channel(XX_name) | ||
end | ||
|
||
local function do_after_each() | ||
mineunit:execute_on_leaveplayer(XX) | ||
XX = nil | ||
XX_name = nil | ||
XX_channel = nil | ||
end | ||
|
||
describe("channel_ban command", function() | ||
|
||
setup(do_setup) | ||
teardown(do_teardown) | ||
before_each(do_before_each) | ||
after_each(do_after_each) | ||
|
||
it("records channel ban", function() | ||
assert.is_false(beerchat.ban.is_player_banned(XX_channel, XX_name)) | ||
SX:send_chat_message("/channel_ban "..XX_name) | ||
assert.is_true(beerchat.ban.is_player_banned(XX_channel, XX_name)) | ||
end) | ||
|
||
it("handles players that are already banned", function() | ||
SX:send_chat_message("/channel_ban "..XX_name) | ||
SX:send_chat_message("/channel_ban "..XX_name) | ||
assert.is_true(beerchat.ban.is_player_banned(XX_channel, XX_name)) | ||
end) | ||
|
||
it("handles invalid player name", function() | ||
pending("Mineunit auth handler raises exception for invalid names, this test wont work") | ||
SX:send_chat_message("/channel_ban ***") | ||
end) | ||
|
||
it("handles empty player name", function() | ||
SX:send_chat_message("/channel_ban") | ||
assert.equals("main", beerchat.get_player_channel("SX")) | ||
assert.is_false(beerchat.ban.is_player_banned("main", "SX")) | ||
end) | ||
|
||
end) | ||
|
||
describe("channel_unban command", function() | ||
|
||
setup(do_setup) | ||
teardown(do_teardown) | ||
before_each(do_before_each) | ||
after_each(do_after_each) | ||
|
||
it("handles invalid player name", function() | ||
SX:send_chat_message("/channel_unban ***") | ||
end) | ||
|
||
it("handles empty player name", function() | ||
SX:send_chat_message("/channel_unban") | ||
end) | ||
|
||
it("handles players that are not banned", function() | ||
SX:send_chat_message("/channel_unban "..XX_name) | ||
assert.equals(XX_channel, beerchat.get_player_channel(XX_name)) | ||
assert.is_false(beerchat.ban.is_player_banned(XX_channel, XX_name)) | ||
end) | ||
|
||
end) |