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