]> Untitled Git - lemmy.git/blob - crates/utils/src/utils/slurs.rs
Cache & Optimize Woodpecker CI (#3450)
[lemmy.git] / crates / utils / src / utils / slurs.rs
1 use crate::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
2 use regex::{Regex, RegexBuilder};
3
4 pub fn remove_slurs(test: &str, slur_regex: &Option<Regex>) -> String {
5   if let Some(slur_regex) = slur_regex {
6     slur_regex.replace_all(test, "*removed*").to_string()
7   } else {
8     test.to_string()
9   }
10 }
11
12 pub(crate) fn slur_check<'a>(
13   test: &'a str,
14   slur_regex: &'a Option<Regex>,
15 ) -> Result<(), Vec<&'a str>> {
16   if let Some(slur_regex) = slur_regex {
17     let mut matches: Vec<&str> = slur_regex.find_iter(test).map(|mat| mat.as_str()).collect();
18
19     // Unique
20     matches.sort_unstable();
21     matches.dedup();
22
23     if matches.is_empty() {
24       Ok(())
25     } else {
26       Err(matches)
27     }
28   } else {
29     Ok(())
30   }
31 }
32
33 pub fn build_slur_regex(regex_str: Option<&str>) -> Option<Regex> {
34   regex_str.map(|slurs| {
35     RegexBuilder::new(slurs)
36       .case_insensitive(true)
37       .build()
38       .expect("compile regex")
39   })
40 }
41
42 pub fn check_slurs(text: &str, slur_regex: &Option<Regex>) -> Result<(), LemmyError> {
43   if let Err(slurs) = slur_check(text, slur_regex) {
44     Err(anyhow::anyhow!("{}", slurs_vec_to_str(&slurs))).with_lemmy_type(LemmyErrorType::Slurs)
45   } else {
46     Ok(())
47   }
48 }
49
50 pub fn check_slurs_opt(
51   text: &Option<String>,
52   slur_regex: &Option<Regex>,
53 ) -> Result<(), LemmyError> {
54   match text {
55     Some(t) => check_slurs(t, slur_regex),
56     None => Ok(()),
57   }
58 }
59
60 pub(crate) fn slurs_vec_to_str(slurs: &[&str]) -> String {
61   let start = "No slurs - ";
62   let combined = &slurs.join(", ");
63   [start, combined].concat()
64 }
65
66 #[cfg(test)]
67 mod test {
68   #![allow(clippy::unwrap_used)]
69   #![allow(clippy::indexing_slicing)]
70
71   use crate::utils::slurs::{remove_slurs, slur_check, slurs_vec_to_str};
72   use regex::RegexBuilder;
73
74   #[test]
75   fn test_slur_filter() {
76     let slur_regex = Some(RegexBuilder::new(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?)").case_insensitive(true).build().unwrap());
77     let test =
78       "faggot test kike tranny cocksucker retardeds. Capitalized Niggerz. This is a bunch of other safe text.";
79     let slur_free = "No slurs here";
80     assert_eq!(
81       remove_slurs(test, &slur_regex),
82       "*removed* test *removed* *removed* *removed* *removed*. Capitalized *removed*. This is a bunch of other safe text."
83         .to_string()
84     );
85
86     let has_slurs_vec = vec![
87       "Niggerz",
88       "cocksucker",
89       "faggot",
90       "kike",
91       "retardeds",
92       "tranny",
93     ];
94     let has_slurs_err_str = "No slurs - Niggerz, cocksucker, faggot, kike, retardeds, tranny";
95
96     assert_eq!(slur_check(test, &slur_regex), Err(has_slurs_vec));
97     assert_eq!(slur_check(slur_free, &slur_regex), Ok(()));
98     if let Err(slur_vec) = slur_check(test, &slur_regex) {
99       assert_eq!(&slurs_vec_to_str(&slur_vec), has_slurs_err_str);
100     }
101   }
102
103   // These helped with testing
104   // #[test]
105   // fn test_send_email() {
106   //  let result =  send_email("not a subject", "test_email@gmail.com", "ur user", "<h1>HI there</h1>");
107   //   assert!(result.is_ok());
108   // }
109 }