using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using ProfanityFilter.Interfaces;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Stephen Haunts")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Profanity Filter used to detect or censor text in an application. You can use the inbuilt profanity list, or load up your organizations custom list.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ProfanityFilter")]
[assembly: AssemblyTitle("ProfanityFilter")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ProfanityFilter
{
public class AllowList : IAllowList
{
private List<string> _allowList;
public ReadOnlyCollection<string> ToList => new ReadOnlyCollection<string>(_allowList);
public int Count => _allowList.Count;
public AllowList()
{
_allowList = new List<string>();
}
public void Add(string wordToAllowlist)
{
if (string.IsNullOrEmpty(wordToAllowlist))
{
throw new ArgumentNullException("wordToAllowlist");
}
if (!_allowList.Contains(wordToAllowlist.ToLower(CultureInfo.InvariantCulture)))
{
_allowList.Add(wordToAllowlist.ToLower(CultureInfo.InvariantCulture));
}
}
public bool Contains(string wordToCheck)
{
if (string.IsNullOrEmpty(wordToCheck))
{
throw new ArgumentNullException("wordToCheck");
}
return _allowList.Contains(wordToCheck.ToLower(CultureInfo.InvariantCulture));
}
public void Clear()
{
_allowList.Clear();
}
public bool Remove(string wordToRemove)
{
if (string.IsNullOrEmpty(wordToRemove))
{
throw new ArgumentNullException("wordToRemove");
}
return _allowList.Remove(wordToRemove.ToLower(CultureInfo.InvariantCulture));
}
}
public class ProfanityBase
{
protected List<string> _profanities;
private readonly string[] _wordList = new string[1626]
{
"8===D", "8==D", "8=D", "2 girls 1 cup", "two girls one cup", "two girls 1 cup", "2 girls one cup", "2g1c", "4r5e", "5h1t",
"5hit", "a$$", "a$$hole", "a_s_s", "a2m", "a55", "a55hole", "acrotomophilia", "aeolus", "ahole",
"alabama hot pocket", "alaskan pipeline", "anal", "anal impaler", "anal leakage", "analprobe", "anilingus", "angrydragon", "angry dragon", "anus",
"apeshit", "ar5e", "arian", "arrse", "arse", "arses", "arsehole", "aryan", "ass", "ass fuck",
"ass hole", "assbag", "assbandit", "assbang", "assbanged", "assbanger", "assbangs", "assbite", "assclown", "asscock",
"asscracker", "asses", "assface", "assfaces", "assfuck", "assfucker", "ass-fucker", "assfukka", "assgoblin", "assh0le",
"asshat", "ass-hat", "asshead", "assho1e", "asshole", "assholes", "asshopper", "ass-jabber", "assjacker", "asslick",
"asslicker", "assmaster", "assmonkey", "assmucus", "assmunch", "assmuncher", "assnigger", "asspirate", "ass-pirate", "assshit",
"assshole", "asssucker", "asswad", "asswhole", "asswipe", "asswipes", "auto erotic", "autoerotic", "axwound", "axewound",
"axe wound", "azazel", "azz", "b!tch", "b00bs", "b17ch", "b1tch", "babeland", "baby batter", "baby juice",
"ball gag", "ball gravy", "ball kicking", "ball licking", "ball sack", "ball sucking", "ballbag", "balls", "ballsack", "bampot",
"bang (one's) box", "bangbros", "bareback", "barely legal", "barenaked", "barf", "bastard", "bastardo", "bastards", "bastinado",
"batty boy", "bawdy", "bbw", "bdsm", "beaner", "beaners", "beardedclam", "beastial", "beastiality", "beatch",
"beaver", "beaver cleaver", "beaver lips", "beef curtain", "beef curtains", "beeyotch", "bellend", "bender", "beotch", "bescumber",
"bestial", "bestiality", "bi+ch", "biatch", "big black", "big breasts", "big knockers", "big tits", "bigtits", "bimbo",
"bimbos", "bint", "birdlock", "bitch", "bitch tit", "bitchass", "bitched", "bitcher", "bitchers", "bitches",
"bitchin", "bitching", "bitchtits", "bitchy", "black cock", "blonde action", "blonde on blonde action", "bloodclaat", "bloody", "bloody hell",
"blow job", "blow me", "blow mud", "blow your load", "blowjob", "blowjobs", "blue waffle", "blumpkin", "bod", "bodily",
"boink", "boiolas", "bollock", "bollocks", "bollok", "bollox", "bondage", "boned", "boner", "boners",
"bong", "boob", "boobies", "boobs", "booby", "booger", "bookie", "boong", "booobs", "boooobs",
"booooobs", "booooooobs", "bootee", "bootie", "booty", "booty call", "booze", "boozer", "boozy", "bosom",
"bosomy", "breasts", "breeder", "brotherfucker", "brown showers", "brunette action", "buceta", "bugger", "bukkake", "bull shit",
"bulldyke", "bullet vibe", "bullshit", "bullshits", "bullshitted", "bullturds", "bum", "bum boy", "bumblefuck", "bumclat",
"bummer", "buncombe", "bung", "bung hole", "bunghole", "bunny fucker", "bust a load", "busty", "butt", "butt fuck",
"butt plug", "buttcheeks", "buttfuck", "buttfucka", "buttfucker", "butthole", "buttmuch", "buttmunch", "butt-pirate", "buttplug",
"c.0.c.k", "c.o.c.k.", "c.u.n.t", "c0ck", "c-0-c-k", "c0cksucker", "caca", "cacafuego", "cahone", "camel toe",
"cameltoe", "camgirl", "camslut", "camwhore", "carpet muncher", "carpetmuncher", "cawk", "cervix", "chesticle", "chi-chi man",
"chick with a dick", "child-fucker", "chinc", "chincs", "chink", "chinky", "choad", "choade", "choc ice", "chocolate rosebuds",
"chode", "chodes", "chota bags", "cipa", "circlejerk", "cl1t", "cleveland steamer", "climax", "clit", "clit licker",
"clitface", "clitfuck", "clitoris", "clits", "clitty", "clitty litter", "clover clamps", "clunge", "clusterfuck", "cnut",
"cocain", "cocaine", "coccydynia", "cock", "c-o-c-k", "cock pocket", "cock snot", "cock sucker", "cockass", "cockbite",
"cockblock", "cockburger", "cockeye", "cockface", "cockfucker", "cockhead", "cockholster", "cockjockey", "cockknocker", "cockknoker",
"cocklump", "cockmaster", "cockmongler", "cockmongruel", "cockmonkey", "cockmunch", "cockmuncher", "cocknose", "cocknugget", "cocks",
"cockshit", "cocksmith", "cocksmoke", "cocksmoker", "cocksniffer", "cocksuck", "cocksucked", "cocksucker", "cock-sucker", "cocksuckers",
"cocksucking", "cocksucks", "cocksuka", "cocksukka", "cockwaffle", "coffin dodger", "coital", "cok", "cokmuncher", "coksucka",
"commie", "condom", "coochie", "coochy", "coon", "coonnass", "coons", "cooter", "cop some wood", "coprolagnia",
"coprophilia", "corksucker", "cornhole", "corp whore", "corp whore", "corpulent", "cox", "crabs", "crack", "cracker",
"crackwhore", "crap", "crappy", "creampie", "cretin", "crikey", "cripple", "crotte", "cum", "cum chugger",
"cum dumpster", "cum freak", "cum guzzler", "cumbubble", "cumdump", "cumdumpster", "cumguzzler", "cumjockey", "cummer", "cummin",
"cumming", "cums", "cumshot", "cumshots", "cumslut", "cumstain", "cumtart", "cunilingus", "cunillingus", "cunnie",
"cunnilingus", "cunny", "cunt", "c-u-n-t", "cunt hair", "cuntass", "cuntbag", "cuntface", "cunthole", "cunthunter",
"cuntlick", "cuntlicker", "cuntrag", "cunts", "cuntsicle", "cuntslut", "cunt-struck", "cus", "cut rope", "cyalis",
"cyberfuc", "cyberfuck", "cyberfucked", "cyberfucker", "cyberfucking", "d0ng", "d0uch3", "d0uche", "d1ck", "d1ld0",
"d1ldo", "dago", "dagos", "dammit", "damn", "damned", "damnit", "darkie", "darn", "date rape",
"daterape", "dawgie-style", "deep throat", "deepthroat", "deggo", "dendrophilia", "dick", "dick head", "dick hole", "dick shy",
"dickbag", "dickbeaters", "dickdipper", "dickface", "dickflipper", "dickfuck", "dickfucker", "dickhead", "dickheads", "dickhole",
"dickish", "dick-ish", "dickjuice", "dickmilk", "dickmonger", "dickripper", "dicks", "dicksipper", "dickslap", "dick-sneeze",
"dicksucker", "dicksucking", "dicktickler", "dickwad", "dickweasel", "dickweed", "dickwhipper", "dickwod", "dickzipper", "diddle",
"dike", "dildo", "dildos", "diligaf", "dillweed", "dimwit", "dingle", "dingleberries", "dingleberry", "dink",
"dinks", "dipship", "dirsa", "dirty", "dirty pillows", "dirty sanchez", "div", "dlck", "dog style", "dog-fucker",
"doggie style", "doggiestyle", "doggie-style", "doggin", "dogging", "doggy style", "doggystyle", "doggy-style", "dolcett", "domination",
"dominatrix", "dommes", "dong", "donkey punch", "donkeypunch", "donkeyribber", "doochbag", "doofus", "dookie", "doosh",
"dopey", "double dong", "double penetration", "doublelift", "douch3", "douche", "douchebag", "douchebags", "douche-fag", "douchewaffle",
"douchey", "dp action", "drunk", "dry hump", "duche", "dumass", "dumb ass", "dumbass", "dumbasses", "dumbcunt",
"dumbfuck", "dumbshit", "dummy", "dumshit", "dvda", "dyke", "dykes", "eat a dick", "eat hair pie", "eat my ass",
"ecchi", "ejaculate", "ejaculated", "ejaculates", "ejaculating", "ejaculating", "ejaculatings", "ejaculation", "ejakulate", "erect",
"erection", "erotic", "erotism", "escort", "essohbee", "eunuch", "extacy", "extasy", "f u c k", "f u c k e r",
"f.u.c.k", "f_u_c_k", "f4nny", "facial", "fack", "fag", "fagbag", "fagfucker", "fagg", "fagged",
"fagging", "faggit", "faggitt", "faggot", "faggotcock", "faggots", "faggs", "fagot", "fagots", "fags",
"fagtard", "faig", "faigt", "fanny", "fannybandit", "fannyflaps", "fannyfucker", "fanyy", "fart", "fartknocker",
"fatass", "fcuk", "fcuker", "fcuking", "fecal", "feck", "fecker", "feist", "felch", "felcher",
"felching", "fellate", "fellatio", "feltch", "feltcher", "female squirting", "femdom", "fenian", "fice", "figging",
"fingerbang", "fingerfuck", "fingerfucked", "fingerfucker", "fingerfuckers", "fingerfucking", "fingerfucks", "fingering", "fist fuck", "fisted",
"fistfuck", "fistfucked", "fistfucker", "fistfuckers", "fistfuckings", "fistfucks", "fisting", "fisty", "flamer", "flange",
"flaps", "fleshflute", "flog the log", "floozy", "foad", "foah", "fondle", "foobar", "fook", "fooker",
"foot fetish", "footjob", "foreskin", "freex", "frenchify", "frigg", "frigga", "frotting", "fubar", "fuc",
"fuck", "f-u-c-k", "fuck buttons", "fuck hole", "fuck off", "fuck puppet", "fuck trophy", "fuck yo mama", "fuck you", "fucka",
"fuckass", "fuck-ass", "fuckbag", "fuck bag", "fuck-bitch", "fuckboy", "fuckbrain", "fuckbutt", "fuckbutter", "fucked",
"fuckedup", "fucked up", "fucker", "fuckers", "fuckersucker", "fuckface", "fuckhead", "fuckheads", "fuckhole", "fuckin",
"fucking", "fuckings", "fuckme", "fuck me", "fuckmeat", "fucknugget", "fucknut", "fucknutt", "fuckoff", "fucks",
"fuckstick", "fucktard", "fuck-tard", "fucktards", "fucktart", "fucktoy", "fucktwat", "fuckup", "fuckwad", "fuckwhit",
"fuckwit", "fuckwitt", "fudge packer", "fudgepacker", "fudge-packer", "fuk", "fuker", "fukker", "fukkers", "fukkin",
"fuks", "fukwhit", "fukwit", "fuq", "futanari", "fux", "fux0r", "fvck", "fxck", "gae",
"gai", "gang bang", "gangbang", "gang-bang", "gangbanged", "gangbangs", "ganja", "gash", "gassy ass", "gay sex",
"gayass", "gaybob", "gaydo", "gayfuck", "gayfuckist", "gaylord", "gays", "gaysex", "gaytard", "gaywad",
"gender bender", "genitals", "gey", "gfy", "ghay", "ghey", "giant cock", "gigolo", "ginger", "gippo",
"girl on", "girl on top", "girls gone wild", "glans", "goatcx", "goatse", "god", "god damn", "godamn", "godamnit",
"goddam", "god-dam", "goddammit", "goddamn", "goddamned", "god-damned", "goddamnit", "godsdamn", "gokkun", "golden shower",
"goldenshower", "golliwog", "gonad", "gonads", "goo girl", "gooch", "goodpoop", "gook", "gooks", "goregasm",
"gringo", "grope", "group sex", "gspot", "g-spot", "gtfo", "guido", "guro", "h0m0", "h0mo",
"ham flap", "hand job", "handjob", "hard core", "hard on", "hardcore", "hardcoresex", "he11", "hebe", "heeb",
"hell", "hemp", "hentai", "heroin", "herp", "herpes", "herpy", "heshe", "he-she", "hircismus",
"hitler", "hiv", "hoar", "hoare", "hobag", "hoe", "hoer", "holy shit", "hom0", "homey",
"homo", "homodumbshit", "homoerotic", "homoey", "honkey", "honky", "hooch", "hookah", "hooker", "hoor",
"hootch", "hooter", "hooters", "hore", "horniest", "horny", "hot carl", "hot chick", "hotsex", "how to kill",
"how to murdep", "how to murder", "huge fat", "hump", "humped", "humping", "hun", "hussy", "hymen", "iap",
"iberian slap", "inbred", "incest", "injun", "intercourse", "jack off", "jackass", "jackasses", "jackhole", "jackoff",
"jack-off", "jaggi", "jagoff", "jail bait", "jailbait", "jap", "japs", "jelly donut", "jerk", "jerk off",
"jerk0ff", "jerkass", "jerked", "jerkoff", "jerk-off", "jigaboo", "jiggaboo", "jiggerboo", "jism", "jiz",
"jizm", "jizm", "jizz", "jizzed", "jock", "juggs", "jungle bunny", "junglebunny", "junkie", "junky",
"kafir", "kawk", "kike", "kikes", "kill", "kinbaku", "kinkster", "kinky", "klan", "knob",
"knob end", "knobbing", "knobead", "knobed", "knobend", "knobhead", "knobjocky", "knobjokey", "kock", "kondum",
"kondums", "kooch", "kooches", "kootch", "kraut", "kum", "kummer", "kumming", "kums", "kunilingus",
"kunja", "kunt", "kwif", "kyke", "l3i+ch", "l3itch", "labia", "lameass", "lardass", "leather restraint",
"leather straight jacket", "lech", "lemon party", "LEN", "leper", "lesbian", "lesbians", "lesbo", "lesbos", "lez",
"lezza/lesbo", "lezzie", "lmao", "lmfao", "loin", "loins", "lolita", "looney", "lovemaking", "lube",
"lust", "lusting", "lusty", "m0f0", "m0fo", "m45terbate", "ma5terb8", "ma5terbate", "mafugly", "mafugly",
"make me come", "male squirting", "mams", "masochist", "massa", "masterb8", "masterbat*", "masterbat3", "masterbate", "master-bate",
"masterbating", "masterbation", "masterbations", "masturbate", "masturbating", "masturbation", "maxi", "mcfagget", "menage a trois", "menses",
"meth", "m-fucking", "mick", "microphallus", "middle finger", "midget", "milf", "minge", "minger", "missionary position",
"mof0", "mofo", "mo-fo", "molest", "mong", "moo moo foo foo", "moolie", "moron", "mothafuck", "mothafucka",
"mothafuckas", "mothafuckaz", "mothafucked", "mothafucker", "mothafuckers", "mothafuckin", "mothafucking", "mothafucking", "mothafuckings", "mothafucks",
"mother fucker", "motherfuck", "motherfucka", "motherfucked", "motherfucker", "motherfuckers", "motherfuckin", "motherfucking", "motherfuckings", "motherfuckka",
"motherfucks", "mound of venus", "mr hands", "muff", "muff diver", "muff puff", "muffdiver", "muffdiving", "munging", "munter",
"murder", "mutha", "muthafecker", "muthafuckker", "muther", "mutherfucker", "n1gga", "n1gger", "naked", "nambla",
"napalm", "nappy", "nawashi", "nazi", "nazism", "need the dick", "negro", "neonazi", "nig nog", "nigaboo",
"nigg3r", "nigg4h", "nigga", "niggah", "niggas", "niggaz", "nigger", "niggers", "niggle", "niglet",
"nig-nog", "nimphomania", "nimrod", "ninny", "ninnyhammer", "nipple", "nipples", "nob", "nob jokey", "nobhead",
"nobjocky", "nobjokey", "nonce", "nsfw images", "nude", "nudity", "numbnuts", "nut butter", "nut butter", "nut sack",
"nutsack", "nutter", "nympho", "nymphomania", "octopussy", "old bag", "omg", "omorashi", "one cup two girls", "1 cup 2 girls",
"one cup 2 girls", "1 cup two girls", "one guy one jar", "1 guy one jar", "one guy 1 jar", "opiate", "opium", "orally", "organ", "orgasim",
"orgasims", "orgasm", "orgasmic", "orgasms", "orgies", "orgy", "ovary", "ovum", "ovums", "p.u.s.s.y.",
"p.u.s.s.y", "p0rn", "paedophile", "paki", "panooch", "pansy", "pantie", "panties", "panty", "pawn",
"pcp", "pecker", "peckerhead", "pedo", "pedobear", "pedophile", "pedophilia", "pedophiliac", "pee", "peepee",
"pegging", "penetrate", "penetration", "penial", "penile", "penis", "penisbanger", "penisfucker", "penispuffer", "perversion",
"phallic", "phone sex", "phonesex", "phuck", "phuk", "phuked", "phuking", "phukked", "phukking", "phuks",
"phuq", "piece of shit", "pigfucker", "pikey", "pillowbiter", "pimp", "pimpis", "pinko", "piss", "piss off",
"piss pig", "pissed", "pissed off", "pisser", "pissers", "pisses", "pissflaps", "piss flaps", "pissin", "pissin",
"pissing", "pissoff", "pissoff", "piss-off", "pisspig", "playboy", "pleasure chest", "polack", "pole smoker", "polesmoker",
"pollock", "ponyplay", "poof", "poon", "poonani", "poonany", "poontang", "poop", "poop chute", "poopchute",
"Poopuncher", "porch monkey", "porchmonkey", "porn", "porno", "pornography", "pornos", "potty", "prick", "pricks",
"prickteaser", "prig", "prince albert piercing", "prod", "pron", "prone bone", "pronebone", "prone-bone", "prostitute", "prude",
"psycho", "pthc", "pube", "pubes", "pubic", "pubis", "punani", "punanny", "punany", "punkass",
"punky", "punta", "puss", "pusse", "pussi", "pussies", "pussy", "pussy fart", "pussy palace", "pussylicking",
"pussypounder", "pussys", "pust", "puto", "queaf", "queef", "queer", "queerbait", "queerhole", "queero",
"queers", "quicky", "quim", "racy", "raghead", "raging boner", "rape", "raped", "raper", "rapey",
"raping", "rapist", "raunch", "rectal", "rectum", "rectus", "reefer", "reetard", "reich", "renob",
"retard", "retarded", "reverse cowgirl", "revue", "rimjaw", "rimjob", "rimming", "ritard", "rosy palm", "rosy palm and her 5 sisters",
"rtard", "r-tard", "rubbish", "rum", "rump", "rumprammer", "ruski", "rusty trombone", "s&m", "s.h.i.t.",
"s.o.b.", "s_h_i_t", "s0b", "sadism", "sadist", "sambo", "sand nigger", "sandbar", "sandbar", "Sandler",
"sandnigger", "sanger", "santorum", "sausage queen", "scag", "scantily", "scat", "schizo", "schlong", "scissoring",
"screw", "screwed", "screwing", "scroat", "scrog", "scrot", "scrote", "scrotum", "scrud", "scum",
"seaman", "seduce", "seks", "semen", "sex", "sexo", "sexual", "sexy", "sh!+", "sh!t",
"sh1t", "s-h-1-t", "shag", "shagger", "shaggin", "shagging", "shamedame", "shaved beaver", "shaved pussy", "shemale",
"shi+", "shibari", "shirt lifter", "shit", "s-h-i-t", "shit ass", "shit fucker", "shitass", "shitbag", "shitbagger",
"shitblimp", "shitbrains", "shitbreath", "shitcanned", "shitcunt", "shitdick", "shite", "shiteater", "shited", "shitey",
"shitface", "shitfaced", "shitfuck", "shitfull", "shithead", "shitheads", "shithole", "shithouse", "shiting", "shitings",
"shits", "shitspitter", "shitstain", "shitt", "shitted", "shitter", "shitters", "shitters", "shittier", "shittiest",
"shitting", "shittings", "shitty", "shiz", "shiznit", "shota", "shrimping", "sissy", "skag", "skank",
"skeet", "skullfuck", "slag", "slanteye", "slave", "sleaze", "sleazy", "slope", "slut", "slut bucket",
"slutbag", "slutdumper", "slutkiss", "sluts", "smartass", "smartasses", "smeg", "smegma", "smut", "smutty",
"snatch", "sniper", "snowballing", "snuff", "s-o-b", "sod off", "sodom", "sodomize", "sodomy", "son of a bitch",
"son of a motherless goat", "son of a whore", "son-of-a-bitch", "souse", "soused", "spac", "spade", "sperm", "spic", "spick",
"spik", "spiks", "splooge", "splooge moose", "spooge", "spook", "spread legs", "spunk", "stfu", "stiffy",
"stoned", "strap on", "strapon", "strappado", "strip", "strip club", "stroke", "stupid", "style doggy", "suck",
"suckass", "sucked", "sucking", "sucks", "suicide girls", "sultry women", "sumofabiatch", "swastikav", "swinger", "t1t",
"t1tt1e5", "t1tties", "taff", "taig", "tainted love", "taking the piss", "tampon", "tard", "tart", "taste my",
"tawdry", "tea bagging", "teabagging", "teat", "teets", "teez", "teste", "testee", "testes", "testical",
"testicle", "testis", "threesome", "throating", "thrust", "thug", "thundercunt", "thunder cunt", "tied up", "tight white",
"tinkle", "tit", "tit wank", "titfuck", "titi", "tities", "tits", "titt", "tittie5", "tittiefucker",
"titties", "titty", "tittyfuck", "tittyfucker", "tittywank", "titwank", "toke", "tongue in a", "toots", "topless",
"tosser", "towelhead", "tramp", "tranny", "trashy", "tribadism", "trumped", "tub girl", "tubgirl", "turd",
"tush", "tushy", "tw4t", "twat", "twathead", "twatlips", "twats", "twatty", "twatting", "twatwaffle",
"twink", "twinkie", "two fingers", "two fingers with tongue", "two girls one cup", "twunt", "twunter", "ugly", "unclefucker", "undies",
"undressing", "unwed", "upskirt", "urethra play", "urinal", "urine", "urophilia", "uterus", "uzi", "v14gra",
"v1gra", "vag", "vagina", "vajayjay", "va-j-j", "valium", "venus mound", "veqtable", "viagra", "vibrator",
"violet wand", "virgin", "vixen", "vjayjay", "vodka", "vomit", "vorarephilia", "voyeur", "vulgar", "vulva",
"w00se", "wad", "wang", "wank", "wanker", "wankjob", "wanky", "wazoo", "wedgie", "weed",
"weenie", "weewee", "weiner", "weirdo", "wench", "wet dream", "wetback", "wh0re", "wh0reface", "white power",
"whiz", "whoar", "whoralicious", "whore", "whorealicious", "whorebag", "whored", "whoreface", "whorehopper", "whorehouse",
"whores", "whoring", "wigger", "willies", "willy", "window licker", "wiseass", "wiseasses", "wog", "womb",
"wop", "wrapping men", "wrinkled starfish", "xrated", "x-rated", "xx", "xxx", "yaoi", "yeasty", "yellow showers",
"yid", "yiffy", "yobbo", "zibbi", "zoophilia", "zubb"
};
public int Count => _profanities.Count;
public ProfanityBase()
{
_profanities = new List<string>(_wordList);
}
protected ProfanityBase(string[] profanityList)
{
if (profanityList == null)
{
throw new ArgumentNullException("profanityList");
}
_profanities = new List<string>(profanityList);
}
protected ProfanityBase(List<string> profanityList)
{
if (profanityList == null)
{
throw new ArgumentNullException("profanityList");
}
_profanities = profanityList;
}
public void AddProfanity(string profanity)
{
if (string.IsNullOrEmpty(profanity))
{
throw new ArgumentNullException("profanity");
}
_profanities.Add(profanity);
}
public void AddProfanity(string[] profanityList)
{
if (profanityList == null)
{
throw new ArgumentNullException("profanityList");
}
_profanities.AddRange(profanityList);
}
public void AddProfanity(List<string> profanityList)
{
if (profanityList == null)
{
throw new ArgumentNullException("profanityList");
}
_profanities.AddRange(profanityList);
}
public bool RemoveProfanity(string profanity)
{
if (string.IsNullOrEmpty(profanity))
{
throw new ArgumentNullException("profanity");
}
return _profanities.Remove(profanity.ToLower(CultureInfo.InvariantCulture));
}
public bool RemoveProfanity(List<string> profanities)
{
if (profanities == null)
{
throw new ArgumentNullException("profanities");
}
foreach (string profanity in profanities)
{
if (!RemoveProfanity(profanity))
{
return false;
}
}
return true;
}
public bool RemoveProfanity(string[] profanities)
{
if (profanities == null)
{
throw new ArgumentNullException("profanities");
}
foreach (string profanity in profanities)
{
if (!RemoveProfanity(profanity))
{
return false;
}
}
return true;
}
public void Clear()
{
_profanities.Clear();
}
}
public class ProfanityFilter : ProfanityBase, IProfanityFilter
{
public IAllowList AllowList { get; }
public ProfanityFilter()
{
AllowList = new AllowList();
}
public ProfanityFilter(string[] profanityList)
: base(profanityList)
{
AllowList = new AllowList();
}
public ProfanityFilter(List<string> profanityList)
: base(profanityList)
{
AllowList = new AllowList();
}
public bool IsProfanity(string word)
{
if (string.IsNullOrEmpty(word))
{
return false;
}
if (AllowList.Contains(word.ToLower(CultureInfo.InvariantCulture)))
{
return false;
}
return _profanities.Contains(word.ToLower(CultureInfo.InvariantCulture));
}
public ReadOnlyCollection<string> DetectAllProfanities(string sentence)
{
return DetectAllProfanities(sentence, removePartialMatches: false);
}
public ReadOnlyCollection<string> DetectAllProfanities(string sentence, bool removePartialMatches)
{
if (string.IsNullOrEmpty(sentence))
{
return new ReadOnlyCollection<string>(new List<string>());
}
sentence = sentence.ToLower();
sentence = sentence.Replace(".", "");
sentence = sentence.Replace(",", "");
string[] words = sentence.Split(new char[1] { ' ' });
List<string> postAllowList = FilterWordListByAllowList(words);
List<string> swearList = new List<string>();
AddMultiWordProfanities(swearList, ConvertWordListToSentence(postAllowList));
if (removePartialMatches)
{
swearList.RemoveAll((string x) => swearList.Any((string y) => x != y && y.Contains(x)));
}
return new ReadOnlyCollection<string>(FilterSwearListForCompleteWordsOnly(sentence, swearList).Distinct().ToList());
}
public string CensorString(string sentence)
{
return CensorString(sentence, '*');
}
public string CensorString(string sentence, char censorCharacter)
{
return CensorString(sentence, censorCharacter, ignoreNumbers: false);
}
public string CensorString(string sentence, char censorCharacter, bool ignoreNumbers)
{
if (string.IsNullOrEmpty(sentence))
{
return string.Empty;
}
string text = sentence.Trim();
text = text.ToLower();
text = Regex.Replace(text, "[^\\w\\s]", "");
string[] words = text.Split(new char[1] { ' ' });
List<string> postAllowList = FilterWordListByAllowList(words);
List<string> swearList = new List<string>();
AddMultiWordProfanities(swearList, ConvertWordListToSentence(postAllowList));
StringBuilder censored = new StringBuilder(sentence);
StringBuilder tracker = new StringBuilder(sentence);
return CensorStringByProfanityList(censorCharacter, swearList, censored, tracker, ignoreNumbers).ToString();
}
public (int, int, string)? GetCompleteWord(string toCheck, string profanity)
{
if (string.IsNullOrEmpty(toCheck))
{
return null;
}
string value = profanity.ToLower(CultureInfo.InvariantCulture);
string text = toCheck.ToLower(CultureInfo.InvariantCulture);
if (text.Contains(value))
{
int num = text.IndexOf(value, StringComparison.Ordinal);
int i = num;
while (num > 0 && toCheck[num - 1] != ' ' && !char.IsPunctuation(toCheck[num - 1]))
{
num--;
}
for (; i < toCheck.Length && toCheck[i] != ' ' && !char.IsPunctuation(toCheck[i]); i++)
{
}
return (num, i, text.Substring(num, i - num).ToLower(CultureInfo.InvariantCulture));
}
return null;
}
public bool ContainsProfanity(string term)
{
if (string.IsNullOrWhiteSpace(term))
{
return false;
}
List<string> list = _profanities.Where((string word) => word.Length <= term.Length).ToList();
if (list.Count == 0)
{
return false;
}
Regex regex = new Regex(string.Format("(?:{0})", string.Join("|", list).Replace("$", "\\$"), RegexOptions.IgnoreCase));
foreach (Match item in regex.Matches(term))
{
if (!AllowList.Contains(item.Value.ToLower(CultureInfo.InvariantCulture)))
{
return true;
}
}
return false;
}
private StringBuilder CensorStringByProfanityList(char censorCharacter, List<string> swearList, StringBuilder censored, StringBuilder tracker, bool ignoreNumeric)
{
foreach (string item in swearList.OrderByDescending((string x) => x.Length))
{
(int, int, string)? tuple = (0, 0, "");
string[] array = item.Split(new char[1] { ' ' });
if (array.Length == 1)
{
do
{
tuple = GetCompleteWord(tracker.ToString(), item);
if (!tuple.HasValue)
{
continue;
}
string text = tuple.Value.Item3;
if (ignoreNumeric)
{
text = Regex.Replace(tuple.Value.Item3, "[\\d-]", string.Empty);
}
if (text == item)
{
for (int i = tuple.Value.Item1; i < tuple.Value.Item2; i++)
{
censored[i] = censorCharacter;
tracker[i] = censorCharacter;
}
}
else
{
for (int j = tuple.Value.Item1; j < tuple.Value.Item2; j++)
{
tracker[j] = censorCharacter;
}
}
}
while (tuple.HasValue);
}
else
{
censored = censored.Replace(item, CreateCensoredString(item, censorCharacter));
}
}
return censored;
}
private List<string> FilterSwearListForCompleteWordsOnly(string sentence, List<string> swearList)
{
List<string> list = new List<string>();
StringBuilder stringBuilder = new StringBuilder(sentence);
foreach (string item in swearList.OrderByDescending((string x) => x.Length))
{
(int, int, string)? tuple = (0, 0, "");
string[] array = item.Split(new char[1] { ' ' });
if (array.Length == 1)
{
do
{
tuple = GetCompleteWord(stringBuilder.ToString(), item);
if (!tuple.HasValue)
{
continue;
}
if (tuple.Value.Item3 == item)
{
list.Add(item);
for (int i = tuple.Value.Item1; i < tuple.Value.Item2; i++)
{
stringBuilder[i] = '*';
}
break;
}
for (int j = tuple.Value.Item1; j < tuple.Value.Item2; j++)
{
stringBuilder[j] = '*';
}
}
while (tuple.HasValue);
}
else
{
list.Add(item);
stringBuilder.Replace(item, " ");
}
}
return list;
}
private List<string> FilterWordListByAllowList(string[] words)
{
List<string> list = new List<string>();
foreach (string text in words)
{
if (!string.IsNullOrEmpty(text) && !AllowList.Contains(text.ToLower(CultureInfo.InvariantCulture)))
{
list.Add(text);
}
}
return list;
}
private static string ConvertWordListToSentence(List<string> postAllowList)
{
string text = string.Empty;
foreach (string postAllow in postAllowList)
{
text = text + postAllow + " ";
}
return text;
}
private void AddMultiWordProfanities(List<string> swearList, string postAllowListSentence)
{
swearList.AddRange(from string profanity in _profanities
where postAllowListSentence.ToLower(CultureInfo.InvariantCulture).Contains(profanity)
select profanity);
}
private static string CreateCensoredString(string word, char censorCharacter)
{
string text = string.Empty;
for (int i = 0; i < word.Length; i++)
{
text = ((word[i] == ' ') ? (text + " ") : (text + censorCharacter));
}
return text;
}
}
}
namespace ProfanityFilter.Interfaces
{
public interface IAllowList
{
int Count { get; }
ReadOnlyCollection<string> ToList { get; }
void Add(string wordToAllowlist);
bool Contains(string wordToCheck);
bool Remove(string wordToRemove);
void Clear();
}
public interface IProfanityFilter
{
IAllowList AllowList { get; }
int Count { get; }
bool IsProfanity(string word);
ReadOnlyCollection<string> DetectAllProfanities(string sentence);
ReadOnlyCollection<string> DetectAllProfanities(string sentence, bool removePartialMatches);
bool ContainsProfanity(string term);
string CensorString(string sentence);
string CensorString(string sentence, char censorCharacter);
string CensorString(string sentence, char censorCharacter, bool ignoreNumbers);
(int, int, string)? GetCompleteWord(string toCheck, string profanity);
void AddProfanity(string profanity);
void AddProfanity(string[] profanityList);
void AddProfanity(List<string> profanityList);
bool RemoveProfanity(string profanity);
bool RemoveProfanity(List<string> profanities);
bool RemoveProfanity(string[] profanities);
void Clear();
}
}