//Example IRC message: @badges=moderator/1,warcraft/alliance;color=;display-name=Swiftyspiffyv4;emotes=;mod=1;room-id=40876073;subscriber=0;turbo=0;user-id=103325214;user-type=mod :[email protected] PRIVMSG #swiftyspiffy :asd /// <summary>Constructor for ChatMessage object.</summary> /// <param name="botUsername">The username of the bot that received the message.</param> /// <param name="ircString">The raw string received from Twitch to be processed.</param> /// <param name="emoteCollection">The <see cref="MessageEmoteCollection"/> to register new emotes on and, if desired, use for emote replacement.</param> /// <param name="replaceEmotes">Whether to replace emotes for this chat message. Defaults to false.</param> public ChatMessage(string botUsername, string ircString, ref MessageEmoteCollection emoteCollection, bool replaceEmotes = false) { BotUsername = botUsername; RawIrcMessage = ircString; _emoteCollection = emoteCollection; var parts = ircString.Split(';'); foreach (var part in parts) { if (part.Contains("!")) { if (Channel == null) { Channel = part.Split('#')[1].Split(' ')[0]; } if (Username == null) { Username = part.Split('!')[1].Split('@')[0]; } if (part.Split('=').Count() > 1 && part.Split('=')[1].Contains(" ")) { switch (part.Split('=')[1].Split(' ')[0]) { case "mod": UserType = Enums.UserType.Moderator; break; case "global_mod": UserType = Enums.UserType.GlobalModerator; break; case "admin": UserType = Enums.UserType.Admin; break; case "staff": UserType = Enums.UserType.Staff; break; default: UserType = Enums.UserType.Viewer; break; } } } else if (part.Contains("@badges=")) { Badges = new List <KeyValuePair <string, string> >(); string badges = part.Split('=')[1]; if (badges.Contains('/')) { if (!badges.Contains(",")) { Badges.Add(new KeyValuePair <string, string>(badges.Split('/')[0], badges.Split('/')[1])); } else { foreach (string badge in badges.Split(',')) { Badges.Add(new KeyValuePair <string, string>(badge.Split('/')[0], badge.Split('/')[1])); } } } // Iterate through saved badges for special circumstances foreach (KeyValuePair <string, string> badge in Badges) { if (badge.Key == "bits") { CheerBadge = new CheerBadge(int.Parse(badge.Value)); } if (badge.Key == "subscriber") { SubscribedMonthCount = int.Parse(badge.Value); } } } else if (part.Contains("bits=")) { Bits = int.Parse(part.Split('=')[1]); BitsInDollars = convertBitsToUSD(Bits); } else if (part.Contains("color=")) { if (ColorHex == null) { ColorHex = part.Split('=')[1]; } if (!string.IsNullOrEmpty(ColorHex)) { Color = Color.FromArgb(Int32.Parse(ColorHex.Replace("#", ""), NumberStyles.HexNumber)); } } else if (part.Contains("display-name")) { if (DisplayName == null) { DisplayName = part.Split('=')[1]; } } else if (part.Contains("emotes=")) { if (emoteSetStorage == null) { emoteSetStorage = part.Split('=')[1]; } } else if (part.Contains("subscriber=")) { IsSubscriber = part.Split('=')[1] == "1"; } else if (part.Contains("turbo=")) { IsTurbo = part.Split('=')[1] == "1"; } else if (part.Contains("user-id=")) { UserId = part.Split('=')[1]; } else if (part.Contains("mod=")) { IsModerator = part.Split('=')[1] == "1"; } else if (part.Contains("room-id=")) { RoomId = part.Split('=')[1]; } else if (part.Contains("noisy=")) { Noisy = (part.Split('=')[1] == "1") ? Enums.Noisy.True : Enums.Noisy.False; } } Message = ircString.Split(new[] { $" PRIVMSG #{Channel} :" }, StringSplitOptions.None)[1]; EmoteSet = new EmoteSet(emoteSetStorage, Message); if (Message.Length > 0 && (byte)Message[0] == 1 && (byte)Message[Message.Length - 1] == 1) { //Actions (/me {action}) are wrapped by byte=1 and prepended with "ACTION " //This setup clears all of that leaving just the action's text. //If you want to clear just the nonstandard bytes, use: //_message = _message.Substring(1, text.Length-2); Message = Message.Substring(8, Message.Length - 9); IsMe = true; } //Parse the emoteSet if (EmoteSet != null && Message != null && EmoteSet.Emotes.Count > 0) { string[] uniqueEmotes = EmoteSet.RawEmoteSetString.Split('/'); string id, text; int firstColon, firstComma, firstDash, low, high; foreach (string emote in uniqueEmotes) { firstColon = emote.IndexOf(':'); firstComma = emote.IndexOf(','); if (firstComma == -1) { firstComma = emote.Length; } firstDash = emote.IndexOf('-'); if (firstColon > 0 && firstDash > firstColon && firstComma > firstDash) { if (Int32.TryParse(emote.Substring(firstColon + 1, (firstDash - firstColon) - 1), out low) && Int32.TryParse(emote.Substring(firstDash + 1, (firstComma - firstDash) - 1), out high)) { if (low >= 0 && low < high && high < Message.Length) { //Valid emote, let's parse id = emote.Substring(0, firstColon); //Pull the emote text from the message text = Message.Substring(low, (high - low) + 1); _emoteCollection.Add(new MessageEmote(id, text)); } } } } if (replaceEmotes) { EmoteReplacedMessage = _emoteCollection.ReplaceEmotes(Message); } } // Check if display name was set, and if it wasn't, set it to username if (string.IsNullOrEmpty(DisplayName)) { DisplayName = Username; } // Check if message is from broadcaster if (Channel.ToLower() == Username.ToLower()) { UserType = Enums.UserType.Broadcaster; IsBroadcaster = true; } }
/// <summary> /// WhisperMessage constructor. /// </summary> /// <param name="ircString">Received IRC string from Twitch server.</param> /// <param name="botUsername">Active bot username receiving message.</param> public WhisperMessage(string ircString, string botUsername) { Username = ircString.Split('!')[1].Split('@')[0]; BotUsername = botUsername; Message = ircString.Replace($"{ircString.Split('!')[0]}!{Username}@{Username}.tmi.twitch.tv WHISPER {botUsername.ToLower()} :", ""); var props = ircString.Replace(Message, ""); foreach (string part in props.Split(';')) { string key = part.Split('=')[0]; string value = part.Split('=')[1]; switch (key) { case "@badges": Badges = new List <KeyValuePair <string, string> >(); if (value.Contains('/')) { if (!value.Contains(",")) { Badges.Add(new KeyValuePair <string, string>(value.Split('/')[0], value.Split('/')[1])); } else { foreach (string badge in value.Split(',')) { Badges.Add(new KeyValuePair <string, string>(badge.Split('/')[0], badge.Split('/')[1])); } } } break; case "color": ColorHex = value; if (!string.IsNullOrEmpty(ColorHex)) { Color = Color.FromArgb(Int32.Parse(ColorHex.Replace("#", ""), NumberStyles.HexNumber)); } break; case "display-name": DisplayName = value; break; case "emotes": EmoteSet = new EmoteSet(value, Message); break; case "message-id": MessageId = long.Parse(value); break; case "thread-id": ThreadId = value; break; case "turbo": if (value == "1") { Turbo = true; } break; case "user-id": UserId = value; break; case "user-type": switch (part.Split('=')[1].Split(' ')[0]) { case "global_mod": UserType = Enums.UserType.GlobalModerator; break; case "admin": UserType = Enums.UserType.Admin; break; case "staff": UserType = Enums.UserType.Staff; break; default: UserType = Enums.UserType.Viewer; break; } break; } } }
/// <summary>Subscriber object constructor.</summary> public SubscriberBase(string ircString) { RawIrc = ircString; foreach (string section in ircString.Split(';')) { if (section.Contains("=")) { string key = section.Split('=')[0]; string value = section.Split('=')[1]; switch (key) { case "@badges": Badges = new List <KeyValuePair <string, string> >(); foreach (string badgeValue in value.Split(',')) { if (badgeValue.Contains('/')) { Badges.Add(new KeyValuePair <string, string>(badgeValue.Split('/')[0], badgeValue.Split('/')[1])); } } // iterate through badges for special circumstances foreach (var badge in Badges) { if (badge.Key == "partner") { IsPartner = true; } } break; case "color": ColorHex = value; if (!string.IsNullOrEmpty(ColorHex)) { Color = Color.FromArgb(Int32.Parse(ColorHex.Replace("#", ""), NumberStyles.HexNumber)); } break; case "display-name": DisplayName = value.Replace(" ", ""); break; case "emotes": EmoteSet = value; break; case "id": Id = value; break; case "login": Login = value; break; case "mod": IsModerator = value == "1"; break; case "msg-param-months": months = int.Parse(value); break; case "msg-param-sub-plan": switch (value.ToLower()) { case "prime": SubscriptionPlan = Enums.SubscriptionPlan.Prime; break; case "1000": SubscriptionPlan = Enums.SubscriptionPlan.Tier1; break; case "2000": SubscriptionPlan = Enums.SubscriptionPlan.Tier2; break; case "3000": SubscriptionPlan = Enums.SubscriptionPlan.Tier3; break; } break; case "msg-param-sub-plan-name": SubscriptionPlanName = value.Replace("\\s", " "); break; case "room-id": RoomId = value; break; case "subscriber": IsSubscriber = value == "1"; break; case "system-msg": SystemMessage = value; SystemMessageParsed = value.Replace("\\s", " "); break; case "tmi-sent-ts": TmiSentTs = value; break; case "turbo": IsTurbo = value == "1"; break; case "user-id": UserId = value; break; } } } // Parse user-type if (ircString.Contains("=") && ircString.Contains(" ")) { switch (ircString.Split(' ')[0].Split(';')[13].Split('=')[1]) { case "mod": UserType = Enums.UserType.Moderator; break; case "global_mod": UserType = Enums.UserType.GlobalModerator; break; case "admin": UserType = Enums.UserType.Admin; break; case "staff": UserType = Enums.UserType.Staff; break; default: UserType = Enums.UserType.Viewer; break; } } // Parse channel if (ircString.Contains("#")) { if (ircString.Split('#').Count() > 2) { if (ircString.Split('#')[2].Contains(" ")) { Channel = ircString.Split('#')[2].Split(' ')[0].Replace(" ", ""); } else { Channel = ircString.Split('#')[2].Replace(" ", ""); } } else { Channel = ircString.Split('#')[1]; if (Channel.Contains(" ")) { Channel = Channel.Split(' ')[0]; } if (Channel.Contains(":")) { Channel = Channel.Split(':')[0]; } } } // Parse sub message ResubMessage = ""; if (ircString.Contains($"#{Channel} :")) { string rawParsedIrc = ircString.Split(new string[] { $"#{Channel} :" }, StringSplitOptions.None)[0]; ResubMessage = ircString.Replace($"{rawParsedIrc}#{Channel} :", ""); } // Check if Twitch Prime IsTwitchPrime = SubscriptionPlan == Enums.SubscriptionPlan.Prime; }