IRC parsing, tokenization, and state handling in C#
at ircrobotsv2 63 lines 1.8 kB view raw
1using System.Net.Sockets; 2using IRCTokens; 3 4// ReSharper disable StringLiteralTypo 5 6namespace Tokens; 7 8public class Client 9{ 10 private readonly byte[] _bytes = new byte[1024]; 11 private readonly StatefulDecoder _decoder = new(); 12 private readonly StatefulEncoder _encoder = new(); 13 private readonly Socket _socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 14 15 public void Start() 16 { 17 _socket.Connect("127.0.0.1", 6667); 18 while (!_socket.Connected) 19 { 20 Thread.Sleep(1000); 21 } 22 23 Send(new Line("NICK", "tokensbot")); 24 Send(new Line("USER", "tokensbot", "0", "*", "real name")); 25 26 while (true) 27 { 28 var bytesReceived = _socket.Receive(_bytes); 29 30 if (bytesReceived == 0) 31 { 32 Console.WriteLine("! disconnected"); 33 _socket.Shutdown(SocketShutdown.Both); 34 _socket.Close(); 35 break; 36 } 37 38 var lines = _decoder.Push(_bytes, bytesReceived); 39 40 foreach (var line in lines) 41 { 42 Console.WriteLine($"< {line.Format()}"); 43 44 switch (line.Command) 45 { 46 case "PING": Send(new Line("PONG", line.Params[0])); break; 47 case "001": Send(new Line("JOIN", "#irctokens")); break; 48 case "PRIVMSG": Send(new Line("PRIVMSG", line.Params[0], "hello there")); break; 49 } 50 } 51 } 52 } 53 54 private void Send(Line line) 55 { 56 Console.WriteLine($"> {line.Format()}"); 57 _encoder.Push(line); 58 while (_encoder.PendingBytes.Length > 0) 59 { 60 _encoder.Pop(_socket.Send(_encoder.PendingBytes, SocketFlags.None)); 61 } 62 } 63}