Add support for banned word exceptions
This commit is contained in:
Generated
+1
-1
@@ -1431,7 +1431,7 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
|
||||
|
||||
[[package]]
|
||||
name = "payphone"
|
||||
version = "4.0.9"
|
||||
version = "4.0.11"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "payphone"
|
||||
version = "4.0.9"
|
||||
version = "4.0.11"
|
||||
edition = "2024"
|
||||
default-run = "payphone"
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
tasks:
|
||||
- name: Bump Version
|
||||
ansible.builtin.shell: >
|
||||
cargo release commit --execute --no-confirm && \
|
||||
cargo release patch --no-verify --no-publish --execute --no-confirm
|
||||
cargo set-version --bump patch
|
||||
changed_when: false
|
||||
|
||||
- name: Get Cargo Project Metadata
|
||||
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
uv run ansible-playbook -i inventory.ini playbooks/08-payphone.yml --vault-password-file playbooks/00-vault-pwd.txt
|
||||
@@ -59,7 +59,7 @@ huz
|
||||
slut
|
||||
dldo
|
||||
dildo
|
||||
goon
|
||||
goon / go on
|
||||
gooning
|
||||
i will fuh you
|
||||
i will fuck you
|
||||
|
||||
+186
-46
@@ -247,7 +247,7 @@ fn regex_from_phrase(phrase: &str) -> String {
|
||||
///
|
||||
/// Returns:
|
||||
/// [`Regex`] - The merged regex for the phrases.
|
||||
fn regex_from_phrases_list(phrases: &[&str]) -> Regex {
|
||||
fn regex_from_phrases_list(phrases: &[String]) -> Regex {
|
||||
let mut pattern = String::new();
|
||||
|
||||
for phrase in phrases {
|
||||
@@ -405,31 +405,43 @@ pub trait Rule: Send + Sync {
|
||||
/// * `file_content` - The content of the file to parse.
|
||||
///
|
||||
/// Returns:
|
||||
/// [`Vec<&str>`] - The list of phrases found in the file.
|
||||
fn parse_phrases_file(file_content: &str) -> Vec<&str> {
|
||||
file_content
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
let trimmed = line.trim();
|
||||
/// [`(Vec<String>, Vec<String>)`] - The list of phrases found in the file.
|
||||
fn parse_phrases_file(file_content: &str) -> (Vec<String>, Vec<String>) {
|
||||
let mut banned = vec![];
|
||||
let mut exceptions = vec![];
|
||||
|
||||
for line in file_content.lines() {
|
||||
let trimmed = line.trim().to_ascii_lowercase();
|
||||
|
||||
if !trimmed.is_empty() && !trimmed.starts_with("//") {
|
||||
Some(trimmed)
|
||||
if let Some((phrase, phrase_exceptions)) = trimmed.split_once("/") {
|
||||
banned.push(phrase.trim().to_string());
|
||||
exceptions.extend(phrase_exceptions.split(',').map(|s| s.trim().to_string()));
|
||||
} else {
|
||||
None
|
||||
banned.push(trimmed.to_string());
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
(banned, exceptions)
|
||||
}
|
||||
|
||||
struct HateSpeechAndSlursRule(Regex);
|
||||
struct HateSpeechAndSlursRule {
|
||||
pattern: Regex,
|
||||
exceptions: Vec<String>,
|
||||
}
|
||||
|
||||
impl HateSpeechAndSlursRule {
|
||||
fn new() -> Self {
|
||||
let phrases: Vec<&str> =
|
||||
let (phrases, exceptions) =
|
||||
parse_phrases_file(include_str!("lists/hate-speech-and-slurs.txt"));
|
||||
|
||||
let regex = regex_from_phrases_list(&phrases);
|
||||
|
||||
Self(regex)
|
||||
Self {
|
||||
pattern: regex,
|
||||
exceptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,24 +457,43 @@ impl Rule for HateSpeechAndSlursRule {
|
||||
fn detect(&self, _original: &str, normalized: &str) -> (Vec<String>, Vec<String>) {
|
||||
(
|
||||
vec![],
|
||||
self.0
|
||||
self.pattern
|
||||
.find_iter(normalized)
|
||||
.map(|m| normalized[m.start()..m.end()].to_string())
|
||||
.filter_map(|m| {
|
||||
let string = normalized[m.start()..m.end()].to_string();
|
||||
|
||||
if self.exceptions.contains(
|
||||
&string
|
||||
.split_ascii_whitespace()
|
||||
.collect::<String>()
|
||||
.to_ascii_lowercase(),
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(string)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct ThreatsAndSelfHarmRule(Regex);
|
||||
struct ThreatsAndSelfHarmRule {
|
||||
pattern: Regex,
|
||||
exceptions: Vec<String>,
|
||||
}
|
||||
|
||||
impl ThreatsAndSelfHarmRule {
|
||||
fn new() -> Self {
|
||||
let phrases: Vec<&str> =
|
||||
let (phrases, exceptions) =
|
||||
parse_phrases_file(include_str!("lists/threats-and-self-harm.txt"));
|
||||
|
||||
let regex = regex_from_phrases_list(&phrases);
|
||||
|
||||
Self(regex)
|
||||
Self {
|
||||
pattern: regex,
|
||||
exceptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,24 +509,43 @@ impl Rule for ThreatsAndSelfHarmRule {
|
||||
fn detect(&self, _original: &str, normalized: &str) -> (Vec<String>, Vec<String>) {
|
||||
(
|
||||
vec![],
|
||||
self.0
|
||||
self.pattern
|
||||
.find_iter(normalized)
|
||||
.map(|m| normalized[m.start()..m.end()].to_string())
|
||||
.filter_map(|m| {
|
||||
let string = normalized[m.start()..m.end()].to_string();
|
||||
|
||||
if self.exceptions.contains(
|
||||
&string
|
||||
.split_ascii_whitespace()
|
||||
.collect::<String>()
|
||||
.to_ascii_lowercase(),
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(string)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct ExplicitSexualLanguageRule(Regex);
|
||||
struct ExplicitSexualLanguageRule {
|
||||
pattern: Regex,
|
||||
exceptions: Vec<String>,
|
||||
}
|
||||
|
||||
impl ExplicitSexualLanguageRule {
|
||||
fn new() -> Self {
|
||||
let phrases: Vec<&str> =
|
||||
let (phrases, exceptions) =
|
||||
parse_phrases_file(include_str!("lists/explicit-sexual-language.txt"));
|
||||
|
||||
let regex = regex_from_phrases_list(&phrases);
|
||||
|
||||
Self(regex)
|
||||
Self {
|
||||
pattern: regex,
|
||||
exceptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,23 +561,43 @@ impl Rule for ExplicitSexualLanguageRule {
|
||||
fn detect(&self, _original: &str, normalized: &str) -> (Vec<String>, Vec<String>) {
|
||||
(
|
||||
vec![],
|
||||
self.0
|
||||
self.pattern
|
||||
.find_iter(normalized)
|
||||
.map(|m| normalized[m.start()..m.end()].to_string())
|
||||
.filter_map(|m| {
|
||||
let string = normalized[m.start()..m.end()].to_string();
|
||||
|
||||
if self.exceptions.contains(
|
||||
&string
|
||||
.split_ascii_whitespace()
|
||||
.collect::<String>()
|
||||
.to_ascii_lowercase(),
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(string)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct SuggestiveLanguageRule(Regex);
|
||||
struct SuggestiveLanguageRule {
|
||||
pattern: Regex,
|
||||
exceptions: Vec<String>,
|
||||
}
|
||||
|
||||
impl SuggestiveLanguageRule {
|
||||
fn new() -> Self {
|
||||
let phrases: Vec<&str> = parse_phrases_file(include_str!("lists/suggestive-language.txt"));
|
||||
let (phrases, exceptions) =
|
||||
parse_phrases_file(include_str!("lists/suggestive-language.txt"));
|
||||
|
||||
let regex = regex_from_phrases_list(&phrases);
|
||||
|
||||
Self(regex)
|
||||
Self {
|
||||
pattern: regex,
|
||||
exceptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,9 +613,22 @@ impl Rule for SuggestiveLanguageRule {
|
||||
fn detect(&self, _original: &str, normalized: &str) -> (Vec<String>, Vec<String>) {
|
||||
(
|
||||
vec![],
|
||||
self.0
|
||||
self.pattern
|
||||
.find_iter(normalized)
|
||||
.map(|m| normalized[m.start()..m.end()].to_string())
|
||||
.filter_map(|m| {
|
||||
let string = normalized[m.start()..m.end()].to_string();
|
||||
|
||||
if self.exceptions.contains(
|
||||
&string
|
||||
.split_ascii_whitespace()
|
||||
.collect::<String>()
|
||||
.to_ascii_lowercase(),
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(string)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
@@ -580,17 +663,23 @@ impl Rule for AdvertisingRule {
|
||||
}
|
||||
}
|
||||
|
||||
struct SensitiveTopicsAndTriggeringContentRule(Regex);
|
||||
struct SensitiveTopicsAndTriggeringContentRule {
|
||||
pattern: Regex,
|
||||
exceptions: Vec<String>,
|
||||
}
|
||||
|
||||
impl SensitiveTopicsAndTriggeringContentRule {
|
||||
fn new() -> Self {
|
||||
let phrases: Vec<&str> = parse_phrases_file(include_str!(
|
||||
let (phrases, exceptions) = parse_phrases_file(include_str!(
|
||||
"lists/sensitive-topics-and-triggering-content.txt"
|
||||
));
|
||||
|
||||
let regex = regex_from_phrases_list(&phrases);
|
||||
|
||||
Self(regex)
|
||||
Self {
|
||||
pattern: regex,
|
||||
exceptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,23 +695,42 @@ impl Rule for SensitiveTopicsAndTriggeringContentRule {
|
||||
fn detect(&self, _original: &str, normalized: &str) -> (Vec<String>, Vec<String>) {
|
||||
(
|
||||
vec![],
|
||||
self.0
|
||||
self.pattern
|
||||
.find_iter(normalized)
|
||||
.map(|m| normalized[m.start()..m.end()].to_string())
|
||||
.filter_map(|m| {
|
||||
let string = normalized[m.start()..m.end()].to_string();
|
||||
|
||||
if self.exceptions.contains(
|
||||
&string
|
||||
.split_ascii_whitespace()
|
||||
.collect::<String>()
|
||||
.to_ascii_lowercase(),
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(string)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MildSwearWordsRule(Regex);
|
||||
pub struct MildSwearWordsRule {
|
||||
pattern: Regex,
|
||||
exceptions: Vec<String>,
|
||||
}
|
||||
|
||||
impl MildSwearWordsRule {
|
||||
fn new() -> Self {
|
||||
let phrases: Vec<&str> = parse_phrases_file(include_str!("lists/mild-swear-words.txt"));
|
||||
let (phrases, exceptions) = parse_phrases_file(include_str!("lists/mild-swear-words.txt"));
|
||||
|
||||
let regex = regex_from_phrases_list(&phrases);
|
||||
|
||||
Self(regex)
|
||||
Self {
|
||||
pattern: regex,
|
||||
exceptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,24 +746,43 @@ impl Rule for MildSwearWordsRule {
|
||||
fn detect(&self, _original: &str, normalized: &str) -> (Vec<String>, Vec<String>) {
|
||||
(
|
||||
vec![],
|
||||
self.0
|
||||
self.pattern
|
||||
.find_iter(normalized)
|
||||
.map(|m| normalized[m.start()..m.end()].to_string())
|
||||
.filter_map(|m| {
|
||||
let string = normalized[m.start()..m.end()].to_string();
|
||||
|
||||
if self.exceptions.contains(
|
||||
&string
|
||||
.split_ascii_whitespace()
|
||||
.collect::<String>()
|
||||
.to_ascii_lowercase(),
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(string)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CasualInsultsAndTeasing(Regex);
|
||||
pub struct CasualInsultsAndTeasing {
|
||||
pattern: Regex,
|
||||
exceptions: Vec<String>,
|
||||
}
|
||||
|
||||
impl CasualInsultsAndTeasing {
|
||||
fn new() -> Self {
|
||||
let phrases: Vec<&str> =
|
||||
let (phrases, exceptions) =
|
||||
parse_phrases_file(include_str!("lists/casual-insults-and-teasing.txt"));
|
||||
|
||||
let regex = regex_from_phrases_list(&phrases);
|
||||
|
||||
Self(regex)
|
||||
Self {
|
||||
pattern: regex,
|
||||
exceptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,9 +798,22 @@ impl Rule for CasualInsultsAndTeasing {
|
||||
fn detect(&self, _original: &str, normalized: &str) -> (Vec<String>, Vec<String>) {
|
||||
(
|
||||
vec![],
|
||||
self.0
|
||||
self.pattern
|
||||
.find_iter(normalized)
|
||||
.map(|m| normalized[m.start()..m.end()].to_string())
|
||||
.filter_map(|m| {
|
||||
let string = normalized[m.start()..m.end()].to_string();
|
||||
|
||||
if self.exceptions.contains(
|
||||
&string
|
||||
.split_ascii_whitespace()
|
||||
.collect::<String>()
|
||||
.to_ascii_lowercase(),
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(string)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user