Text

Profanity filter

Offensive words found and masked in comments, usernames and chat, with l33t spellings and spaced-out letters caught, and a severity per kind for moderation queues.

Version 1.0.0 · 3 functions · 1 crate

#moderation#text#forms#comments

Functions

What use profanity.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use profanity_found, profanity_mask from profanity (Quillo 0.6).

profanity_found(text: str) → boolor an error

Whether text holds profane, offensive or sexual words: moderate ones or worse, so "damn" passes and slurs do not. Text up to 200 KB.

profanity_mask(text: str, strictness: str) → stror an error

text with offending words masked by *, most keeping their first letter ("f***"). strictness is "mild" (mask even "damn"), "moderate" or "severe" (mask only the worst).

profanity_analyze(text: str) → anyor an error

How bad text is, for moderation queues: { inappropriate, profane, offensive, sexual, mean, evasive, spam }, each but the first "none", "mild", "moderate" or "severe". evasive means words disguised to get past filters.

Get it

$ quillo install profanity               # profanity.qwer into this folder$ quillo install profanity --example     # and its example, profanity.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/profanity.qwer$ curl -O https://quillolang.org/plugins/files/profanity.qwe

Then, in your program, all of it or only what you call:

main.qwe
use profanity.qweruse profanity_found, profanity_mask from profanity      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
rustrict = { version = "0.7", default-features = false, features = ["censor"] }

Example

profanity.qwe
// Comments masked before they are shown, and a username refused when it is offensive.////   quillo run profanity.qwe      then open http://localhost:8080/commentsuse "profanity.qwer"let comments = ["Great post, thanks!", "This is sh1t, you f.u.c.k.i.n.g idiot", "Well, damn, that is clever."]route GET /comments = comments | map((c) => { shown: profanity_mask(c, "moderate")?, flagged: profanity_found(c)? })route GET /username ? { name: str } {    if profanity_found(name)? { reply 422 { error: "Please pick another username." } }    { ok: name }}route GET /analyze ? { text: str } = profanity_analyze(text)?
$ quillo run profanity.qwe$ curl 'localhost:8080/comments'

Source

profanity.qwer
//! Offensive words found and masked in comments, usernames and chat, English, l33t tricks (sh1t, f.u.c.k) and spacing included.//! version: 1.0.0//!//! [dependencies]//! rustrict = { version = "0.7", default-features = false, features = ["censor"] }use rustrict::{Censor, Type};use serde_json::{json, Value};const MAX: usize = 200_000;fn level(t: Type, kind: Type) -> &'static str {    if t.is(kind & Type::SEVERE) { "severe" } else if t.is(kind & Type::MODERATE) { "moderate" } else if t.is(kind & Type::MILD) { "mild" } else { "none" }}fn threshold(strictness: &str) -> Result<Type, String> {    match strictness {        "" | "moderate" => Ok(Type::INAPPROPRIATE & Type::MODERATE_OR_HIGHER),        "mild" => Ok(Type::INAPPROPRIATE),        "severe" => Ok(Type::INAPPROPRIATE & Type::SEVERE),        o => Err(format!("strictness is \"mild\", \"moderate\" or \"severe\", not {:?}", o)),    }}/// Whether `text` holds profane, offensive or sexual words: moderate ones or worse, so "damn" passes and slurs do not. Text up to 200 KB.pub fn profanity_found(text: &str) -> Result<bool, String> {    if text.len() > MAX {        return Err("text up to 200 KB".into());    }    Ok(Censor::from_str(text).analyze().is(threshold("")?))}/// `text` with offending words masked by `*`, most keeping their first letter ("f***"). `strictness` is "mild" (mask even "damn"), "moderate" or "severe" (mask only the worst).pub fn profanity_mask(text: &str, strictness: &str) -> Result<String, String> {    if text.len() > MAX {        return Err("text up to 200 KB".into());    }    Ok(Censor::from_str(text).with_censor_threshold(threshold(strictness)?).censor())}/// How bad `text` is, for moderation queues: `{ inappropriate, profane, offensive, sexual, mean, evasive, spam }`, each but the first "none", "mild", "moderate" or "severe". `evasive` means words disguised to get past filters.pub fn profanity_analyze(text: &str) -> Result<Value, String> {    if text.len() > MAX {        return Err("text up to 200 KB".into());    }    let t = Censor::from_str(text).analyze();    Ok(json!({        "inappropriate": t.is(threshold("")?),        "profane": level(t, Type::PROFANE),        "offensive": level(t, Type::OFFENSIVE),        "sexual": level(t, Type::SEXUAL),        "mean": level(t, Type::MEAN),        "evasive": level(t, Type::EVASIVE),        "spam": level(t, Type::SPAM),    }))}
Thread
88Useful? Like it, or add to its thread below.

Thread 0 posts

On Profanity filter: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.