How to properly filter text?

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
1 Like

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.

2 Likes

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:

image

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.

2 Likes

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.

1 Like

10-4 and 10-8 gets tagged because of the user’s account age (13+, <13). If that was the reason for yours then the filtering does work.

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.

1 Like

Unusual. The code I sent is the code I used for my friend InfinityAlif’s SCP game, which doesn’t censor weirdly like yours. Proof:
image
You must have a special case.

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.

1 Like

Wrong. PlayerFrom, PlayerFrom means that it filters for that player and it shows that same filtering (from my knowledge).

Isn’t it supposed to be PlayerFrom and PlayerTo (or the reverse)?

1 Like

It is. Unless you mark both as PlayerFrom, it doesn’t filter for that person.

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.

1 Like

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.

2 Likes

I get what you mean. Seems weird though.

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.

1 Like

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.