Assistance with a chat command-based ban system

Hey there, so I’m attempting to create a chat command-based ban and unban system. I’ve made an attempt to incorporate a reason string, and this is part of the code. However, it still bans the player but doesn’t provide the reason in the ban message. Can I have some help with this, please? Thank you!

P.S. An example of the command would be /ban Player1 reason. My goal is to ensure the reason translates onto the actual ban message when they attempt to join.

CurrentPlayer.Chatted:Connect(function(Message)
for _, Admin in pairs(Admins) do
    if CurrentPlayer.Name == Admin then
        if string.sub(string.lower(Message), 1, 4) == "/ban" then
            local Player = string.sub(string.lower(Message), 6, #Message + 6)
			local Reason = string.sub(string.lower(Message), 8, #Message + 8)
            local PlayersTable = FindPlayers(Player)
            if #PlayersTable == 1 then
                WhackedDataStore:SetAsync(PlayersTable[1].UserId, {true, CurrentPlayer.Name})
                PlayersTable[1]:Kick(string.format("You have been banned!", CurrentPlayer.Name, Reason))
            elseif #PlayersTable == 2 then
                print(string.format("There are more than one player named %s", Player))
            else
                print(string.format("Nobody in the server is named %s", Player))
            end
        elseif string.sub(string.lower(Message), 1, 6) == "/unban" then
            local Player = string.sub(string.lower(Message), 8, #Message + 8)
            local FindPlayer = Players:GetUserIdFromNameAsync(Player)
            if FindPlayer then
                BanDataStore:SetAsync(FindPlayer, {false, nil}) 
            end
        end
    end
end
end)
end)
2 Likes

For the loop that goes through all admin, you could probably use table.find. For the string.sub mess, can’t you just split the string at spaces? Quick example:

CurrentPlayer.Chatted:Connect(function(Message)
	if table.find(Admins, CurrentPlayer.Name) then
		local args = Message:split(" ")
		if args[1] = "/ban" then
			local Player = args[2]
			local Reason = table.concat({select(3, unpack(args))}, " ") -- everything third arg and after should keep its original spaces
			-- and so on now that u have player/reason easier

Edit: The reason this line doesn’t work…

… is because you don’t have somewhere for the name and reason to fill in. You need a % code to represent where you want string.format to put the other arguments. You did this correctly for the other string.formats, where you put %s, so I’m not sure why you did it differently here.

3 Likes

Thank you for the example. I’ve attempted to implement your example into the main script, but unfortunately failed to work. Here’s the full script for reference, could you perhaps tell me where I’ve gone wrong and how to fix it?

local DataStoreService = game:GetService("DataStoreService")
local BannedDataStore = DataStoreService:GetDataStore("Makeuparandomkeylike123567890")
local Players = game:GetService("Players")
 
local Admins = {"RuffianLewis", "Player1"}
 
function FindPlayers(String)
local FoundPlayers = {}
for _, CurrentPlayer in pairs(Players:GetPlayers()) do
    if string.match(String, string.lower(CurrentPlayer.Name)) then
        table.insert(FoundPlayers, CurrentPlayer)
    end
end
return FoundPlayers
end
 
Players.PlayerAdded:Connect(function(CurrentPlayer)
local Data = BannedDataStore:GetAsync(CurrentPlayer.UserId)
--[[
    Data[1] = IsBanned
    Data[2] = PlayerWhoBanned
    Data[3] = Reason
--]]
if Data then
    if Data[1] == true then
        CurrentPlayer:Kick("You have been banned by an admin")
    end
end
 
CurrentPlayer.Chatted:Connect(function(Message)
	if table.find(Admins, CurrentPlayer.Name) then
		local args = Message:split(" ")
		if args[1] == "/ban" then
			local Player = args[2]
			local Reason = table.concat({select(3, unpack(args))}, " ")
			if #PlayersTable ==  1 then
				BannedDataStore:SetAsync(PlayersTable[1].UserId, {true, CurrentPlayer.Name, Reason})
				PlayersTable[1]:Kick(string.format(args[3]))
                elseif #PlayersTable == 2 then
                    print(string.format("There are more than one player named %s", Player))
                else
                    print(string.format("Nobody in the server is named %s", Player))
                end
            elseif string.sub(string.lower(Message), 1, 6) == "/unban" then
                local Player = string.sub(string.lower(Message), 8, #Message + 8)
                local FindPlayer = Players:GetUserIdFromNameAsync(Player)
                if FindPlayer then
                    BannedDataStore:SetAsync(FindPlayer, {false, nil, nil}) 
                end
            end
        end
    end
end)
end)

Reason is the reason. You don’t need to do args[3], that will just be the first word of the reason. Also,

There’s no reason to use string.format here if you’re not formatting anything, and you’re not using the reason here:

Regardless, it should at least display something. Does it error, or just not display what you would expect?

3 Likes

The script completely failed. No output, no error. I think it did work, but it just didn’t ban the player because of my modifications to the script. Maybe I confused it? I’d just like to ensure that I am able to input a reason in the command whilst banning the player, and that the script is neat and works fully.

I’ve tried adding this to test out the function, but I’m still getting no output. Have I done anything wrong here?

CurrentPlayer.Chatted:Connect(function(Message)
if table.find(Admins, CurrentPlayer.Name) then
	local args = Message:Split(" ")
	if args[1] == "/ban" then
		print("Command fired by "..CurrentPlayer.Name)
		local Player = args[2]
		local Reason = table.concat({select(3, unpack(args))}, " ")
		print(Player, Reason)
	end
end
end)
1 Like

If that’s your exact code, it should be erroring at least. It’s :split(whatever), not :Split(whatever). Not erroring at all means I either messed up the if statement (try going back to your loop for that part) or the function doesn’t run at all.

2 Likes