Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System.Text.RegularExpressions;
- using UnityEditor;
- using UnityEngine.Events;
- using UnityEngine.Analytics;
- using System.Net.Sockets;
- using System.Threading;
- using System.IO;
- using System.Diagnostics;
- [System.Serializable]
- public class TwitchChat : MonoBehaviour {
- public Twitch twitchBox = new Twitch();
- public Twitch.MsgEvent inbox = new Twitch.MsgEvent();
- [SerializeField] public string un = "";
- [SerializeField] public string pw = "";
- [SerializeField] public string[] ch;
- [SerializeField] public bool logg = true;
- [SerializeField] public bool ac = false;
- [SerializeField] public CommandEntry[] commands;
- [SerializeField] public string tctn = "TwitchChatInbox";
- [SerializeField] public GameObject boltFlowGameObject = null;
- public void Start() {
- twitchBox.nickname = un;
- twitchBox.oauth = pw;
- twitchBox.channels = ch;
- twitchBox.logging = logg;
- twitchBox.messageRecievedEvent.AddListener(internalInbox);
- if(ac) {twitchBox.StartTwitchChat();}
- }
- public void Update() {
- twitchBox.Tick();
- }
- private void internalInbox(Twitch.MSGInfo msg) {
- if(twitchBox.logging) {
- UnityEngine.Debug.Log(msg.channel + " > " + msg.name + ": " + msg.message);
- }
- foreach(CommandEntry i in commands) {
- Regex r = new Regex("^" + i.commandTrigger);
- if(r.IsMatch(msg.message)) {
- if(twitchBox.logging) {
- UnityEngine.Debug.Log(msg.channel + " > " + msg.name + " used " + i.commandName);
- }
- i.action.Invoke();
- }
- }
- System.Type t1 = System.Type.GetType("Bolt.CustomEvent, Bolt.Flow.Runtime");
- if(t1 != null) {
- System.Reflection.MethodInfo mt = null;
- foreach(System.Reflection.MethodInfo mi in t1.GetMethods()) {
- if(mi.Name == "Trigger") {
- mt = mi;
- break;
- }
- }
- GameObject tgo = boltFlowGameObject;
- if(tgo == null) {
- boltFlowGameObject = this.gameObject;
- }
- mt.Invoke(t1, new System.Object[] {tgo, tctn, new System.Object[] {msg}});
- }
- inbox.Invoke(msg);
- }
- public void SendChatMsg(string msg) {
- twitchBox.SendMsg(msg);
- }
- public void OnDisable() {
- twitchBox.StopTwitchChat();
- }
- public void OnDestroy() {
- twitchBox.StopTwitchChat();
- }
- }
- [System.Serializable]
- public class CommandEntry {
- [SerializeField] public string commandName;
- [SerializeField] public string commandTrigger;
- [SerializeField] public UnityEvent action;
- public CommandEntry (string name) {
- commandName = name;
- }
- }
- [CustomEditor(typeof(TwitchChat))]
- public class TwitchChatEditor : Editor {
- Twitch th;
- string msg;
- string[] msgl;
- GUIStyle style;
- bool isActive;
- bool isActive2;
- bool wasActive;
- bool showOauth;
- bool showMultichat;
- bool showchE;
- bool showcoE;
- public void DrawStringArray(SerializedProperty property, string foldoutName, ref bool fold) {
- GUILayout.BeginHorizontal();
- fold = EditorGUILayout.Foldout(fold, new GUIContent(foldoutName), true);
- var arraySizeProp = property.FindPropertyRelative("Array.size");
- if(fold) {
- EditorGUILayout.LabelField("Size", GUILayout.Width(50));
- arraySizeProp.intValue = EditorGUILayout.IntField(arraySizeProp.intValue, GUILayout.Width(70));
- GUILayout.EndHorizontal();
- if(arraySizeProp.intValue < 1) {
- EditorGUILayout.LabelField("No entries", style);
- }
- for (var i = 0; i < arraySizeProp.intValue; i++) {
- GUILayout.BeginHorizontal();
- EditorGUILayout.LabelField("", GUILayout.Width(10));
- EditorGUILayout.LabelField(i.ToString(), GUILayout.Width(40));
- property.GetArrayElementAtIndex(i).stringValue = EditorGUILayout.TextField(property.GetArrayElementAtIndex(i).stringValue);
- GUILayout.EndHorizontal();
- }
- } else {
- EditorGUILayout.LabelField(arraySizeProp.intValue.ToString(), GUILayout.Width(68));
- GUILayout.EndHorizontal();
- }
- }
- public void DrawPropertyArray(SerializedProperty property, string foldoutName, ref bool fold) {
- GUILayout.BeginHorizontal();
- fold = EditorGUILayout.Foldout(fold, new GUIContent(foldoutName), true);
- var arraySizeProp = property.FindPropertyRelative("Array.size");
- if (fold) {
- EditorGUILayout.LabelField("Size", GUILayout.Width(50));
- arraySizeProp.intValue = EditorGUILayout.IntField(arraySizeProp.intValue, GUILayout.Width(70));
- GUILayout.EndHorizontal();
- if(arraySizeProp.intValue < 1) {
- EditorGUILayout.LabelField("No entries", style);
- }
- for (var i = 0; i < arraySizeProp.intValue; i++) {
- GUILayout.BeginHorizontal();
- EditorGUILayout.LabelField("", GUILayout.Width(10));
- EditorGUILayout.PropertyField(property.GetArrayElementAtIndex(i), new GUIContent(i.ToString()));
- GUILayout.EndHorizontal();
- }
- } else {
- EditorGUILayout.LabelField(arraySizeProp.intValue.ToString(), GUILayout.Width(68));
- GUILayout.EndHorizontal();
- }
- }
- public void addUserLoginFields() {
- GUILayout.BeginHorizontal();
- EditorGUILayout.LabelField("User:", GUILayout.Width(80));
- serializedObject.FindProperty("un").stringValue = EditorGUILayout.TextField(serializedObject.FindProperty("un").stringValue);
- GUILayout.EndHorizontal();
- GUILayout.BeginHorizontal();
- EditorGUILayout.LabelField("OAuth:", GUILayout.Width(80));
- showOauth = EditorGUILayout.Toggle(GUIContent.none, showOauth, GUILayout.Width(30));
- if(showOauth) {
- serializedObject.FindProperty("pw").stringValue = EditorGUILayout.TextField(serializedObject.FindProperty("pw").stringValue);
- } else {
- serializedObject.FindProperty("pw").stringValue = EditorGUILayout.PasswordField(serializedObject.FindProperty("pw").stringValue);
- }
- if(GUILayout.Button("TMI")) {
- Application.OpenURL("https://www.twitchapps.com/tmi/");
- }
- GUILayout.EndHorizontal();
- GUILayout.Space(4);
- EditorGUILayout.LabelField("Be careful! Checkbox reveals oauth field!", style);
- GUILayout.Space(10);
- }
- public void addChannelArrayFields() {
- DrawStringArray(chE, "Channel list:", ref showchE);
- }
- public void addCommandArrayFields() {
- DrawPropertyArray(coE, "Commands:", ref showcoE);
- }
- public void addDebugOption() {
- GUILayout.BeginHorizontal();
- serializedObject.FindProperty("logg").boolValue = EditorGUILayout.Toggle(serializedObject.FindProperty("logg").boolValue, GUILayout.Width(20));
- EditorGUILayout.LabelField(new GUIContent("Debug Log"), GUILayout.Width(100));
- EditorGUILayout.LabelField("Show every action from chat inside unity log.", style);
- GUILayout.EndHorizontal();
- GUILayout.Space(4);
- }
- public void addBoltTriggerConfig() {
- serializedObject.FindProperty("tctn").stringValue = EditorGUILayout.TextField("Bolt Trigger Name", serializedObject.FindProperty("tctn").stringValue);
- EditorGUILayout.PropertyField(serializedObject.FindProperty("boltFlowGameObject"), new GUIContent("Bolt Trigger Target"));
- EditorGUILayout.LabelField("Custom trigger name for Bolt\nRequires 1 parameter, wich contains\nthe MSGInfo.", style, GUILayout.Height(50));
- }
- public void addConfigArea() {
- isActive = EditorGUILayout.Foldout(isActive, "Configuration");
- EditorGUI.indentLevel = 1;
- if(isActive) {
- addDebugOption();
- addUserLoginFields();
- addChannelArrayFields();
- addCommandArrayFields();
- System.Type t1 = System.Type.GetType("Bolt.CustomEvent, Bolt.Flow.Runtime");
- if(t1 != null) {
- isActive2 = EditorGUILayout.Foldout(isActive2, "Bolt");
- if(isActive2) {
- addBoltTriggerConfig();
- }
- }
- }
- EditorGUI.indentLevel = 0;
- }
- public void addOnTheRunHandling() {
- GUI.enabled = true;if (!EditorApplication.isPlaying && !Application.isPlaying) {GUI.enabled = false;}
- GUILayout.Space(15);
- GUILayout.BeginHorizontal();
- if(th.isConnected) {
- if(GUILayout.Button("Disconnect")) {
- th.StopTwitchChat();
- msg = "";
- }
- } else {
- if(GUILayout.Button("Connect")) {
- th.StartTwitchChat();
- }
- GUI.enabled = true;if (!EditorApplication.isPlaying && !Application.isPlaying) {GUI.enabled = false;}
- }
- GUI.enabled = true;
- serializedObject.FindProperty("ac").boolValue = EditorGUILayout.ToggleLeft("Auto-Connect", serializedObject.FindProperty("ac").boolValue, GUILayout.Width(110));
- GUI.enabled = true;if (!EditorApplication.isPlaying && !Application.isPlaying) {GUI.enabled = false;}
- GUILayout.EndHorizontal();
- if (!EditorApplication.isPlaying && !Application.isPlaying) {
- EditorGUILayout.LabelField("On the run controls only available while running", style);
- }
- GUI.enabled = th.isConnected;
- GUILayout.Space(5);
- if(msgl == null || chE.arraySize > msgl.Length) {
- msgl = new string[chE.arraySize];
- }
- if(chE.arraySize == 1) {
- msg = GUILayout.TextField(msg);
- if (GUILayout.Button("Send", GUILayout.Width(60))) {
- th.SendMsg(msg);
- msg = "";
- }
- }else{
- showMultichat = EditorGUILayout.Foldout(showMultichat, "Channel List (Direct chat)");
- if(showMultichat) {
- GUILayout.BeginHorizontal();
- GUILayout.Label("All", GUILayout.Width(35));
- msg = GUILayout.TextField(msg);
- if (GUILayout.Button("Send", GUILayout.Width(60))) {
- th.SendMsg(msg);
- msg = "";
- }
- GUILayout.EndHorizontal();
- for(int chIndex = 0;chIndex < chE.arraySize;chIndex++) {
- string chName = chE.GetArrayElementAtIndex(chIndex).stringValue;
- GUILayout.BeginHorizontal();
- GUILayout.Label("", GUILayout.Width(4));
- GUILayout.Label(chName, GUILayout.Width(90));
- msgl[chIndex] = GUILayout.TextField(msgl[chIndex]);
- if (GUILayout.Button("Send", GUILayout.Width(60))) {
- th.SendMsg(msgl[chIndex], chIndex);
- msgl[chIndex] = "";
- }
- GUILayout.EndHorizontal();
- }
- }
- }
- GUI.enabled = true;
- }
- SerializedProperty chE = null;
- SerializedProperty coE = null;
- public override void OnInspectorGUI() {
- serializedObject.Update();
- chE = serializedObject.FindProperty("ch");
- coE = serializedObject.FindProperty("commands");
- th = (serializedObject.targetObject as TwitchChat).twitchBox;
- if(style == null) {
- style = new GUIStyle();
- style.alignment = TextAnchor.MiddleCenter;
- style.fontSize = 10;
- style.normal.textColor = Color.yellow;
- }
- if (EditorApplication.isPlaying && Application.isPlaying) {
- GUI.enabled = false;
- }
- if(th != null) {
- addConfigArea();
- addOnTheRunHandling();
- }
- if(serializedObject.hasModifiedProperties) {
- serializedObject.ApplyModifiedProperties();
- }
- }
- }
- public class Twitch {
- public string oauth;
- public string nickname;
- public string[] channels;
- public class MsgEvent : UnityEvent<MSGInfo> { }
- public MsgEvent messageRecievedEvent = new MsgEvent();
- [HideInInspector]
- public string server = "irc.twitch.tv";
- [HideInInspector]
- public int port = 6667;
- [HideInInspector]
- public bool logging = true;
- private string buffer = string.Empty;
- private bool stopThreads = false;
- private Queue<string> commandQueue = new Queue<string>();
- private List<string> recievedMsgs = new List<string>();
- private Thread inProc, outProc;
- private Regex r = new Regex("^(.*?)PRIVMSG #(.*?) :(.*)$");
- private Regex r2 = new Regex("^(.*?):");
- [HideInInspector]
- public bool isConnected = false;
- private void StartIRC() {
- // start connection
- TcpClient sock = new TcpClient();
- sock.Connect(server, port);
- if (!sock.Connected) {
- // connection failed
- UnityEngine.Debug.Log("Failed to connect!");
- return;
- }
- // get stream-handlers
- NetworkStream networkStream = sock.GetStream();
- TextReader input = (new StreamReader(networkStream)) as TextReader;
- StreamWriter output = new StreamWriter(networkStream);
- // do the login
- output.WriteLine("PASS " + oauth);
- output.WriteLine("NICK " + nickname.ToLower());
- // add tags-request
- output.WriteLine("CAP REQ :twitch.tv/tags");
- output.Flush();
- // start threats
- isConnected = true;
- outProc = new Thread(() => IRCOutputProcedure(output));
- outProc.Start();
- inProc = new Thread(() => IRCInputProcedure(input, networkStream));
- inProc.Start();
- }
- private void IRCInputProcedure(TextReader input, NetworkStream networkStream) {
- while (!stopThreads) {
- if (!networkStream.DataAvailable) {
- continue;
- }
- buffer = input.ReadLine();
- if (buffer.Contains("PRIVMSG #")) {
- lock (recievedMsgs) {
- recievedMsgs.Add(buffer);
- }
- }
- if (buffer.StartsWith("PING ")) {
- SendCommand(buffer.Replace("PING", "PONG"));
- }
- if (buffer.Split(' ')[1] == "001") {
- for(int i = 0;i < channels.Length;i++) {
- SendCommand("JOIN #" + channels[i]);
- }
- }
- }
- isConnected = false;
- }
- private void IRCOutputProcedure(TextWriter output) {
- Stopwatch stopWatch = new Stopwatch();
- stopWatch.Start();
- while (!stopThreads) {
- lock (commandQueue) {
- if (commandQueue.Count > 0) {
- if (stopWatch.ElapsedMilliseconds > 1750) {
- output.WriteLine(commandQueue.Peek());
- output.Flush();
- commandQueue.Dequeue();
- stopWatch.Reset();
- stopWatch.Start();
- }
- }
- }
- }
- isConnected = false;
- }
- public void SendCommand(string cmd) {
- lock (commandQueue) {
- commandQueue.Enqueue(cmd);
- }
- }
- public void SendMsg(string msg) {
- for(int i = 0;i < channels.Length;i++) {
- SendMsg(msg, i);
- }
- }
- public void SendMsg(string msg, int channelIndex) {
- lock (commandQueue) {
- commandQueue.Enqueue("PRIVMSG #" + channels[channelIndex] + " :" + msg);
- }
- MSGInfo mi = new MSGInfo(new string[] {"color=#ff0000", "display-name=" + nickname, "subscriber=0", "mod=0"}, msg, channels[channelIndex]);
- messageRecievedEvent.Invoke(mi);
- }
- public void StartTwitchChat() {
- stopThreads = false;
- StartIRC();
- }
- public void StopTwitchChat() {
- stopThreads = true;
- }
- public void Tick() {
- lock (recievedMsgs) {
- if (recievedMsgs.Count > 0) {
- for (int i = 0; i < recievedMsgs.Count; i++) {
- handleMsg(recievedMsgs[i]);
- }
- recievedMsgs.Clear();
- }
- }
- }
- private void handleMsg(string msg) {
- Match match = r.Match(msg);
- string infoBlock = match.Groups[1].Value;
- Match match2 = r2.Match(infoBlock);
- MSGInfo mi = new MSGInfo(match2.Groups[1].Value.Split(';'), match.Groups[3].Value, match.Groups[2].Value);
- messageRecievedEvent.Invoke(mi);
- }
- public class MSGInfo {
- public string channel {get; private set;}
- public string name {get; private set;}
- public Color color {get; private set;}
- public bool isSubscriber {get; private set;}
- public bool isModerator {get; private set;}
- public string message {get; private set;}
- public int bits {get; private set;}
- public bool isRaid {get; private set;}
- public string raidName {get; private set;}
- public int raidSize {get; private set;}
- public bool isSub {get; private set;}
- public bool isResub {get; private set;}
- public int subMonths {get; private set;}
- public MSGInfo(string[] data, string txt, string chn) {
- channel = chn;
- message = txt;
- string colorData = "";
- foreach(string j in data) {
- string[] v = j.Split('=');
- if(v[0] == "display-name") {
- name = v[1];
- } else if(v[0] == "color") {
- colorData = v[1];
- } else if(v[0] == "subscriber") {
- isSubscriber = (v[1] == "1");
- } else if(v[0] == "mod") {
- isModerator = (v[1] == "1");
- } else if(v[0] == "bits") {
- bits = int.Parse(v[1]);
- } else if(v[0] == "msg-param-displayName") {
- raidName = v[1];
- } else if(v[0] == "msg-param-viewerCount") {
- raidSize = int.Parse(v[1]);
- } else if(v[0] == "msg-id") {
- if(v[1] == "raid") {
- isRaid = true;
- } else if (v[1] == "sub") {
- isSub = true;
- } else if (v[1] == "resub") {
- isResub = true;
- }
- } else if(v[0] == "msg-param-cumulative-months") {
- subMonths = int.Parse(v[1]);
- }
- }
- color = cfu(name);
- if(colorData != "") {
- Color genColor = color;
- if(ColorUtility.TryParseHtmlString(colorData, out genColor)) {
- color = genColor;
- }
- }
- }
- private Color cfu(string username) {
- Random.InitState(username.Length + (int)username[0] + (int)username[username.Length - 1]);
- return new Color(Random.Range(0.25f, 0.55f), Random.Range(0.20f, 0.55f), Random.Range(0.25f, 0.55f));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement