private void InputThread(TextReader inputStream, NetworkStream networkStream) { while (enabled) { if (!networkStream.DataAvailable) { continue; } buffer = inputStream.ReadLine(); if (buffer.Contains("PRIVMSG #")) { lock (chatBuffer) { string username = buffer.Split('!')[1].Split('@')[0]; string message = buffer.Substring(buffer.IndexOf("PRIVMSG #") + "PRIVMSG #".Length + channelName.Length + 2); string color = "#" + new System.Random(username.GetHashCode()).Next((int)Math.Pow(256, 3) - 1).ToString("X6"); chatBuffer.Add(new ChatMessage(username, message, color)); } } if (buffer.StartsWith("PING ")) { SendTwitchCommand(buffer.Replace("PING", "PONG")); } if (buffer.Split(' ')[1] == "001") { SendTwitchCommand("JOIN #" + channelName); } OnRawMessageReceived?.Invoke(buffer); } }
/// <summary> /// Callback used by StreamReader when a read finishes /// </summary> /// <param name="task"></param> private void OnAsyncRead(Task <String> task) { try { if (task.Exception == null && task.Result != null) { lock (streamReader.BaseStream) { streamReader.ReadLineAsync().ContinueWith(OnAsyncRead); } } else if (task.Result == null) { throw new System.IO.EndOfStreamException(); } else { throw task.Exception; } if (OnRawMessageReceived != null) { foreach (var d in OnRawMessageReceived.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(this, task.Result)); } } } catch (Exception e) { Exception = e; if (OnException != null) { foreach (var d in OnException.GetInvocationList()) { var task2 = Task.Run(() => d.DynamicInvoke(this, e)); } } } finally { } }
/// <summary> /// Receiver task, receives messages from server, handles joining intial join to channels, if the server responses with a 004 (which is a welcome message, meaning it has succesfully connected) /// Handles PRIVMSG messages /// Handles PING messages /// Handles JOIN messages /// Handles QUIT messages (though it's not yet possible to determine which channels these users have left /// Handles 353 messages (Users list per channel) /// Handles 366 messages (Finished user list per channel) /// Handles DCC SEND messages /// </summary> private void ReceiveChat() { try { OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("STARTING LISTENER!", "IRC RECEIVER")); Dictionary <string, List <string> > usersPerChannelDictionary = new Dictionary <string, List <string> >(); _IsClientRunning = true; _isConnectionEstablised = true; while (!_stopTask) { string ircData = _streamReader.ReadLine(); OnRawMessageReceived?.Invoke(this, new IrcRawReceivedEventArgs(ircData)); if (ircData.Contains("PING")) { string pingID = ircData.Split(':')[1]; WriteIrc("PONG :" + pingID); } if (ircData.Contains("PRIVMSG")) { //:[email protected] PRIVMSG #RareIRC :wassup try { string messageAndChannel = ircData.Split(new string[] { "PRIVMSG" }, StringSplitOptions.None)[1]; string message = messageAndChannel.Split(':')[1].Trim(); string channel = messageAndChannel.Split(':')[0].Trim(); string user = ircData.Split(new string[] { "PRIVMSG" }, StringSplitOptions.None)[0].Split('!')[0].Substring(1); channel = channel.Replace("=", string.Empty); OnMessageReceived?.Invoke(this, new IrcReceivedEventArgs(message, user, channel)); } catch (Exception ex) { OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (PRIVMSG)")); } } else if (ircData.Contains("JOIN")) { //RAW: :[email protected] JOIN :#NIBL try { string channel = ircData.Split(new string[] { "JOIN" }, StringSplitOptions.None)[1].Split(':')[1]; string userThatJoined = ircData.Split(new string[] { "JOIN" }, StringSplitOptions.None)[0].Split(':')[1].Split('!')[0]; OnMessageReceived?.Invoke(this, new IrcReceivedEventArgs("User Joined", userThatJoined, channel)); } catch (Exception ex) { OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (JOIN)")); } } else if (ircData.Contains("QUIT")) { //RAW: :[email protected] QUIT try { string user = ircData.Split(new string[] { "QUIT" }, StringSplitOptions.None)[0].Split('!')[0].Substring(1); OnMessageReceived?.Invoke(this, new IrcReceivedEventArgs("User Left", user, "unknown")); } catch (Exception ex) { OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (JOIN)")); }; } if (ircData.Contains("DCC SEND") && ircData.Contains(_NewUsername)) { _dccClient.StartDownloader(ircData, _downloadDirectory, _bot, _packNumber, this); } //RareIRC_Client = #weebirc :RareIRC_Client if (ircData.Contains(" 353 ")) { //:irc.x2x.cc 353 RoflHerp = #RareIRC :RoflHerp @MrRareie try { string channel = ircData.Split(new[] { " " + _NewUsername + " =" }, StringSplitOptions.None)[1].Split(':')[0].Replace(" ", string.Empty); string userListFullString = ircData.Split(new[] { " " + _NewUsername + " =" }, StringSplitOptions.None)[1].Split(':')[1]; if (!channel.Contains(_NewUsername) && !channel.Contains("=")) { string[] users = userListFullString.Split(' '); if (usersPerChannelDictionary.ContainsKey(channel)) { usersPerChannelDictionary.TryGetValue(channel, out var currentUsers); foreach (string name in users) { if (!name.Contains(_NewUsername)) { currentUsers.Add(name); } } usersPerChannelDictionary[channel.Trim()] = currentUsers; } else { List <string> currentUsers = new List <string>(); foreach (string name in users) { currentUsers.Add(name); } usersPerChannelDictionary.Add(channel.Trim(), currentUsers); } } } catch (Exception ex) { OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs(ex.ToString(), "MESSAGE RECEIVED ERROR (USERLIST)")); } } if (ircData.ToLower().Contains(" 366 ")) { OnUserListReceived?.Invoke(this, new IrcUserListReceivedEventArgs(usersPerChannelDictionary)); usersPerChannelDictionary.Clear(); } Thread.Sleep(1); } OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("RECEIVER HAS STOPPED RUNNING", "MESSAGE RECEIVER")); QuitConnect(); _stopTask = false; } catch (Exception ioex) { OnDebugMessage?.Invoke(this, new IrcDebugMessageEventArgs("LOST CONNECTION: " + ioex.ToString(), "MESSAGE RECEIVER")); if (_isConnectionEstablised) { _stopTask = false; QuitConnect(); } } _IsClientRunning = false; }