Decompiled source of TwitchIntegrationAPI v1.0.0

TwitchIntegrationAPI.dll

Decompiled 9 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TwitchIntegrationAPI.Managers;
using TwitchIntegrationAPI.Managers.Commands;
using TwitchIntegrationAPI.Patches;
using TwitchIntegrationAPI.Utilities;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TwitchIntegrationAPI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TwitchIntegrationAPI")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fcfdc058-c36a-49d9-aeeb-d62084100186")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TwitchIntegrationAPI
{
	[BepInPlugin("SZAKI.TwitchIntegrationAPI", "Twitch Integration API", "1.0.0.0")]
	[BepInProcess("Lethal Company.exe")]
	public class Base : BaseUnityPlugin
	{
		private static Base _instance;

		private Logger _log;

		private Twitch _twitch;

		private CommandManager _cmdManager;

		private Harmony harmony = new Harmony("SZAKI.TwitchIntegrationAPI");

		public static Base Instance
		{
			get
			{
				return _instance;
			}
			private set
			{
				_instance = value;
			}
		}

		public Logger Log
		{
			get
			{
				return _log;
			}
			private set
			{
				_log = value;
			}
		}

		public Twitch Twitch
		{
			get
			{
				return _twitch;
			}
			private set
			{
				_twitch = value;
			}
		}

		public CommandManager Commands
		{
			get
			{
				return _cmdManager;
			}
			private set
			{
				_cmdManager = value;
			}
		}

		private void Awake()
		{
			if ((Object)(object)_instance == (Object)null)
			{
				Instance = this;
			}
			if (Log == null)
			{
				Log = new Logger();
			}
			if (Commands == null)
			{
				Commands = new CommandManager();
			}
			Commands.RegisterCommand(new PING());
			Config.Init();
			if ((Object)(object)Twitch == (Object)null)
			{
				Twitch = new Twitch();
			}
			harmony.PatchAll(typeof(Base));
			harmony.PatchAll(typeof(IntegrateTwitch));
			Log.LogInfo("Successfully Awakened!");
		}
	}
}
namespace TwitchIntegrationAPI.Utilities
{
	public static class Config
	{
		public const string CONFIG_NAME = "twitch-integration-api.cfg";

		private static ConfigFile _config;

		private static ConfigEntry<string> _url;

		private static ConfigEntry<int> _port;

		private static ConfigEntry<string> _user;

		private static ConfigEntry<string> _oauth;

		private static ConfigEntry<string> _channel;

		public static string URL => _url.Value;

		public static int PORT => _port.Value;

		public static string USER => _user.Value;

		public static string OAUTH => _oauth.Value;

		public static string CHANNEL => _channel.Value;

		public static void Init()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			Base.Instance.Log.LogInfo("Initializing config...");
			_config = new ConfigFile(Path.Combine(Paths.ConfigPath, "twitch-integration-api.cfg"), true);
			_url = _config.Bind<string>("Twitch", "Url", "irc.twitch.tv", "Default url for the twitch chat");
			_port = _config.Bind<int>("Twitch", "Port", 6667, "Default port for the twitch chat");
			_user = _config.Bind<string>("Twitch Auth", "User", "dummy", "Twitch Login name ( could be yours or a \"bot\" login name");
			_oauth = _config.Bind<string>("Twitch Auth", "OAuth", "dummy", "You can create an oauth app id here: https://twitchapps.com/tmi - This is needed for authentication (DON'T SHOW IT TO ANYONE)");
			_channel = _config.Bind<string>("Twitch Auth", "Channel", "dummy", "Your Twitch Channel name (this specify which twitch chat should connect)");
			Base.Instance.Log.LogInfo("Initializing completed!");
		}
	}
	public class Logger
	{
		private ManualLogSource mls;

		public Logger()
		{
			mls = Logger.CreateLogSource("Twitch Integration API");
		}

		private void Log(LogLevel level, string message)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			mls.Log(level, (object)(" " + message));
		}

		public void LogInfo(string message)
		{
			Log((LogLevel)16, message);
		}

		public void LogWarning(string message)
		{
			Log((LogLevel)4, message);
		}

		public void LogError(string message)
		{
			Log((LogLevel)2, message);
		}

		public void LogDebug(string message)
		{
			Log((LogLevel)32, message);
		}
	}
	public static class PluginInfos
	{
		public const string GUID = "SZAKI.TwitchIntegrationAPI";

		public const string NAME = "Twitch Integration API";

		public const string VERSION = "1.0.0.0";
	}
	public class Twitch : MonoBehaviour
	{
		private enum ConnectionStatus
		{
			DISCONNECTED,
			DISCONNECTING,
			CONNECTING,
			CONNECTED
		}

		private static Twitch _instance;

		private TcpClient _client;

		private StreamReader _reader;

		private StreamWriter _writer;

		private ConnectionStatus connectionState = ConnectionStatus.DISCONNECTED;

		private void Start()
		{
			if ((Object)(object)_instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			_instance = this;
			ConnectToTwitch();
		}

		private void ConnectToTwitch()
		{
			try
			{
				Base.Instance.Log.LogWarning($"Twitch - Connecting to {Config.URL}:{Config.PORT}");
				connectionState = ConnectionStatus.CONNECTING;
				_client = new TcpClient(Config.URL, Config.PORT);
				_reader = new StreamReader(_client.GetStream());
				_writer = new StreamWriter(_client.GetStream());
				Base.Instance.Log.LogWarning("Twitch - Connected! Try to get user (" + Config.USER + ", " + Config.CHANNEL + ")");
				_writer.WriteLine("PASS " + Config.OAUTH);
				_writer.WriteLine("NICK " + Config.USER.ToLower());
				_writer.WriteLine("JOIN #" + Config.CHANNEL.ToLower());
				_writer.Flush();
				connectionState = ConnectionStatus.CONNECTED;
				((MonoBehaviour)this).StartCoroutine(ReadStream());
			}
			catch (Exception ex)
			{
				Base.Instance.Log.LogWarning("Twitch - Connection failed! " + ex.Message);
			}
		}

		private void OnDestroy()
		{
			if (connectionState == ConnectionStatus.CONNECTED)
			{
				connectionState = ConnectionStatus.DISCONNECTING;
				Base.Instance.Log.LogWarning("Twitch - Closing Connection...");
				_client.Close();
				_reader.Close();
				_writer.Close();
				connectionState = ConnectionStatus.DISCONNECTED;
				Base.Instance.Log.LogWarning("Twitch - Connection successfully closed!");
			}
		}

		private IEnumerator ReadStream()
		{
			while (connectionState == ConnectionStatus.CONNECTED)
			{
				if (_client.Available > 0 || _reader.Peek() > 0)
				{
					string message = _reader.ReadLine();
					ProcessLine(message);
				}
				yield return null;
			}
			Base.Instance.Log.LogWarning("Twitch - Stop listening! ConnectionState: " + connectionState);
		}

		private void ProcessLine(string line)
		{
			string text;
			string text2;
			string text3;
			(text, text2, text3) = ParseMessage(line);
			if (text == "PING")
			{
				SendLine("PING " + text3);
			}
			else if (text == "PRIVMSG" && text3.StartsWith("!"))
			{
				text3 = text3.Substring(1);
				string[] array = text3.Split(new char[1] { ' ' });
				string[] array2 = new string[array.Length - 1];
				try
				{
					array.CopyTo(array2, 1);
					Base.Instance.Commands.ExecuteCommand(array[0], array2);
				}
				catch (Exception)
				{
					Base.Instance.Commands.ExecuteCommand(array[0]);
				}
			}
		}

		private void SendLine(string line)
		{
			_writer.WriteLine(line);
			_writer.Flush();
		}

		private (string, string, string) ParseMessage(string message)
		{
			string item = null;
			string item2 = null;
			int num = 0;
			string rawSourceComponent = null;
			string text = null;
			int num2;
			if (message[num] == '@')
			{
				num2 = message.IndexOf(' ');
				num = num2 + 1;
			}
			if (message[num] == ':')
			{
				num++;
				num2 = message.IndexOf(' ', num);
				rawSourceComponent = message.Substring(num, num2 - num);
				num = num2 + 1;
			}
			num2 = message.IndexOf(':', num);
			if (num2 == -1)
			{
				num2 = message.Length;
			}
			string rawCommandComponent = message.Substring(num, num2 - num).Trim();
			if (num2 != message.Length)
			{
				num = num2 + 1;
				text = message.Substring(num);
			}
			string text2 = ParseCommand(rawCommandComponent);
			if (text2 != null)
			{
				item = ParseSource(rawSourceComponent);
				item2 = text?.Trim();
			}
			return (text2, item, item2);
		}

		private string ParseCommand(string rawCommandComponent)
		{
			if (string.IsNullOrEmpty(rawCommandComponent))
			{
				return null;
			}
			string[] array = rawCommandComponent.Split(new char[1] { ' ' });
			return array[0];
		}

		private string ParseSource(string rawSourceComponent)
		{
			if (string.IsNullOrEmpty(rawSourceComponent))
			{
				return null;
			}
			string[] array = rawSourceComponent.Split(new char[1] { '!' });
			if (array.Length == 2)
			{
				return array[0];
			}
			return null;
		}
	}
}
namespace TwitchIntegrationAPI.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager), "Awake")]
	internal class IntegrateTwitch
	{
		[HarmonyPrefix]
		private static void Prefix(ref GameNetworkManager __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<Twitch>()))
			{
				((Component)__instance).gameObject.AddComponent<Twitch>();
			}
		}
	}
}
namespace TwitchIntegrationAPI.Managers
{
	public abstract class Command
	{
		private string name;

		public Command(string name)
		{
			this.name = name.ToUpper();
		}

		public virtual string GetName()
		{
			return name;
		}

		public abstract void Execute(params string[] args);
	}
	public class CommandManager
	{
		private Dictionary<string, Command> registeredCommands;

		public CommandManager()
		{
			registeredCommands = new Dictionary<string, Command>();
		}

		public bool RegisterCommand(Command command)
		{
			Base.Instance.Log.LogInfo("Registering " + command.GetName() + "...");
			if (!registeredCommands.ContainsKey(command.GetName()))
			{
				registeredCommands.Add(command.GetName(), command);
				Base.Instance.Log.LogInfo("Successfully registered!");
				return true;
			}
			Base.Instance.Log.LogInfo("This command is already in registered!");
			return false;
		}

		public bool UnRegisterCommand(string name)
		{
			Base.Instance.Log.LogInfo("UnRegistering " + name.ToUpper() + "...");
			if (registeredCommands.ContainsKey(name.ToUpper()))
			{
				registeredCommands.Remove(name.ToUpper());
				Base.Instance.Log.LogInfo("Successfully unregistered!");
				return true;
			}
			Base.Instance.Log.LogInfo("The command is not in the list!");
			return false;
		}

		public bool UnRegisterCommad(Command command)
		{
			return UnRegisterCommand(command.GetName());
		}

		public bool ExecuteCommand(string name, params string[] args)
		{
			Command value = null;
			if (registeredCommands.TryGetValue(name.ToUpper(), out value))
			{
				Base.Instance.Log.LogInfo("Executing " + name.ToUpper() + "...");
				value.Execute(args);
				return true;
			}
			return false;
		}

		public void ExecuteAll()
		{
			Base.Instance.Log.LogInfo("Executing all the registered commands...");
			foreach (KeyValuePair<string, Command> registeredCommand in registeredCommands)
			{
				registeredCommand.Value.Execute();
			}
		}
	}
}
namespace TwitchIntegrationAPI.Managers.Commands
{
	public class PING : Command
	{
		public PING(params string[] args)
			: base("PING")
		{
		}

		public override void Execute(params string[] args)
		{
			Base.Instance.Log.LogInfo("PONG");
		}
	}
}