How to find if a player is spamming - Custom Chat

So for my custom chat I want it so the player cannot keep spamming, and if they do, then it will be like the default chat where you cant send another message for let’s say, 10 seconds.

How would I do this? I already have a variable…
Here’s my script:

local Event = game.ReplicatedStorage.Remotes.ChatEvent

local devs = {"CaptainShipster","GavinJohnTheGreat"}
local owner = "IAmPinleon"

local UIS = game:GetService("UserInputService")

local frame = script.Parent.Messages
local chatBar = script.Parent.ChatBar

local temp = game.ReplicatedStorage.Template

local IsSpamming = false -- bool for checking if player keeps spamming

chatBar.FocusLost:Connect(function(ep)
	if (ep) and chatBar.Text ~= "" then
		Event:FireServer(chatBar.Text)
		chatBar.Text = ""
	else
		warn("Enter text")
	end
end)

UIS.InputBegan:Connect(function(input, gpe)
	if gpe then return end
	if input.KeyCode == Enum.KeyCode.Slash then
		chatBar:CaptureFocus()
		chatBar.Text = ""
	end
end)

Event.OnClientEvent:Connect(function(message, plr)
	local newChatMessage = temp:Clone()
	for i, name in pairs(devs) do
		if plr.Name == name then
			newChatMessage.PlayerName.Text = "[Developer] ".. tostring(plr) .. ":"
		elseif plr.Name == owner then
			newChatMessage.PlayerName.Text = "[Owner] ".. tostring(plr) .. ":"
		else
			newChatMessage.PlayerName.Text = tostring(plr) .. ":"
		end
	end
	newChatMessage.Message.Text = tostring(message)
	newChatMessage.Parent = frame
end)

You could achieve that by creating a table on the server and storing the player in it for 10 seconds.
Each time you get a new message, check if the player is in the table.


local Cooldown = {} -- The cooldown table.

function isOnCooldown(player)
	for Index, Value in pairs(Cooldown) do -- Looping through the Cooldown table
		if player.UserId == Value then -- If the user is found in the table, return true
			return true
		end
	end
	return false -- The loop finished and nothing has been returned, returning false.
end

function setCooldown(player, cooldown)
	if not isOnCooldown(player) then
		table.insert(Cooldown, player.UserId) -- Inserting the user into the table.
		delay(cooldown, function() -- Waiting X seconds and then looping through the table again.
			for Index, Value in pairs(Cooldown) do
				if Value == player.UserId then -- If the user is found in the table, we are removing it.
					table.remove(Cooldown, Index) -- Removing the user from the table.
				end
			end
		end)
	end
end

Here’s an example using the above functions:

game.Players.PlayerAdded:Connect(function(player)
	player.Chatted:Connect(function()
		if not isOnCooldown(player) then
			print("Sent!")
			setCooldown(player, 2)
		else
			print("On Cooldown")
		end
	end)
end)
1 Like

Try counting every 10 messages they make and if the time since the 10th message and the 1st message is a low time (lets say 3 seconds) you can assume they’re spamming chat.

Some logic code:

local messages = {} --// store temporary messages

local isOnCoolDown = false --// state that determine whether messageCreated can continue
local coolDownLength = 10 --// they're muted for 10 seconds
local thresholdUntilCooldown = 3 --// if you send more than 10 messages in 3 seconds you get muted
local messagesUntilCooldownCheck = 10 --// check for spam every 10 messages

local function messageCreated(contents)
    if (isOnCoolDown) then return end --// exit function if on cooldown
    
    messages[#messages + 1] = {
        content = contents,
        time = tick()
    }

    if (#messages == messagesUntilCooldownCheck) then --// check if length of current messages is equal to the amount until cooldown check. 
        if ((messages[messagesUntilCooldownCheck].time - messages[1].time) < thresholdUntilCooldown) then
            isOnCoolDown = true
            messages = {} --// "clear" the messages table by overwriting the old one
            wait(coolDownLength)
            isOnCoolDown = false
        end
    end

    --// do other stuff with contents
end
2 Likes

This is what I’m looking for, except the function isn’t working yet.
Here’s my code:

local Event = game.ReplicatedStorage.Remotes.ChatEvent

local messages = {}

local devs = {"CaptainShipster","GavinJohnTheGreat"}
local owner = "IAmPinleon"

local UIS = game:GetService("UserInputService")

local frame = script.Parent.Messages
local chatBar = script.Parent.ChatBar

local temp = game.ReplicatedStorage.Template

local cooldown = false
local cooldownLength = 10
local thresholdUntilCooldown = 3
local messagesUntilCooldown = 6

local function messageCreated(contents)
    if (cooldown) then return end --// exit function if on cooldown
    
    messages[#messages + 1] = {
        content = contents,
        time = tick()
    }

    if (#messages == messagesUntilCooldown) then --// check if length of current messages is equal to the amount until cooldown check. 
        if ((messages[messagesUntilCooldown].time - messages[1].time) < thresholdUntilCooldown) then
            cooldown = true
            messages = {} --// "clear" the messages table by overwriting the old one
            wait(cooldownLength)
            cooldown = false
        end
    end

    --// do other stuff with contents
end

chatBar.FocusLost:Connect(function(ep)
	if (ep) and chatBar.Text ~= "" then
		Event:FireServer(chatBar.Text)
		chatBar.Text = ""
	end
end)

UIS.InputBegan:Connect(function(input, gpe)
	if gpe then return end
	if input.KeyCode == Enum.KeyCode.Slash then
		chatBar:CaptureFocus()
		game:GetService("RunService").RenderStepped:Wait()
		chatBar.Text = ""
	end
end)

Event.OnClientEvent:Connect(function(message, plr)
	local newChatMessage = temp:Clone()
	for i, name in pairs(devs) do
		if plr.Name == name then
			newChatMessage.PlayerName.Text = "[Developer] ".. tostring(plr) .. ":"
		elseif plr.Name == owner then
			newChatMessage.PlayerName.Text = "[Owner] ".. tostring(plr) .. ":"
		else
			newChatMessage.PlayerName.Text = tostring(plr) .. ":"
		end
	end
	newChatMessage.Message.Text = tostring(message)
	newChatMessage.Parent = frame
	messageCreated(message)
end)

Because you have the logic that does the creation of messages in the wrong place of the code.
image

Here you’re creating the message, then you’re just calling messageCreated(message). You should move the outlined block into messageCreated where the comment --// do other stuff with contents is mentioned.

local function messageCreated(contents, plr)
    if (isOnCoolDown) then return end --// exit function if on cooldown
    
    messages[#messages + 1] = {
        content = contents,
        time = tick()
    }

    if (#messages == messagesUntilCooldownCheck) then --// check if length of current messages is equal to the amount until cooldown check. 
        if ((messages[messagesUntilCooldownCheck].time - messages[1].time) < thresholdUntilCooldown) then
            isOnCoolDown = true
            messages = {} --// "clear" the messages table by overwriting the old one
            wait(coolDownLength)
            isOnCoolDown = false
        end
    end

    --// do other stuff with contents

    local newChatMessage = temp:Clone()
	for i, name in pairs(devs) do
		if plr.Name == name then
			newChatMessage.PlayerName.Text = "[Developer] ".. tostring(plr) .. ":"
		elseif plr.Name == owner then
			newChatMessage.PlayerName.Text = "[Owner] ".. tostring(plr) .. ":"
		else
			newChatMessage.PlayerName.Text = tostring(plr) .. ":"
		end
	end
	newChatMessage.Message.Text = tostring(contents)
	newChatMessage.Parent = frame
end

Event.OnClientEvent:Connect(messageCreated)

P.S. didn’t test my code so not sure if it actually works when just pasting it. The code I provided was meant to be a framework of how you could do it.

1 Like

Tested my code as I should’ve done initially and I actually did make a mistake in my example code.

messages will only be cleared if spam was detected, however you would want to do that every time the #messages is equal to messagesUntilCooldownCheck

Here is the tested logic code if you still want to use that!

local messages = {} --// store temporary messages

local isOnCoolDown = false --// state that determine whether messageCreated can continue
local coolDownLength = 10 --// they're muted for 10 seconds
local thresholdUntilCooldown = 5 --// if you send 10 messages in 3 seconds you get muted
local messagesUntilCooldownCheck = 10 --// check for spam every 10 messages

local function messageCreated(contents)
    if (isOnCoolDown) then return end --// exit function if on cooldown
    
    messages[#messages + 1] = {
        content = contents,
        time = tick()
    }

    if (#messages == messagesUntilCooldownCheck) then --// check if length of current messages is equal to the amount until cooldown check. 
		local firstMessage = messages[1].time
		local lastMessage = messages[messagesUntilCooldownCheck].time
		
		local difference = lastMessage - firstMessage
		
		 if (difference < thresholdUntilCooldown) then
		     isOnCoolDown = true
		     wait(coolDownLength)
		     isOnCoolDown = false
		 end

		 messages = {} --// "clear" the messages table by overwriting the old one
    end

    --// do other stuff with contents
end