local t={}PlayersService.PlayerAdded:connect(function(E)for t,n in pairs(t)do local e=ChatService:GetSpeaker(t.Name)if e then for t=1,#n,1 do local S=n[t]if S==E.UserId then e:AddMutedSpeaker(E.Name)end end end end end)PlayersService.PlayerRemoving:connect(function(E)t[E]=nil end)EventFolder.SetBlockedUserIdsRequest.OnServerEvent:Connect(function(E,n)if type(n)~="\116\097\098\108\101"then return end local e={}local S=ChatService:GetSpeaker(E.Name)if S then for t=1,math.min(#n,MAX_BLOCKED_SPEAKERS_PER_REQ),1 do if type(n[t])=="\110\117\109\098\101\114"then table.insert(e,n[t])local E=PlayersService:GetPlayerByUserId(n[t])if E then S:AddMutedSpeaker(E.Name)end end end t[E]=e end end)EventFolder.GetInitDataRequest.OnServerInvoke=function(t)local E=ChatService:GetSpeaker(t.Name)if not(E and E:GetPlayer())then CreatePlayerSpeakerObject(t)E=ChatService:GetSpeaker(t.Name)end local n={}n.Channels={}n.SpeakerExtraData={}for t,e in pairs(E:GetChannelList())do local S=ChatService:GetChannel(e)if S then local t={e;S:GetWelcomeMessageForSpeaker(E),S:GetHistoryLogForSpeaker(E),S.ChannelNameColor}table.insert(n.Channels,t)end end for t,E in pairs(ChatService:GetSpeakerList())do local e=ChatService:GetSpeaker(E)n.SpeakerExtraData[E]=e.ExtraData end return n end local function E(t,E,n)local e=ChatService:GetSpeaker(t)local S=ChatService:GetChannel(E)if e then if S then if S.Joinable then if not e:IsInChannel(S.Name)then e:JoinChannel(S.Name)else e:SetMainChannel(S.Name)local t=ChatLocalization:FormatMessageToSend("\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\'",S.Name),"\082\066\088\095\078\065\077\069",S.Name)e:SendSystemMessage(t,S.Name)end else local t=ChatLocalization:FormatMessageToSend("\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 \'"..(E.."\'\046"),"\082\066\088\095\078\065\077\069",E)e:SendSystemMessage(t,n)end else local t=ChatLocalization:FormatMessageToSend("\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 \'"..(E.."\' \100\111\101\115 \110\111\116 \101\120\105\115\116\046"),"\082\066\088\095\078\065\077\069",E)e:SendSystemMessage(t,n)end end end local function n(t,E,n)local e=ChatService:GetSpeaker(t)local S=ChatService:GetChannel(E)if e then if e:IsInChannel(E)then if S.Leavable then e:LeaveChannel(S.Name)local t=ChatLocalization:FormatMessageToSend("\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\'",E),"\082\066\088\095\078\065\077\069",S.Name)e:SendSystemMessage(t,"\083\121\115\116\101\109")else local t=ChatLocalization:FormatMessageToSend("\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 \'"..(E.."\'\046"),"\082\066\088\095\078\065\077\069",E)e:SendSystemMessage(t,n)end else local t=ChatLocalization:FormatMessageToSend("\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 \'"..(E.."\'\046"),"\082\066\088\095\078\065\077\069",E)e:SendSystemMessage(t,n)end end end ChatService:RegisterProcessCommandsFunction("\100\101\102\097\117\108\116\095\099\111\109\109\097\110\100\115",function(t,e,S)if(string.sub(e,1,6)):lower()=="\047\106\111\105\110 "then E(t,string.sub(e,7),S)return true elseif(string.sub(e,1,3)):lower()=="\047\106 "then E(t,string.sub(e,4),S)return true elseif(string.sub(e,1,7)):lower()=="\047\108\101\097\118\101 "then n(t,string.sub(e,8),S)return true elseif(string.sub(e,1,3)):lower()=="\047\108 "then n(t,string.sub(e,4),S)return true end return false end)if ChatSettings.GeneralChannelName and ChatSettings.GeneralChannelName~=""then local t=ChatService:AddChannel(ChatSettings.GeneralChannelName)t.Leavable=false t.AutoJoin=true t:RegisterGetWelcomeMessageFunction(function(t)if RunService:IsStudio()then return nil end local E=t:GetPlayer()if E then local t,n=pcall(function()return Chat:CanUserChatAsync(E.UserId)end)if t and not n then return""end end end)end local e=ChatService:AddChannel("\083\121\115\116\101\109")e.Leavable=false e.AutoJoin=true e.WelcomeMessage=ChatLocalization:FormatMessageToSend("\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")e.SpeakerJoined:connect(function(t)e:MuteSpeaker(t)end)local function S(t)if t:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then local E=require(t)if type(E)=="\102\117\110\099\116\105\111\110"then E(ChatService)end end end local W=Chat:WaitForChild("\067\104\097\116\077\111\100\117\108\101\115")W.ChildAdded:connect(function(t)local E,n=pcall(S,t)if not E and n then print("\069\114\114\111\114 \114\117\110\110\105\110\103 \109\111\100\117\108\101 "..(t.Name..("\058 "..n)))end end)for t,E in pairs(W:GetChildren())do local n,e=pcall(S,E)if not n and e then print("\069\114\114\111\114 \114\117\110\110\105\110\103 \109\111\100\117\108\101 "..(E.Name..("\058 "..e)))end end PlayersService.PlayerRemoving:connect(function(t)if ChatService:GetSpeaker(t.Name)then ChatService:RemoveSpeaker(t.Name)end end)

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)
	if type(blockedUserIdsList) ~= "table" then
		return
	end

	local prunedBlockedUserIdsList = {}
	local speaker = ChatService:GetSpeaker(player.Name)
	if speaker then
		for i = 1, math.min(#blockedUserIdsList, MAX_BLOCKED_SPEAKERS_PER_REQ) do
			if type(blockedUserIdsList[i]) == "number" then

				table.insert(prunedBlockedUserIdsList, blockedUserIdsList[i])

				local blockedPlayer = PlayersService:GetPlayerByUserId(blockedUserIdsList[i])
				if blockedPlayer then
					speaker:AddMutedSpeaker(blockedPlayer.Name)
				end
			end
		end

		-- We only want to store the first
		-- MAX_BLOCKED_SPEAKERS_PER_REQ number of ids as needed
		BlockedUserIdsMap[player] = prunedBlockedUserIdsList
	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 _, 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 _, 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)
					local msg = ChatLocalization:FormatMessageToSend(
						"GameChat_SwitchChannel_NowInChannel",
						string.format("You are now chatting in channel: '%s'", channel.Name),
						"RBX_NAME",
						channel.Name)
					speaker:SendSystemMessage(msg, channel.Name)
				end
			else
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatServiceRunner_YouCannotJoinChannel",
					"You cannot join channel '" .. channelName .. "'.",
					"RBX_NAME",
					channelName)
				speaker:SendSystemMessage(msg, fromChannelName)
			end
		else
			local msg = ChatLocalization:FormatMessageToSend(
				"GameChat_ChatServiceRunner_ChannelDoesNotExist",
				"Channel '" .. channelName .. "' does not exist.",
				"RBX_NAME",
				channelName)
			speaker:SendSystemMessage(msg, 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)
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatService_YouHaveLeftChannel",
					string.format("You have left channel '%s'", channelName),
					"RBX_NAME",
					channel.Name)
				speaker:SendSystemMessage(msg, "System")
			else
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatServiceRunner_YouCannotLeaveChannel",
					("You cannot leave channel '" .. channelName .. "'."),
					"RBX_NAME",
					channelName)
				speaker:SendSystemMessage(msg, fromChannelName)
			end
		else
			local msg = ChatLocalization:FormatMessageToSend(
				"GameChat_ChatServiceRunner_YouAreNotInChannel",
				("You are not in channel '" .. channelName .. "'."),
				"RBX_NAME",
				channelName)
			speaker:SendSystemMessage(msg, 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
	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:FormatMessageToSend(
	"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 = 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 _, 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

PlayersService.PlayerRemoving:connect(function(playerObj)
	if (ChatService:GetSpeaker(playerObj.Name)) then
		ChatService:RemoveSpeaker(playerObj.Name)
	end
end)
