mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-09 07:09:41 -04:00
Add ability to configure profanity filter exceptions
Fix minor bug where color codes counted for censored word length
This commit is contained in:
parent
ba80413526
commit
04d100393c
@ -24,7 +24,8 @@ using MCGalaxy.Util;
|
||||
namespace MCGalaxy {
|
||||
public static class ProfanityFilter {
|
||||
static string[] reduceKeys, reduceValues;
|
||||
static List<string> filters;
|
||||
static List<string> goodWords;
|
||||
static List<string> badWords;
|
||||
static bool hookedFilter;
|
||||
|
||||
public static void Init() {
|
||||
@ -37,28 +38,31 @@ namespace MCGalaxy {
|
||||
string[] words = text.SplitSpaces();
|
||||
string[] reduced = Reduce(text).SplitSpaces();
|
||||
|
||||
// Loop through each reduced word, looking for a bad word
|
||||
for (int i = 0; i < reduced.Length; i++)
|
||||
{
|
||||
bool isFiltered = false;
|
||||
foreach (string filter in filters)
|
||||
{
|
||||
if (reduced[i].Contains(filter)) {
|
||||
isFiltered = true; break;
|
||||
for (int i = 0; i < reduced.Length; i++) {
|
||||
|
||||
foreach (string goodWord in goodWords) {
|
||||
// If the word is a good word, skip bad word check
|
||||
if (Colors.Strip(words[i].ToLower()) == goodWord) {
|
||||
goto nextWord;
|
||||
}
|
||||
}
|
||||
if (!isFiltered) continue;
|
||||
|
||||
// If a bad word is found anywhere in the word, replace the word
|
||||
words[i] = Replace(words[i]);
|
||||
foreach (string badWord in badWords) {
|
||||
if (reduced[i].Contains(badWord)) {
|
||||
// If a bad word is found anywhere in the word, replace the word
|
||||
words[i] = Censor(Colors.Strip(words[i]).Length);
|
||||
goto nextWord;
|
||||
}
|
||||
}
|
||||
// This is more readable than the previous implementation. Don't @ me
|
||||
nextWord:;
|
||||
}
|
||||
return String.Join(" ", words);
|
||||
}
|
||||
|
||||
static string Replace(string word) {
|
||||
static string Censor(int badWordLength) {
|
||||
string replacement = Server.Config.ProfanityReplacement;
|
||||
// for * repeat to ****
|
||||
return replacement.Length == 1 ? new string(replacement[0], word.Length) : replacement;
|
||||
return replacement.Length == 1 ? new string(replacement[0], badWordLength) : replacement;
|
||||
}
|
||||
|
||||
static void InitReduceTable() {
|
||||
@ -70,23 +74,27 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
static void LoadBadWords() {
|
||||
TextFile filterFile = TextFile.Files["Profanity filter"];
|
||||
filterFile.EnsureExists();
|
||||
// Duplicated literal const values? tsk x1000
|
||||
TextFile goodWordsFile = TextFile.Files["Profanity filter exceptions"];
|
||||
TextFile badWordsFile = TextFile.Files["Profanity filter"];
|
||||
goodWordsFile.EnsureExists();
|
||||
badWordsFile.EnsureExists();
|
||||
|
||||
if (!hookedFilter) {
|
||||
hookedFilter = true;
|
||||
filterFile.OnTextChanged += LoadBadWords;
|
||||
badWordsFile.OnTextChanged += LoadBadWords;
|
||||
}
|
||||
|
||||
string[] lines = filterFile.GetText();
|
||||
filters = new List<string>();
|
||||
// Run the badwords through the reducer to ensure things like Ls become Is and everything is lowercase
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.StartsWith("#") || line.Trim().Length == 0) continue;
|
||||
goodWords = goodWordsFile.GetTextWithoutComments();
|
||||
badWords = badWordsFile.GetTextWithoutComments();
|
||||
|
||||
string word = Reduce(line);
|
||||
filters.Add(word);
|
||||
// Convert all goodwords to lowercase to make later comparisons simpler
|
||||
for (int i = 0; i < goodWords.Count; i++) {
|
||||
goodWords[i] = goodWords[i].ToLower();
|
||||
}
|
||||
// Run the badwords through the reducer to ensure things like Ls become Is and everything is lowercase
|
||||
for (int i = 0; i < badWords.Count; i++) {
|
||||
badWords[i] = Reduce(badWords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ namespace MCGalaxy
|
||||
public const string TempBansFile = "text/tempbans.txt";
|
||||
public const string CustomTokensFile = "text/custom$s.txt";
|
||||
public const string BadWordsFile = "text/badwords.txt";
|
||||
public const string BadWordsExceptionsFile = "text/badwords_exceptions.txt";
|
||||
public const string EatMessagesFile = "text/eatmessages.txt";
|
||||
public const string RulesFile = "text/rules.txt";
|
||||
public const string OprulesFile = "text/oprules.txt";
|
||||
|
@ -51,6 +51,19 @@ namespace MCGalaxy.Util
|
||||
public string[] GetText() {
|
||||
return File.ReadAllLines(Filename);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns all text lines in the file that do not begin with # and are not empty.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<string> GetTextWithoutComments() {
|
||||
string[] lines = GetText();
|
||||
List<string> text = new List<string>();
|
||||
foreach (string line in lines) {
|
||||
if (line.StartsWith("#") || line.Trim().Length == 0) continue;
|
||||
text.Add(line);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public void SetText(string[] text) {
|
||||
File.WriteAllLines(Filename, text);
|
||||
@ -75,6 +88,12 @@ namespace MCGalaxy.Util
|
||||
{ "Profanity filter", new TextFile(Paths.BadWordsFile,
|
||||
"# This file is a list of words to remove via the profanity filter",
|
||||
"# Each word to remove must be on an individual line") },
|
||||
{ "Profanity filter exceptions", new TextFile(Paths.BadWordsExceptionsFile,
|
||||
"# This file is a list of words that the profanity filter will not filter,",
|
||||
"# even when part of the word has been added to "+Paths.BadWordsFile,
|
||||
"# This allows mitigation of the \"Scunthorpe problem\" on a case-by-case basis.",
|
||||
"# For instance, one may want to block the word \"Thor\", but allow the word \"Scunthorpe\".",
|
||||
"# Each word to allow must be on an individual line") },
|
||||
{ "Announcements", new TextFile(Paths.AnnouncementsFile, null) },
|
||||
{ "Joker", new TextFile(Paths.JokerFile, null) },
|
||||
{ "8ball", new TextFile(Paths.EightBallFile,
|
||||
|
Loading…
x
Reference in New Issue
Block a user