Hello, I am currently trying to make a roleplay police game inside of which it has a radio (of course), but as of recently I have discovered that messages sent into the radio don’t get filtered, and the unfiltered message gets sent through all of the checks untouched and gets published on the radio. This is a big problem and I’m trying to fix it, but I can’t seem to figure it out.
What are you attempting to achieve? I am trying to filter the text (minimally if possible) What is the issue? It is not filtering at all, or it gets filtered too much. For example, when I say 10-4, it does not get censored in the Roblox chat, but on the radio. What solutions have you tried so far? I’ve tried the following code (from the wiki), but it happens to censor the chat excessively even for radio codes such as “10-4”
local success, message = pcall(function()
filteredMsgObject = textService:FilterStringAsync(msg, p.UserId)
end)
if success then
local worked, errorMessage = pcall(function()
filteredmsg = filteredMsgObject:GetNonChatStringForBroadcastAsync()
end)
if worked then
print(filteredmsg)
AST_Events:WaitForChild("Radio"):WaitForChild("addChat"):FireClient(v,p,filteredmsg)
end
Chief, suggestion, please use the returns of pcall effectively. Wrap the actual method over an anonymous function.
-- Use descriptive variables. "p" is ugly.
local success, result = pcall(TextService.FilterStringAsync, TextService, msg, p.UserId)
if success then
-- No need to pcall this. It just returns a string.
-- Only need to wrap the initial call, as it's internally a web call.
local chatString = result:GetNonChatStringForBroadcastAsync()
print(chatString)
-- Remote fire here
end
That aside, you aren’t filtering wrongly - you’re doing this right. There’s probably a different concern. The chat uses a different method of filtering which respects player privacy settings and such. Broadcast’s filter is much more strict to accommodate all ages and contexts.
I have a radio too, so I’ve went through this problem. After talking to developers which use such stuff, the best way to do is by adding a whitelist of words. In my radio, the radio itself filters word-by-word instead of the whole message. If having such system, you can just see if the word is whitelisted and if so, then do not filter it. What I did is that I used two modules for filtering the message:
The code in the Whitelist script is as simple as this:
local module = {}
-- Tables --
local Whitelist = {
"3M08";
"3M06";
}
-- Scripting --
module.GetWhitelist = function()
return Whitelist
end
return module
The code for the TextFilteringMainHandler is:
local module = {}
-- Variables --
local TextService = game:GetService("TextService")
local WhitelistModule = require(script:WaitForChild("Whitelist"))
-- Functions --
local IsWhitelisted = function(Message)
local Whitelist = WhitelistModule.GetWhitelist()
for i, v in pairs(Whitelist) do
if v == Message then
return true
end
end
return false
end
local GetTextObject = function(Message, FromPlayerId)
local TextObject
local Success, ErrorMessage = pcall(function()
TextObject = TextService:FilterStringAsync(Message, FromPlayerId)
end)
if Success then
return TextObject
end
return false
end
local GetFilteredMessage = function(TextObject)
local FilteredMessage
local Success, ErrorMessage = pcall(function()
FilteredMessage = TextObject:GetNonChatStringForBroadcastAsync()
end)
if Success then
return FilteredMessage
end
return false
end
local OnFilterText = function(Player, Text)
if Text ~= "" then
local MessageObject = GetTextObject(Text, Player.UserId)
local FilteredText = ""
FilteredText = GetFilteredMessage(MessageObject)
return FilteredText
end
end
-- Scripting --
module.GetFilteredText = function(Player, Message)
if IsWhitelisted(Message) == false then
return OnFilterText(Player, Message)
elseif IsWhitelisted(Message) == true then
return Message
end
end
return module
Keep in mind that my radio filters word-by-word, so each word is filtered separately. If yours does not do that, then you can use string.match and try to find a whitelisted word that way, or split it in another script/function and then return word by word.
There’s one way you can filter it that I like to do it that’s a bit easier to use than TextService.
local TextFiltered=game:GetService("Chat"):FilterStringAsync(Message,PlayerFrom,PlayerFrom)
Message is of course what’s being chatted, PlayerFrom is who’s chatting this, and the third option can be the local player (the one getting the radio message, of course). But you can keep it like this if wanted.
I’ve used that method before too, but it makes no difference. The string still gets filtered and codes like “10-4” or “10-8” get tagged.
I also do not like how it requires you to put a second player in as a radio is from one player to all players with access to it, but good recommendation.
Even though my account is over 13, it still sensors. I am guessing that they use the Super-Safe Chat anyways whether you are over 13 or not. Also, I noticed that most of the stuff that gets tagged on the radio does not get tagged on the actual chat, which proves the Super-Safe Chat point. The only ways to do it is by making your own Safe Chat (not recommended as you would have to put some naughty words in there and I do not think Roblox would allow that), or by adding a whitelist which is a very good way of not sensoring stuff that are taken as inappropriate but are completely appropriate, like 10 codes.
Maybe they changed it. Here is the problem thought. If you use that one and a user is under 13 and someone types a 10 code, then it will censor that text for the for the user. Also, it seems like that the text gets filtered after it gets received, and that is why it adjusts with each player’s settings. That is in fact a solution, but then you have to deal with this problem if the user is under 13.
One of reason that I do not use that method is because I break that rule of PlayerFrom and PlayerTo. This is required because it is used when making a report. I know that Roblox report system is not the greatest, but it is helpful. If you do PlayerFrom and replace PlayerTo to PlayerFrom, you break the request role and also disable reporting of a player using the Roblox system (what the Roblox report system does is that it takes logs from any messages the player sent either to you or the server in general, and if replaced, then the message(s) won’t count as the player is pretty much whispering to themselves.) Breaking that rule is pretty much cheating an argument using Roblox’s chat services and I do not find that right.
This confused me. I don’t get what you mean. But from what I can assume is you mean that making it PlayerFrom and PlayerTo both PlayerFrom it breaks the report system. I don’t get what you mean because ROBLOX can see the logs of any player that was chatted on the system. So if someone was saying something mean to another person, ROBLOX would still log that and have a conversation recorded in the logs.
They can see the logs of any player, but it makes it more difficult I think. Either way, it is not right to cheat an argument like that unless you are actually sending a message to yourself. Roblox has that argument there for a reason and cheating the system like that is not right. I recommend the whitelist method as it is quarantined to work with any age groups and you can have custom words that the system itself marks as inappropriate when they are not.
Don’t get me wrong, at first, I tried using that system too, but it did not feel right cheating an argument like that. It also did not help as much as there were still things that got censored anyways but were completely appropriate (if I remember correctly, E/R is one of them). Still, it is a way to solve it, just not the best one.
It’s not really easier, it’s just taking an extra step away. You still have to wrap that method in a pcall because it’s internally a web call. TextService is the canonical way to filter a string.