local b={}PlayersService.PlayerAdded:connect(function(H)for b,J in pairs(b)do local Y=ChatService:GetSpeaker(b.Name)if Y then for b=1,#J,1 do local w=J[b]if w==H.UserId then Y:AddMutedSpeaker(H.Name)end end end end end)PlayersService.PlayerRemoving:connect(function(H)b[H]=nil end)EventFolder.SetBlockedUserIdsRequest.OnServerEvent:connect(function(H,J)b[H]=J local Y=ChatService:GetSpeaker(H.Name)if Y then for b=1,#J,1 do local H=PlayersService:GetPlayerByUserId(J[b])if H then Y:AddMutedSpeaker(H.Name)end end end end)EventFolder.GetInitDataRequest.OnServerInvoke=function(b)local H=ChatService:GetSpeaker(b.Name)if not(H and H:GetPlayer())then CreatePlayerSpeakerObject(b)H=ChatService:GetSpeaker(b.Name)end local J={}J.Channels={}J.SpeakerExtraData={}for b,Y in pairs(H:GetChannelList())do local w=ChatService:GetChannel(Y)if w then local b={Y;w:GetWelcomeMessageForSpeaker(H);w:GetHistoryLogForSpeaker(H);w.ChannelNameColor}table.insert(J.Channels,b)end end for b,H in pairs(ChatService:GetSpeakerList())do local Y=ChatService:GetSpeaker(H)J.SpeakerExtraData[H]=Y.ExtraData end return J end local function H(b,H,J)local Y=ChatService:GetSpeaker(b)local w=ChatService:GetChannel(H)if Y then if w then if w.Joinable then if not Y:IsInChannel(w.Name)then Y:JoinChannel(w.Name)else Y:SetMainChannel(w.Name)Y:SendSystemMessage(string.gsub(ChatLocalization:Get("\071\097\109\101\067\104\097\116\095\083\119\105\116\099\104\067\104\097\110\110\101\108\095\078\111\119\073\110\067\104\097\110\110\101\108",string.format("\089\111\117 \097\114\101 \110\111\119 \099\104\097\116\116\105\110\103 \105\110 \099\104\097\110\110\101\108\058 \'\037\115\'",w.Name)),"\123\082\066\088\095\078\065\077\069\125",w.Name),w.Name)end else Y:SendSystemMessage(string.gsub(ChatLocalization:Get("\071\097\109\101\067\104\097\116\095\067\104\097\116\083\101\114\118\105\099\101\082\117\110\110\101\114\095\089\111\117\067\097\110\110\111\116\074\111\105\110\067\104\097\110\110\101\108","\089\111\117 \099\097\110\110\111\116 \106\111\105\110 \099\104\097\110\110\101\108 \'"..(H.."\'\046")),"\123\082\066\088\095\078\065\077\069\125",H),J)end else Y:SendSystemMessage(string.gsub(ChatLocalization:Get("\071\097\109\101\067\104\097\116\095\067\104\097\116\083\101\114\118\105\099\101\082\117\110\110\101\114\095\067\104\097\110\110\101\108\068\111\101\115\078\111\116\069\120\105\115\116","\067\104\097\110\110\101\108 \'"..(H.."\' \100\111\101\115 \110\111\116 \101\120\105\115\116\046")),"\123\082\066\088\095\078\065\077\069\125",H),J)end end end local function J(b,H,J)local Y=ChatService:GetSpeaker(b)local w=ChatService:GetChannel(H)if Y then if Y:IsInChannel(H)then if w.Leavable then Y:LeaveChannel(w.Name)Y:SendSystemMessage(string.gsub(ChatLocalization:Get("\071\097\109\101\067\104\097\116\095\067\104\097\116\083\101\114\118\105\099\101\095\089\111\117\072\097\118\101\076\101\102\116\067\104\097\110\110\101\108",string.format("\089\111\117 \104\097\118\101 \108\101\102\116 \099\104\097\110\110\101\108 \'\037\115\'",H)),"\123\082\066\088\095\078\065\077\069\125",w.Name),"\083\121\115\116\101\109")else Y:SendSystemMessage(string.gsub(ChatLocalization:Get("\071\097\109\101\067\104\097\116\095\067\104\097\116\083\101\114\118\105\099\101\082\117\110\110\101\114\095\089\111\117\067\097\110\110\111\116\076\101\097\118\101\067\104\097\110\110\101\108","\089\111\117 \099\097\110\110\111\116 \108\101\097\118\101 \099\104\097\110\110\101\108 \'"..(H.."\'\046")),"\123\082\066\088\095\078\065\077\069\125",H),J)end else Y:SendSystemMessage(string.gsub(ChatLocalization:Get("\071\097\109\101\067\104\097\116\095\067\104\097\116\083\101\114\118\105\099\101\082\117\110\110\101\114\095\089\111\117\065\114\101\078\111\116\073\110\067\104\097\110\110\101\108","\089\111\117 \097\114\101 \110\111\116 \105\110 \099\104\097\110\110\101\108 \'"..(H.."\'\046")),"\123\082\066\088\095\078\065\077\069\125",H),J)end end end ChatService:RegisterProcessCommandsFunction("\100\101\102\097\117\108\116\095\099\111\109\109\097\110\100\115",function(b,Y,w)if(string.sub(Y,1,6)):lower()=="\047\106\111\105\110 "then H(b,string.sub(Y,7),w)return true elseif(string.sub(Y,1,3)):lower()=="\047\106 "then H(b,string.sub(Y,4),w)return true elseif(string.sub(Y,1,7)):lower()=="\047\108\101\097\118\101 "then J(b,string.sub(Y,8),w)return true elseif(string.sub(Y,1,3)):lower()=="\047\108 "then J(b,string.sub(Y,4),w)return true elseif string.sub(Y,1,3)=="\047\101 "or string.sub(Y,1,7)=="\047\101\109\111\116\101 "then return true end return false end)if ChatSettings.GeneralChannelName and ChatSettings.GeneralChannelName~=""then local b=ChatService:AddChannel(ChatSettings.GeneralChannelName)b.Leavable=false b.AutoJoin=true b:RegisterGetWelcomeMessageFunction(function(b)if RunService:IsStudio()then return nil end local H=b:GetPlayer()if H then local b,J=pcall(function()return Chat:CanUserChatAsync(H.UserId)end)if b and not J then return""end end end)end local Y=ChatService:AddChannel("\083\121\115\116\101\109")Y.Leavable=false Y.AutoJoin=true Y.WelcomeMessage=ChatLocalization:Get("\071\097\109\101\067\104\097\116\095\067\104\097\116\083\101\114\118\105\099\101\082\117\110\110\101\114\095\083\121\115\116\101\109\067\104\097\110\110\101\108\087\101\108\099\111\109\101\077\101\115\115\097\103\101","\084\104\105\115 \099\104\097\110\110\101\108 \105\115 \102\111\114 \115\121\115\116\101\109 \097\110\100 \103\097\109\101 \110\111\116\105\102\105\099\097\116\105\111\110\115\046")Y.SpeakerJoined:connect(function(b)Y:MuteSpeaker(b)end)local function w(b)if b:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then local H=require(b)if type(H)=="\102\117\110\099\116\105\111\110"then H(ChatService)end end end local O=(game:GetService("\067\104\097\116")):WaitForChild("\067\104\097\116\077\111\100\117\108\101\115")O.ChildAdded:connect(function(b)local H,J=pcall(w,b)if not H and J then print("\069\114\114\111\114 \114\117\110\110\105\110\103 \109\111\100\117\108\101 "..(b.Name..("\058 "..J)))end end)for b,H in pairs(O:GetChildren())do local J,Y=pcall(w,H)if not J and Y then print("\069\114\114\111\114 \114\117\110\110\105\110\103 \109\111\100\117\108\101 "..(H.Name..("\058 "..Y)))end end local P=game:GetService("\080\108\097\121\101\114\115")P.PlayerRemoving:connect(function(b)if ChatService:GetSpeaker(b.Name)then ChatService:RemoveSpeaker(b.Name)end end)
-- Map storing Player -> Blocked user Ids.
local BlockedUserIdsMap = {}

PlayersService.PlayerAdded:connect(function(newPlayer)
	for player, blockedUsers in pairs(BlockedUserIdsMap) do
		local speaker = ChatService:GetSpeaker(player.Name)
		if speaker then
			for i = 1, #blockedUsers do
				local blockedUserId = blockedUsers[i]
				if blockedUserId == newPlayer.UserId then
					speaker:AddMutedSpeaker(newPlayer.Name)
				end
			end
		end
	end
end)

PlayersService.PlayerRemoving:connect(function(removingPlayer)
	BlockedUserIdsMap[removingPlayer] = nil
end)

EventFolder.SetBlockedUserIdsRequest.OnServerEvent:connect(function(player, blockedUserIdsList)
	BlockedUserIdsMap[player] = blockedUserIdsList
	local speaker = ChatService:GetSpeaker(player.Name)
	if speaker then
		for i = 1, #blockedUserIdsList do
			local blockedPlayer = PlayersService:GetPlayerByUserId(blockedUserIdsList[i])
			if blockedPlayer then
				speaker:AddMutedSpeaker(blockedPlayer.Name)
			end
		end
	end
end)

EventFolder.GetInitDataRequest.OnServerInvoke = function(playerObj)
	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if not (speaker and speaker:GetPlayer()) then
		CreatePlayerSpeakerObject(playerObj)
		speaker = ChatService:GetSpeaker(playerObj.Name)
	end

	local data = {}
	data.Channels = {}
	data.SpeakerExtraData = {}

	for i, channelName in pairs(speaker:GetChannelList()) do
		local channelObj = ChatService:GetChannel(channelName)
		if channelObj then
			local channelData = {
				channelName,
				channelObj:GetWelcomeMessageForSpeaker(speaker),
				channelObj:GetHistoryLogForSpeaker(speaker),
				channelObj.ChannelNameColor,
			}

			table.insert(data.Channels, channelData)
		end
	end

	for i, oSpeakerName in pairs(ChatService:GetSpeakerList()) do
		local oSpeaker = ChatService:GetSpeaker(oSpeakerName)
		data.SpeakerExtraData[oSpeakerName] = oSpeaker.ExtraData
	end

	return data
end

local function DoJoinCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if speaker then
		if channel then
			if channel.Joinable then
				if not speaker:IsInChannel(channel.Name) then
					speaker:JoinChannel(channel.Name)
				else
					speaker:SetMainChannel(channel.Name)
					speaker:SendSystemMessage(
						string.gsub(
							ChatLocalization:Get(
								"GameChat_SwitchChannel_NowInChannel",
								string.format("You are now chatting in channel: '%s'", channel.Name)
							),
							"{RBX_NAME}",
							channel.Name
						),
						channel.Name
					)
				end
			else
				speaker:SendSystemMessage(
					string.gsub(
						ChatLocalization:Get(
							"GameChat_ChatServiceRunner_YouCannotJoinChannel",
							("You cannot join channel '" .. channelName .. "'.")
						),
						"{RBX_NAME}",
						channelName
					),
					fromChannelName
				)
			end
		else
			speaker:SendSystemMessage(
				string.gsub(
					ChatLocalization:Get(
						"GameChat_ChatServiceRunner_ChannelDoesNotExist",
						("Channel '" .. channelName .. "' does not exist.")
					),
					"{RBX_NAME}",
					channelName
				),
				fromChannelName
			)
		end
	end
end

local function DoLeaveCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if speaker then
		if speaker:IsInChannel(channelName) then
			if channel.Leavable then
				speaker:LeaveChannel(channel.Name)
				speaker:SendSystemMessage(
					string.gsub(
						ChatLocalization:Get(
							"GameChat_ChatService_YouHaveLeftChannel",
							string.format("You have left channel '%s'", channelName)
						),
						"{RBX_NAME}",
						channel.Name
					),
					"System"
				)
			else
				speaker:SendSystemMessage(
					string.gsub(
						ChatLocalization:Get(
							"GameChat_ChatServiceRunner_YouCannotLeaveChannel",
							("You cannot leave channel '" .. channelName .. "'.")
						),
						"{RBX_NAME}",
						channelName
					),
					fromChannelName
				)
			end
		else
			speaker:SendSystemMessage(
				string.gsub(
					ChatLocalization:Get(
						"GameChat_ChatServiceRunner_YouAreNotInChannel",
						("You are not in channel '" .. channelName .. "'.")
					),
					"{RBX_NAME}",
					channelName
				),
				fromChannelName
			)
		end
	end
end

ChatService:RegisterProcessCommandsFunction("default_commands", function(fromSpeaker, message, channel)
	if string.sub(message, 1, 6):lower() == "/join " then
		DoJoinCommand(fromSpeaker, string.sub(message, 7), channel)
		return true
	elseif string.sub(message, 1, 3):lower() == "/j " then
		DoJoinCommand(fromSpeaker, string.sub(message, 4), channel)
		return true
	elseif string.sub(message, 1, 7):lower() == "/leave " then
		DoLeaveCommand(fromSpeaker, string.sub(message, 8), channel)
		return true
	elseif string.sub(message, 1, 3):lower() == "/l " then
		DoLeaveCommand(fromSpeaker, string.sub(message, 4), channel)
		return true
	elseif string.sub(message, 1, 3) == "/e " or string.sub(message, 1, 7) == "/emote " then
		-- Just don't show these in the chatlog. The animation script listens on these.
		return true
	end

	return false
end)

if ChatSettings.GeneralChannelName and ChatSettings.GeneralChannelName ~= "" then
	local allChannel = ChatService:AddChannel(ChatSettings.GeneralChannelName)

	allChannel.Leavable = false
	allChannel.AutoJoin = true

	allChannel:RegisterGetWelcomeMessageFunction(function(speaker)
		if RunService:IsStudio() then
			return nil
		end
		local player = speaker:GetPlayer()
		if player then
			local success, canChat = pcall(function()
				return Chat:CanUserChatAsync(player.UserId)
			end)
			if success and not canChat then
				return ""
			end
		end
	end)
end

local systemChannel = ChatService:AddChannel("System")
systemChannel.Leavable = false
systemChannel.AutoJoin = true
systemChannel.WelcomeMessage = ChatLocalization:Get(
	"GameChat_ChatServiceRunner_SystemChannelWelcomeMessage",
	"This channel is for system and game notifications."
)

systemChannel.SpeakerJoined:connect(function(speakerName)
	systemChannel:MuteSpeaker(speakerName)
end)

local function TryRunModule(module)
	if module:IsA("ModuleScript") then
		local ret = require(module)
		if type(ret) == "function" then
			ret(ChatService)
		end
	end
end

local modules = game:GetService("Chat"):WaitForChild("ChatModules")
modules.ChildAdded:connect(function(child)
	local success, returnval = pcall(TryRunModule, child)
	if not success and returnval then
		print("Error running module " .. child.Name .. ": " .. returnval)
	end
end)

for i, module in pairs(modules:GetChildren()) do
	local success, returnval = pcall(TryRunModule, module)
	if not success and returnval then
		print("Error running module " .. module.Name .. ": " .. returnval)
	end
end

local Players = game:GetService("Players")
Players.PlayerRemoving:connect(function(playerObj)
	if ChatService:GetSpeaker(playerObj.Name) then
		ChatService:RemoveSpeaker(playerObj.Name)
	end
end)
