diff --git a/README.md b/README.md index ed07c15..83dedb5 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,10 @@ You can take a look at the `Client` API documentation on [DUB](https://birchwood ## Compatibiloty -- [ ] rfc1459 - * Should be more or less stable in supporting this standard +- [x] [rfc1459](https://www.rfc-editor.org/rfc/rfc1459) + * Supports all the numeric codes +- [x] [rfc2812](https://www.rfc-editor.org/rfc/rfc2812) + * Supports all the numeric codes More standards will be added within the next month or so, mostly relating to new response codes that just need to be added. diff --git a/source/birchwood/client/client.d b/source/birchwood/client/client.d index 74fd7b1..403ef5a 100644 --- a/source/birchwood/client/client.d +++ b/source/birchwood/client/client.d @@ -139,8 +139,28 @@ public class Client : Thread if(commandReply.getReplyType() == ReplyType.RPL_ISUPPORT) { - string params = commandReply.getParams(); - logger.log("RPL_ISUPPORT_PARAMS:\n\n"~params); + // TODO: Testing code was here + // logger.log(); + // logger.log("<<<>>>"); + + // logger.log("Take a look:\n\n"~commandReply.getParams()); + + // logger.log("And here is key-value pairs: ", commandReply.getKVPairs()); + // logger.log("And here is array: ", commandReply.getPairs()); + + // // TODO: DLog bug, this prints nothing + // logger.log("And here is trailing: ", commandReply.getTrailing()); + + // import std.stdio; + // writeln("Trailer: "~commandReply.getTrailing()); + + // writeln(cast(ubyte[])commandReply.getTrailing()); + + // logger.log("<<<>>>"); + // logger.log(); + + + } } @@ -610,6 +630,14 @@ public class Client : Thread if(cmp(command, "PRIVMSG") == 0) { + // TODO: We will need a non kv pair thing as well to see (in the + // ... case of channel messages) the singular pair + // ... name. + // + // Then our message will be in `getTrailing()` + logger.debug_("PrivMessage parser (kv-pairs): ", ircMessage.getKVPairs()); + logger.debug_("PrivMessage parser (trailing): ", ircMessage.getTrailing()); + /* Split up into (channel/nick) and (message)*/ long firstSpaceIdx = indexOf(params, " "); //TODO: validity check; string chanNick = params[0..firstSpaceIdx]; diff --git a/source/birchwood/config/conninfo.d b/source/birchwood/config/conninfo.d index ce2b9be..2eebd76 100644 --- a/source/birchwood/config/conninfo.d +++ b/source/birchwood/config/conninfo.d @@ -1,8 +1,15 @@ +/** + * COnfiguration-related types + */ module birchwood.config.conninfo; import std.socket : SocketException, Address, getAddress; import birchwood.client.exceptions : BirchwoodException; +/** + * Represents the connection details for a server + * to connect to + */ public struct ConnectionInfo { /* Server address information */ @@ -36,16 +43,32 @@ public struct ConnectionInfo return this.bulkReadSize; } + /** + * Get the address of the endpoint server + * + * Returns: the server's address + */ public Address getAddr() { return addrInfo; } + /** + * Get the chosen fake lag + * + * Returns: the fake lag in seconds + */ public ulong getFakeLag() { return fakeLag; } + /** + * Sets the fake lag in seconds + * + * Params: + * fakeLag = the fake lag to use + */ public void setFakeLag(ulong fakeLag) { this.fakeLag = fakeLag; diff --git a/source/birchwood/protocol/messages.d b/source/birchwood/protocol/messages.d index 590335c..1e29dc1 100644 --- a/source/birchwood/protocol/messages.d +++ b/source/birchwood/protocol/messages.d @@ -138,6 +138,9 @@ public final class Message logger.log(e); } } + + /* Parse the parameters into key-value pairs (if any) and trailing text (if any) */ + parameterParse(); } /* TODO: Implement encoder function */ @@ -276,6 +279,192 @@ public final class Message return params; } + /** + * Retrieves the trailing text in the paramaters + * (if any) + * + * Returns: the trailing text + */ + public string getTrailing() + { + return ppTrailing; + } + + /** + * Returns the parameters excluding the trailing text + * which are seperated by spaces but only those + * which are key-value pairs + * + * Returns: the key-value pair parameters + */ + public string[string] getKVPairs() + { + return ppKVPairs; + } + + /** + * Returns the parameters excluding the trailing text + * which are seperated by spaces + * + * Returns: the parameters + */ + public string[] getPairs() + { + return ppPairs; + } + + private string ppTrailing; + private string[string] ppKVPairs; + private string[] ppPairs; + + + version(unittest) + { + import std.stdio; + } + + unittest + { + string testInput = "A:=1 A=2 :Hello this is text"; + writeln("Input: ", testInput); + + bool hasTrailer; + string[] splitted = splitting(testInput, hasTrailer); + writeln("Input (split): ", splitted); + + + + assert(cmp(splitted[0], "A:=1") == 0); + assert(cmp(splitted[1], "A=2") == 0); + + /* Trailer test */ + assert(hasTrailer); + assert(cmp(splitted[2], "Hello this is text") == 0); + } + + unittest + { + string testInput = ":Hello this is text"; + bool hasTrailer; + string[] splitted = splitting(testInput, hasTrailer); + + /* Trailer test */ + assert(hasTrailer); + assert(cmp(splitted[0], "Hello this is text") == 0); + } + + /** + * Imagine: `A:=1 A=2 :Hello` + * + * Params: + * input = + * Returns: + */ + private static string[] splitting(string input, ref bool hasTrailer) + { + string[] splits; + + bool trailingMode; + string buildUp; + for(ulong idx = 0; idx < input.length; idx++) + { + /* Get current character */ + char curCHar = input[idx]; + + + if(trailingMode) + { + buildUp ~= curCHar; + continue; + } + + if(buildUp.length == 0) + { + if(curCHar == ':') + { + trailingMode = true; + continue; + } + } + + + if(curCHar == ' ') + { + /* Flush */ + splits ~= buildUp; + buildUp = ""; + } + else + { + buildUp ~= curCHar; + } + } + + if(buildUp.length) + { + splits ~= buildUp; + } + + hasTrailer = trailingMode; + + return splits; + } + + /** + * NOTE: This needs more work with trailing support + * we must make sure we only look for lastInex of `:` + * where it is first cyaracter after space but NOT within + * an active parameter + */ + private void parameterParse() + { + /* Only parse if there are params */ + if(params.length) + { + /* Trailing text */ + string trailing; + + /* Split the `` */ + bool hasTrailer; + string[] paramsSplit = splitting(params, hasTrailer); + + logger.debug_("ParamsSPlit direct:", paramsSplit); + + + + /* Extract the trailer as the last item in the array (if it exists) */ + if(hasTrailer) + { + trailing = paramsSplit[paramsSplit.length-1]; + + /* Remove it from the parameters */ + paramsSplit = paramsSplit[0..$-1]; + + logger.debug_("GOt railer ", trailing); + } + + ppPairs = paramsSplit; + + + /* Generate the key-value pairs */ + foreach(string pair; paramsSplit) + { + /* Only do this if we have an `=` in the current pair */ + if(indexOf(pair, "=") > -1) + { + string key = split(pair, "=")[0]; + string value = split(pair, "=")[1]; + ppKVPairs[key] = value; + } + } + + /* Save the trailing */ + ppTrailing = trailing; + + logger.debug_("ppTrailing: ", ppTrailing); + } + } + /** * Returns whether or not this message was * a numeric response