1 /++ 2 + 3 +/ 4 module virc.numerics.rfc2812; 5 6 import std.range : ElementType; 7 8 import virc.numerics.definitions; 9 /++ 10 + 004 RPL_MYINFO response. 11 +/ 12 struct MyInfo { 13 import virc.common : User; 14 import virc.numerics.magicparser : Optional; 15 User me; 16 ///Server name. Typically a valid hostname, but not necessarily. 17 string name; 18 ///Version string of the software run by server. 19 string version_; 20 ///Modes that can be set on users. 21 string userModes; 22 ///Modes that can be set on channels. 23 string channelModes; 24 /++ 25 + Modes that can be set on channels that have parameters. If non-empty, it is 26 + assumed that the modes in channelModes do not have parameters. 27 +/ 28 @Optional string channelModesWithParams; 29 /++ 30 + Modes that can be set on users that have parameters. If non-empty, it is 31 + assumed that the modes in userModes do not have parameters. 32 +/ 33 @Optional string userModesWithParams; 34 ///Modes that can be set on servers. 35 @Optional string serverModes; 36 /++ 37 + Modes that can be set on servers that have parameters. If non-empty, it is 38 + assumed that the modes in serverModes do not have parameters. 39 +/ 40 @Optional string serverModesWithParams; 41 } 42 /++ 43 + 44 +/ 45 //004 <username> <server_name> <version> <user_modes> <chan_modes> [<channel_modes_with_params> <user_modes_with_params> <server_modes> <server_modes_with_params>] 46 auto parseNumeric(Numeric numeric : Numeric.RPL_MYINFO, T)(T input) { 47 import virc.numerics.magicparser : autoParse; 48 return autoParse!MyInfo(input); 49 } 50 /// 51 @safe pure nothrow @nogc unittest { //Numeric.RPL_MYINFO 52 import std.range : only; 53 { 54 immutable info = parseNumeric!(Numeric.RPL_MYINFO)(only("someone", "localhost", "IRCd-2.0", "BGHIRSWcdgikorswx", "ABCDFGIJKLMNOPQRSTYabcefghijklmnopqrstuvz", "FIJLYabefghjkloqv")); 55 assert(info.get.name == "localhost"); 56 assert(info.get.version_ == "IRCd-2.0"); 57 assert(info.get.userModes == "BGHIRSWcdgikorswx"); 58 assert(info.get.userModesWithParams == ""); 59 assert(info.get.channelModes == "ABCDFGIJKLMNOPQRSTYabcefghijklmnopqrstuvz"); 60 assert(info.get.channelModesWithParams == "FIJLYabefghjkloqv"); 61 assert(info.get.serverModes == ""); 62 assert(info.get.serverModesWithParams == ""); 63 } 64 { 65 immutable info = parseNumeric!(Numeric.RPL_MYINFO)(only("someone", "localhost", "IRCd-2.0", "BGHIRSWcdgikorswx", "ABCDFGIJKLMNOPQRSTYabcefghijklmnopqrstuvz", "FIJLYabefghjkloqv", "q", "w", "x")); 66 assert(info.get.name == "localhost"); 67 assert(info.get.version_ == "IRCd-2.0"); 68 assert(info.get.userModes == "BGHIRSWcdgikorswx"); 69 assert(info.get.userModesWithParams == "q"); 70 assert(info.get.channelModes == "ABCDFGIJKLMNOPQRSTYabcefghijklmnopqrstuvz"); 71 assert(info.get.channelModesWithParams == "FIJLYabefghjkloqv"); 72 assert(info.get.serverModes == "w"); 73 assert(info.get.serverModesWithParams == "x"); 74 } 75 { 76 immutable info = parseNumeric!(Numeric.RPL_MYINFO)(only("someone", "localhost", "IRCd-2.0", "BGHIRSWcdgikorswx ABCDFGIJKLMNOPQRSTYabcefghijklmnopqrstuvz FIJLYabefghjkloqv")); 77 assert(info.isNull); 78 } 79 } 80 struct RPL_TraceService { 81 import virc.common : User; 82 User me; 83 string service; 84 string class_; 85 string name; 86 string type; 87 string activeType; 88 } 89 /++ 90 + Parser for RPL_TRACESERVICE. 91 + 92 + Format is `207 <client> Service <class> <name> <type> <active_type>` 93 +/ 94 auto parseNumeric(Numeric numeric : Numeric.RPL_TRACESERVICE, T)(T input) if (is(ElementType!T : string)) { 95 import virc.numerics.magicparser : autoParse; 96 return autoParse!RPL_TraceService(input); 97 } 98 /// 99 @safe pure @nogc nothrow unittest { 100 import std.range : only, takeNone; 101 //Need real world examples... No idea what these will really look like 102 { 103 immutable trace = parseNumeric!(Numeric.RPL_TRACESERVICE)(only("someone", "Service", "classy", "fred", "something", "no_idea")); 104 assert(trace.get.class_ == "classy"); 105 assert(trace.get.name == "fred"); 106 assert(trace.get.type == "something"); 107 assert(trace.get.activeType == "no_idea"); 108 } 109 { 110 immutable badTrace = parseNumeric!(Numeric.RPL_TRACESERVICE)(takeNone!(string[])); 111 assert(badTrace.isNull); 112 } 113 { 114 immutable badTrace = parseNumeric!(Numeric.RPL_TRACESERVICE)(only("someone")); 115 assert(badTrace.isNull); 116 } 117 { 118 immutable badTrace = parseNumeric!(Numeric.RPL_TRACESERVICE)(only("someone", "Service")); 119 assert(badTrace.isNull); 120 } 121 { 122 immutable badTrace = parseNumeric!(Numeric.RPL_TRACESERVICE)(only("someone", "Service", "classy")); 123 assert(badTrace.isNull); 124 } 125 { 126 immutable badTrace = parseNumeric!(Numeric.RPL_TRACESERVICE)(only("someone", "Service", "classy", "fred")); 127 assert(badTrace.isNull); 128 } 129 { 130 immutable badTrace = parseNumeric!(Numeric.RPL_TRACESERVICE)(only("someone", "Service", "classy", "fred", "something")); 131 assert(badTrace.isNull); 132 } 133 } 134 struct RPL_TraceClass { 135 import virc.common : User; 136 User me; 137 string classConstant; 138 string class_; 139 string count; 140 } 141 /++ 142 + Parser for RPL_TRACECLASS. 143 + 144 + Format is `209 <client> Class <class> <count>` 145 +/ 146 auto parseNumeric(Numeric numeric : Numeric.RPL_TRACECLASS, T)(T input) { 147 import virc.numerics.magicparser : autoParse; 148 return autoParse!RPL_TraceClass(input); 149 } 150 /// 151 @safe pure unittest { 152 import std.range : only, takeNone; 153 //Need real world examples... No idea what these will really look like 154 { 155 immutable trace = parseNumeric!(Numeric.RPL_TRACECLASS)(only("someone", "CLASS", "classy", "238525813")); 156 assert(trace.get.class_ == "classy"); 157 assert(trace.get.count == "238525813"); 158 } 159 { 160 immutable badTrace = parseNumeric!(Numeric.RPL_TRACECLASS)(takeNone!(string[])); 161 assert(badTrace.isNull); 162 } 163 { 164 immutable badTrace = parseNumeric!(Numeric.RPL_TRACECLASS)(only("someone")); 165 assert(badTrace.isNull); 166 } 167 { 168 immutable badTrace = parseNumeric!(Numeric.RPL_TRACECLASS)(only("someone", "Class")); 169 assert(badTrace.isNull); 170 } 171 { 172 immutable badTrace = parseNumeric!(Numeric.RPL_TRACECLASS)(only("someone", "Class", "classy")); 173 assert(badTrace.isNull); 174 } 175 }