How could I improve this code?

I want this code to be better.
I cannot think of an other ways to improve it.
I tried coming here and that is it.
The groupId for the getmainrank function is purposely set to 0. The add customproperties function is from the SimpleAdmin model made by Crywink.

AddCustomProperties = function(inst, props)
	return setmetatable({}, {
		__index = function(self, key)
			if props[key] then
				return props[key]
			elseif inst[key] then
				if type(inst[key]) == "function" then
					return function(self, ...)
						return inst[key](inst, ...)
					end
				end
				return inst[key]
			end
		end,
		__newindex = function(self, key, val)
			if props[key] then
				props[key] = val
			elseif inst[key] then
				inst[key] = val
			end
		end
	})
end

GetService = function(ServiceName, DoesCreate)
	local service
	if not DoesCreate then 
		service = game:FindService(ServiceName)
	else 
		service = game:GetService(ServiceName)
	end
	return service
end

GetPlayerGroupInfo = function(GroupId, Player)
	local IsInGroup, Rank, Role = Player:IsInGroup(GroupId), Player:GetRankInGroup(GroupId), Player:GetRoleInGroup(GroupId)

	if IsInGroup then
		return IsInGroup, Rank, Role
	else
		return IsInGroup, 0, 'Guest'
	end
end

local WrapEvents = {
	['BanPlayer'] = function(Player, Config)
		local players = GetService('Players')
		if Config['UserIds'] then
			if #Config.UserIds > 1 then
				Config.UserIds = {Player.UserId}
			end
		end
		players:BanAsync(Config)
	end,

	['UnbanPlayer'] = function(Player, Config)
		local players = GetService('Players')
		if Config['UserIds'] then
			if #Config.UserIds > 1 then
				Config.UserIds = {Player.UserId}
			end
		end
		players:UnbanAsync(Config)
	end,
}

Wrap = function(FunctionIndex, ...)
	for i, v in next, WrapEvents do
		if FunctionIndex == i then
			v(...)
		end
	end
end

local Events = {
	['Players'] = {
		['PlayerAdded'] = function(Player)
			local NewProperties = {['plr'] = Player}

			function NewProperties:GetChar()
				if self then
					local Char = self['plr'].Character
					if not Char then
						Char = self['plr'].CharacterAdded:Wait()
					end
					return Char
				end
			end

			function NewProperties:ChangeBackgroundNoise(NewSoundId)
				local Rep = GetService('ReplicatedStorage')
				if Rep:FindFirstChild('Client') then
					local Remotes = Rep.Client.Remotes
					if not string.find(NewSoundId, 'rbxassetid://') then
						local sub = string.sub(NewSoundId, 1, string.len('rbxassetid://'))
						if sub:lower() ~= 'rbxassetid://' then
							NewSoundId = 'rbxassetid://' .. NewSoundId
						end
					end
					
					Remotes.Communicator:FireClient(Player, 'ChangeBg', NewSoundId)
				end
			end

			function NewProperties:GetMainRank()
				local IsInGroup, Rank, Role = GetPlayerGroupInfo(0, Player)
				return {[1] = IsInGroup, [2] = Rank, [3] = Role}
			end

			function NewProperties:BanPlayer(Reason, ApplyToUniverse, Duration, ExcludeAlts)
				if string.len(Reason) > 400 then
					Reason = string.sub(Reason, 1, 400) .. '...'
				end
				Wrap('BanPlayer', {
					['UserIds'] = {Player.UserId},
					['ApplyToUniverse'] = ApplyToUniverse,
					['Duration'] = Duration,
					['DisplayReason'] = Reason,
					['PrivateReason'] = Reason,
					['ExcludeAlts'] = ExcludeAlts,
				})
			end

			function NewProperties:UnbanPlayer(ApplyToUniverse)
				Wrap('UnbanPlayer', {
					['UserIds'] = {Player.UserId},
					['ApplyToUniverse'] = ApplyToUniverse
				})
			end
			
			for i,v in next,NewProperties do
				if i ~= 'plr' then
					AddCustomProperties(Player,v)
				end
			end
		end,
	}
}

for _, v in ipairs(game:GetChildren()) do
	if Events[v.Name] then
		for _, connectionName in ipairs(Events[v.Name]) do
			local connection = v[connectionName]
			if typeof(connection) == "RBXScriptSignal" then
				connection:Connect(function(...)
					local eventFunc = Events[v.Name][connectionName]
					if type(eventFunc) == "function" then
						eventFunc(...)
					end
				end)
			end
		end
	end
end