Adds the ability to soft filter words, also fixes some word filter bugs (#62158)

This commit is contained in:
NamelessFairy
2021-10-26 20:45:36 +01:00
committed by GitHub
parent 6e8872f178
commit 1238ce2373
27 changed files with 186 additions and 27 deletions

View File

@@ -1,6 +1,6 @@
// [2] is the group index of the blocked term when it is not using word bounds. // [2] is the group index of the blocked term when it is not using word bounds.
// This is sanity checked by unit tests. // This is sanity checked by unit tests.
#define GET_MATCHED_GROUP(regex) (regex.group[2] || regex.match) #define GET_MATCHED_GROUP(regex) (lowertext(regex.group[2] || regex.match))
/// Given a text, will return what word is on the IC filter, with the reason. /// Given a text, will return what word is on the IC filter, with the reason.
/// Returns null if the message is OK. /// Returns null if the message is OK.
@@ -35,4 +35,37 @@
return null return null
/// Given a text, will return what word is on the soft IC filter, with the reason.
/// Returns null if the message is OK.
/proc/is_soft_ic_filtered(message)
if (config.soft_ic_filter_regex?.Find(message))
var/matched_group = GET_MATCHED_GROUP(config.soft_ic_filter_regex)
return list(
matched_group,
config.soft_ic_filter_reasons[matched_group] || config.soft_ic_outside_pda_filter_reasons[matched_group] || config.soft_shared_filter_reasons[matched_group],
)
return null
/// Given a text, will return what word is on the soft IC filter, ignoring words allowed on the PDA, with the reason.
/// Returns null if the message is OK.
/proc/is_soft_ic_filtered_for_pdas(message)
if (config.soft_ic_outside_pda_filter_regex?.Find(message))
var/matched_group = GET_MATCHED_GROUP(config.soft_ic_outside_pda_filter_regex)
return list(
matched_group,
config.soft_ic_filter_reasons[matched_group] || config.soft_shared_filter_reasons[matched_group],
)
return null
///Given a text, will return that word is on the soft OOC filter, with the reason.
/// Returns null if the message is OK.
/proc/is_soft_ooc_filtered(message)
if (config.soft_ooc_filter_regex?.Find(message))
var/matched_group = GET_MATCHED_GROUP(config.soft_ooc_filter_regex)
return list(matched_group, config.soft_shared_filter_reasons[matched_group])
return null
#undef GET_MATCHED_GROUP #undef GET_MATCHED_GROUP

View File

@@ -23,7 +23,7 @@
///returns nothing with an alert instead of the message if it contains something in the ic filter, and sanitizes normally if the name is fine. It returns nothing so it backs out of the input the same way as if you had entered nothing. ///returns nothing with an alert instead of the message if it contains something in the ic filter, and sanitizes normally if the name is fine. It returns nothing so it backs out of the input the same way as if you had entered nothing.
/proc/sanitize_name(t,allow_numbers=FALSE) /proc/sanitize_name(t,allow_numbers=FALSE)
if(is_ic_filtered(t)) if(is_ic_filtered(t) || is_soft_ic_filtered(t))
tgui_alert(usr, "You cannot set a name that contains a word prohibited in IC chat!") tgui_alert(usr, "You cannot set a name that contains a word prohibited in IC chat!")
return "" return ""
var/r = reject_bad_name(t,allow_numbers=allow_numbers,strict=TRUE) var/r = reject_bad_name(t,allow_numbers=allow_numbers,strict=TRUE)
@@ -221,7 +221,7 @@
return //(not case sensitive) return //(not case sensitive)
// Protects against names containing IC chat prohibited words. // Protects against names containing IC chat prohibited words.
if(is_ic_filtered(t_out)) if(is_ic_filtered(t_out) || is_soft_ic_filtered(t_out))
return return
return t_out return t_out

View File

@@ -32,6 +32,15 @@
/// A regex that matches words blocked IC, but not in PDAs /// A regex that matches words blocked IC, but not in PDAs
var/static/regex/ic_outside_pda_filter_regex var/static/regex/ic_outside_pda_filter_regex
/// A regex that matches words soft blocked IC
var/static/regex/soft_ic_filter_regex
/// A regex that matches words soft blocked OOC
var/static/regex/soft_ooc_filter_regex
/// A regex that matches words soft blocked IC, but not in PDAs
var/static/regex/soft_ic_outside_pda_filter_regex
/// An assoc list of blocked IC words to their reasons /// An assoc list of blocked IC words to their reasons
var/static/list/ic_filter_reasons var/static/list/ic_filter_reasons
@@ -42,6 +51,15 @@
/// An assoc list of words that are blocked both IC and OOC to their reasons /// An assoc list of words that are blocked both IC and OOC to their reasons
var/static/list/shared_filter_reasons var/static/list/shared_filter_reasons
/// An assoc list of soft blocked IC words to their reasons
var/static/list/soft_ic_filter_reasons
/// An assoc list of words that are soft blocked IC, but not in PDAs, to their reasons
var/static/list/soft_ic_outside_pda_filter_reasons
/// An assoc list of words that are soft blocked both IC and OOC to their reasons
var/static/list/soft_shared_filter_reasons
/datum/controller/configuration/proc/admin_reload() /datum/controller/configuration/proc/admin_reload()
if(IsAdminAdvancedProcCall()) if(IsAdminAdvancedProcCall())
return return
@@ -370,6 +388,9 @@ Example config:
ic_filter_reasons = try_extract_from_word_filter(word_filter, "ic") 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") 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") shared_filter_reasons = try_extract_from_word_filter(word_filter, "shared")
soft_ic_filter_reasons = try_extract_from_word_filter(word_filter, "soft_ic")
soft_ic_outside_pda_filter_reasons = try_extract_from_word_filter(word_filter, "soft_ic_outside_pda")
soft_shared_filter_reasons = try_extract_from_word_filter(word_filter, "soft_shared")
update_chat_filter_regexes() update_chat_filter_regexes()
@@ -382,6 +403,9 @@ Example config:
ic_filter_reasons = list() ic_filter_reasons = list()
ic_outside_pda_filter_reasons = list() ic_outside_pda_filter_reasons = list()
shared_filter_reasons = list() shared_filter_reasons = list()
soft_ic_filter_reasons = list()
soft_ic_outside_pda_filter_reasons = list()
soft_shared_filter_reasons = list()
for (var/line in world.file2list("[directory]/in_character_filter.txt")) for (var/line in world.file2list("[directory]/in_character_filter.txt"))
if (!line) if (!line)
@@ -398,6 +422,9 @@ Example config:
ic_filter_regex = compile_filter_regex(ic_filter_reasons + ic_outside_pda_filter_reasons + shared_filter_reasons) 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) ic_outside_pda_filter_regex = compile_filter_regex(ic_filter_reasons + shared_filter_reasons)
ooc_filter_regex = compile_filter_regex(shared_filter_reasons) ooc_filter_regex = compile_filter_regex(shared_filter_reasons)
soft_ic_filter_regex = compile_filter_regex(soft_ic_filter_reasons + soft_ic_outside_pda_filter_reasons + soft_shared_filter_reasons)
soft_ic_outside_pda_filter_regex = compile_filter_regex(soft_ic_filter_reasons + soft_shared_filter_reasons)
soft_ooc_filter_regex = compile_filter_regex(soft_shared_filter_reasons)
/datum/controller/configuration/proc/try_extract_from_word_filter(list/word_filter, key) /datum/controller/configuration/proc/try_extract_from_word_filter(list/word_filter, key)
var/list/banned_words = word_filter[key] var/list/banned_words = word_filter[key]
@@ -410,7 +437,11 @@ Example config:
DelayedMessageAdmins(message) DelayedMessageAdmins(message)
return list() return list()
return banned_words var/list/formatted_banned_words = list()
for (var/banned_word in banned_words)
formatted_banned_words[lowertext(banned_word)] = banned_words[banned_word]
return formatted_banned_words
/datum/controller/configuration/proc/compile_filter_regex(list/banned_words) /datum/controller/configuration/proc/compile_filter_regex(list/banned_words)
if (isnull(banned_words) || banned_words.len == 0) if (isnull(banned_words) || banned_words.len == 0)

View File

@@ -180,7 +180,7 @@
client.images.Remove(human_image) client.images.Remove(human_image)
return ..() return ..()
/mob/camera/imaginary_friend/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/camera/imaginary_friend/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if (!message) if (!message)
return return

View File

@@ -163,7 +163,7 @@
to_chat(src, span_notice("As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality.")) to_chat(src, span_notice("As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality."))
to_chat(src, span_warning("<b>Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.</b>")) to_chat(src, span_warning("<b>Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.</b>"))
/mob/living/split_personality/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/split_personality/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
to_chat(src, span_warning("You cannot speak, your other self is controlling your body!")) to_chat(src, span_warning("You cannot speak, your other self is controlling your body!"))
return FALSE return FALSE

View File

@@ -1313,7 +1313,7 @@
if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT)) if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT))
var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text
// Check the new name against the chat filter. If it triggers the IC chat filter, give an option to confirm. // Check the new name against the chat filter. If it triggers the IC chat filter, give an option to confirm.
if(newname && !(is_ic_filtered(newname) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) != "Confirm")) if(newname && !(is_ic_filtered(newname) || is_soft_ic_filtered(newname) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) != "Confirm"))
vv_auto_rename(newname) vv_auto_rename(newname)
if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT)) if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT))

View File

@@ -261,6 +261,12 @@ AI MODULES
if(is_ic_filtered(targName)) if(is_ic_filtered(targName))
to_chat(user, span_warning("Error: Law contains invalid text.")) // AI LAW 2 SAY U W U WITHOUT THE SPACES to_chat(user, span_warning("Error: Law contains invalid text.")) // AI LAW 2 SAY U W U WITHOUT THE SPACES
return return
var/list/soft_filter_result = is_soft_ooc_filtered(targName)
if(soft_filter_result)
if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
return
message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"")
log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"")
laws[1] = targName laws[1] = targName
..() ..()
@@ -468,6 +474,12 @@ AI MODULES
if(is_ic_filtered(targName)) if(is_ic_filtered(targName))
to_chat(user, span_warning("Error: Law contains invalid text.")) to_chat(user, span_warning("Error: Law contains invalid text."))
return return
var/list/soft_filter_result = is_soft_ooc_filtered(targName)
if(soft_filter_result)
if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
return
message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"")
log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"")
laws[1] = targName laws[1] = targName
..() ..()
@@ -490,6 +502,12 @@ AI MODULES
if(is_ic_filtered(targName)) // not even the syndicate can uwu if(is_ic_filtered(targName)) // not even the syndicate can uwu
to_chat(user, span_warning("Error: Law contains invalid text.")) to_chat(user, span_warning("Error: Law contains invalid text."))
return return
var/list/soft_filter_result = is_soft_ooc_filtered(targName)
if(soft_filter_result)
if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
return
message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"")
log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"")
laws[1] = targName laws[1] = targName
..() ..()

View File

@@ -764,6 +764,13 @@ GLOBAL_LIST_EMPTY(PDAs)
REPORT_CHAT_FILTER_TO_USER(user, filter_result) REPORT_CHAT_FILTER_TO_USER(user, filter_result)
return return
var/list/soft_filter_result = is_soft_ic_filtered_for_pdas(message)
if (soft_filter_result)
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to send it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
return
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[html_encode(message)]\"")
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[message]\"")
if(prob(1)) if(prob(1))
message += "\nSent from my PDA" message += "\nSent from my PDA"
// Send the signal // Send the signal

View File

@@ -20,7 +20,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
"[FREQ_CTF_YELLOW]" = "yellowteamradio" "[FREQ_CTF_YELLOW]" = "yellowteamradio"
)) ))
/atom/movable/proc/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /atom/movable/proc/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if(!can_speak()) if(!can_speak())
return return
if(sanitize) if(sanitize)

View File

@@ -32,7 +32,7 @@
// If the new name is something that would be restricted by IC chat filters, // If the new name is something that would be restricted by IC chat filters,
// give the admin a warning but allow them to do it anyway if they want. // give the admin a warning but allow them to do it anyway if they want.
if(is_ic_filtered(new_name) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) == "Cancel") if(is_ic_filtered(new_name) || is_soft_ic_filtered(new_name) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) == "Cancel")
return return
if( !new_name || !M ) if( !new_name || !M )

View File

@@ -72,7 +72,7 @@
return 1 return 1
return ..() return ..()
/mob/living/simple_animal/hostile/blob/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/simple_animal/hostile/blob/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if(sanitize) if(sanitize)
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
var/spanned_message = say_quote(message) var/spanned_message = say_quote(message)

View File

@@ -243,7 +243,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
blob_points = clamp(blob_points + points, 0, max_blob_points) blob_points = clamp(blob_points + points, 0, max_blob_points)
hud_used.blobpwrdisplay.maptext = MAPTEXT("<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#e36600'>[round(blob_points)]</font></div>") hud_used.blobpwrdisplay.maptext = MAPTEXT("<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#e36600'>[round(blob_points)]</font></div>")
/mob/camera/blob/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/camera/blob/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if (!message) if (!message)
return return

View File

@@ -25,6 +25,13 @@
if(filter_result) if(filter_result)
REPORT_CHAT_FILTER_TO_USER(usr, filter_result) REPORT_CHAT_FILTER_TO_USER(usr, filter_result)
return return
var/list/soft_filter_result = is_soft_ic_filtered(input)
if(soft_filter_result)
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to say it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
return
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[html_encode(input)]\"")
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[input]\"")
cultist_commune(usr, input) cultist_commune(usr, input)
/datum/action/innate/cult/comm/proc/cultist_commune(mob/living/user, message) /datum/action/innate/cult/comm/proc/cultist_commune(mob/living/user, message)
@@ -32,7 +39,7 @@
if(!message) if(!message)
return return
user.whisper("O bidai nabora se[pick("'","`")]sma!", language = /datum/language/common) user.whisper("O bidai nabora se[pick("'","`")]sma!", language = /datum/language/common)
user.whisper(html_decode(message)) user.whisper(html_decode(message), filterproof = TRUE)
var/title = "Acolyte" var/title = "Acolyte"
var/span = "cult italic" var/span = "cult italic"
if(user.mind && user.mind.has_antag_datum(/datum/antagonist/cult/master)) if(user.mind && user.mind.has_antag_datum(/datum/antagonist/cult/master))

View File

@@ -111,7 +111,7 @@ the new instance inside the host to be updated to the template's stats.
for(var/datum/disease_ability/ability in purchased_abilities) for(var/datum/disease_ability/ability in purchased_abilities)
. += span_notice("[ability.name]") . += span_notice("[ability.name]")
/mob/camera/disease/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/camera/disease/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if(!message) if(!message)
return return
if(sanitize) if(sanitize)

View File

@@ -158,7 +158,7 @@
/mob/living/simple_animal/revenant/med_hud_set_status() /mob/living/simple_animal/revenant/med_hud_set_status()
return //we use no hud return //we use no hud
/mob/living/simple_animal/revenant/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/simple_animal/revenant/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if(!message) if(!message)
return return
if(sanitize) if(sanitize)

View File

@@ -36,6 +36,13 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
REPORT_CHAT_FILTER_TO_USER(usr, filter_result) REPORT_CHAT_FILTER_TO_USER(usr, filter_result)
return return
var/list/soft_filter_result = is_soft_ooc_filtered(msg)
if (soft_filter_result)
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to say it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
return
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[msg]\"")
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[msg]\"")
if(!msg) if(!msg)
return return

View File

@@ -9,8 +9,21 @@
mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]] mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]]
return message return message
/mob/dead/observer/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/dead/observer/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
message = trim(message) //trim now and sanitize after checking for special admin radio keys message = trim(message) //trim now and sanitize after checking for special admin radio keys
var/list/filter_result = is_ooc_filtered(message)
if (filter_result)
REPORT_CHAT_FILTER_TO_USER(usr, filter_result)
return
var/list/soft_filter_result = is_soft_ooc_filtered(message)
if (soft_filter_result)
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to say it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
return
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
if(!message) if(!message)
return return
var/list/message_mods = list() var/list/message_mods = list()

View File

@@ -1,4 +1,4 @@
/mob/living/brain/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/brain/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterpoof = null)
if(!(container && istype(container, /obj/item/mmi))) if(!(container && istype(container, /obj/item/mmi)))
return //No MMI, can't speak, bucko./N return //No MMI, can't speak, bucko./N
else else

View File

@@ -92,24 +92,36 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
return new_msg return new_msg
/mob/living/say(message, bubble_type,list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/say(message, bubble_type,list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof)
var/list/filter_result var/list/filter_result
if(client && !forced) var/list/soft_filter_result
if(client && !forced && !filterproof)
//The filter doesn't act on the sanitized message, but the raw message. //The filter doesn't act on the sanitized message, but the raw message.
filter_result = is_ic_filtered(message) filter_result = is_ic_filtered(message)
if(!filter_result)
soft_filter_result = is_soft_ic_filtered(message)
if(sanitize) if(sanitize)
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
if(!message || message == "") if(!message || message == "")
return return
if(filter_result) if(filter_result && !filterproof)
//The filter warning message shows the sanitized message though. //The filter warning message shows the sanitized message though.
to_chat(src, span_warning("That message contained a word prohibited in IC chat! Consider reviewing the server rules.")) to_chat(src, span_warning("That message contained a word prohibited in IC chat! Consider reviewing the server rules."))
to_chat(src, span_warning("\"[message]\"")) to_chat(src, span_warning("\"[message]\""))
REPORT_CHAT_FILTER_TO_USER(src, filter_result) REPORT_CHAT_FILTER_TO_USER(src, filter_result)
SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match)) SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match))
return return
if(soft_filter_result && !filterproof)
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to say it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
return
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
var/list/message_mods = list() var/list/message_mods = list()
var/original_message = message var/original_message = message
message = get_message_mods(message, message_mods) message = get_message_mods(message, message_mods)
@@ -465,10 +477,10 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
else else
. = ..() . = ..()
/mob/living/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof)
if(!message) if(!message)
return return
say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced) say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced, filterproof)
/mob/living/get_language_holder(get_minds = TRUE) /mob/living/get_language_holder(get_minds = TRUE)
if(get_minds && mind) if(get_minds && mind)

View File

@@ -1,4 +1,4 @@
/mob/living/silicon/ai/say(message, bubble_type,list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/silicon/ai/say(message, bubble_type,list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if(parent && istype(parent) && parent.stat != DEAD) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead. if(parent && istype(parent) && parent.stat != DEAD) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
return parent.say(arglist(args)) return parent.say(arglist(args))
return ..() return ..()

View File

@@ -1,4 +1,4 @@
/mob/living/silicon/pai/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/silicon/pai/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if(silent) if(silent)
to_chat(src, span_warning("Communication circuits remain uninitialized.")) to_chat(src, span_warning("Communication circuits remain uninitialized."))
else else

View File

@@ -57,7 +57,7 @@
M.take_damage(50, BRUTE, MELEE, 1) M.take_damage(50, BRUTE, MELEE, 1)
//Elites can't talk (normally)! //Elites can't talk (normally)!
/mob/living/simple_animal/hostile/asteroid/elite/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/simple_animal/hostile/asteroid/elite/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
if(can_talk) if(can_talk)
. = ..() . = ..()
return TRUE return TRUE

View File

@@ -60,7 +60,7 @@
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost() /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost()
icon_state = "herald_ghost" icon_state = "herald_ghost"
/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
. = ..() . = ..()
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)

View File

@@ -109,7 +109,7 @@
. = ..() . = ..()
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_aler.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/runtime/hyperspace/hyperspace_begin.ogg', 'sound/runtime/hyperspace/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/ratvar_reveal.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desecration-01.ogg', 'sound/misc/desecration-02.ogg', 'sound/misc/desecration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gun/pistol/shot_suppressed.ogg', 'sound/weapons/gun/pistol/shot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/default/outbreak5.ogg', 'sound/ai/default/outbreak7.ogg', 'sound/ai/default/poweroff.ogg', 'sound/ai/default/radiation.ogg', 'sound/ai/default/shuttlecalled.ogg', 'sound/ai/default/shuttledock.ogg', 'sound/ai/default/shuttlerecalled.ogg', 'sound/ai/default/aimalf.ogg') //hahahaha fuck you code divers migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_aler.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/runtime/hyperspace/hyperspace_begin.ogg', 'sound/runtime/hyperspace/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/ratvar_reveal.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desecration-01.ogg', 'sound/misc/desecration-02.ogg', 'sound/misc/desecration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gun/pistol/shot_suppressed.ogg', 'sound/weapons/gun/pistol/shot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/default/outbreak5.ogg', 'sound/ai/default/outbreak7.ogg', 'sound/ai/default/poweroff.ogg', 'sound/ai/default/radiation.ogg', 'sound/ai/default/shuttlecalled.ogg', 'sound/ai/default/shuttledock.ogg', 'sound/ai/default/shuttlerecalled.ogg', 'sound/ai/default/aimalf.ogg') //hahahaha fuck you code divers
/mob/living/simple_animal/hostile/netherworld/migo/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/simple_animal/hostile/netherworld/migo/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
..() ..()
if(stat) if(stat)
return return

View File

@@ -144,7 +144,7 @@
// Cannot talk // Cannot talk
/mob/living/simple_animal/hostile/statue/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) /mob/living/simple_animal/hostile/statue/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
return return
// Turn to dust when gibbed // Turn to dust when gibbed

View File

@@ -1,6 +1,9 @@
#define BLOCKED_IC "This message is not allowed IC, please use a different weird test phrase." #define BLOCKED_IC "This message is not allowed IC, please use a different weird test phrase."
#define BLOCKED_IC_OUTSIDE_PDA "Kirby dancing is strictly prohibited on this server." #define BLOCKED_IC_OUTSIDE_PDA "Kirby dancing is strictly prohibited on this server."
#define BLOCKED_SHARED "This message is not allowed anywhere, please use a different weird test phrase." #define BLOCKED_SHARED "This message is not allowed anywhere, please use a different weird test phrase."
#define SOFT_BLOCKED_IC "This term is commonly considered OOC, only use it with context."
#define SOFT_BLOCKED_IC_OUTSIDE_PDA "Stop saying debug phrases ICly."
#define SOFT_BLOCKED_SHARED "You risk being banned if this term is used improperly."
/// Tests the sanity of the chat filter, ensuring it properly blocks words and gives the reason /// Tests the sanity of the chat filter, ensuring it properly blocks words and gives the reason
/datum/unit_test/chat_filter_sanity /datum/unit_test/chat_filter_sanity
@@ -10,6 +13,9 @@
config.shared_filter_reasons = list("blockedinshared" = BLOCKED_SHARED) config.shared_filter_reasons = list("blockedinshared" = BLOCKED_SHARED)
config.ic_filter_reasons = list("blockedinic" = BLOCKED_IC) config.ic_filter_reasons = list("blockedinic" = BLOCKED_IC)
config.ic_outside_pda_filter_reasons = list("<(0_0<)" = BLOCKED_IC_OUTSIDE_PDA) config.ic_outside_pda_filter_reasons = list("<(0_0<)" = BLOCKED_IC_OUTSIDE_PDA)
config.soft_shared_filter_reasons = list("testsoftblocks" = SOFT_BLOCKED_SHARED)
config.soft_ic_filter_reasons = list("testsofterblocks" = SOFT_BLOCKED_IC)
config.soft_ic_outside_pda_filter_reasons = list("testsoftestblocks" = SOFT_BLOCKED_IC_OUTSIDE_PDA)
config.update_chat_filter_regexes() config.update_chat_filter_regexes()
test_filter( test_filter(
@@ -50,14 +56,23 @@
ic_filter_result, ic_filter_result,
pda_filter_result, pda_filter_result,
ooc_filter_result, ooc_filter_result,
soft_ic_filter_result,
soft_pda_filter_result,
soft_ooc_filter_result,
) )
var/ic_filter = is_ic_filtered(message) var/ic_filter = is_ic_filtered(message)
var/pda_filter = is_ic_filtered_for_pdas(message) var/pda_filter = is_ic_filtered_for_pdas(message)
var/ooc_filter = is_ooc_filtered(message) var/ooc_filter = is_ooc_filtered(message)
var/soft_ic_filter = is_soft_ic_filtered(message)
var/soft_pda_filter = is_soft_ic_filtered_for_pdas(message)
var/soft_ooc_filter = is_soft_ooc_filtered(message)
test_filter_result("IC", message, ic_filter, ic_filter_result, blocked_word) test_filter_result("IC", message, ic_filter, ic_filter_result, blocked_word)
test_filter_result("PDA", message, pda_filter, pda_filter_result, blocked_word) test_filter_result("PDA", message, pda_filter, pda_filter_result, blocked_word)
test_filter_result("OOC", message, ooc_filter, ooc_filter_result, blocked_word) test_filter_result("OOC", message, ooc_filter, ooc_filter_result, blocked_word)
test_filter_result("Soft_IC", message, soft_ic_filter, soft_ic_filter_result, blocked_word)
test_filter_result("Soft_PDA", message, soft_pda_filter, soft_pda_filter_result, blocked_word)
test_filter_result("Soft_OOC", message, soft_ooc_filter, soft_ooc_filter_result, blocked_word)
/datum/unit_test/chat_filter_sanity/proc/test_filter_result( /datum/unit_test/chat_filter_sanity/proc/test_filter_result(
filter_type, filter_type,
@@ -87,3 +102,6 @@
#undef BLOCKED_IC #undef BLOCKED_IC
#undef BLOCKED_IC_OUTSIDE_PDA #undef BLOCKED_IC_OUTSIDE_PDA
#undef BLOCKED_SHARED #undef BLOCKED_SHARED
#undef SOFT_BLOCKED_IC
#undef SOFT_BLOCKED_IC_OUTSIDE_PDA
#undef SOFT_BLOCKED_SHARED

View File

@@ -1,5 +1,6 @@
# This configuration file forms the in-game chat filter. # This configuration file forms the in-game chat filter.
# Values are stored as "word" = "reason for being banned". # Values are stored as "word" = "reason for being banned".
# Soft filter reasons should be kept short or the tgui gets messy.
# Anything in here will be blocked from IC interactions, dead chat, and OOC # Anything in here will be blocked from IC interactions, dead chat, and OOC
[shared] [shared]
@@ -13,3 +14,15 @@
# On /tg/, netspeak is OK in PDAs. # On /tg/, netspeak is OK in PDAs.
[ic_outside_pda] [ic_outside_pda]
"<(0_0<)" = "Kirby dancing is strictly prohibited on this server." "<(0_0<)" = "Kirby dancing is strictly prohibited on this server."
# Anything in here will warn the player if said in IC, dead chat or OOC, the player must approve their message to send it
[soft_shared]
"testsoftblocks" = "You risk being banned if this term is used improperly."
# Anything in here will warn the player if said ICly, but is allowed in dead chat and OOC, the player must approve their message to send it
[soft_ic]
"testsofterblocks" = "This term is commonly considered OOC, only use it with context."
# Anything in here will warn the player if said ICly *except* PDAs. the player must approve their message to send it
[soft_ic_outside_pda]
"testsoftestblocks" = "Stop saying debug phrases ICly."