Chat Filter System

Implements a filtering system for type chat. 
This incorporates a character replacement system that replaces what the server sees with other characters (For example, "à" would be replaced by "a"). What characters are replaced by what can be customized in `chatfilter.json`. Spaces and commas are hardcoded to be removed from the message that the server reads due to a lack of experience with .NET.
Includes a feature that replaces blocked messages with "This message has been removed." The message can be changed in `chatfilter.json`. It can be removed by making the string empty.
This system also logs messages into the console, and marks which messages are blocked.
This commit is contained in:
YoshiCraft64 2025-09-07 18:59:02 -05:00 committed by GitHub
parent a94e5f75e0
commit 15aacc282e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 217 additions and 4 deletions

View File

@ -9,20 +9,57 @@ namespace sodoffmmo.CommandHandlers;
class ChatMessageHandler : CommandHandler {
public override Task Handle(Client client, NetworkObject receivedObject) {
string message = receivedObject.Get<NetworkObject>("p").Get<string>("chm");
string messageFilter = message.ToLower();
if (ManagementCommandProcessor.ProcessCommand(message, client))
return Task.CompletedTask;
if (client.TempMuted) {
if (client.TempMuted)
{
ClientMuted(client);
return Task.CompletedTask;
}
if (!Configuration.ServerConfiguration.EnableChat && !client.Room.AllowChatOverride) {
}
messageFilter = messageFilter.Replace(",", "");//Hardcoded to remove commas from the message due to some issues
foreach (var replaceable in ChatFilter.ChatFilterConfiguration.charsToRemove)//Rolls through the entire character replacement list
{
if (replaceable.Contains(","))//Checks if the replace string is valid (has a comma)
{
string char1 = replaceable.Remove(replaceable.LastIndexOf(','));//Gets the character to be replaced
string char2 = replaceable.Remove(0, replaceable.LastIndexOf(',') + 1);//Gets the replacement
messageFilter = messageFilter.Replace(char1, char2);
}
}
messageFilter = messageFilter.Replace(" ", "");
foreach (var banned in ChatFilter.ChatFilterConfiguration.FilteredWords)//Rolls through the entire denylist
{
if (messageFilter.Contains(banned))//Checks if your message contains a word from the denylist
{
Console.WriteLine("Banned message from " + client.PlayerData.Uid + " (" + client.PlayerData.DiplayName + "): \"" + messageFilter + "\", \"" + message + "\" in game: " + client.PlayerData.ZoneName);
ClientFilter(client);
if (!ChatFilter.ChatFilterConfiguration.blockedMessage.Equals(""))
Chat(client, ChatFilter.ChatFilterConfiguration.blockedMessage);//This replaces the user's message with the message in the string. TODO: Add the string to the chatfilter json for the purpose of customization (How do I do that)
return Task.CompletedTask;
}
}
if (!Configuration.ServerConfiguration.EnableChat && !client.Room.AllowChatOverride)
{
ChatDisabled(client);
} else {
}
else
{
Console.WriteLine("Message from " + client.PlayerData.Uid + " (" + client.PlayerData.DiplayName + "): \"" + messageFilter + "\", \"" + message + "\" in game: " + client.PlayerData.ZoneName);
Chat(client, message);
}
return Task.CompletedTask;
}
public void ClientFilter(Client client)
{
client.Send(Utils.BuildServerSideMessage("This message contains a word or phrase not allowed on this server.", "Server"));
}
public void ChatDisabled(Client client) {
client.Send(Utils.BuildServerSideMessage("Unfortunately, chat has been disabled by server administrators", "Server"));
}

42
src/Core/ChatFilter.cs Normal file
View File

@ -0,0 +1,42 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace sodoffmmo.Core;
internal static class ChatFilter
{
public static ChatFilterConfiguration ChatFilterConfiguration { get; private set; } = new ChatFilterConfiguration();
public static void Initialize()
{
using FileStream stream = File.OpenRead("src\\chatfilter.json");
ChatFilterConfiguration? ChatFilterConfiguration = JsonSerializer.Deserialize<ChatFilterConfiguration>(stream);
ChatFilter.ChatFilterConfiguration = ChatFilterConfiguration;
if (ChatFilter.ChatFilterConfiguration is null)
{
Console.WriteLine("Filter list returned null");
return;
}
}
}
internal sealed class ChatFilterConfiguration
{
public string[] FilteredWords { get; set; } = Array.Empty<string>();
public string[] charsToRemove { get; set; } = Array.Empty<string>();
public string blockedMessage { get; set; } = string.Empty;
}

View File

@ -3,6 +3,7 @@ using sodoffmmo.Core;
using System.Net;
Configuration.Initialize();
ChatFilter.Initialize();
Server server;

133
src/chatfilter.json Normal file
View File

@ -0,0 +1,133 @@
{
"FilteredWords": [
"pineapplepizzaisbad",
"ihatepineapplepizza",
"pineappleonpizzaisbad",
"ihatepineappleonpizza"
],
"charsToRemove": [
"., ",
";, ",
"', ",
"\", ",
"*, ",
"!, ",
"#, ",
"$, ",
"%, ",
"&, ",
"*, ",
"(, ",
"), ",
"^, ",
"{, ",
"}, ",
"[, ",
"], ",
"?, ",
"/, ",
"\\, ",
"-, ",
"_, ",
"¤, ",
"¦, ",
"§, ",
"¨, ",
"«, ",
"¬, ",
"¯, ",
"°, ",
"±, ",
"+, ",
"´, ",
"¶, ",
"·, ",
"¸, ",
"º, ",
"», ",
"¼, ",
"½, ",
"¾, ",
"¿, ",
"÷, ",
"¹,1",
"²,2",
"³,3",
"@,a",
"ª,a",
"¢,c",
"©,c",
"£,e",
"¡,i",
"®,r",
"$,s",
"µ,u",
"×,x",
"¥,y",
"Þ,th",
"þ,th",
"À,a",
"Á,a",
"Â,a",
"Ã,a",
"Ä,a",
"Å,a",
"Æ,ae",
"Ç,c",
"È,e",
"É,e",
"Ê,e",
"Ë,e",
"Ì,i",
"Í,i",
"Î,i",
"Ï,i",
"Đ,dz",
"Ñ,n",
"Ò,o",
"Ó,o",
"Ô,o",
"Õ,o",
"Ö,o",
"Ø,o",
"Ù,u",
"Ú,u",
"Û,u",
"Ü,u",
"Ý,y",
"ß, ",
"à,a",
"á,a",
"â,a",
"ã,a",
"ä,a",
"å,a",
"æ,ae",
"ç,c",
"è,e",
"é,e",
"ê,e",
"ë,e",
"ì,i",
"í,i",
"î,i",
"ï,i",
"ð,dz",
"ñ,n",
"ò,o",
"ó,o",
"ô,o",
"õ,o",
"ö,o",
"ø,o",
"ù,u",
"ú,u",
"û,u",
"ü,u",
"ý,y",
"night,nite"
],
"blockedMessage" : "This message has been removed."
}