Add message auto-censorship

This commit is contained in:
2025-08-12 16:52:29 -03:00
parent 28f8c8e702
commit 4df7c8ce7d
3 changed files with 60 additions and 16 deletions
+7 -4
View File
@@ -1,15 +1,18 @@
use std::{collections::HashMap, sync::Arc};
use std::sync::Arc;
use async_trait::async_trait;
use linkify::LinkFinder;
use twilight_model::{gateway::payload::incoming::MessageCreate, id::Id};
use twilight_validate::request::webhook_username;
use crate::{
database::models::{Call, Channel}, discord::{images, sanitizing::SanitizeDiscordMarkdown}, framework::{
database::models::{Call, Channel},
discord::images,
framework::{
events::traits::{EventResult, OnMessageHandler},
runtime::Runtime,
}, groups::calls::moderation::escape_message, state::State
},
groups::calls::moderation::escape_message,
state::State,
};
#[derive(Debug)]
@@ -0,0 +1 @@
slap that ass
+51 -11
View File
@@ -62,11 +62,11 @@ pub fn escape_message(event: &MessageCreate) -> String {
message = message.replace(url, &"\\#".repeat(url.len()));
}
let normalized = normalize(message.clone());
let (censored, rules) = moderate_message(&message);
log::debug!("Escaped and normalized message: {normalized:?}");
log::debug!("Escaped and normalized message: {censored:?}");
message.sanitize(false)
censored
}
#[derive(Debug)]
@@ -113,13 +113,16 @@ pub fn normalize(message: String) -> NormalizedMessage {
for char in unidecoded.chars() {
if char.is_alphanumeric() {
normalized.push(char);
mappings.push(i);
} else {
normalized.push(' ');
}
mappings.push(i);
}
}
NormalizedMessage {
message: normalized,
message: normalized.to_ascii_lowercase(),
mappings,
}
}
@@ -127,9 +130,13 @@ pub fn normalize(message: String) -> NormalizedMessage {
fn regex_from_phrase(phrase: &str) -> String {
let mut pattern = String::new();
for ch in phrase.replace(" ", "").chars() {
for (i, ch) in phrase.replace(" ", "").chars().enumerate() {
if i == phrase.len() - 1 {
pattern.push_str(&format!("{ch}+"));
} else {
pattern.push_str(&format!("{ch}+\\s*"));
}
}
let pattern = format!("\\b{pattern}\\b");
@@ -170,19 +177,44 @@ pub fn censor_message(
) -> String {
let mut censored = original.to_string();
for (findings, rule) in analysis {
for finding in findings {
while let Some(start) = normalized.message.find(finding) {
let end = start + finding.len();
// Collect all ranges to censor
let mut ranges = Vec::new();
todo!();
for (findings, _) in analysis {
for finding in findings {
for (index, _) in normalized.message.match_indices(finding) {
let start_index = normalized.mappings.get(index).cloned().unwrap_or(0);
let end_index = normalized.mappings.get(index + finding.len()).cloned().unwrap_or(original.len());
ranges.push((start_index, end_index));
}
}
}
// Sort ranges in reverse order to avoid shifting indices
ranges.sort_by(|a, b| b.0.cmp(&a.0));
for (start_index, end_index) in ranges {
log::trace!("Censoring from {start_index} to {end_index}");
if start_index < end_index && end_index <= censored.len() {
censored.replace_range(start_index..end_index, "[censored]");
}
}
censored
}
pub fn moderate_message(original: &str) -> (String, Vec<Arc<dyn Rule>>) {
let normalized = normalize(original.to_string());
log::trace!("Normalized message: {:?}", normalized.message);
let analysis = analyze_message(&normalized.message);
let censored = censor_message(original, normalized, &analysis);
(censored, analysis.iter().map(|(_, r)| r.clone()).collect())
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Action {
BlockAndPenalty,
@@ -218,6 +250,8 @@ impl HateSpeechAndSlursRule {
let regex = regex_from_phrases_list(&phrases);
log::trace!("Hate Speech and Slurs Rule regex: {regex}");
Self(regex)
}
}
@@ -248,6 +282,8 @@ impl ThreatsAndSelfHarmRule {
let regex = regex_from_phrases_list(&phrases);
log::trace!("Threats and Self Harm Rule regex: {regex}");
Self(regex)
}
}
@@ -278,6 +314,8 @@ impl ExplicitSexualLanguageRule {
let regex = regex_from_phrases_list(&phrases);
log::trace!("Explicit Sexual Language Rule regex: {regex}");
Self(regex)
}
}
@@ -307,6 +345,8 @@ impl SuggestiveLanguageRule {
let regex = regex_from_phrases_list(&phrases);
log::trace!("Suggestive Language Rule regex: {regex}");
Self(regex)
}
}