Renaming to slur_filter. Fixes #1773 (#1801)

* Renaming to slur_filter. Fixes #1773

* Fixing config

* Updating doku for slur filter.

* Updating doku for slur filter again.

* Remove comment.
This commit is contained in:
Dessalines 2021-10-28 16:47:25 -04:00 committed by GitHub
parent f1f7c45017
commit b18ea3e0cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 32 deletions

View file

@ -5,4 +5,8 @@
federation: { federation: {
enabled: true enabled: true
} }
slur_filter:
'''
(fag(g|got|tard)?\b|cock\s?sucker(s|ing)?|ni((g{2,}|q)+|[gq]{2,})[e3r]+(s|z)?|mudslime?s?|kikes?|\bspi(c|k)s?\b|\bchinks?|gooks?|bitch(es|ing|y)?|whor(es?|ing)|\btr(a|@)nn?(y|ies?)|\b(b|re|r)tard(ed)?s?)
'''
} }

View file

@ -104,8 +104,7 @@
tls_enabled: true tls_enabled: true
# Address where pictrs is available (for image hosting) # Address where pictrs is available (for image hosting)
pictrs_url: "http:#localhost:8080" pictrs_url: "http:#localhost:8080"
# Regex for slurs which are prohibited. Example: `(\bThis\b)|(\bis\b)|(\bsample\b)` slur_filter: "(\bThis\b)|(\bis\b)|(\bsample\b)"
additional_slurs: "string"
# Maximum length of local community and user names # Maximum length of local community and user names
actor_name_max_length: 20 actor_name_max_length: 20
} }

View file

@ -113,15 +113,12 @@ impl Settings {
WEBFINGER_USER_REGEX.to_owned() WEBFINGER_USER_REGEX.to_owned()
} }
pub fn slur_regex(&self) -> Regex { pub fn slur_regex(&self) -> Option<Regex> {
let mut slurs = r"(fag(g|got|tard)?\b|cock\s?sucker(s|ing)?|ni((g{2,}|q)+|[gq]{2,})[e3r]+(s|z)?|mudslime?s?|kikes?|\bspi(c|k)s?\b|\bchinks?|gooks?|bitch(es|ing|y)?|whor(es?|ing)|\btr(a|@)nn?(y|ies?)|\b(b|re|r)tard(ed)?s?)".to_string(); self.slur_filter.as_ref().map(|slurs| {
if let Some(additional_slurs) = &self.additional_slurs { RegexBuilder::new(slurs)
slurs.push('|'); .case_insensitive(true)
slurs.push_str(additional_slurs); .build()
}; .expect("compile regex")
RegexBuilder::new(&slurs) })
.case_insensitive(true)
.build()
.expect("compile regex")
} }
} }

View file

@ -40,9 +40,9 @@ pub struct Settings {
#[default(None)] #[default(None)]
#[doku(example = "http://localhost:8080")] #[doku(example = "http://localhost:8080")]
pub pictrs_url: Option<String>, pub pictrs_url: Option<String>,
/// Regex for slurs which are prohibited. Example: `(\bThis\b)|(\bis\b)|(\bsample\b)`
#[default(None)] #[default(None)]
pub additional_slurs: Option<String>, #[doku(example = "(\\bThis\\b)|(\\bis\\b)|(\\bsample\\b)")]
pub slur_filter: Option<String>,
/// Maximum length of local community and user names /// Maximum length of local community and user names
#[default(20)] #[default(20)]
pub actor_name_max_length: usize, pub actor_name_max_length: usize,

View file

@ -28,30 +28,44 @@ pub fn convert_datetime(datetime: NaiveDateTime) -> DateTime<FixedOffset> {
DateTime::<FixedOffset>::from_utc(datetime, FixedOffset::east(0)) DateTime::<FixedOffset>::from_utc(datetime, FixedOffset::east(0))
} }
pub fn remove_slurs(test: &str, slur_regex: &Regex) -> String { pub fn remove_slurs(test: &str, slur_regex: &Option<Regex>) -> String {
slur_regex.replace_all(test, "*removed*").to_string() if let Some(slur_regex) = slur_regex {
} slur_regex.replace_all(test, "*removed*").to_string()
pub(crate) fn slur_check<'a>(test: &'a str, slur_regex: &'a Regex) -> Result<(), Vec<&'a str>> {
let mut matches: Vec<&str> = slur_regex.find_iter(test).map(|mat| mat.as_str()).collect();
// Unique
matches.sort_unstable();
matches.dedup();
if matches.is_empty() {
Ok(())
} else { } else {
Err(matches) test.to_string()
} }
} }
pub fn check_slurs(text: &str, slur_regex: &Regex) -> Result<(), ApiError> { pub(crate) fn slur_check<'a>(
slur_check(text, slur_regex) test: &'a str,
.map_err(|slurs| ApiError::err_plain(&slurs_vec_to_str(slurs.clone()))) slur_regex: &'a Option<Regex>,
) -> Result<(), Vec<&'a str>> {
if let Some(slur_regex) = slur_regex {
let mut matches: Vec<&str> = slur_regex.find_iter(test).map(|mat| mat.as_str()).collect();
// Unique
matches.sort_unstable();
matches.dedup();
if matches.is_empty() {
Ok(())
} else {
Err(matches)
}
} else {
Ok(())
}
} }
pub fn check_slurs_opt(text: &Option<String>, slur_regex: &Regex) -> Result<(), ApiError> { pub fn check_slurs(text: &str, slur_regex: &Option<Regex>) -> Result<(), ApiError> {
if let Err(slurs) = slur_check(text, slur_regex) {
Err(ApiError::err_plain(&slurs_vec_to_str(slurs)))
} else {
Ok(())
}
}
pub fn check_slurs_opt(text: &Option<String>, slur_regex: &Option<Regex>) -> Result<(), ApiError> {
match text { match text {
Some(t) => check_slurs(t, slur_regex), Some(t) => check_slurs(t, slur_regex),
None => Ok(()), None => Ok(()),

View file

@ -34,6 +34,10 @@
# maximum number of active sql connections # maximum number of active sql connections
pool_size: 5 pool_size: 5
} }
slur_filter:
'''
(fag(g|got|tard)?\b|cock\s?sucker(s|ing)?|ni((g{2,}|q)+|[gq]{2,})[e3r]+(s|z)?|mudslime?s?|kikes?|\bspi(c|k)s?\b|\bchinks?|gooks?|bitch(es|ing|y)?|whor(es?|ing)|\btr(a|@)nn?(y|ies?)|\b(b|re|r)tard(ed)?s?)
'''
# # optional: email sending configuration # # optional: email sending configuration
# email: { # email: {
# # hostname and port of the smtp server # # hostname and port of the smtp server