Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Chat Filter functionality #191

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Added Chat Filter functionality #191

wants to merge 3 commits into from

Conversation

Adonca2203
Copy link
Contributor

Added a chat filter setting which enables/disables chat filters for the local client.

There is a new json setting called "ChatSettings" which host a filter list as well as a boolean to enable/disable the feature (default disabled)

The feature can be enabled/disabled in the General Settings tab, you can add your own words to filter using regular string or regex as well as have a replacement word if you'd like to replace instances of the bad word.

This change is only reflected locally and not enforced lobby wide so everyone has their own filter list. There is a default list of words which got pulled in discord but these too can be removed.

Also did some cleaning up of removing unused dependencies in scripts.

@Adonca2203 Adonca2203 requested a review from rc174945 November 17, 2024 23:56
Copy link
Collaborator

@AutumnThyme AutumnThyme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have an example program that you can use to validate your filters.
You may want to look to use this as a basis for your implementation though I have no idea what the performance is. Looking this up online, this seems to be a hard problem that most people have just left to report review and AI since analyzing text is hard.

The tl;dr/most important parts of this review are:
Load from a dedicated json resource file we include with the game, no hardcoding profanities in code.
Load profanity list on game start IF the user has it enabled -> do not waste memory/performance on a disabled feature.
Current implementation is a bit messy and not performant at scale, use example program as a basis for this (prioritize not doing a ton of string operations since C# is absolutely horrible at handling those)
Finally, ensure that the implementation does not break rich text formatting (honestly I have no idea how to handle this and its going to be an annoying task likely)

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

public class ProfanityTest
{
    public static void Main(string[] args)
    {
        List<string> filters = new List<string>() {
            "\\bt\\w*st\\b",
            "\\b\\w*input\\b",
            "\\btha+t\\b",
            "\\bchecK\\b",
            "\\bis\\b"
        };
        string input = "This is a test input that we want to check for profanities. Let's commit to retesting to ensure only word against words are checked.";
        
        List<Regex> compiledPatterns = filters.ConvertAll(pattern => new Regex(pattern, RegexOptions.IgnoreCase));
        
        foreach (var regex in compiledPatterns)
        {
            input = regex.Replace(input, match => 
            {
                string word = match.Value;
                if (word.Length > 2)
                {
                    return word[0] + new string('*', word.Length - 2) + word[word.Length-1];
                }
                return new string('*', word.Length);
            });
        }
        
        Console.WriteLine(input);
    }
}

Expected Output:

This ** a t**t i***t t**t we want to c***k for profanities. Let's commit to retesting to ensure only word against words are checked.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with all the asset changes?

StringSetting,
StringSetting
>(
new Dictionary<StringSetting, StringSetting>()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be loaded from a file, having this stuff hardcoded in the game is a bit weird and takes up unnecessary memory.

foreach(KeyValuePair<StringSetting, StringSetting> entry in _chatSettings.filters)
{
// Regex Key is stored with leading and trailing quotes so need to remove those
string cleaned_pattern = entry.Key.Value.TrimStart('"').TrimEnd('"');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you aren't getting a clean string from the json, there is an issue with your implementation.

{
// Regex Key is stored with leading and trailing quotes so need to remove those
string cleaned_pattern = entry.Key.Value.TrimStart('"').TrimEnd('"');
Regex pattern = new Regex(cleaned_pattern, RegexOptions.IgnoreCase);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should pre-compile each regex if its going to be called on every message (ofc not pre-compiled if the setting is off otherwise this will use up memory)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is really needed, we should just load this stuff like all other json files we load (think UI.Locale).
Optimally what I would want out of this is for us to potentially ship the game with a single "FilteredWords.json" file, this should include at most a list of string patterns and potentially a integer/float value for filter level.

On Game Join, if the setting is enabled, load the list into memory. Otherwise do not load it into memory and have the filter be a null check/quickly return each message as valid.


while (match.Success)
{
for (int i = 1; i <= 2; i++)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer if we use a more linq/C# approach to iterating over matches.
Likewise if we're allowing user defined patterns, then there can be any number of groups.
We should pick either a dedicated rule, 1 word/phrase per pattern. I should note that this also looks like its going to cause issues with word boundaries, basically a phrase containing profanity is not necessary profanity which means entries will need to either be defined correctly wrapping each with \b or we do this for the user (less control but less complaints about it not working)

@@ -225,6 +225,8 @@
"General.FPSFOVMinTooltip": "Field of view when not moving and using 0 camera distance.",
"General.FPSFOVMax": "FPS FOV max",
"General.FPSFOVMaxTooltip": "Field of view when moving at high speeds and using 0 camera distance.",
"General.FilterChat": "Enable chat filters.",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix tabbing

@@ -283,7 +283,196 @@ PlayerSettings:
m_Width: 128
m_Height: 128
m_Kind: 0
m_BuildTargetPlatformIcons: []
m_BuildTargetPlatformIcons:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't targeting these platforms?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants