Need some help with string.sub/Chatted function

Hi there, I’ve made this little command script that bans and unbans players from my game, and I was wondering how I could incorporate a feature that includes the reason for the ban in the script? It’s a chat command based thing.

It should work like this:
/ban Player1 toxicity

Here’s the script below for reference. Thanks!

local DataStoreService = game:GetService("DataStoreService")
local BannedDataStore = DataStoreService:GetDataStore("Makeuparandomkeylike123567890")
local Players = game:GetService("Players")
 
local Admins = {"RuffianLewis"}
 
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)
    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 PlayersTable = FindPlayers(Player)
                if #PlayersTable == 1 then
                    BannedDataStore:SetAsync(PlayersTable[1].UserId, {true, CurrentPlayer.Name})
                    PlayersTable[1]:Kick(string.format("You have been banned by %s", CurrentPlayer.Name))
                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}) 
                end
            end
        end
    end
end)
end)

Maybe store it as a list for each player, something like {Player = {isBanned, Reason}} for each banned player

Thank you, however I don’t really understand.

With the overall script, when I say a reason, how can I add it to the string and link it to the actual ban function?

e.g. If I say ‘/ban Player1 Being a noob’, I want it so that it actually links to the ban message when they attempt to rejoin.

In the roblox DataStore you can set tables, and so get information.

For the kick message just add a string value to the kick example:

Player:Kick(Data[3])
Player:Kick("You are banned, Reason: "..Data[3])

Data3 Value must be a string.

For my point i use an external DataBase to ban people

I see. Looking at my script however, how exactly do I add this in? Currently the script is configured with just /ban player and not /ban player reason, so I just want to make sure on how to implement this in properly without the whole thing breaking.

So you are able to figure out if the message starts with /ban, then you can split the entire message into a list of words (“/ban manky94 for this reason” would become {“/ban”, “manky94”, “for”, “this”, “reason”}, and say list[2] is the player, list[3 - list length] is the reason

Could you please provide a short script example? Thanks.

This code splits the string and reconcatenates the reason:

local s = "/ban manky94 for this reason"

-- split string into list of words
words = {}
for word in s:gmatch("%w+") do table.insert(words, word) end

local player = words[2] -- get second index of string, which is the player
local reason = ""

-- concat reason, may be better ways to do this
for i=3, #words do
	reason = reason .. words[i] .. " "
end

print(player)
print(reason)

And the output (which I have stored as variables) is:

manky94
for this reason

Thanks for trying to help. However, I just wanted to know how I can add a third string into the chat command and store it, so the ban script can get it later to display in the ban message.

/ban - 1st string
player - 2nd string
reason - 3rd string

I didn’t really want it to be split like that. I just wanted to figure out how to add it in as another string for the ban script’s DataStore.

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?

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)

Try replacing lines 5&6 with this:

local MessageSections = string.split(string.lower(Message),’ ‘)
local Player = MessageSections[2]
for i = 3, #MessageSections do
   MessageSections[3] = MessageSections[3]..’ ‘..MessageSections[i]
end
local Reason = MessageSections[3]

We have to use string.split to find each word seperated by spaces, and we already know that the first word will be ‘/ban’, the second being the player’s username (as they can’t have spaces) and the third onwards being the reason.

Hope it helps. Tell me if there’s any more problems.