TwoSide3Point0

Not tags on roblox in your own game use an alt for sure when you make this game

Apr 6th, 2021 (edited)
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.54 KB | None | 0 0
  1. -- // FileName: ChatService.lua
  2. -- // Written by: TwoSiide
  3. -- // Description: No tags.
  4.  
  5. local MAX_FILTER_RETRIES = 3
  6. local FILTER_BACKOFF_INTERVALS = {50/1000, 100/1000, 200/1000}
  7. local MAX_FILTER_DURATION = 60
  8.  
  9. --- Constants used to decide when to notify that the chat filter is having issues filtering messages.
  10. local FILTER_NOTIFCATION_THRESHOLD = 3 --Number of notifcation failures before an error message is output.
  11. local FILTER_NOTIFCATION_INTERVAL = 60 --Time between error messages.
  12. local FILTER_THRESHOLD_TIME = 60 --If there has not been an issue in this many seconds, the count of issues resets.
  13.  
  14. local module = {}
  15.  
  16. local RunService = game:GetService("RunService")
  17. local Chat = game:GetService("Chat")
  18. local ReplicatedModules = Chat:WaitForChild("ClientChatModules")
  19.  
  20. local modulesFolder = script.Parent
  21. local ReplicatedModules = Chat:WaitForChild("ClientChatModules")
  22. local ChatSettings = require(ReplicatedModules:WaitForChild("ChatSettings"))
  23.  
  24. local errorTextColor = ChatSettings.ErrorMessageTextColor or Color3.fromRGB(245, 50, 50)
  25. local errorExtraData = {ChatColor = errorTextColor}
  26.  
  27. --////////////////////////////// Include
  28. --//////////////////////////////////////
  29. local ChatConstants = require(ReplicatedModules:WaitForChild("ChatConstants"))
  30.  
  31. local ChatChannel = require(modulesFolder:WaitForChild("ChatChannel"))
  32. local Speaker = require(modulesFolder:WaitForChild("Speaker"))
  33. local Util = require(modulesFolder:WaitForChild("Util"))
  34.  
  35. local ChatLocalization = nil
  36. pcall(function() ChatLocalization = require(game:GetService("Chat").ClientChatModules.ChatLocalization) end)
  37. ChatLocalization = ChatLocalization or {}
  38.  
  39. if not ChatLocalization.FormatMessageToSend or not ChatLocalization.LocalizeFormattedMessage then
  40. function ChatLocalization:FormatMessageToSend(key,default) return default end
  41. end
  42.  
  43. local function allSpaces(inputString)
  44. local testString = string.gsub(inputString, " ", "")
  45. return string.len(testString) == 0
  46. end
  47.  
  48. --////////////////////////////// Methods
  49. --//////////////////////////////////////
  50. local methods = {}
  51. methods.__index = methods
  52.  
  53. function methods:AddChannel(channelName, autoJoin)
  54. if (self.ChatChannels[channelName:lower()]) then
  55. error(string.format("Channel %q alrady exists.", channelName))
  56. end
  57.  
  58. local function DefaultChannelCommands(fromSpeaker, message)
  59. if (message:lower() == "/leave") then
  60. local channel = self:GetChannel(channelName)
  61. local speaker = self:GetSpeaker(fromSpeaker)
  62. if (channel and speaker) then
  63. if (channel.Leavable) then
  64. speaker:LeaveChannel(channelName)
  65. local msg = ChatLocalization:FormatMessageToSend(
  66. "GameChat_ChatService_YouHaveLeftChannel",
  67. string.format("You have left channel '%s'", channelName),
  68. "RBX_NAME",
  69. channelName)
  70. speaker:SendSystemMessage(msg, "System")
  71. else
  72. speaker:SendSystemMessage(ChatLocalization:FormatMessageToSend("GameChat_ChatService_CannotLeaveChannel","You cannot leave this channel."), channelName)
  73. end
  74. end
  75.  
  76. return true
  77. end
  78. return false
  79. end
  80.  
  81.  
  82. local channel = ChatChannel.new(self, channelName)
  83. self.ChatChannels[channelName:lower()] = channel
  84.  
  85. channel:RegisterProcessCommandsFunction("default_commands", DefaultChannelCommands, ChatConstants.HighPriority)
  86.  
  87. local success, err = pcall(function() self.eChannelAdded:Fire(channelName) end)
  88. if not success and err then
  89. print("Error addding channel: " ..err)
  90. end
  91.  
  92. if autoJoin ~= nil then
  93. channel.AutoJoin = autoJoin
  94. if autoJoin then
  95. for _, speaker in pairs(self.Speakers) do
  96. speaker:JoinChannel(channelName)
  97. end
  98. end
  99. end
  100.  
  101. return channel
  102. end
  103.  
  104. function methods:RemoveChannel(channelName)
  105. if (self.ChatChannels[channelName:lower()]) then
  106. local n = self.ChatChannels[channelName:lower()].Name
  107.  
  108. self.ChatChannels[channelName:lower()]:InternalDestroy()
  109. self.ChatChannels[channelName:lower()] = nil
  110.  
  111. local success, err = pcall(function() self.eChannelRemoved:Fire(n) end)
  112. if not success and err then
  113. print("Error removing channel: " ..err)
  114. end
  115. else
  116. warn(string.format("Channel %q does not exist.", channelName))
  117. end
  118. end
  119.  
  120. function methods:GetChannel(channelName)
  121. return self.ChatChannels[channelName:lower()]
  122. end
  123.  
  124.  
  125. function methods:AddSpeaker(speakerName)
  126. if (self.Speakers[speakerName:lower()]) then
  127. error("Speaker \"" .. speakerName .. "\" already exists!")
  128. end
  129.  
  130. local speaker = Speaker.new(self, speakerName)
  131. self.Speakers[speakerName:lower()] = speaker
  132.  
  133. local success, err = pcall(function() self.eSpeakerAdded:Fire(speakerName) end)
  134. if not success and err then
  135. print("Error adding speaker: " ..err)
  136. end
  137.  
  138. return speaker
  139. end
  140.  
  141. function methods:InternalUnmuteSpeaker(speakerName)
  142. for channelName, channel in pairs(self.ChatChannels) do
  143. if channel:IsSpeakerMuted(speakerName) then
  144. channel:UnmuteSpeaker(speakerName)
  145. end
  146. end
  147. end
  148.  
  149. function methods:RemoveSpeaker(speakerName)
  150. if (self.Speakers[speakerName:lower()]) then
  151. local n = self.Speakers[speakerName:lower()].Name
  152.  
  153. self:InternalUnmuteSpeaker(n)
  154.  
  155. self.Speakers[speakerName:lower()]:InternalDestroy()
  156. self.Speakers[speakerName:lower()] = nil
  157.  
  158. local success, err = pcall(function() self.eSpeakerRemoved:Fire(n) end)
  159. if not success and err then
  160. print("Error removing speaker: " ..err)
  161. end
  162.  
  163. else
  164. warn("Speaker \"" .. speakerName .. "\" does not exist!")
  165. end
  166. end
  167.  
  168. function methods:GetSpeaker(speakerName)
  169. return self.Speakers[speakerName:lower()]
  170. end
  171.  
  172. function methods:GetSpeakerByUserOrDisplayName(speakerName)
  173. local speakerByUserName = self.Speakers[speakerName:lower()]
  174.  
  175. if speakerByUserName then
  176. return speakerByUserName
  177. end
  178.  
  179. for _, potentialSpeaker in pairs(self.Speakers) do
  180. local player = potentialSpeaker:GetPlayer()
  181.  
  182. if player and player.DisplayName:lower() == speakerName:lower() then
  183. return potentialSpeaker
  184. end
  185. end
  186. end
  187.  
  188. function methods:GetChannelList()
  189. local list = {}
  190. for i, channel in pairs(self.ChatChannels) do
  191. if (not channel.Private) then
  192. table.insert(list, channel.Name)
  193. end
  194. end
  195. return list
  196. end
  197.  
  198. function methods:GetAutoJoinChannelList()
  199. local list = {}
  200. for i, channel in pairs(self.ChatChannels) do
  201. if channel.AutoJoin then
  202. table.insert(list, channel)
  203. end
  204. end
  205. return list
  206. end
  207.  
  208. function methods:GetSpeakerList()
  209. local list = {}
  210. for i, speaker in pairs(self.Speakers) do
  211. table.insert(list, speaker.Name)
  212. end
  213. return list
  214. end
  215.  
  216. function methods:SendGlobalSystemMessage(message)
  217. for i, speaker in pairs(self.Speakers) do
  218. speaker:SendSystemMessage(message, nil)
  219. end
  220. end
  221.  
  222. function methods:RegisterFilterMessageFunction(funcId, func, priority)
  223. if self.FilterMessageFunctions:HasFunction(funcId) then
  224. error(string.format("FilterMessageFunction '%s' already exists", funcId))
  225. end
  226. self.FilterMessageFunctions:AddFunction(funcId, func, priority)
  227. end
  228.  
  229. function methods:FilterMessageFunctionExists(funcId)
  230. return self.FilterMessageFunctions:HasFunction(funcId)
  231. end
  232.  
  233. function methods:UnregisterFilterMessageFunction(funcId)
  234. if not self.FilterMessageFunctions:HasFunction(funcId) then
  235. error(string.format("FilterMessageFunction '%s' does not exists", funcId))
  236. end
  237. self.FilterMessageFunctions:RemoveFunction(funcId)
  238. end
  239.  
  240. function methods:RegisterProcessCommandsFunction(funcId, func, priority)
  241. if self.ProcessCommandsFunctions:HasFunction(funcId) then
  242. error(string.format("ProcessCommandsFunction '%s' already exists", funcId))
  243. end
  244. self.ProcessCommandsFunctions:AddFunction(funcId, func, priority)
  245. end
  246.  
  247. function methods:ProcessCommandsFunctionExists(funcId)
  248. return self.ProcessCommandsFunctions:HasFunction(funcId)
  249. end
  250.  
  251. function methods:UnregisterProcessCommandsFunction(funcId)
  252. if not self.ProcessCommandsFunctions:HasFunction(funcId) then
  253. error(string.format("ProcessCommandsFunction '%s' does not exist", funcId))
  254. end
  255. self.ProcessCommandsFunctions:RemoveFunction(funcId)
  256. end
  257.  
  258. local LastFilterNoficationTime = 0
  259. local LastFilterIssueTime = 0
  260. local FilterIssueCount = 0
  261. function methods:InternalNotifyFilterIssue()
  262. if (tick() - LastFilterIssueTime) > FILTER_THRESHOLD_TIME then
  263. FilterIssueCount = 0
  264. end
  265. FilterIssueCount = FilterIssueCount + 1
  266. LastFilterIssueTime = tick()
  267. if FilterIssueCount >= FILTER_NOTIFCATION_THRESHOLD then
  268. if (tick() - LastFilterNoficationTime) > FILTER_NOTIFCATION_INTERVAL then
  269. LastFilterNoficationTime = tick()
  270. local systemChannel = self:GetChannel("System")
  271. if systemChannel then
  272. systemChannel:SendSystemMessage(
  273. ChatLocalization:FormatMessageToSend(
  274. "GameChat_ChatService_ChatFilterIssues",
  275. "The chat filter is currently experiencing issues and messages may be slow to appear."
  276. ),
  277. errorExtraData
  278. )
  279. end
  280. end
  281. end
  282. end
  283.  
  284. local StudioMessageFilteredCache = {}
  285.  
  286. --///////////////// Internal-Use Methods
  287. --//////////////////////////////////////
  288. --DO NOT REMOVE THIS. Chat must be filtered or your game will face
  289. --moderation.
  290. function methods:InternalApplyRobloxFilter(speakerName, message, toSpeakerName) --// USES FFLAG
  291. local runfilter = false
  292. if (runfilter) then
  293. local fromSpeaker = self:GetSpeaker(speakerName)
  294. local toSpeaker = toSpeakerName and self:GetSpeaker(toSpeakerName)
  295.  
  296. if fromSpeaker == nil then
  297. return nil
  298. end
  299.  
  300. local fromPlayerObj = fromSpeaker:GetPlayer()
  301. local toPlayerObj = toSpeaker and toSpeaker:GetPlayer()
  302.  
  303. if fromPlayerObj == nil then
  304. return message
  305. end
  306.  
  307. if allSpaces(message) then
  308. return message
  309. end
  310.  
  311. local filterStartTime = tick()
  312. local filterRetries = 0
  313. while true do
  314. local success, message = pcall(function()
  315. if toPlayerObj then
  316. return Chat:FilterStringAsync(message, fromPlayerObj, toPlayerObj)
  317. else
  318. return Chat:FilterStringForBroadcast(message, fromPlayerObj)
  319. end
  320. end)
  321. if success then
  322. return message
  323. else
  324. warn("Error filtering message:", message)
  325. end
  326. filterRetries = filterRetries + 1
  327. if filterRetries > MAX_FILTER_RETRIES or (tick() - filterStartTime) > MAX_FILTER_DURATION then
  328. self:InternalNotifyFilterIssue()
  329. return nil
  330. end
  331. local backoffInterval = FILTER_BACKOFF_INTERVALS[math.min(#FILTER_BACKOFF_INTERVALS, filterRetries)]
  332. -- backoffWait = backoffInterval +/- (0 -> backoffInterval)
  333. local backoffWait = backoffInterval + ((math.random()*2 - 1) * backoffInterval)
  334. wait(backoffWait)
  335. end
  336. else
  337. --// Simulate filtering latency.
  338. --// There is only latency the first time the message is filtered, all following calls will be instant.
  339. if not StudioMessageFilteredCache[message] then
  340. StudioMessageFilteredCache[message] = true
  341. wait()
  342. end
  343. return message
  344. end
  345.  
  346. return nil
  347. end
  348.  
  349. --// Return values: bool filterSuccess, bool resultIsFilterObject, variant result
  350. function methods:InternalApplyRobloxFilterNewAPI(speakerName, message, textFilterContext) --// USES FFLAG
  351. local alwaysRunFilter = false
  352. local runFilter = false
  353. if (alwaysRunFilter or runFilter) then
  354.  
  355. local fromSpeaker = self:GetSpeaker(speakerName)
  356. if fromSpeaker == nil then
  357. return false, nil, nil
  358. end
  359.  
  360. local fromPlayerObj = fromSpeaker:GetPlayer()
  361. if fromPlayerObj == nil then
  362. return true, false, message
  363. end
  364.  
  365. if allSpaces(message) then
  366. return true, false, message
  367. end
  368.  
  369. local success, filterResult = pcall(function()
  370. local ts = game:GetService("TextService")
  371. local result = ts:FilterStringAsync(message, fromPlayerObj.UserId, textFilterContext)
  372. return result
  373. end)
  374. if (success) then
  375. return true, true, filterResult
  376. else
  377. warn("Error filtering message:", message, filterResult)
  378. self:InternalNotifyFilterIssue()
  379. return false, nil, nil
  380. end
  381. end
  382.  
  383. --// Simulate filtering latency.
  384. wait()
  385. return true, false, message
  386. end
  387.  
  388. function methods:InternalDoMessageFilter(speakerName, messageObj, channel)
  389. local filtersIterator = self.FilterMessageFunctions:GetIterator()
  390.  
  391. for funcId, func, priority in filtersIterator do
  392. local success, errorMessage = pcall(function()
  393. func(speakerName, messageObj, channel)
  394. end)
  395.  
  396. if not success then
  397. warn(string.format("DoMessageFilter Function '%s' failed for reason: %s", funcId, errorMessage))
  398. end
  399. end
  400. end
  401.  
  402. function methods:InternalDoProcessCommands(speakerName, message, channel)
  403. local commandsIterator = self.ProcessCommandsFunctions:GetIterator()
  404.  
  405. for funcId, func, priority in commandsIterator do
  406. local success, returnValue = pcall(function()
  407. local ret = func(speakerName, message, channel)
  408. if type(ret) ~= "boolean" then
  409. error("Process command functions must return a bool")
  410. end
  411. return ret
  412. end)
  413.  
  414. if not success then
  415. warn(string.format("DoProcessCommands Function '%s' failed for reason: %s", funcId, returnValue))
  416. elseif returnValue then
  417. return true
  418. end
  419. end
  420.  
  421. return false
  422. end
  423.  
  424. function methods:InternalGetUniqueMessageId()
  425. local id = self.MessageIdCounter
  426. self.MessageIdCounter = id + 1
  427. return id
  428. end
  429.  
  430. function methods:InternalAddSpeakerWithPlayerObject(speakerName, playerObj, fireSpeakerAdded)
  431. if (self.Speakers[speakerName:lower()]) then
  432. error("Speaker \"" .. speakerName .. "\" already exists!")
  433. end
  434.  
  435. local speaker = Speaker.new(self, speakerName)
  436. speaker:InternalAssignPlayerObject(playerObj)
  437. self.Speakers[speakerName:lower()] = speaker
  438.  
  439. if fireSpeakerAdded then
  440. local success, err = pcall(function() self.eSpeakerAdded:Fire(speakerName) end)
  441. if not success and err then
  442. print("Error adding speaker: " ..err)
  443. end
  444. end
  445.  
  446. return speaker
  447. end
  448.  
  449. function methods:InternalFireSpeakerAdded(speakerName)
  450. local success, err = pcall(function() self.eSpeakerAdded:Fire(speakerName) end)
  451. if not success and err then
  452. print("Error firing speaker added: " ..err)
  453. end
  454. end
  455.  
  456. --///////////////////////// Constructors
  457. --//////////////////////////////////////
  458.  
  459. function module.new()
  460. local obj = setmetatable({}, methods)
  461.  
  462. obj.MessageIdCounter = 0
  463.  
  464. obj.ChatChannels = {}
  465. obj.Speakers = {}
  466.  
  467. obj.FilterMessageFunctions = Util:NewSortedFunctionContainer()
  468. obj.ProcessCommandsFunctions = Util:NewSortedFunctionContainer()
  469.  
  470. obj.eChannelAdded = Instance.new("BindableEvent")
  471. obj.eChannelRemoved = Instance.new("BindableEvent")
  472. obj.eSpeakerAdded = Instance.new("BindableEvent")
  473. obj.eSpeakerRemoved = Instance.new("BindableEvent")
  474.  
  475. obj.ChannelAdded = obj.eChannelAdded.Event
  476. obj.ChannelRemoved = obj.eChannelRemoved.Event
  477. obj.SpeakerAdded = obj.eSpeakerAdded.Event
  478. obj.SpeakerRemoved = obj.eSpeakerRemoved.Event
  479.  
  480. obj.ChatServiceMajorVersion = 0
  481. obj.ChatServiceMinorVersion = 5
  482.  
  483. return obj
  484. end
  485.  
  486. return module.new()
  487.  
Advertisement
Add Comment
Please, Sign In to add comment