<Chat>:RegisterChatCallback()

Hello all,

Currently, I am working on a small system which, on a basic level, corrects grammar in a game. For example, this adds a period to the end of sentences, alters some specified “phrases” to the preferred option(“u” → “you”, “cant” → “can’t”), and will alter names documented (tom → Tom).

I had successfully completed this with the TextChatService, however this caused some other issues in my game.

So, I’ve moved to using the <Chat>:RegisterChatCallback() function. I am using the OnServerReceiving chatCallbackType and running the script on a ServerScript, located in ServerScriptService.

Something to note, as you can see in my script, I print the “message” object twice. The first time, the “Message” data (found via message.Message) is the uncorrected form and the second print is the corrected form, yet this doesn’t seem to actually apply in-game.

Please can you provide any advice or solutions, it would be appreciated.

--:// Services
local robloxChatService = game:GetService('Chat')

--:// Variables
local toReplace = {
	["I"] = "i",
	["haha"] = {"lol", "lmao", "lmxo", "lel"},
	["you're"] = "youre",
	["you"] = "u",
	["they're"] = "theyre",
	["I'm"] = "im",
	["she's"] = "shes",
	["he's"] = "hes",
	["can't"] = "cant",
}
local names = {
	"Adam",
	"Alex",
	"Alexander",
	"Arthur",
	"Ben",
	"Benjamin",
	"Benny",
	"Charles",
	"Ewan",
	"Harrison",
	"Harry",
	"Henry",
	"Isaac",
	"Ollie",
	"Peter",
	"Reece",
	"Rhys",
	"Thomas",
	"Tom",
	"Tori",
	"Xavier",
}

--:// Functions
local function startsWith(text, key)
	local keyLength = string.len(key)
	local textLength = string.len(text)

	if keyLength > textLength then
		return false
	end

	local sub = string.sub(text, 1, keyLength)

	if sub == key then
		return true
	end

	return false
end

local function endsWith(text, key)
	local keyLength = string.len(key)
	local textLength = string.len(text)

	if keyLength > textLength then
		return false
	end

	local sub = string.sub(text, (textLength - keyLength + 1), textLength)

	if sub == key then
		return true
	end

	return false
end

local function endsWithGrammar(text)
	local grammarOptions = {
		".",
		",",
		"?",
		"!",
		":",
		";",
	}

	for _, option in pairs(grammarOptions) do
		local response = endsWith(text, option)

		if response == true then
			return true
		end
	end

	return false
end

local function replaceText(text, isFinal, prevText)
	for better, data in pairs(toReplace) do
		if type(data) == "table" then
			for _, textVariant in pairs(data) do
				if string.lower(text) == textVariant then
					text = better
				end
			end
		elseif type(data) == "string" then
			if string.lower(text) == data then
				text = better
			end
		end
	end

	if endsWithGrammar(text) then
		local possibleName = string.sub(text, 1, (string.len(text) - 1))
		local savedEnd = string.sub(text, (string.len(text) - 1 + 1), string.len(text))

		for _, name in pairs(names) do
			if string.lower(possibleName) == string.lower(name) then
				text = name..savedEnd
			end
		end
	else
		for _, name in pairs(names) do
			if string.lower(text) == string.lower(name) then
				text = name
			end
		end
	end


	if prevText == "" or (endsWith(prevText, ".") and not endsWith(prevText, "..")) then	
		local textA = string.sub(text, 1, 1)
		local textB = string.sub(text, 2, string.len(text))

		text = string.upper(textA)..textB
	end

	if isFinal and not endsWithGrammar(text) then
		text = text.."."
	end

	return text
end

local function messageChange(message)	
	if not startsWith(message.Message, ":") and not startsWith(message.Message, "/e :") then	
		print(message) -- First print
		local textArgs = string.split(message.Message, " ")
		local currentString = ""
		local prevText = ""

		for index, text in pairs(textArgs) do
			local isFinal = false

			if index == #textArgs then
				isFinal = true
			end

			local replacement = replaceText(text, isFinal, prevText)
			prevText = replacement

			currentString = currentString..(currentString == "" and "" or " ")..replacement
		end

		message.Message = currentString
	end
	
	print(message) -- Second print
	
	return message
end

--:// Methods
robloxChatService:RegisterChatCallback(Enum.ChatCallbackType.OnServerReceivingMessage, messageChange)

Thanks in advance,
Tom

I haven’t worked with this particular API so I can’t say for sure but I suspect the issue is that Roblox ChatService has its own filters in place that don’t interact with the RegisterChatCallback API.

I’ve seen other people use this function before, however it just doesn’t seem to work for me.

In addition, it isn’t returning any errors at all.