mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-09 15:23:28 -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 {
|
namespace MCGalaxy {
|
||||||
public static class ProfanityFilter {
|
public static class ProfanityFilter {
|
||||||
static string[] reduceKeys, reduceValues;
|
static string[] reduceKeys, reduceValues;
|
||||||
static List<string> filters;
|
static List<string> goodWords;
|
||||||
|
static List<string> badWords;
|
||||||
static bool hookedFilter;
|
static bool hookedFilter;
|
||||||
|
|
||||||
public static void Init() {
|
public static void Init() {
|
||||||
@ -37,28 +38,31 @@ namespace MCGalaxy {
|
|||||||
string[] words = text.SplitSpaces();
|
string[] words = text.SplitSpaces();
|
||||||
string[] reduced = Reduce(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++) {
|
||||||
for (int i = 0; i < reduced.Length; i++)
|
|
||||||
{
|
foreach (string goodWord in goodWords) {
|
||||||
bool isFiltered = false;
|
// If the word is a good word, skip bad word check
|
||||||
foreach (string filter in filters)
|
if (Colors.Strip(words[i].ToLower()) == goodWord) {
|
||||||
{
|
goto nextWord;
|
||||||
if (reduced[i].Contains(filter)) {
|
}
|
||||||
isFiltered = true; break;
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isFiltered) continue;
|
// This is more readable than the previous implementation. Don't @ me
|
||||||
|
nextWord:;
|
||||||
// If a bad word is found anywhere in the word, replace the word
|
}
|
||||||
words[i] = Replace(words[i]);
|
|
||||||
}
|
|
||||||
return String.Join(" ", words);
|
return String.Join(" ", words);
|
||||||
}
|
}
|
||||||
|
|
||||||
static string Replace(string word) {
|
static string Censor(int badWordLength) {
|
||||||
string replacement = Server.Config.ProfanityReplacement;
|
string replacement = Server.Config.ProfanityReplacement;
|
||||||
// for * repeat to ****
|
// 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() {
|
static void InitReduceTable() {
|
||||||
@ -70,23 +74,27 @@ namespace MCGalaxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void LoadBadWords() {
|
static void LoadBadWords() {
|
||||||
TextFile filterFile = TextFile.Files["Profanity filter"];
|
// Duplicated literal const values? tsk x1000
|
||||||
filterFile.EnsureExists();
|
TextFile goodWordsFile = TextFile.Files["Profanity filter exceptions"];
|
||||||
|
TextFile badWordsFile = TextFile.Files["Profanity filter"];
|
||||||
|
goodWordsFile.EnsureExists();
|
||||||
|
badWordsFile.EnsureExists();
|
||||||
|
|
||||||
if (!hookedFilter) {
|
if (!hookedFilter) {
|
||||||
hookedFilter = true;
|
hookedFilter = true;
|
||||||
filterFile.OnTextChanged += LoadBadWords;
|
badWordsFile.OnTextChanged += LoadBadWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] lines = filterFile.GetText();
|
goodWords = goodWordsFile.GetTextWithoutComments();
|
||||||
filters = new List<string>();
|
badWords = badWordsFile.GetTextWithoutComments();
|
||||||
|
|
||||||
|
// 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
|
// Run the badwords through the reducer to ensure things like Ls become Is and everything is lowercase
|
||||||
foreach (string line in lines)
|
for (int i = 0; i < badWords.Count; i++) {
|
||||||
{
|
badWords[i] = Reduce(badWords[i]);
|
||||||
if (line.StartsWith("#") || line.Trim().Length == 0) continue;
|
|
||||||
|
|
||||||
string word = Reduce(line);
|
|
||||||
filters.Add(word);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ namespace MCGalaxy
|
|||||||
public const string TempBansFile = "text/tempbans.txt";
|
public const string TempBansFile = "text/tempbans.txt";
|
||||||
public const string CustomTokensFile = "text/custom$s.txt";
|
public const string CustomTokensFile = "text/custom$s.txt";
|
||||||
public const string BadWordsFile = "text/badwords.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 EatMessagesFile = "text/eatmessages.txt";
|
||||||
public const string RulesFile = "text/rules.txt";
|
public const string RulesFile = "text/rules.txt";
|
||||||
public const string OprulesFile = "text/oprules.txt";
|
public const string OprulesFile = "text/oprules.txt";
|
||||||
|
@ -51,6 +51,19 @@ namespace MCGalaxy.Util
|
|||||||
public string[] GetText() {
|
public string[] GetText() {
|
||||||
return File.ReadAllLines(Filename);
|
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) {
|
public void SetText(string[] text) {
|
||||||
File.WriteAllLines(Filename, text);
|
File.WriteAllLines(Filename, text);
|
||||||
@ -75,6 +88,12 @@ namespace MCGalaxy.Util
|
|||||||
{ "Profanity filter", new TextFile(Paths.BadWordsFile,
|
{ "Profanity filter", new TextFile(Paths.BadWordsFile,
|
||||||
"# This file is a list of words to remove via the profanity filter",
|
"# This file is a list of words to remove via the profanity filter",
|
||||||
"# Each word to remove must be on an individual line") },
|
"# 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) },
|
{ "Announcements", new TextFile(Paths.AnnouncementsFile, null) },
|
||||||
{ "Joker", new TextFile(Paths.JokerFile, null) },
|
{ "Joker", new TextFile(Paths.JokerFile, null) },
|
||||||
{ "8ball", new TextFile(Paths.EightBallFile,
|
{ "8ball", new TextFile(Paths.EightBallFile,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user