mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-28 19:52:27 +00:00
Move filter to separate config and add more scanning (#603)
* Create .gitattributes Added a .gitattributes file that excludes the local customWordFilter.txt file from merged updates, allowing server operators to maintain their own word filter list and not have it overwritten. * Update .gitignore Added chatCensoredList to gitignore * Update .gitignore * Dynamic censor list file changes Removed .gitattributes file, attempted to make chatCensoredList.txt into a dynamic file loaded at runtime instead. * Added additional censorship coverage Censorship now covers: Level titles Level descriptions Reviews Comments * Delete chatCensoredList.txt * Update .gitignore Co-authored-by: Josh <josh@slendy.pw> * Update filter verbiage * Update ProjectLighthouse.Servers.GameServer/Controllers/CommentController.cs Co-authored-by: Josh <josh@slendy.pw> * Update ProjectLighthouse/Helpers/CensorHelper.cs Co-authored-by: Josh <josh@slendy.pw> * Add CensorConfiguration and add more filters Co-authored-by: Josh <josh@slendy.pw>
This commit is contained in:
parent
850cfcefb3
commit
326b9e5529
14 changed files with 70 additions and 53 deletions
|
@ -119,7 +119,9 @@ public class CommentController : ControllerBase
|
|||
targetId = await this.database.UserIdFromUsername(username!);
|
||||
}
|
||||
|
||||
bool success = await this.database.PostComment(token.UserId, targetId, type, comment.Message);
|
||||
string filteredText = CensorHelper.FilterMessage(comment.Message);
|
||||
|
||||
bool success = await this.database.PostComment(token.UserId, targetId, type, filteredText);
|
||||
if (success) return this.Ok();
|
||||
|
||||
return this.BadRequest();
|
||||
|
|
|
@ -116,13 +116,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.";
|
|||
return this.Ok();
|
||||
}
|
||||
|
||||
string scannedText = CensorHelper.ScanMessage(message);
|
||||
string filteredText = CensorHelper.FilterMessage(message);
|
||||
|
||||
string username = await this.database.UsernameFromGameToken(token);
|
||||
|
||||
if (ServerConfiguration.Instance.LogChatFiltering)
|
||||
Logger.Info($"{username}: {message} / {scannedText}", LogArea.Filter);
|
||||
Logger.Info($"{username}: {message} / {filteredText}", LogArea.Filter);
|
||||
|
||||
return this.Ok(scannedText);
|
||||
return this.Ok(filteredText);
|
||||
}
|
||||
}
|
|
@ -107,12 +107,16 @@ public class PublishController : ControllerBase
|
|||
return this.BadRequest();
|
||||
}
|
||||
|
||||
slot.Description = CensorHelper.FilterMessage(slot.Description);
|
||||
|
||||
if (slot.Description.Length > 512)
|
||||
{
|
||||
Logger.Warn($"Rejecting level upload, description too long ({slot.Description.Length} characters)", LogArea.Publish);
|
||||
return this.BadRequest();
|
||||
}
|
||||
|
||||
slot.Name = CensorHelper.FilterMessage(slot.Name);
|
||||
|
||||
if (slot.Name.Length > 64)
|
||||
{
|
||||
Logger.Warn($"Rejecting level upload, title too long ({slot.Name.Length} characters)", LogArea.Publish);
|
||||
|
|
|
@ -94,6 +94,8 @@ public class ReviewController : ControllerBase
|
|||
Review? newReview = await this.DeserializeBody<Review>();
|
||||
if (newReview == null) return this.BadRequest();
|
||||
|
||||
newReview.Text = CensorHelper.FilterMessage(newReview.Text);
|
||||
|
||||
if (newReview.Text.Length > 512) return this.BadRequest();
|
||||
|
||||
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == token.UserId);
|
||||
|
|
|
@ -69,7 +69,9 @@ public class SlotPageController : ControllerBase
|
|||
return this.Redirect("~/slot/" + id);
|
||||
}
|
||||
|
||||
// Prevent potential xml injection and censor content
|
||||
msg = SanitizationHelper.SanitizeString(msg);
|
||||
msg = CensorHelper.FilterMessage(msg);
|
||||
|
||||
await this.database.PostComment(token.UserId, id, CommentType.Level, msg);
|
||||
Logger.Success($"Posted comment from {token.UserId}: \"{msg}\" on user {id}", LogArea.Comments);
|
||||
|
|
|
@ -43,7 +43,9 @@ public class UserPageController : ControllerBase
|
|||
return this.Redirect("~/user/" + id);
|
||||
}
|
||||
|
||||
// Prevent potential xml injection and censor content
|
||||
msg = SanitizationHelper.SanitizeString(msg);
|
||||
msg = CensorHelper.FilterMessage(msg);
|
||||
|
||||
await this.database.PostComment(token.UserId, id, CommentType.Profile, msg);
|
||||
Logger.Success($"Posted comment from {token.UserId}: \"{msg}\" on user {id}", LogArea.Comments);
|
||||
|
|
|
@ -15,7 +15,7 @@ public class FilterTestPage : BaseLayout
|
|||
#if DEBUG
|
||||
public IActionResult OnGet(string? text = null)
|
||||
{
|
||||
if (text != null) this.FilteredText = CensorHelper.ScanMessage(text);
|
||||
if (text != null) this.FilteredText = CensorHelper.FilterMessage(text);
|
||||
this.Text = text;
|
||||
|
||||
return this.Page();
|
||||
|
|
|
@ -29,9 +29,11 @@ public class SlotSettingsPage : BaseLayout
|
|||
if (avatarHash != null) this.Slot.IconHash = avatarHash;
|
||||
|
||||
name = SanitizationHelper.SanitizeString(name);
|
||||
name = CensorHelper.FilterMessage(name);
|
||||
if (this.Slot.Name != name && name.Length <= 64) this.Slot.Name = name;
|
||||
|
||||
description = SanitizationHelper.SanitizeString(description);
|
||||
description = CensorHelper.FilterMessage(description);
|
||||
if (this.Slot.Description != description && description.Length <= 512) this.Slot.Description = description;
|
||||
|
||||
labels = LabelHelper.RemoveInvalidLabels(SanitizationHelper.SanitizeString(labels));
|
||||
|
|
|
@ -33,6 +33,7 @@ public class UserSettingsPage : BaseLayout
|
|||
if (avatarHash != null) this.ProfileUser.IconHash = avatarHash;
|
||||
|
||||
biography = SanitizationHelper.SanitizeString(biography);
|
||||
biography = CensorHelper.FilterMessage(biography);
|
||||
|
||||
if (this.ProfileUser.Biography != biography && biography.Length <= 512) this.ProfileUser.Biography = biography;
|
||||
|
||||
|
|
37
ProjectLighthouse/Configuration/CensorConfiguration.cs
Normal file
37
ProjectLighthouse/Configuration/CensorConfiguration.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using System.Collections.Generic;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Configuration;
|
||||
|
||||
public class CensorConfiguration : ConfigurationBase<CensorConfiguration>
|
||||
{
|
||||
public override int ConfigVersion { get; set; } = 1;
|
||||
public override string ConfigName { get; set; } = "censor.yml";
|
||||
public override bool NeedsConfiguration { get; set; } = false;
|
||||
|
||||
public FilterMode UserInputFilterMode { get; set; } = FilterMode.None;
|
||||
|
||||
public List<string> FilteredWordList { get; set; } = new()
|
||||
{
|
||||
"cunt",
|
||||
"fag",
|
||||
"faggot",
|
||||
"horny",
|
||||
"kook",
|
||||
"kys",
|
||||
"loli",
|
||||
"nigga",
|
||||
"nigger",
|
||||
"penis",
|
||||
"pussy",
|
||||
"retard",
|
||||
"retarded",
|
||||
"vagina",
|
||||
"vore",
|
||||
"restitched",
|
||||
"h4h",
|
||||
};
|
||||
|
||||
public override ConfigurationBase<CensorConfiguration> Deserialize(IDeserializer deserializer, string text) => deserializer.Deserialize<CensorConfiguration>(text);
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Configuration;
|
||||
|
@ -12,7 +11,7 @@ public class ServerConfiguration : ConfigurationBase<ServerConfiguration>
|
|||
// This is so Lighthouse can properly identify outdated configurations and update them with newer settings accordingly.
|
||||
// If you are modifying anything here, this value MUST be incremented.
|
||||
// Thanks for listening~
|
||||
public override int ConfigVersion { get; set; } = 16;
|
||||
public override int ConfigVersion { get; set; } = 17;
|
||||
|
||||
public override string ConfigName { get; set; } = "lighthouse.yml";
|
||||
public string WebsiteListenUrl { get; set; } = "http://localhost:10060";
|
||||
|
@ -32,8 +31,6 @@ public class ServerConfiguration : ConfigurationBase<ServerConfiguration>
|
|||
public bool CheckForUnsafeFiles { get; set; } = true;
|
||||
public bool LogChatFiltering { get; set; } = false;
|
||||
|
||||
public FilterMode UserInputFilterMode { get; set; } = FilterMode.None;
|
||||
|
||||
public AuthenticationConfiguration Authentication { get; set; } = new();
|
||||
public CaptchaConfiguration Captcha { get; set; } = new();
|
||||
public DigestKeyConfiguration DigestKey { get; set; } = new();
|
||||
|
|
|
@ -18,15 +18,13 @@ public static class CensorHelper
|
|||
"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").Replace("\r", "").Split("\n");
|
||||
|
||||
public static string ScanMessage(string message)
|
||||
public static string FilterMessage(string message)
|
||||
{
|
||||
if (ServerConfiguration.Instance.UserInputFilterMode == FilterMode.None) return message;
|
||||
if (CensorConfiguration.Instance.UserInputFilterMode == FilterMode.None) return message;
|
||||
|
||||
int profaneIndex = -1;
|
||||
int profaneIndex;
|
||||
|
||||
foreach (string profanity in censorList)
|
||||
foreach (string profanity in CensorConfiguration.Instance.FilteredWordList)
|
||||
do
|
||||
{
|
||||
profaneIndex = message.ToLower().IndexOf(profanity, StringComparison.Ordinal);
|
||||
|
@ -45,7 +43,7 @@ public static class CensorHelper
|
|||
|
||||
sb.Append(message.AsSpan(0, profanityIndex));
|
||||
|
||||
switch (ServerConfiguration.Instance.UserInputFilterMode)
|
||||
switch (CensorConfiguration.Instance.UserInputFilterMode)
|
||||
{
|
||||
case FilterMode.Random:
|
||||
for(int i = 0; i < profanityLength; i++)
|
||||
|
@ -70,14 +68,7 @@ public static class CensorHelper
|
|||
case FilterMode.Asterisks:
|
||||
for(int i = 0; i < profanityLength; i++)
|
||||
{
|
||||
if (message[i] == ' ')
|
||||
{
|
||||
sb.Append(' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append('*');
|
||||
}
|
||||
sb.Append(message[i] == ' ' ? ' ' : '*');
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -89,6 +80,8 @@ public static class CensorHelper
|
|||
}
|
||||
|
||||
break;
|
||||
case FilterMode.None: break;
|
||||
default: throw new ArgumentOutOfRangeException(nameof(message));
|
||||
}
|
||||
|
||||
sb.Append(message.AsSpan(profanityIndex + profanityLength));
|
||||
|
@ -103,14 +96,10 @@ public static class CensorHelper
|
|||
string[] emailArr = email.Split('@');
|
||||
string domainExt = Path.GetExtension(email);
|
||||
|
||||
string maskedEmail = string.Format("{0}****{1}@{2}****{3}{4}",
|
||||
emailArr[0][0],
|
||||
emailArr[0].Substring(emailArr[0].Length - 1),
|
||||
emailArr[1][0],
|
||||
emailArr[1]
|
||||
// Hides everything except the first and last character of the username and domain, preserves the domain extension (.net, .com)
|
||||
string maskedEmail = $"{emailArr[0][0]}****{emailArr[0][^1..]}@{emailArr[1][0]}****{emailArr[1]
|
||||
.Substring(emailArr[1].Length - domainExt.Length - 1,
|
||||
1),
|
||||
domainExt);
|
||||
1)}{domainExt}";
|
||||
|
||||
return maskedEmail;
|
||||
}
|
||||
|
|
|
@ -46,10 +46,6 @@
|
|||
<EmbeddedResource Include="gitUnpushed.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<None Remove="chatCensoredList.txt" />
|
||||
<EmbeddedResource Include="chatCensoredList.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
cunt
|
||||
fag
|
||||
faggot
|
||||
horny
|
||||
kook
|
||||
kys
|
||||
loli
|
||||
nigga
|
||||
nigger
|
||||
penis
|
||||
pussy
|
||||
retard
|
||||
retarded
|
||||
vagina
|
||||
vore
|
||||
restitched
|
||||
h4h
|
Loading…
Add table
Add a link
Reference in a new issue