function methods.InternalApplyRobloxFilter(b,q,y,K)if RunService:IsServer()and not RunService:IsStudio()then local d=b:GetSpeaker(q)local c=b:GetSpeaker(K)if d and c then local q=d:GetPlayer()local K=c:GetPlayer()if q and K then local d=tick()local c=0 while true do local E,j=pcall(function()return Chat:FilterStringAsync(y,q,K)end)if E then return j else warn("\069\114\114\111\114 \102\105\108\116\101\114\105\110\103 \109\101\115\115\097\103\101\058",j)end c=c+1 if c>MAX_FILTER_RETRIES or tick()-d>MAX_FILTER_DURATION then b:InternalNotifyFilterIssue()return nil end end end end else if not StudioMessageFilteredCache[y]then StudioMessageFilteredCache[y]=true wait(.2)end return y end return nil end function methods.InternalDoMessageFilter(b,q,y,K)local d=b.FilterMessageFunctions:GetIterator()for b,d,c in d do local E,j=pcall(function()d(q,y,K)end)if not E then warn(string.format("\068\111\077\101\115\115\097\103\101\070\105\108\116\101\114 \070\117\110\099\116\105\111\110 \'\037\115\' \102\097\105\108\101\100 \102\111\114 \114\101\097\115\111\110\058 \037\115",b,j))end end end function methods.InternalDoProcessCommands(b,q,y,K)local d=b.ProcessCommandsFunctions:GetIterator()for b,d,c in d do local E,j=pcall(function()local b=d(q,y,K)assert(type(b)=="\098\111\111\108\101\097\110")return b end)if not E then warn(string.format("\068\111\080\114\111\099\101\115\115\067\111\109\109\097\110\100\115 \070\117\110\099\116\105\111\110 \'\037\115\' \102\097\105\108\101\100 \102\111\114 \114\101\097\115\111\110\058 \037\115",b,j))elseif j then return true end end return false end function methods.InternalGetUniqueMessageId(q)local y=q.MessageIdCounter q.MessageIdCounter=y+1 return y end function methods.InternalAddSpeakerWithPlayerObject(b,q,y,K)if b.Speakers[q:lower()]then error("\083\112\101\097\107\101\114 \""..(q.."\" \097\108\114\101\097\100\121 \101\120\105\115\116\115\033"))end local d=Speaker.new(b,q)d:InternalAssignPlayerObject(y)b.Speakers[q:lower()]=d if K then local y,K=pcall(function()b.eSpeakerAdded:Fire(q)end)if not y and K then print("\069\114\114\111\114 \097\100\100\105\110\103 \115\112\101\097\107\101\114\058 "..K)end end return d end function methods.InternalFireSpeakerAdded(y,q)local K,b=pcall(function()y.eSpeakerAdded:Fire(q)end)if not K and b then print("\069\114\114\111\114 \102\105\114\105\110\103 \115\112\101\097\107\101\114 \097\100\100\101\100\058 "..b)end end

function methods:InternalApplyRobloxFilter(speakerName, message, toSpeakerName)
	if (RunService:IsServer() and not RunService:IsStudio()) then
		local fromSpeaker = self:GetSpeaker(speakerName)
		local toSpeaker = self:GetSpeaker(toSpeakerName)
		if (fromSpeaker and toSpeaker) then
			local fromPlayerObj = fromSpeaker:GetPlayer()
			local toPlayerObj = toSpeaker:GetPlayer()
			if (fromPlayerObj and toPlayerObj) then
				local filterStartTime = tick()
				local filterRetries = 0
				while true do
					local success, message = pcall(function()
						return Chat:FilterStringAsync(message, fromPlayerObj, toPlayerObj)
					--[[ To uncensor the chat, turn the line above into the following:
						Chat:FilterStringAsync(message, fromPlayerObj, toPlayerObj)
						return message
					--]]
					end)
					if success then
						return message
					else
						warn("Error filtering message:", message)
					end
					filterRetries = filterRetries + 1
					if filterRetries > MAX_FILTER_RETRIES or (tick() - filterStartTime) > MAX_FILTER_DURATION then
						self:InternalNotifyFilterIssue()
						return nil
					end
				end
			end
		end
	else
		--// Simulate filtering latency.
		--// There is only latency the first time the message is filtered, all following calls will be instant.
		if not StudioMessageFilteredCache[message] then
			StudioMessageFilteredCache[message] = true
			wait(0.2)
		end
		return message
	end

	return nil
end

function methods:InternalDoMessageFilter(speakerName, messageObj, channel)
	local filtersIterator = self.FilterMessageFunctions:GetIterator()

	for funcId, func, priority in filtersIterator do
		local success, errorMessage = pcall(function()
			func(speakerName, messageObj, channel)
		end)

		if not success then
			warn(string.format("DoMessageFilter Function '%s' failed for reason: %s", funcId, errorMessage))
		end
	end
end

function methods:InternalDoProcessCommands(speakerName, message, channel)
	local commandsIterator = self.ProcessCommandsFunctions:GetIterator()

	for funcId, func, priority in commandsIterator do
		local success, returnValue = pcall(function()
			local ret = func(speakerName, message, channel)
			assert(type(ret) == "boolean")
			return ret
		end)

		if not success then
			warn(string.format("DoProcessCommands Function '%s' failed for reason: %s", funcId, returnValue))
		elseif returnValue then
			return true
		end
	end

	return false
end

function methods:InternalGetUniqueMessageId()
	local id = self.MessageIdCounter
	self.MessageIdCounter = id + 1
	return id
end

function methods:InternalAddSpeakerWithPlayerObject(speakerName, playerObj, fireSpeakerAdded)
	if (self.Speakers[speakerName:lower()]) then
		error("Speaker \"" .. speakerName .. "\" already exists!")
	end

	local speaker = Speaker.new(self, speakerName)
	speaker:InternalAssignPlayerObject(playerObj)
	self.Speakers[speakerName:lower()] = speaker

	if fireSpeakerAdded then
		local success, err = pcall(function() self.eSpeakerAdded:Fire(speakerName) end)
		if not success and err then
			print("Error adding speaker: " ..err)
		end
	end

	return speaker
end

function methods:InternalFireSpeakerAdded(speakerName)
	local success, err = pcall(function() self.eSpeakerAdded:Fire(speakerName) end)
	if not success and err then
		print("Error firing speaker added: " ..err)
	end
end
