From 0d54c5ade18c39b809c4cc6c5255ec8d8f93c7db Mon Sep 17 00:00:00 2001 From: Logan Lowe Date: Tue, 8 Mar 2022 00:43:00 -0700 Subject: [PATCH] Add server-side text safety features - user input will now be checked against a known list of profanities (such as toyo). Filter mode can be adjusted in global config file between four levels according to desired level of punishment; 0 - None 1 - Asterisks 2 - Random Characters 3 - Furry Fixes #34 --- .../Controllers/GameApi/MessageController.cs | 10 +- ProjectLighthouse/Helpers/CensorHelper.cs | 142 ++++++ ProjectLighthouse/Helpers/HashHelper.cs | 9 +- ProjectLighthouse/Helpers/RandomHelper.cs | 8 + ProjectLighthouse/Helpers/ResourceHelper.cs | 20 + ProjectLighthouse/Helpers/VersionHelper.cs | 16 +- ProjectLighthouse/ProjectLighthouse.csproj | 50 +- .../Types/Settings/ServerSettings.cs | 5 +- ProjectLighthouse/chatCensoredList.txt | 437 ++++++++++++++++++ 9 files changed, 655 insertions(+), 42 deletions(-) create mode 100644 ProjectLighthouse/Helpers/CensorHelper.cs create mode 100644 ProjectLighthouse/Helpers/RandomHelper.cs create mode 100644 ProjectLighthouse/Helpers/ResourceHelper.cs create mode 100644 ProjectLighthouse/chatCensoredList.txt diff --git a/ProjectLighthouse/Controllers/GameApi/MessageController.cs b/ProjectLighthouse/Controllers/GameApi/MessageController.cs index 6a5d653b..b378413d 100644 --- a/ProjectLighthouse/Controllers/GameApi/MessageController.cs +++ b/ProjectLighthouse/Controllers/GameApi/MessageController.cs @@ -78,11 +78,15 @@ public class MessageController : ControllerBase public async Task Filter() { User? user = await this.database.UserFromGameRequest(this.Request); + if (user == null) return this.StatusCode(403, ""); - string loggedText = await new StreamReader(this.Request.Body).ReadToEndAsync(); + string response = await new StreamReader(this.Request.Body).ReadToEndAsync(); + + string scannedText = CensorHelper.ScanMessage(response); - Logger.Log($"{user.Username}: {loggedText}", LoggerLevelFilter.Instance); - return this.Ok(loggedText); + Logger.Log($"{user.Username}: {response} / {scannedText}", LoggerLevelFilter.Instance); + + return this.Ok(scannedText); } } \ No newline at end of file diff --git a/ProjectLighthouse/Helpers/CensorHelper.cs b/ProjectLighthouse/Helpers/CensorHelper.cs new file mode 100644 index 00000000..eb164d49 --- /dev/null +++ b/ProjectLighthouse/Helpers/CensorHelper.cs @@ -0,0 +1,142 @@ +using System.Text; +using LBPUnion.ProjectLighthouse.Types.Settings; + +namespace LBPUnion.ProjectLighthouse.Helpers; + +public enum FilterMode +{ + None, + Asterisks, + Random, + Furry, +} + +public static class CensorHelper +{ + private static readonly char[] _randomCharacters = + { + '!', + '@', + '#', + '$', + '&', + '%', + '-', + 'A', + 'b', + 'C', + 'd', + 'E', + 'f', + 'G', + 'h', + 'I', + 'j', + 'K', + 'l', + 'M', + 'n', + 'O', + 'p', + 'Q', + 'r', + 'S', + 't', + 'U', + 'v', + 'W', + 'x', + 'Y', + 'z', + }; + + private static readonly string[] _randomFurry = + { + "UwU", + "OwO", + "uwu", + "owo", + "o3o", + ">.>", + "*pounces on you*", + "*boops*", + "*baps*", + ":P", + "x3", + "O_O", + "xD", + ":3", + ";3", + "^w^", + }; + + private static readonly string[] _censorList = ResourceHelper.readManifestFile("chatCensoredList.txt").Split("\n"); + + public static string ScanMessage(string message) + { + if (ServerSettings.Instance.UserInputFilterMode == FilterMode.None) return message; + + int profaneIndex = -1; + + foreach (string profanity in _censorList) + do + { + profaneIndex = message.ToLower().IndexOf(profanity); + if (profaneIndex != -1) + message = Censor(profaneIndex, + profanity.Length, + message); + } + while (profaneIndex != -1); + + return message; + } + + private static string Censor(int profanityIndex, int profanityLength, string message) + { + StringBuilder sb = new(); + + string randomWord; + char randomChar; + char prevRandomChar = '\0'; + + sb.Append(message.Substring(0, + profanityIndex)); + + switch (ServerSettings.Instance.UserInputFilterMode) + { + case FilterMode.Random: + for (int i = 0; i < profanityLength; i++) + lock (RandomHelper.random) + { + randomChar = _randomCharacters[RandomHelper.random.Next(0, + _randomCharacters.Length - 1)]; + if (randomChar == prevRandomChar) + randomChar = _randomCharacters[RandomHelper.random.Next(0, + _randomCharacters.Length - 1)]; + + prevRandomChar = randomChar; + + sb.Append(randomChar); + } + + break; + case FilterMode.Asterisks: + for (int i = 0; i < profanityLength; i++) sb.Append('*'); + break; + case FilterMode.Furry: + lock (RandomHelper.random) + { + randomWord = _randomFurry[RandomHelper.random.Next(0, + _randomFurry.Length - 1)]; + sb.Append(randomWord); + } + + break; + } + + sb.Append(message.Substring(profanityIndex + profanityLength)); + + return sb.ToString(); + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Helpers/HashHelper.cs b/ProjectLighthouse/Helpers/HashHelper.cs index e613df39..3cfe3a2a 100644 --- a/ProjectLighthouse/Helpers/HashHelper.cs +++ b/ProjectLighthouse/Helpers/HashHelper.cs @@ -14,7 +14,6 @@ public static class HashHelper { // private static readonly SHA1 sha1 = SHA1.Create(); private static readonly SHA256 sha256 = SHA256.Create(); - private static readonly Random random = new(); /// /// Generates a specified amount of random bytes in an array. @@ -24,8 +23,12 @@ public static class HashHelper public static IEnumerable GenerateRandomBytes(int count) { byte[] b = new byte[count]; - random.NextBytes(b); - + + lock (RandomHelper.random) + { + RandomHelper.random.NextBytes(b); + } + return b; } diff --git a/ProjectLighthouse/Helpers/RandomHelper.cs b/ProjectLighthouse/Helpers/RandomHelper.cs new file mode 100644 index 00000000..f978717e --- /dev/null +++ b/ProjectLighthouse/Helpers/RandomHelper.cs @@ -0,0 +1,8 @@ +using System; + +namespace LBPUnion.ProjectLighthouse.Helpers; + +public static class RandomHelper +{ + public static readonly Random random = new(); +} \ No newline at end of file diff --git a/ProjectLighthouse/Helpers/ResourceHelper.cs b/ProjectLighthouse/Helpers/ResourceHelper.cs new file mode 100644 index 00000000..389155bd --- /dev/null +++ b/ProjectLighthouse/Helpers/ResourceHelper.cs @@ -0,0 +1,20 @@ +using System; +using System.IO; +using System.Linq; +using Kettu; +using LBPUnion.ProjectLighthouse.Logging; +using LBPUnion.ProjectLighthouse.Types.Settings; + +namespace LBPUnion.ProjectLighthouse.Helpers; + +public static class ResourceHelper +{ + public static string readManifestFile(string fileName) + { + using Stream stream = + typeof(Program).Assembly.GetManifestResourceStream($"{typeof(Program).Namespace}.{fileName}"); + using StreamReader reader = new(stream ?? throw new Exception("The assembly or manifest resource is null.")); + + return reader.ReadToEnd().Trim(); + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Helpers/VersionHelper.cs b/ProjectLighthouse/Helpers/VersionHelper.cs index 3a806a5c..0e229ccb 100644 --- a/ProjectLighthouse/Helpers/VersionHelper.cs +++ b/ProjectLighthouse/Helpers/VersionHelper.cs @@ -13,10 +13,10 @@ public static class VersionHelper { try { - CommitHash = readManifestFile("gitVersion.txt"); - Branch = readManifestFile("gitBranch.txt"); + CommitHash = ResourceHelper.readManifestFile("gitVersion.txt"); + Branch = ResourceHelper.readManifestFile("gitBranch.txt"); - string remotesFile = readManifestFile("gitRemotes.txt"); + string remotesFile = ResourceHelper.readManifestFile("gitRemotes.txt"); string[] lines = remotesFile.Split('\n'); @@ -26,7 +26,7 @@ public static class VersionHelper // linq is a serious and painful catastrophe but its useful so i'm gonna keep using it Remotes = lines.Select(line => line.Split("\t")[1]).ToArray(); - CommitsOutOfDate = readManifestFile("gitUnpushed.txt").Split('\n').Length; + CommitsOutOfDate = ResourceHelper.readManifestFile("gitUnpushed.txt").Split('\n').Length; CanCheckForUpdates = true; } @@ -55,14 +55,6 @@ public static class VersionHelper } } - private static string readManifestFile(string fileName) - { - using Stream stream = typeof(Program).Assembly.GetManifestResourceStream($"{typeof(Program).Namespace}.{fileName}"); - using StreamReader reader = new(stream ?? throw new Exception("The assembly or manifest resource is null.")); - - return reader.ReadToEnd().Trim(); - } - public static string CommitHash { get; set; } public static string Branch { get; set; } public static string FullVersion => $"{ServerStatics.ServerName} {Branch}@{CommitHash} {Build}"; diff --git a/ProjectLighthouse/ProjectLighthouse.csproj b/ProjectLighthouse/ProjectLighthouse.csproj index cc178e8a..12487b64 100644 --- a/ProjectLighthouse/ProjectLighthouse.csproj +++ b/ProjectLighthouse/ProjectLighthouse.csproj @@ -12,53 +12,57 @@ - - - - - - - - - + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - + Always - + Always - + Always - + Always - - + + + Always + + + - + - - - - + + + + diff --git a/ProjectLighthouse/Types/Settings/ServerSettings.cs b/ProjectLighthouse/Types/Settings/ServerSettings.cs index 1ea4e3e5..06c7ff72 100644 --- a/ProjectLighthouse/Types/Settings/ServerSettings.cs +++ b/ProjectLighthouse/Types/Settings/ServerSettings.cs @@ -5,6 +5,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using JetBrains.Annotations; using Kettu; +using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Logging; namespace LBPUnion.ProjectLighthouse.Types.Settings; @@ -12,7 +13,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings; [Serializable] public class ServerSettings { - public const int CurrentConfigVersion = 24; // MUST BE INCREMENTED FOR EVERY CONFIG CHANGE! + public const int CurrentConfigVersion = 25; // MUST BE INCREMENTED FOR EVERY CONFIG CHANGE! private static FileSystemWatcher fileWatcher; static ServerSettings() { @@ -144,6 +145,8 @@ public class ServerSettings public bool BooingEnabled { get; set; } = true; + public FilterMode UserInputFilterMode { get; set; } = FilterMode.None; + public bool DiscordWebhookEnabled { get; set; } public string DiscordWebhookUrl { get; set; } = ""; diff --git a/ProjectLighthouse/chatCensoredList.txt b/ProjectLighthouse/chatCensoredList.txt new file mode 100644 index 00000000..d24656b8 --- /dev/null +++ b/ProjectLighthouse/chatCensoredList.txt @@ -0,0 +1,437 @@ +4r5e +5h1t +5hit +a55 +anal +anus +ar5e +arrse +ass-fucker +asses +assfucker +assfukka +assholes +asswhole +a_s_s +b!tch +b00bs +b17ch +b1tch +ballbag +ballsack +bastard +beastial +beastiality +bellend +bestial +bestiality +bi+ch +biatch +bitch +bitcher +bitchers +bitches +bitching +bloody +blow job +blowjob +blowjobs +boiolas +bollock +bollok +boner +boob +boobs +booobs +boooobs +booooobs +booooooobs +breasts +buceta +bugger +bum +bunny fucker +butt +butthole +buttmunch +buttplug +c0ck +c0cksucker +carpet muncher +cawk +chink +cipa +cl1t +clit +clitoris +clits +cnut +cock +cock-sucker +cockface +cockhead +cockmunch +cockmuncher +cocks +cocksuck +cocksucked +cocksucker +cocksucking +cocksucks +cocksuka +cocksukka +cok +cokmuncher +coksucka +coon +cox +crap +cum +cummer +cumming +cums +cumshot +cunilingus +cunillingus +cunnilingus +cunt +cuntlick +cuntlicker +cuntlicking +cunts +cyalis +cyberfuc +cyberfuck +cyberfucked +cyberfucker +cyberfuckers +cyberfucking +d1ck +dick +dickhead +dildo +dildos +dink +dinks +dirsa +dlck +dog-fucker +doggin +dogging +donkeyribber +doosh +duche +dyke +ejaculate +ejaculated +ejaculates +ejaculating +ejaculatings +ejaculation +ejakulate +f u c k +f u c k e r +f4nny +fridinator +fag +fagging +faggitt +faggot +faggs +fagot +fagots +fags +fanny +fannyflaps +fannyfucker +fanyy +fatass +fcuk +fcuker +fcuking +fecker +felching +fellate +fellatio +fingerfuck +fingerfucked +fingerfucker +fingerfuckers +fingerfucking +fingerfucks +fistfuck +fistfucked +fistfucker +fistfuckers +fistfucking +fistfuckings +fistfucks +flange +fook +fooker +fucka +fucked +fucker +fuckers +fuckhead +fuckheads +fuckin +fucking +fuckings +fuckingshitmotherfucker +fuckme +fucks +fuckwhit +fuckwit +fudge packer +fudgepacker +fuk +fuker +fukker +fukkin +fuks +fukwhit +fukwit +fux +fux0r +f_u_c_k +gangbang +gangbanged +gangbangs +gaylord +gaysex +goatse +hardcoresex +heshe +hoar +hoare +hoer +hore +horniest +horny +hotsex +jack-off +jackoff +jap +jerk-off +jism +jiz +jizm +jizz +kawk +knob +knobead +knobed +knobend +knobhead +knobjocky +knobjokey +kock +kondum +kondums +kum +kummer +kumming +kums +kunilingus +kiunt +l3i+ch +l3itch +labia +lmfao +lust +lusting +m0f0 +m0fo +m45terbate +ma5terb8 +ma5terbate +masochist +master-bate +masterb8 +masterbat* +masterbat3 +masterbate +masterbation +masterbations +masturbate +mo-fo +mof0 +mofo +mothafuck +mothafucka +mothafuckas +mothafuckaz +mothafucked +mothafucker +mothafuckers +mothafuckin +mothafucking +mothafuckings +mothafucks +mother fucker +motherfuck +motherfucked +motherfucker +motherfuckers +motherfuckin +motherfucking +motherfuckings +motherfuckka +motherfucks +muff +mutha +muthafecker +muthafuckker +muther +mutherfucker +n1gga +n1gger +nazi +nft +nigg3r +nigg4h +nigga +niggah +niggas +niggaz +nigger +niggers +nob +nob jokey +nobhead +nobjocky +nobjokey +numbnuts +nutsack +orgasim +orgasims +orgasm +orgasms +p0rn +pawn +pecker +penis +penisfucker +phonesex +phuck +phuk +phuked +phuking +phukked +phukking +phuks +phuq +pigfucker +pimpis +pissed +pisser +pissers +pisses +pissflaps +pissin +pissing +pissoff +porn +porno +pornography +pornos +prick +pricks +pron +pube +pusse +pussi +pussies +pussy +pussys +rectum +restitched +retard +rimjaw +rimming +s hit +s.o.b. +sadist +schlong +screwing +scroat +scrote +scrotum +semen +sex +sh!+ +sh!t +sh1t +shag +shagger +shaggin +shagging +shemale +shi+ +shitdick +shited +shitey +shitfuck +shitfull +shithead +shiting +shitings +shits +shitted +shitter +shitters +shitting +shittings +shitty +skank +slut +shiftos +sluts +smegma +smut +snatch +son-of-a-bitch +spac +spunk +s_h_i_t +t1tt1e5 +t1tties +teets +teez +testical +testicle +tit +titfuck +tits +titt +tittie5 +tittiefucker +titties +tittyfuck +tittywank +titwank +toyo +tosser +tw4t +twat +twathead +twatty +twunt +twunter +v14gra +v1gra +vagina +viagra +vulva +w00se +wang +wank +wanker +wanky +whoar +whore +willies +willy +xrated +xxx \ No newline at end of file