Change the word filter configuration to allow providing reasons, fix emotes not working in filters, and implement separate OOC/IC/PDA filters (#61606)

This commit is contained in:
Mothblocks
2021-09-25 21:13:43 -07:00
committed by GitHub
parent 0211a2e9eb
commit dbe560f4d9
20 changed files with 269 additions and 33 deletions
@@ -24,8 +24,24 @@
/// If the configuration is loaded
var/loaded = FALSE
/// A regex that matches words blocked IC
var/static/regex/ic_filter_regex
/// A regex that matches words blocked OOC
var/static/regex/ooc_filter_regex
/// A regex that matches words blocked IC, but not in PDAs
var/static/regex/ic_outside_pda_filter_regex
/// An assoc list of blocked IC words to their reasons
var/static/list/ic_filter_reasons
/// An assoc list of words that are blocked IC, but not in PDAs, to their reasons
var/static/list/ic_outside_pda_filter_reasons
/// An assoc list of words that are blocked both IC and OOC to their reasons
var/static/list/shared_filter_reasons
/datum/controller/configuration/proc/admin_reload()
if(IsAdminAdvancedProcCall())
return
@@ -338,17 +354,84 @@ Example config:
log_config("Unknown command in map vote config: '[command]'")
/datum/controller/configuration/proc/LoadChatFilter()
var/list/in_character_filter = list()
if(!fexists("[directory]/in_character_filter.txt"))
if(!fexists("[directory]/word_filter.toml"))
load_legacy_chat_filter()
return
log_config("Loading config file word_filter.toml...")
var/list/word_filter = rustg_read_toml_file("[directory]/word_filter.toml")
if (!islist(word_filter))
var/message = "The word filter configuration did not output a list, contact someone with configuration access to make sure it's setup properly."
log_config(message)
DelayedMessageAdmins(message)
return
ic_filter_reasons = try_extract_from_word_filter(word_filter, "ic")
ic_outside_pda_filter_reasons = try_extract_from_word_filter(word_filter, "ic_outside_pda")
shared_filter_reasons = try_extract_from_word_filter(word_filter, "shared")
update_chat_filter_regexes()
/datum/controller/configuration/proc/load_legacy_chat_filter()
if (!fexists("[directory]/in_character_filter.txt"))
return
log_config("Loading config file in_character_filter.txt...")
for(var/line in world.file2list("[directory]/in_character_filter.txt"))
if(!line)
ic_filter_reasons = list()
ic_outside_pda_filter_reasons = list()
shared_filter_reasons = list()
for (var/line in world.file2list("[directory]/in_character_filter.txt"))
if (!line)
continue
if(findtextEx(line,"#",1,2))
if (findtextEx(line, "#", 1, 2))
continue
in_character_filter += REGEX_QUOTE(line)
ic_filter_regex = in_character_filter.len ? regex("\\b([jointext(in_character_filter, "|")])\\b", "i") : null
// The older filter didn't apply to PDA
ic_outside_pda_filter_reasons[line] = "No reason available"
update_chat_filter_regexes()
/// Will update the internal regexes of the chat filter based on the filter reasons
/datum/controller/configuration/proc/update_chat_filter_regexes()
ic_filter_regex = compile_filter_regex(ic_filter_reasons + ic_outside_pda_filter_reasons + shared_filter_reasons)
ic_outside_pda_filter_regex = compile_filter_regex(ic_filter_reasons + shared_filter_reasons)
ooc_filter_regex = compile_filter_regex(shared_filter_reasons)
/datum/controller/configuration/proc/try_extract_from_word_filter(list/word_filter, key)
var/list/banned_words = word_filter[key]
if (isnull(banned_words))
return list()
else if (!islist(banned_words))
var/message = "The word filter configuration's '[key]' key was invalid, contact someone with configuration access to make sure it's setup properly."
log_config(message)
DelayedMessageAdmins(message)
return list()
return banned_words
/datum/controller/configuration/proc/compile_filter_regex(list/banned_words)
if (isnull(banned_words) || banned_words.len == 0)
return null
var/static/regex/should_join_on_word_bounds = regex(@"^\w+$")
// Stuff like emoticons needs another split, since there's no way to get ":)" on a word bound.
// Furthermore, normal words need to be on word bounds, so "(adminhelp)" gets filtered.
var/list/to_join_on_whitespace_splits = list()
var/list/to_join_on_word_bounds = list()
for (var/banned_word in banned_words)
if (findtext(banned_word, should_join_on_word_bounds))
to_join_on_word_bounds += REGEX_QUOTE(banned_word)
else
to_join_on_whitespace_splits += REGEX_QUOTE(banned_word)
var/whitespace_split = @"(?:(?:^|\s+)(" + jointext(to_join_on_whitespace_splits, "|") + @")(?:$|\s+))"
var/word_bounds = @"(\b(" + jointext(to_join_on_word_bounds, "|") + "))"
return regex("([whitespace_split]|[word_bounds])", "i")
//Message admins when you can.
/datum/controller/configuration/proc/DelayedMessageAdmins(text)