Decompiled source of CrimsonChatFilter v0.1.1

CrimsonChatFilter.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Bloodstone.API;
using Bloodstone.Hooks;
using CrimsonChatFilter.Structs;
using CrimsonChatFilter.Utils;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Network;
using Unity.Collections;
using Unity.Entities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("CrimsonChatFilter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Filter server chat!")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+1.Branch.master.Sha.37841d6f9d2c9bc3e1c5219e49add8ceb5914507")]
[assembly: AssemblyProduct("CrimsonChatFilter")]
[assembly: AssemblyTitle("CrimsonChatFilter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.0")]
[module: UnverifiableCode]
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;
		}
	}
}
namespace CrimsonChatFilter
{
	[BepInPlugin("CrimsonChatFilter", "CrimsonChatFilter", "0.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[Reloadable]
	public class Plugin : BasePlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ChatEventHandler <>9__9_0;

			internal void <Load>b__9_0(VChatEvent x)
			{
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Expected O, but got Unknown
				if (Settings.GetActiveOption(Settings.Options.Enable) && Settings.GetActiveOption(Settings.Options.FullRemove) && x.Message.ContainsFiltered())
				{
					ManualLogSource logger = Logger;
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(10, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("FILTERED: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(x.Message);
					}
					logger.LogWarning(val);
					x.Cancel();
				}
			}
		}

		private Harmony _harmony;

		public static Settings Settings { get; private set; }

		public static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			Settings = new Settings(((BasePlugin)this).Config);
			Settings.InitConfig();
			Database.InitFiltered("filtered_words");
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("CrimsonChatFilter");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("0.1.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!");
			}
			log.LogInfo(val);
			_harmony = new Harmony("CrimsonChatFilter");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			object obj = <>c.<>9__9_0;
			if (obj == null)
			{
				ChatEventHandler val2 = delegate(VChatEvent x)
				{
					//IL_0039: Unknown result type (might be due to invalid IL or missing references)
					//IL_003f: Expected O, but got Unknown
					if (Settings.GetActiveOption(Settings.Options.Enable) && Settings.GetActiveOption(Settings.Options.FullRemove) && x.Message.ContainsFiltered())
					{
						ManualLogSource logger = Logger;
						bool flag2 = default(bool);
						BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(10, 1, ref flag2);
						if (flag2)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("FILTERED: ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(x.Message);
						}
						logger.LogWarning(val3);
						x.Cancel();
					}
				};
				<>c.<>9__9_0 = val2;
				obj = (object)val2;
			}
			Chat.OnChatMessage += (ChatEventHandler)obj;
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			return true;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "CrimsonChatFilter";

		public const string PLUGIN_NAME = "CrimsonChatFilter";

		public const string PLUGIN_VERSION = "0.1.1";
	}
}
namespace CrimsonChatFilter.Utils
{
	internal static class FilterString
	{
		public static List<string> FilteredWords;

		private static string addressFilter = ".[0-9]+[0-9][0-9].[0-9]+[0-9][0-9].[0-9]+[0-9][0-9].[0-9]+[0-9][0-9]*";

		private static string domainFilter = "\\bhttp:\\/\\/([^\\/]*)\\/([^\\s]*)";

		public static string Filter(this string input)
		{
			if (Plugin.Settings.GetActiveOption(Settings.Options.FilterUrl))
			{
				input = Regex.Replace(input, addressFilter, "****", RegexOptions.IgnoreCase);
				input = Regex.Replace(input, domainFilter, "****", RegexOptions.IgnoreCase);
			}
			foreach (string filteredWord in FilteredWords)
			{
				string pattern = "\\b" + Regex.Escape(filteredWord) + "\\b";
				input = Regex.Replace(input, pattern, "****", RegexOptions.IgnoreCase);
			}
			return input;
		}

		public static bool ContainsFiltered(this string input)
		{
			if (Plugin.Settings.GetActiveOption(Settings.Options.FilterUrl))
			{
				if (Regex.IsMatch(input, addressFilter))
				{
					return true;
				}
				if (Regex.IsMatch(input, domainFilter))
				{
					return true;
				}
			}
			foreach (string filteredWord in FilteredWords)
			{
				if (input.Contains(filteredWord))
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace CrimsonChatFilter.Structs
{
	public class Database
	{
		private static Database INSTANCE;

		public string FilteredPath { get; set; }

		public Database(string _path, string _db)
		{
			FilteredPath = Path.Combine(_path, _db + ".json");
		}

		public static void InitFiltered(string db)
		{
			INSTANCE = new Database(Path.Combine(Paths.ConfigPath, "CrimsonChatFilter"), db);
			if (File.Exists(INSTANCE.FilteredPath))
			{
				FilterString.FilteredWords = JsonSerializer.Deserialize<List<string>>(File.ReadAllText(INSTANCE.FilteredPath));
			}
		}
	}
	public readonly struct Settings
	{
		public enum Options
		{
			Enable,
			FullRemove,
			FilterUrl
		}

		private readonly ConfigFile CONFIG;

		private readonly ConfigEntry<bool> ENABLE_MOD;

		private readonly ConfigEntry<bool> FULL_REMOVE;

		private readonly ConfigEntry<bool> FILTER_URLS;

		public static readonly string CONFIG_PATH = Path.Combine(Paths.ConfigPath, "CrimsonChatFilter");

		public Settings(ConfigFile config)
		{
			CONFIG = config;
			ENABLE_MOD = CONFIG.Bind<bool>("Config", "EnableMod", true, "Enable or disable chat filtering");
			FULL_REMOVE = CONFIG.Bind<bool>("Config", "FullRemove", false, "If enabled, others won't see the message, otherwise replaces filtered words with ****");
			FILTER_URLS = CONFIG.Bind<bool>("Config", "FilterURLs", true, "Includes .com and server addresses in filter list");
		}

		public void InitConfig()
		{
			WriteConfig();
		}

		public void WriteConfig()
		{
			if (!Directory.Exists(CONFIG_PATH))
			{
				Directory.CreateDirectory(CONFIG_PATH);
			}
			if (!File.Exists(Path.Combine(CONFIG_PATH, "filtered_words.json")))
			{
				string contents = JsonSerializer.Serialize(GenerateTemplate(), new JsonSerializerOptions
				{
					WriteIndented = true
				});
				File.WriteAllText(Path.Combine(CONFIG_PATH, "filtered_words.json"), contents);
			}
		}

		private List<string> GenerateTemplate()
		{
			return new List<string> { "coon", "jim crow", "nigger", "gook", "chink", "towelhead", "honky", "beaner", "spic" };
		}

		public bool GetActiveOption(Options option)
		{
			return option switch
			{
				Options.Enable => ENABLE_MOD.Value, 
				Options.FullRemove => FULL_REMOVE.Value, 
				Options.FilterUrl => FILTER_URLS.Value, 
				_ => false, 
			};
		}
	}
}
namespace CrimsonChatFilter.Hooks
{
	[HarmonyPatch]
	public static class ChatMessageSystem_Patch
	{
		[HarmonyPatch(typeof(ChatMessageSystem), "OnUpdate")]
		[HarmonyPrefix]
		public static bool OnUpdate(ChatMessageSystem __instance)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Settings.GetActiveOption(Settings.Options.Enable))
			{
				return true;
			}
			if (Plugin.Settings.GetActiveOption(Settings.Options.FullRemove))
			{
				return true;
			}
			_ = __instance.__query_661171423_0;
			EntityQuery _query_661171423_ = __instance.__query_661171423_0;
			Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_661171423_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
			while (enumerator.MoveNext())
			{
				Entity current = enumerator.Current;
				EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager;
				FromCharacter componentData = ((EntityManager)(ref entityManager)).GetComponentData<FromCharacter>(current);
				entityManager = ((ComponentSystemBase)__instance).EntityManager;
				((EntityManager)(ref entityManager)).GetComponentData<User>(componentData.User);
				entityManager = ((ComponentSystemBase)__instance).EntityManager;
				ChatMessageEvent componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<ChatMessageEvent>(current);
				string input = ((object)(FixedString512Bytes)(ref componentData2.MessageText)).ToString();
				input = input.Filter();
				componentData2.MessageText = FixedString512Bytes.op_Implicit(input);
				entityManager = ((ComponentSystemBase)__instance).EntityManager;
				((EntityManager)(ref entityManager)).SetComponentData<ChatMessageEvent>(current, componentData2);
			}
			return true;
		}
	}
}