IRC parsing, tokenization, and state handling in C#
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.Linq;
5
6// ReSharper disable InconsistentNaming
7// ReSharper disable StringLiteralTypo
8
9namespace IRCStates
10{
11 public class ISupport
12 {
13 public Dictionary<string, string> Raw { get; } = new Dictionary<string, string>();
14 public string Network { get; private set; }
15 public ISupportChanModes ChanModes { get; private set; } = new ISupportChanModes("b,k,l,imnpst");
16 public ISupportPrefix Prefix { get; private set; } = new ISupportPrefix("(ov)@+");
17 public int? Modes { get; private set; } = 3;
18 public Casemap.CaseMapping CaseMapping { get; private set; } = Casemap.CaseMapping.Rfc1459;
19 public List<string> ChanTypes { get; private set; } = new List<string> { "#" };
20 public List<string> StatusMsg { get; private set; } = new List<string>();
21 public string CallerId { get; private set; }
22 public string Excepts { get; private set; }
23 public string Invex { get; private set; }
24 public int? Monitor { get; private set; }
25 public int? Watch { get; private set; }
26 public bool Whox { get; private set; }
27
28 /// <summary>
29 /// Parse the ISupport values from the line's parameters
30 /// </summary>
31 /// <param name="tokens"></param>
32 public void Parse(IEnumerable<string> tokens)
33 {
34 if (tokens == null) return;
35
36 // remove first and last
37 tokens = tokens.Skip(1).SkipLast(1);
38
39 foreach (var token in tokens)
40 {
41 var split = token.Split('=', 2);
42 var key = split[0];
43
44 var value = string.Empty;
45 if (split.Length > 1)
46 {
47 value = split[1];
48 Raw[key] = value;
49 }
50
51 switch (split[0])
52 {
53 case "NETWORK":
54 Network = value;
55 break;
56 case "CHANMODES":
57 ChanModes = new ISupportChanModes(value);
58 break;
59 case "PREFIX":
60 Prefix = new ISupportPrefix(value);
61 break;
62 case "STATUSMSG":
63 StatusMsg = new List<string>();
64 StatusMsg.AddRange(value.Select(c => c.ToString(CultureInfo.InvariantCulture)));
65 break;
66 case "MODES":
67 if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var modes))
68 Modes = modes;
69 else
70 Modes = -1;
71 break;
72 case "MONITOR":
73 if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var monitor))
74 Monitor = monitor;
75 else
76 Monitor = -1;
77 break;
78 case "WATCH":
79 if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var watch))
80 Watch = watch;
81 else
82 Watch = -1;
83 break;
84 case "CASEMAPPING":
85 if (Enum.TryParse(value, true, out Casemap.CaseMapping caseMapping)) CaseMapping = caseMapping;
86 break;
87 case "CHANTYPES":
88 ChanTypes = new List<string>();
89 ChanTypes.AddRange(value.Select(c => c.ToString(CultureInfo.InvariantCulture)));
90 break;
91 case "CALLERID":
92 CallerId = string.IsNullOrEmpty(value) ? "g" : value;
93 break;
94 case "EXCEPTS":
95 Excepts = string.IsNullOrEmpty(value) ? "e" : value;
96 break;
97 case "INVEX":
98 Invex = string.IsNullOrEmpty(value) ? "I" : value;
99 break;
100 case "WHOX":
101 Whox = true;
102 break;
103 }
104 }
105 }
106 }
107}