Ejemplo n.º 1
0
        public IRCMessage(byte[] msg)
        {
            Time       = DateTime.UtcNow;
            Raw        = Encoding.UTF8.GetString(msg);
            RawTrimmed = Encoding.UTF8.GetString(msg).Trim();
            Parsed     = false;

            Prefix        = string.Empty;
            Server        = string.Empty;
            Nick          = string.Empty;
            User          = string.Empty;
            Host          = string.Empty;
            Command       = string.Empty;
            RawParameters = string.Empty;
            Parameters    = new string[0];

            #region Actual Parsing
            if (RawTrimmed.Length > 0)
            {
                var subIdx = 0; // If we find a prefix, we shift this value to the end of the prefix
                // Prefix Section
                #region Prefix Parsing (Optional in Message Format)
                if (RawTrimmed.StartsWith(':') || RawTrimmed.Contains('!') || RawTrimmed.Contains('@')) // Contains prefix if the 1st char is :
                {                                                                                       // (Sometimes twitch replies without the ':' in which case we search for other giveaways that it is a prefix e.g. '!' / '@')
                                                                                                        // [':' <prefix> <SPACE> ]
                                                                                                        // < prefix >   ::= < servername > | < nick > ['!' < user > ]['@' < host > ]

                    subIdx = RawTrimmed.IndexOf(' ');                                                   // searches for the <SPACE>

                    if (RawTrimmed.StartsWith(':'))
                    {
                        Prefix = RawTrimmed.Substring(1, subIdx - 1); // Omit ':' and ' '
                    }
                    else
                    {
                        Prefix = RawTrimmed.Substring(0, subIdx); // In the event we detect a prefix without the :
                    }

                    var excIdx = Prefix.IndexOf('!'); // Finds '!'
                    var atIdx  = Prefix.IndexOf('@'); // Finds '@', use this info to determine if its a nickname or servername (?, unsure about this)

                    if (excIdx == -1 && atIdx == -1)
                    {
                        Server = Prefix;
                        Nick   = string.Empty;
                    }
                    else
                    {
                        if (atIdx != -1)
                        {
                            Host = Prefix.Substring(atIdx);
                        }
                        else
                        {
                            Host = string.Empty;
                        }
                        if (excIdx != -1)
                        {
                            if (atIdx != -1) // We need to calculate the length of the User section based of the position of the '@'
                            {
                                User = Prefix.Substring(excIdx, (Prefix.Length - excIdx) - Host.Length);
                            }
                            else
                            {
                                User = Prefix.Substring(excIdx);
                            }
                        }

                        Server = string.Empty;
                        Nick   = Prefix.Substring(0, Prefix.Length - User.Length - Host.Length);
                    }
                }
                #endregion
                // Commands Section
                #region Command Parsing
                {
                    // < command >  ::= < letter > { < letter > } | < number > < number > < number >
                    if (subIdx != 0)
                    {
                        Command = RawTrimmed.Substring(subIdx + 1);
                    }
                    else
                    {
                        Command = RawTrimmed.Substring(subIdx);
                    }

                    var cmdIndex = Command.IndexOf(' ');
                    if (cmdIndex == -1)
                    {
                        return; // Invalid Message, cant be parsed.
                    }
                    // TODO: Log it to see why

                    Command        = Command.Substring(0, cmdIndex); // <command> <params> (<params> starts with <SPACE>)
                    IsNumericReply = false;

                    char startChar = (char)Command.ToCharArray().GetValue(0);
                    if (startChar >= 0x30 && startChar <= 0x39) // Between 0 - 9
                    {
                        // Number Code
                        var num = 0;
                        if (int.TryParse(Command, out num))
                        {
                            IRCReply       = (IRCReply)num;
                            IsNumericReply = true;
                        }
                    }
                }
                #endregion
                // RawParameters Section
                #region RawParameters Parsing
                {
                    // <params>   ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
                    if (subIdx == 0)
                    {
                        // No prefix detected,
                        subIdx        = RawTrimmed.IndexOf(' ');
                        RawParameters = RawTrimmed.Substring(subIdx + 1);
                    }
                    else
                    {
                        // We detected a prefix, so there is already a SPACE, find the next one
                        subIdx        = RawTrimmed.IndexOf(' ', subIdx + 1);
                        RawParameters = RawTrimmed.Substring(subIdx + 1);
                    }

                    var paramsList = new List <string>();
                    var paramsChar = RawParameters.ToCharArray();

                    for (int i = 0; i < paramsChar.Length; i++)
                    {
                        var ch = paramsChar[i];

                        if (ch == ':')  //[':' < trailing > | ... ]
                        {
                            paramsList.Add(new string(paramsChar.Skip(i).Take(paramsChar.Length - i).ToArray()));
                            break; // Last parameter
                        }
                        else // [ ... | < middle > <params> ]
                        {
                            var nextSpace = RawParameters.IndexOf(' ', i);
                            if (nextSpace == -1)
                            {
                                paramsList.Add(new string(paramsChar.ToArray()));
                                break; // There are no more parameters twitch lied to us (where was the ':' :( )
                            }
                            else
                            {
                                paramsList.Add(new string(paramsChar.Skip(i).Take(nextSpace - i).ToArray()));
                                i = nextSpace;
                            }
                        }
                    }
                    Parameters = paramsList.ToArray();
                }
                #endregion
                Parsed = true;
            }
            else
            {
                // Empty message
                Prefix        = string.Empty;
                Server        = string.Empty;
                Nick          = string.Empty;
                User          = string.Empty;
                Host          = string.Empty;
                Command       = string.Empty;
                RawParameters = string.Empty;
                Parameters    = new string[0];
            }

            #endregion
        }