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");
}
}
}