Decompiled source of NiceFaces v0.1.2

BepInEx/plugins/FaceFilter/FaceFilter.dll

Decompiled 8 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using ProfanityFilter;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Ashley.MeshSplitter")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("com.rlabrecque.steamworks.net")]
[assembly: IgnoresAccessChecksTo("Discord")]
[assembly: IgnoresAccessChecksTo("HBAO.Demo.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("HBAO.Runtime")]
[assembly: IgnoresAccessChecksTo("HBAO.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("MeshSplit")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("pworld")]
[assembly: IgnoresAccessChecksTo("sc.posteffects.runtime")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Tayx.Graphy")]
[assembly: IgnoresAccessChecksTo("Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.013")]
[assembly: IgnoresAccessChecksTo("Unity.Localization")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.PlayableGraphVisualizer")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipeline.Universal.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Shaders")]
[assembly: IgnoresAccessChecksTo("Unity.ResourceManager")]
[assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")]
[assembly: IgnoresAccessChecksTo("Unity.Splines")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Antlr3.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Core")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Flow")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.State")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.PhotonUtility")]
[assembly: IgnoresAccessChecksTo("Zorro.Recorder")]
[assembly: IgnoresAccessChecksTo("Zorro.Settings.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.UI.Runtime")]
[assembly: AssemblyCompany("FaceFilter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: AssemblyInformationalVersion("0.1.2+e6135f6fa0fcac990308665513aed73fbcd6476d")]
[assembly: AssemblyProduct("FaceFilter")]
[assembly: AssemblyTitle("FaceFilter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FaceFilter
{
	public static class Filtration
	{
		public static bool Initialized = false;

		public static ProfanityFilter Filter { get; } = new ProfanityFilter();


		public static bool IsProfane(string text)
		{
			if (!Initialized)
			{
				Initialized = true;
				Init();
			}
			if (!Filter.IsProfanity(text) && Filter.DetectAllProfanities(text).Count <= 0)
			{
				return text.Aggregate(seed: false, (bool b, char c) => b || Filter.IsProfanity(c.ToString()));
			}
			return true;
		}

		public static void Init()
		{
			string text = typeof(FaceFilter).Namespace + ".WordBlock.txt";
			Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
			if (manifestResourceStream == null)
			{
				throw new ArgumentException(text);
			}
			using StreamReader streamReader = new StreamReader(manifestResourceStream);
			while (!streamReader.EndOfStream)
			{
				string text2 = streamReader.ReadLine();
				((ProfanityBase)Filter).AddProfanity(text2);
			}
		}
	}
	[ContentWarningPlugin("FaceFilter", "0.1.2", true)]
	[BepInPlugin("FaceFilter", "FaceFilter", "0.1.2")]
	public class FaceFilter : BaseUnityPlugin
	{
		public static FaceFilter Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static Harmony? Harmony { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Patch();
			Logger.LogInfo((object)"FaceFilter v0.1.2 has loaded!");
		}

		internal static void Patch()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("FaceFilter");
			}
			Logger.LogDebug((object)"Patching...");
			Harmony.PatchAll();
			Logger.LogDebug((object)"Finished patching!");
		}

		internal static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "FaceFilter";

		public const string PLUGIN_NAME = "FaceFilter";

		public const string PLUGIN_VERSION = "0.1.2";
	}
}
namespace FaceFilter.Patches
{
	[HarmonyPatch(typeof(GameHandler))]
	public static class GameHandlerCheckPluginsPatch
	{
		public static void RemoveProfanityDll(ref FileInfo[] files)
		{
			List<FileInfo> list = files.ToList();
			int num = -1;
			string assemLocation = typeof(ProfanityFilter).Assembly.Location;
			if ((num = list.FindIndex((FileInfo info) => info.FullName == assemLocation)) >= 0)
			{
				list.RemoveAt(num);
				files = list.ToArray();
			}
		}

		[HarmonyPatch("CheckPlugins")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> AddExceptionForProfanityFilter(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			return new CodeMatcher(instructions, ilGenerator).MatchForward(true, (CodeMatch[])(object)new CodeMatch[5]
			{
				new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"*.dll", (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Stloc_2, (object)null, (string)null)
			}).Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldloca_S, (object)2),
				new CodeInstruction(OpCodes.Call, (object)typeof(GameHandlerCheckPluginsPatch).GetMethod("RemoveProfanityDll"))
			})
				.ThrowIfInvalid("Couldn't find directoryInfo.GetFiles(...)")
				.Instructions();
		}
	}
	[HarmonyPatch(typeof(PlayerCustomizer))]
	public static class PlayerCustomizerSetFaceTextPatch
	{
		[HarmonyPatch("SetFaceText")]
		[HarmonyPrefix]
		[HarmonyPriority(100)]
		private static void CensorFaceText(PlayerCustomizer __instance, ref string text)
		{
			if (Filtration.IsProfane(text))
			{
				text = "***";
			}
		}
	}
	[HarmonyPatch(typeof(PlayerVisor))]
	public static class PlayerVisorSetVisorTextRPCPatch
	{
		[HarmonyPatch("RPCA_SetVisorText")]
		[HarmonyPostfix]
		private static void PreventPlebsFromUsingBadNames(PlayerVisor __instance)
		{
			string text = ((TMP_Text)__instance.visorFaceText).text;
			if (Filtration.IsProfane(text))
			{
				((TMP_Text)__instance.visorFaceText).text = FaceDatabase.GetFace(FaceDatabase.GetRandomFaceIndex());
				FaceFilter.Logger.LogInfo((object)("Blocking profane face text from '" + ((Object)__instance.m_player).name + "': '" + text + "' -> '" + ((TMP_Text)__instance.visorFaceText).text + "'"));
				((MonoBehaviour)__instance).StartCoroutine(DelayedFaceTransmission(__instance, text));
			}
		}

		private static IEnumerator DelayedFaceTransmission(PlayerVisor visor, string profanity)
		{
			int playerID = PlayerHandler.instance.GetPlayerID(Player.localPlayer);
			yield return (object)new WaitForSeconds(0.25f * (float)(playerID + 1));
			if (!(((TMP_Text)visor.visorFaceText).text != profanity))
			{
				visor.m_player.refs.view.RPC("RPCA_SetVisorText", (RpcTarget)0, new object[1] { ((TMP_Text)visor.visorFaceText).text });
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

BepInEx/plugins/FaceFilter/ProfanityFilter.dll

Decompiled 8 months ago
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();
	}
}