Ban System with Reason and who Banned the person

Please only respond if you have scripting knowledge on how to make these 2 things happen

  1. How can I make the moderator put in a ban reason?
    2 How can I make it show who banned the player? If u say something like add some admin list (idk how that would work) I just want to clarify I put this script in.
game.Players.PlayerAdded:Connect(function(Player)
	if Player:GetRankInGroup(15423675) >= 245 then
		Player.Chatted:Connect(function(Command)

Script:

DataStoreService = game:GetService("DataStoreService")
DataStore= DataStoreService:GetDataStore("TESTING")


			elseif SplitCommand[1] == ":ban" or SplitCommand[1] == ":Ban" then
				local TargetedPlayer = SplitCommand[2]
				local Name = game.Players:FindFirstChild(TargetedPlayer)
				DataStore:SetAsync(Name.UserId, true)



				local Banned
				local Success, Error pcall(function()
					Banned = BanDataStore:GetAsync(Player.UserId)
				end)
				if Banned == true then
					Player:Kick("You have been banned by a Blossom County moderator. If this was a mistake, please appeal in our Discord server linked below our game. Moderator:")

				end
			end
1 Like

Would be useful if you gave us the script properly, instead of two incomplete parts.

Also, try and avoid making multiple topics on the same subject, keep it in Showing who banned the player - Help and Feedback / Scripting Support - DevForum | Roblox.

Yea ik, I’m trying to make it all in one post. Next time I gonna just put it all in 1 post.

Wait rq… I think I might of found a way to insert a reason.

Assuming this is a .chatted function just do

local Moderator = Player.Name -- If its .chatted //\\ You can also do .DisplayName

local Reason = SplitCommand[3]
if Reason == nil or Reason == "" then
    Reason = "Default message here"
end

-- All your banning stuff
Player:Kick("You have been banned by a Blossom County moderator. Reason: " .. Reason  .. ". If this was a mistake, please appeal in our Discord server linked below our game. Moderator: " .. Moderator

That might work

Basically it only capture’s the 3rd argument and the first word of it.

Here’s some of my code and the “local Reason = SplitCommand[3]” is the problem. It’s only capturing the 3rd argument’s first word since the other word’s would count as the 4, 5, 6 arguments. So how can I make the Split capture more than a 3rd argument and everything including the 3rd argument and after since a Reason would be a long message sometimes MORE THAN 1 word.

local SplitCommand = Command:split(" ")

			elseif SplitCommand[1] == ":kick" or SplitCommand[1] == ":Kick" then
				local TargetedPlayer = SplitCommand[2]
				local Reason = SplitCommand[3]
				local Name = game.Players:FindFirstChild(TargetedPlayer)
				Name:Kick("You have been kicked by a Blossom County moderator. Reason: "..Reason)

What I do in my games is that I have four variables in the session data table that have the ban information.

sessionData = {
	Banned = false;
	BanReason = "";
	BanModUserId = -1;
	BanModUserName = "";
}

Of course that’s a subset of the entire session data table. Then on the PlayerAdded event, when the player’s data is loaded from the datastore, it checks if Banned is true or false. If true, then the player is kicked. The message gets generated as follows:

local function kickBannedPlayer(player, data)
	message = string.format("You have been banned from this game by %s for %s.",
		data.BanModUserName, data.BanReason)
	player:Kick(message)
end

I’m a bit confused since the reason wouldn’t show since you would need to split it, but split only captures 1 argument. I’m trying to make it capture MULTIPLE arguments since a message is multiple arguments needed.

elseif SplitCommand[1]:lower() == ":ban" then
				local TargetedPlayer = SplitCommand[2]
                local Reason = SplitCommand[3]
                if Reason then
				local Name = game.Players:FindFirstChild(TargetedPlayer)
				DataStore:SetAsync(Name.UserId, true)

				local Banned
				local Success, Error pcall(function()
					Banned = BanDataStore:GetAsync(Player.UserId)
				end)
				if Banned == true then
					Player:Kick("You have been banned by a Blossom County moderator For :"..Reason",If this was a mistake, please appeal in our Discord server linked below our game. Moderator: "..Player.Name)

				end
			end
end

Would that just capture the 3rd argument which could just be a letter? Since it’s only the 3rd argument which a message is multiple.

elseif SplitCommand[1]:lower() == ":ban" then
				local TargetedPlayer = SplitCommand[2]
                local ReasonTable = {}
                for i,v in pairs(SplitCommand) do
                if i ~= 1 and i ~= 2 then
                table.insert(ReasonTable,v)
                end
                end
                local Reason = table.concat(ReasonTable)
                table.clear(ReasonTable)
                if Reason then
				local Name = game.Players:FindFirstChild(TargetedPlayer)
				DataStore:SetAsync(Name.UserId, true)

				local Banned
				local Success, Error pcall(function()
					Banned = BanDataStore:GetAsync(Player.UserId)
				end)
				if Banned == true then
					Player:Kick("You have been banned by a Blossom County moderator For :"..Reason",If this was a mistake, please appeal in our Discord server linked below our game. Moderator: "..Player.Name)

				end
			end
end

One thing is in my opinion, you shouldn’t use discord for ban appeals, what if someone that is not allowed discord gets falsely banned? Then that user cannot appeal, maybe you should have a seprate game that makes a ticket from the game to a discord server via a API. That way people not allowed discord can still appeal their bans. Thats just my opinion on this. I don’t have any Luau scripting knowledge, im just giving you an idea for your appeal system.

What does the table thing mean? with concat???

it converts a table into a string.

Why do you need to split the message? The point is to combine the information into a message, if I read your original post correctly. Oh, I see. You’re trying to grab the reason. Take a look at this code:

local function tokenizeString(str)
	local tokens = string.split(str, " ")
	local prefix = string.sub(tokens[1], 1, 1)
	tokens[1] = string.lower(string.sub(tokens[1], 2))
	if prefix == config.chatService.prefix then
		return tokens
	end
	return nil
end

This code takes the input string and splits it into a table using the space character. For me, config.chatService.prefix = "/". Then it removes the first character from the string at index 1. If it’s a command, then this will be the prefix. If the prefix is the command prefix, then it returns the tokenized string as a table (with the prefix removed from the command) or nil if it’s not.

After that, the following indices apply:

  1. The command to process. “ban” in your case.
  2. The name or user id of the player to ban.
  3. The first word of the reason.

To combine the reason, you use table.concat starting at index 3 to the end of the table. Something like reason = table.concat(tokens, " ", 3) will reconstruct the reason string. Afterwards, if the player tries to log in, you ban them. The name of the moderator is captured in the process and is displayed according to string.format. If you’re familiar with C at all, C has a function called printf which uses replaceable parameters %d for decimal number, %s for string, %f for floating point number, %x for hex number, etc… which string.format also uses. Below is an excerpt from my sessionData table and my kickBannedPlayer function again for reference:

sessionData = {
	Banned = false;
	BanReason = "";
	BanModUserId = -1;
	BanModUserName = "";
}
local function kickBannedPlayer(player, data)
	message = string.format("You have been banned from this game by %s for %s.",
		data.BanModUserName, data.BanReason)
	player:Kick(message)
end

Looking at your code, instead of checking for both “:Ban” and “:ban”, just check for “ban” if you use my code. Doing it my way, you can set a variable to be the prefix and then just check for the command as tokens[1] will always be lower case and the prefix will be removed.

When building my admin commands system, I used this post as a guideline. My code is way more complicated than what is shown there, partly because I have implemented a method of banning offline players too.

Hope this helps.

Huh…I’m so confused. Could you show me code for just adding a kick reason? Since I’m trying to split it since the 3rd argument would be the message but a reason should contain multiple arguments since multiple spaces/words.

I gave you the code to recombine the table into a string if you are using my code. Here it is again:

reason = table.concat(tokens, " ", 3)

What this does is that it takes the table tokens, and starting at index 3, builds a string from each entry of the table using space as a separator. The tokenizeString function that I showed you will split the line into multiple components. Since index 3 and beyond is the reason, you recombine the table starting at index 3 to the end of the table. This requires that the reason be the last parameter of the command.