1 /++ 2 + 3 +/ 4 module virc.numerics.sasl; 5 6 import std.algorithm : among; 7 8 import virc.numerics.definitions; 9 10 /++ 11 + 12 + Format is `900 <nick> <nick>!<ident>@<host> <account> :You are now logged in as <user>` 13 +/ 14 //900 <nick> <nick>!<ident>@<host> <account> :You are now logged in as <user> 15 auto parseNumeric(Numeric numeric : Numeric.RPL_LOGGEDIN, T)(T input) { 16 import std.typecons : Nullable; 17 import virc.common : User; 18 import virc.usermask : UserMask; 19 Nullable!User user; 20 if (input.empty) { 21 return user; 22 } 23 input.popFront(); 24 if (input.empty) { 25 return user.init; 26 } 27 user = User(input.front); 28 input.popFront(); 29 if (input.empty) { 30 return user.init; 31 } 32 user.get.account = input.front; 33 return user; 34 } 35 /// 36 @safe pure nothrow @nogc unittest { //Numeric.RPL_LOGGEDIN 37 import std.range : only, takeNone; 38 { 39 immutable logon = parseNumeric!(Numeric.RPL_LOGGEDIN)(only("test", "someone!someIdent@example.net", "some_account", "Well hello there")); 40 assert(logon.get.mask.nickname == "someone"); 41 assert(logon.get.mask.ident == "someIdent"); 42 assert(logon.get.mask.host == "example.net"); 43 assert(logon.get.account == "some_account"); 44 } 45 { 46 immutable logon = parseNumeric!(Numeric.RPL_LOGGEDIN)(takeNone(only(""))); 47 assert(logon.isNull); 48 } 49 { 50 immutable logon = parseNumeric!(Numeric.RPL_LOGGEDIN)(only("test")); 51 assert(logon.isNull); 52 } 53 { 54 immutable logon = parseNumeric!(Numeric.RPL_LOGGEDIN)(only("test", "someone!someIdent@example.net")); 55 assert(logon.isNull); 56 } 57 } 58 /++ 59 + 60 + Format is `901 <nick> <nick>!<ident>@<host> :You are now logged out` 61 +/ 62 auto parseNumeric(Numeric numeric : Numeric.RPL_LOGGEDOUT, T)(T input) { 63 import std.typecons : Nullable; 64 import virc.common : User; 65 import virc.usermask : UserMask; 66 Nullable!User user; 67 if (input.empty) { 68 return user; 69 } 70 input.popFront(); 71 if (input.empty) { 72 return user.init; 73 } 74 user = User(input.front); 75 return user; 76 } 77 /// 78 @safe pure nothrow @nogc unittest { //Numeric.RPL_LOGGEDOUT 79 import std.range : only, takeNone; 80 { 81 immutable logon = parseNumeric!(Numeric.RPL_LOGGEDOUT)(only("test", "someone!someIdent@example.net", "Well hello there")); 82 assert(logon.get.mask.nickname == "someone"); 83 assert(logon.get.mask.ident == "someIdent"); 84 assert(logon.get.mask.host == "example.net"); 85 assert(logon.get.account.isNull); 86 } 87 { 88 immutable logon = parseNumeric!(Numeric.RPL_LOGGEDOUT)(takeNone(only(""))); 89 assert(logon.isNull); 90 } 91 { 92 immutable logon = parseNumeric!(Numeric.RPL_LOGGEDOUT)(only("test")); 93 assert(logon.isNull); 94 } 95 } 96 /++ 97 + SASL numerics that don't have any parsable information. 98 + 99 + This includes 902, 903, 904, 905, 906 and 907. 100 +/ 101 void parseNumeric(Numeric numeric, T)(T) if (numeric.among(Numeric.ERR_NICKLOCKED, Numeric.RPL_SASLSUCCESS, Numeric.ERR_SASLFAIL, Numeric.ERR_SASLTOOLONG, Numeric.ERR_SASLABORTED, Numeric.ERR_SASLALREADY)) { 102 } 103 /// 104 @safe pure nothrow @nogc unittest { //Numeric.RPL_LOGGEDOUT 105 import std.range : only; 106 { 107 parseNumeric!(Numeric.ERR_NICKLOCKED)(only("test", "You must use a nick assigned to you")); 108 } 109 { 110 parseNumeric!(Numeric.RPL_SASLSUCCESS)(only("test", "SASL authentication successful")); 111 } 112 { 113 parseNumeric!(Numeric.ERR_SASLFAIL)(only("test", "SASL authentication failed")); 114 } 115 { 116 parseNumeric!(Numeric.ERR_SASLTOOLONG)(only("test", "SASL message too long")); 117 } 118 { 119 parseNumeric!(Numeric.ERR_SASLABORTED)(only("test", "SASL authentication aborted")); 120 } 121 { 122 parseNumeric!(Numeric.ERR_SASLALREADY)(only("test", "You have already authenticated using SASL")); 123 } 124 } 125 126 /++ 127 + RPL_SASLMECHS. This is sent in response to a request for a mechanism the 128 + server does not support, and will list any mechanisms that are available. 129 + 130 + Format is `908 <nick> <mechanisms> :are available SASL mechanisms` 131 +/ 132 auto parseNumeric(Numeric numeric : Numeric.RPL_SASLMECHS, T)(T input) { 133 import std.algorithm : splitter; 134 import std.typecons : nullable; 135 if (!input.empty) { 136 input.popFront(); 137 } 138 if (!input.empty) { 139 return nullable(input.front.splitter(",")); 140 } else { 141 return typeof(return).init; 142 } 143 } 144 /// 145 @safe pure nothrow @nogc unittest { //Numeric.RPL_SASLMECHS 146 import std.algorithm.searching : canFind; 147 import std.range : only, takeNone; 148 { 149 auto logon = parseNumeric!(Numeric.RPL_SASLMECHS)(only("test", "EXTERNAL,PLAIN", "Well hello there")); 150 assert(logon.get.canFind("EXTERNAL")); 151 assert(logon.get.canFind("PLAIN")); 152 } 153 { 154 immutable logon = parseNumeric!(Numeric.RPL_SASLMECHS)(takeNone(only(""))); 155 assert(logon.isNull); 156 } 157 { 158 immutable logon = parseNumeric!(Numeric.RPL_SASLMECHS)(only("test")); 159 assert(logon.isNull); 160 } 161 }