예제 #1
0
        /// <summary>
        /// Parses a Twitch Chat TMI message, from the raw IRC message.
        /// </summary>
        /// <param name="raw">The raw IRC messages, as received on the wire.</param>
        /// <returns>Parsed message data, either as an instance of TmiMessage, or a more specific model subtype if appropriate.</returns>
        public static TmiMessage Parse(string raw)
        {
            /**
             * // On room join, we get a USERSTATE message for ourselves:
             *
             * @badge-info=;badges=;color=;display-name=Toxmeter;emote-sets=0;mod=0;subscriber=0;user-type= :tmi.twitch.tv USERSTATE #kinamazing
             * @badge-info=;badges=;color=;display-name=Toxmeter;emote-sets=0;mod=0;subscriber=0;user-type= :tmi.twitch.tv USERSTATE #vader
             *
             * // On room join, we also get a ROOMSTATE message:
             *
             * @emote-only=0;followers-only=0;r9k=0;rituals=0;room-id=90091619;slow=0;subs-only=0 :tmi.twitch.tv ROOMSTATE #kinamazing
             * @emote-only=0;followers-only=10;r9k=0;rituals=0;room-id=69759951;slow=0;subs-only=0 :tmi.twitch.tv ROOMSTATE #vader
             *
             * // Regular messages are also prefixed with their full USERSTATE:
             *
             * @badge-info=subscriber/3;badges=subscriber/3;color=#1959B3;display-name=Crtka;emote-only=1;emotes=9:0-1;flags=;id=d4d8826d-0ac0-4966-b58a-830353b3a56a;mod=0;room-id=90091619;subscriber=1;tmi-sent-ts=1560102937011;turbo=0;user-id=180341394;user-type= :[email protected] PRIVMSG #kinamazing :<3
             *
             * // The IRC library does not understand this, so:
             *
             * e.Message.Command == The full @badge-info[...] block
             * e.Message.Parameters[0] == The IRC user identifier e.g. ":[email protected]"
             * e.Message.Parameters[1] == command "PRIVMSG"
             * e.Message.Parameters[2] == channel "#kinamazing"
             * e.Message.Parameters[3] == just the basic plain old message no markers "<3"
             *
             * // What a WHISPER looks like:
             *
             * @badges=twitchcon2018/1;color=#FF69B4;display-name=AFluHatinRapper;emotes=;message-id=19;thread-id=63469880_248897310;turbo=0;user-id=63469880;user-type= :[email protected] WHISPER toxmeter :test 123
             */

            var reader = new TmiIrcReader(raw);

            // Step 1: Read the state prefix, @-prefixed properties
            var stateProperties = new Dictionary <string, string>();
            var hasStatePrefix  = raw.StartsWith("@");

            if (hasStatePrefix)
            {
                var stateReader = reader.ReadNextUntil(' ');
                stateReader.Skip(1); // @

                do
                {
                    var nextPropKv = stateReader.ReadNextUntil(';', true);

                    if (nextPropKv.IsNullOrEmpty)
                    {
                        break;
                    }

                    var key   = nextPropKv.ReadNextUntil('=');
                    var value = nextPropKv.ReadRemainder();

                    stateProperties[key] = value;
                }while (true);
            }

            // Step 2: Read server name, channel name, and command name
            string serverName  = reader.ReadNextUntil(' ');
            string commandName = reader.ReadNextUntil(' ');
            string channelName = null;
            string message     = null;
            bool   isWhisper   = false;

            switch (commandName)
            {
            case "GLOBALUSERSTATE":
                // No message, no channel
                break;

            case "ROOMSTATE":
            case "USERSTATE":
                // No message, but has channel
                channelName = reader.ReadRemainder();
                break;

            case "PRIVMSG":
            default:
                // Has both message and channel
                channelName = reader.ReadNextUntil(' ');
                message     = reader.ReadRemainder();
                break;

            case "WHISPER":
                // In case of whispers, the channel is your own username w/o # prefix
                isWhisper   = true;
                channelName = reader.ReadNextUntil(' ');
                message     = reader.ReadRemainder();
                break;
            }

            // Step 3: Clean up
            if (channelName != null && channelName.Length > 1 && !isWhisper)
            {
                channelName = channelName.ToString().Substring(1); // Skip "#"
            }
            if (serverName != null && serverName.Length > 1)
            {
                serverName = serverName.ToString().Substring(1); // Skip ":"
            }
            if (message != null && message.Length > 1)
            {
                message = message.ToString().Substring(1); // Skip ":"
            }
            // Step 4: Factory
            TmiMessage result;

            if (commandName == "PRIVMSG" || commandName == "WHISPER")
            {
                result = new TmiChatMessage();
            }
            else
            {
                result = new TmiMessage();
            }

            result.ChannelName      = channelName;
            result.CommandName      = commandName;
            result.Message          = message;
            result.ServerName       = serverName;
            result.StateProperties  = stateProperties;
            result.IsPrivateWhisper = isWhisper;
            return(result);
        }
 public TmiChatMessageEventArgs(TmiChatMessage message)
 {
     this.Message = message;
 }