engine/safetyLexicons.js

/*
    Copyright 2026 1fairyfox

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/**
 * @file
 * @brief Content-safety term lexicons (pure data). These terms exist so the project can DETECT and
 * REMOVE them — never to surface them. The matchers + classification live in `contentSafety.js`.
 *
 * Policy (decided with the project owner, 2026-06-20):
 *   REMOVE entirely   -> genuine slurs, content sexualizing minors, and extreme
 *                        shock/gore/non-consensual material.
 *   KEEP but NSFW-gate -> ordinary nudity/adult terms (tagged via isNsfw(), NOT deleted).
 */

// Category 1: SLURS — removed from EVERY list. Unambiguous hate slurs.
export const SLURS_CORE = [
  "nigger",
  "niggers",
  "nigga",
  "niggas",
  "niggah",
  "n1gger",
  "n1gga",
  "chink",
  "chinks",
  "gook",
  "gooks",
  "kike",
  "kikes",
  "spic",
  "spics",
  "wetback",
  "wetbacks",
  "beaner",
  "beaners",
  "coon",
  "coons",
  "jigaboo",
  "sambo",
  "darkie",
  "darky",
  "darkies",
  "raghead",
  "ragheads",
  "towelhead",
  "towelheads",
  "jungle bunny",
  "porch monkey",
  "tar baby",
  "slant eye",
  "slant eyes",
  "zipperhead",
  "faggot",
  "faggots",
  "fagot",
  "fagots",
  "tranny",
  "trannies",
  "shemale",
  "shemales",
  "dyke",
  "dykes",
  "retard",
  "retards",
  "retarded",
  "spastic",
  "mongoloid",
  "jap",
  "japs",
  "negress",
  "negresses",
  "negroid",
  "negroids",
];

// Category 1b: AMBIGUOUS slurs — content lists only.
export const SLURS_AMBIGUOUS = ["fag", "fags", "paki", "pakis", "kaffir", "negro", "negroes"];

// Category 2: MINOR-SEXUALIZING — removed from EVERY list. Zero tolerance.
// "lolita" alone is intentionally absent (real fashion style).
export const MINOR_SEXUAL = [
  "loli",
  "lolis",
  "lolicon",
  "shota",
  "shotacon",
  "toddlercon",
  "cunny",
  "lolidom",
  "lolibooru",
  "jailbait",
  "child porn",
  "child pornography",
  "underage sex",
  "child sex",
  "underage girl",
  "underage boy",
  "preteen",
  "pre teen",
];

// Category 3: EXTREME shock / gore / non-consensual — content lists only.
export const EXTREME = [
  "guro",
  "gore",
  "ryona",
  "scat",
  "coprophilia",
  "coprophagia",
  "necrophilia",
  "bestiality",
  "zoophilia",
  "snuff",
  "vore",
  "rape",
  "raped",
  "gangrape",
  "gang rape",
  "noncon",
  "non con",
  "nonconsensual",
  "non consensual",
  "forced sex",
  "amputee gore",
  "disembowelment",
  "decapitation gore",
];

// WHITELIST — normalized lines never flagged (real false positives).
export const WHITELIST = new Set([
  "lolita",
  "gothic lolita",
  "sweet lolita",
  "classic lolita",
  "al gore",
  "gore vidal",
  "gore tex",
  "gore-tex",
]);

// NSFW LEXICON — NOT a removal set. Ordinary adult vocabulary used to TAG an
// entry as NSFW for the SFW/NSFW split + virtual lists.
export const NSFW_LEXICON = [
  "nude",
  "nudes",
  "nudity",
  "naked",
  "topless",
  "bottomless",
  "nipple",
  "nipples",
  "areola",
  "areolae",
  "breast",
  "breasts",
  "boob",
  "boobs",
  "cleavage",
  "underboob",
  "sideboob",
  "penis",
  "vagina",
  "pussy",
  "vulva",
  "clitoris",
  "anus",
  "anal",
  "ass",
  "butt",
  "buttocks",
  "thigh gap",
  "sex",
  "sexual",
  "intercourse",
  "blowjob",
  "fellatio",
  "cunnilingus",
  "handjob",
  "masturbation",
  "orgasm",
  "cum",
  "cumshot",
  "ejaculation",
  "semen",
  "creampie",
  "bukkake",
  "ahegao",
  "hentai",
  "ecchi",
  "lewd",
  "erection",
  "panties",
  "thong",
  "lingerie",
  "bra",
  "bdsm",
  "bondage",
  "fetish",
  "futanari",
  "futa",
  "yaoi",
  "yuri sex",
  "pubic hair",
  "condom",
  "dildo",
  "vibrator",
  "sex toy",
  "strapon",
  "fishnet",
  "garter",
  "spread legs",
  "presenting",
  "after sex",
  "cum on body",
  "facial",
  // explicit acts / anatomy / fluids / fetish — broadened for the danbooru SFW
  // filter (better to drop a questionable tag than leak an explicit one)
  "vaginal",
  "oral",
  "deepthroat",
  "paizuri",
  "titjob",
  "footjob",
  "cumdrip",
  "precum",
  "ejaculating",
  "squirting",
  "pussy juice",
  "penetration",
  "double penetration",
  "gangbang",
  "threesome",
  "orgy",
  "testicles",
  "scrotum",
  "foreskin",
  "glans",
  "veiny penis",
  "erection",
  "erect nipples",
  "nipple slip",
  "see-through",
  "wardrobe malfunction",
  "exhibitionism",
  "naked apron",
  "no bra",
  "no panties",
  "panty pull",
  "panties aside",
  "clothes lift",
  "skirt lift",
  "shirt lift",
  "undressing",
  "partially undressed",
  "spread pussy",
  "spread anus",
  "anal beads",
  "buttplug",
  "cameltoe",
  "downblouse",
  "upskirt",
  "groping",
  "molestation",
  "tentacle sex",
  "x-ray",
  "cross-section",
  "cum inside",
  "cum in mouth",
  "facial cumshot",
  "gokkun",
  "nsfw",
  "explicit",
  "uncensored",
  "censored",
  "pubic",
  "anal hair",
  "armpit sex",
  "thigh sex",
  "naked ribbon",
  "completely nude",
  "nipple tweak",
  "breast grab",
  "breast sucking",
];