private static void HandleUserNotice(IrcMessage ircMessage) { var successMsgId = ircMessage.Tags.TryGetValue(Tags.MsgId, out var msgId); if (!successMsgId) { Console.WriteLine($"Unaccounted for: {ircMessage.ToString()}"); return; } switch (msgId) { case MsgIds.Raid: break; case MsgIds.ReSubscription: break; case MsgIds.Ritual: break; case MsgIds.SubGift: break; case MsgIds.Subscription: break; default: Console.WriteLine($"Unaccounted for: {ircMessage.ToString()}"); break; } }
public void IrcMsg_ToStringArgWithSpace() { var expected = ":prefix PRIVMSG blabla :string with a lot of spaces"; var actual = new IrcMessage("PRIVMSG", "prefix", "blabla", "string with a lot of spaces"); Assert.AreEqual(expected, actual.ToString()); }
private static void HandleNotice(IrcMessage ircMessage) { if (ircMessage.Message.Contains("Improperly formatted auth")) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Incorrect Login Details"); return; } var success = ircMessage.Tags.TryGetValue(Tags.MsgId, out var msgId); if (!success) { Console.WriteLine($"Unaccounted for: {ircMessage.ToString()}"); } switch (msgId) { case MsgIds.ColorChanged: break; case MsgIds.HostOn: break; case MsgIds.HostOff: break; case MsgIds.ModeratorsReceived: break; case MsgIds.NoPermission: break; case MsgIds.RaidErrorSelf: break; case MsgIds.RaidNoticeMature: break; case MsgIds.MsgChannelSuspended: break; default: Console.WriteLine($"Unaccounted for: {ircMessage.ToString()}"); break; } }
public void CanParseIrc3Tags() { var inputString = "@badges=premium/1;color=#AAAAAA;display-name=UserName;emote-sets=0,42,19194,375457;mod=0;subscriber=0;user-type= :server.com USERSTATE #channel"; var parsed = new IrcMessage(inputString); Assert.AreEqual(inputString, parsed.ToString()); Assert.AreEqual(7, parsed.Tags.Count()); }
public void CanParseMultipleMiddles() { var inputString = ":server.com CAP * ACK :server.com/cap server.com/ack"; var parsed = new IrcMessage(inputString); Assert.AreEqual(inputString, parsed.ToString()); Assert.AreEqual(2, parsed.Middles.Count()); }
public void CanParseMiddleWithoutTrailing() { var inputString = ":[email protected] JOIN #channel"; var parsed = new IrcMessage(inputString); Assert.AreEqual(inputString, parsed.ToString()); Assert.AreEqual(1, parsed.Middles.Count()); Assert.IsNull(parsed.Trailing); }
public void CanParseTrailingWithNoMiddle() { var inputString = "PING :server.com"; var parsed = new IrcMessage(inputString); Assert.AreEqual(inputString, parsed.ToString()); Assert.AreEqual(0, parsed.Middles.Count()); Assert.IsNotNull(parsed.Trailing); }
/// <summary> /// Broadcasts an <see cref="IRCSharp.IrcMessage"/> to all users listening on this channel. /// </summary> /// <param name="sender">The IIrcUser that sent the message.</param> /// <param name="message">The IrcMessage</param> /// <param name="ignoreSender">Whether to ignore the sender when sending this message.</param> public void SendMessage(IIrcUser sender, IrcMessage message, bool ignoreSender = false) { Users.Where(user => { if (ignoreSender) { return(user != sender); } return(true); }).ForEach(user => user.Write(message)); IrcServer.Logger.Log(LogLevel.Debug, message.ToString()); }
protected internal void ProcessMessageJoin(IrcMessage message) { logger.Debug("ProcessMessageJoin - Process JOIN messages received from the server:"); logger.Debug(message.ToString()); var sourceUser = message.Source as IrcUser; if (sourceUser == null) throw new ProtocolViolationException(string.Format( Properties.Resources.MessageSourceNotUser, message.Source.Name)); // Local or remote user has joined one or more channels. Debug.Assert(message.Parameters[0] != null); var channels = GetChannelsFromList(message.Parameters[0]).ToArray(); if (sourceUser == this.localUser) channels.ForEach(c => this.localUser.HandleJoinedChannel(c)); else channels.ForEach(c => c.HandleUserJoined(new IrcChannelUser(sourceUser))); }
void SendChannelMessage(string channelname, IrcMessage message) { if (!TrySendChannelMessage(channelname, message)) { Logger.Warning(this, $"Message for channel '{channelname}' but channel not registered in client.", message.ToString()); } }
private void Client_OnMessageReceived(IrcMessage message) { var parsedMessage = new ChatMessage(message.User, message.Middles.First(), message.Trailing, message.Tags); if (this.commandMap.ContainsKey(message.Command)) { this.commandMap[message.Command](parsedMessage); } else { var bytes = Encoding.Default.GetBytes("Unknown command received: " + message.Command + "\r\n" + message.ToString()); Console.OpenStandardError().Write(bytes, 0, bytes.Length); this.OnChatEvent?.Invoke(parsedMessage); } }
//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="ircMessage">The IRC message 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, IrcMessage ircMessage, ref MessageEmoteCollection emoteCollection, bool replaceEmotes = false) { BotUsername = botUsername; RawIrcMessage = ircMessage.ToString(); Message = ircMessage.Message; _emoteCollection = emoteCollection; Username = ircMessage.User; Channel = ircMessage.Channel; foreach (var tag in ircMessage.Tags.Keys) { var tagValue = ircMessage.Tags[tag]; switch (tag) { case Tags.Badges: Badges = Common.Helpers.ParseBadges(tagValue); // Iterate through saved badges for special circumstances foreach (var badge in Badges) { switch (badge.Key) { case "bits": CheerBadge = new CheerBadge(int.Parse(badge.Value)); break; case "subscriber": // Prioritize BadgeInfo subscribe count, as its more accurate if (SubscribedMonthCount == 0) { SubscribedMonthCount = int.Parse(badge.Value); } break; case "vip": IsVip = true; break; } } break; case Tags.BadgeInfo: BadgeInfo = Common.Helpers.ParseBadges(tagValue); // check if founder is one of them, and get months from that var founderBadge = BadgeInfo.Find(b => b.Key == "founder"); if (!founderBadge.Equals(default(KeyValuePair <string, string>))) { IsSubscriber = true; SubscribedMonthCount = int.Parse(founderBadge.Value); } else { var subBadge = BadgeInfo.Find(b => b.Key == "subscriber"); // BadgeInfo has better accuracy than Badges subscriber value if (!subBadge.Equals(default(KeyValuePair <string, string>))) { SubscribedMonthCount = int.Parse(subBadge.Value); } } break; case Tags.Bits: Bits = int.Parse(tagValue); BitsInDollars = ConvertBitsToUsd(Bits); break; case Tags.Color: ColorHex = tagValue; if (!string.IsNullOrWhiteSpace(ColorHex)) { Color = ColorTranslator.FromHtml(ColorHex); } break; case Tags.CustomRewardId: CustomRewardId = tagValue; break; case Tags.DisplayName: DisplayName = tagValue; break; case Tags.Emotes: EmoteSet = new EmoteSet(tagValue, Message); break; case Tags.Id: Id = tagValue; break; case Tags.MsgId: handleMsgId(tagValue); break; case Tags.Mod: IsModerator = Common.Helpers.ConvertToBool(tagValue); break; case Tags.Noisy: Noisy = Common.Helpers.ConvertToBool(tagValue) ? Noisy.True : Noisy.False; break; case Tags.RoomId: RoomId = tagValue; break; case Tags.Subscriber: // this check because when founder is set, the subscriber value is actually 0, which is problematic IsSubscriber = IsSubscriber == false?Common.Helpers.ConvertToBool(tagValue) : true; break; case Tags.TmiSentTs: TmiSentTs = tagValue; break; case Tags.Turbo: IsTurbo = Common.Helpers.ConvertToBool(tagValue); break; case Tags.UserId: UserId = tagValue; break; case Tags.UserType: switch (tagValue) { case "mod": UserType = UserType.Moderator; break; case "global_mod": UserType = UserType.GlobalModerator; break; case "admin": UserType = UserType.Admin; break; case "staff": UserType = UserType.Staff; break; default: UserType = UserType.Viewer; break; } break; } } 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); if (Message.StartsWith("\u0001ACTION ") && Message.EndsWith("\u0001")) { Message = Message.Trim('\u0001').Substring(7); IsMe = true; } } //Parse the emoteSet if (EmoteSet != null && Message != null && EmoteSet.Emotes.Count > 0) { var uniqueEmotes = EmoteSet.RawEmoteSetString.Split('/'); foreach (var emote in uniqueEmotes) { var firstColon = emote.IndexOf(':'); var firstComma = emote.IndexOf(','); if (firstComma == -1) { firstComma = emote.Length; } var firstDash = emote.IndexOf('-'); if (firstColon > 0 && firstDash > firstColon && firstComma > firstDash) { if (int.TryParse(emote.Substring(firstColon + 1, firstDash - firstColon - 1), out var low) && int.TryParse(emote.Substring(firstDash + 1, firstComma - firstDash - 1), out var high)) { if (low >= 0 && low < high && high < Message.Length) { //Valid emote, let's parse var id = emote.Substring(0, firstColon); //Pull the emote text from the message var text = Message.Substring(low, high - low + 1); _emoteCollection.Add(new MessageEmote(id, text)); } } } } if (replaceEmotes) { EmoteReplacedMessage = _emoteCollection.ReplaceEmotes(Message); } } if (EmoteSet == null) { EmoteSet = new EmoteSet(default(string), 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 (string.Equals(Channel, Username, StringComparison.InvariantCultureIgnoreCase)) { UserType = UserType.Broadcaster; IsBroadcaster = true; } if (Channel.Split(':').Length == 3) { if (string.Equals(Channel.Split(':')[1], UserId, StringComparison.InvariantCultureIgnoreCase)) { UserType = UserType.Broadcaster; IsBroadcaster = true; } } }
public void WhenMessageStringGenerated() { _messageString = _message.ToString(); }
public void IrcMsg_ToStringWithPrefixNoArgs() { var expected = ":jakub PING"; var actual = new IrcMessage("PING", "jakub"); Assert.AreEqual(expected, actual.ToString()); }
private static void HandleIrcMessage(IrcMessage ircMessage) { if (ircMessage.Message.Contains("Login authentication failed")) { } switch (ircMessage.Command) { case IrcCommand.PrivMsg: HandlePrivMsg(ircMessage); return; case IrcCommand.Notice: HandleNotice(ircMessage); break; case IrcCommand.Ping: _twitch.ReplyPong("PONG"); return; case IrcCommand.Pong: return; case IrcCommand.Join: HandleJoin(ircMessage); break; case IrcCommand.Part: HandlePart(ircMessage); break; case IrcCommand.HostTarget: break; case IrcCommand.ClearChat: break; case IrcCommand.UserState: HandleUserState(ircMessage); break; case IrcCommand.GlobalUserState: break; case IrcCommand.RPL_001: break; case IrcCommand.RPL_002: break; case IrcCommand.RPL_003: break; case IrcCommand.RPL_004: Handle004(); break; case IrcCommand.RPL_353: Handle353(ircMessage); break; case IrcCommand.RPL_366: break; case IrcCommand.RPL_372: break; case IrcCommand.RPL_375: break; case IrcCommand.RPL_376: break; case IrcCommand.Whisper: break; case IrcCommand.RoomState: HandleRoomState(ircMessage); break; case IrcCommand.Reconnect: break; case IrcCommand.UserNotice: HandleUserNotice(ircMessage); break; case IrcCommand.Mode: HandleMode(ircMessage); break; case IrcCommand.Unknown: Console.WriteLine($"Unaccounted for: {ircMessage.ToString()}"); break; default: Console.WriteLine($"Unaccounted for: {ircMessage.ToString()}"); break; } }
void ProcessMessage(IrcMessage message) { if (message.Command == $":{message.Source}" && message.Arguments.Length > 0) { // twitch seems to have issues building proper irc messages ProcessMessage(new IrcMessage(message.Arguments[0], message.Arguments.Skip(1).ToArray())); return; } string channelname; switch (message.Command) { case "CAP": if (message.Arguments.Length < 3) { break; } if (message.Arguments[1] == "ACK") { CapAcknowledged?.Invoke(message.Arguments[2]); } break; case "PING": SendMessage(new IrcMessage("PONG", message.Arguments)); break; case "JOIN": channelname = GetChannelName(message.Arguments[0]); if (message.ExtractUser().ToLower() == user.ToLower()) { JoinChannel(channelname); } SendChannelMessage(channelname, message); break; case "PART": channelname = GetChannelName(message.Arguments[0]); SendChannelMessage(channelname, message); if (message.ExtractUser().ToLower() == user.ToLower()) { ChatChannel channel; lock (channellock) { if (channels.TryGetValue(channelname, out channel)) { channels.Remove(channelname); } } if (channel != null) { ChannelLeft?.Invoke(channel); } } break; case "tmi.twitch.tv RECONNECT": case "RECONNECT": Reconnect?.Invoke(); break; case "001": case "002": case "003": case "004": // connection success break; case "372": case "375": // message of the day break; case "376": connectionwait.Set(); // end of message of the day break; case "353": GetChannel(message.Arguments[2])?.OnMessage(message); break; case "366": GetChannel(message.Arguments[1])?.OnMessage(message); break; case "ROOMSTATE": case "PRIVMSG": case "USERNOTICE": case "NOTICE": case "USERSTATE": SendChannelMessage(message.Arguments[0], message); break; case "HOSTTARGET": if (!message.Arguments[1].StartsWith("-")) { TrySendChannelMessage(message.Arguments[0], message); TrySendChannelMessage(message.Arguments[1].Split(' ')[0], message); } break; case "MODE": // channel or user mode ... not that important for now break; default: Logger.Warning(this, "Unprocessed message", message.ToString()); break; } }
/// <summary>Subscriber object constructor.</summary> protected SubscriberBase(IrcMessage ircMessage) { RawIrc = ircMessage.ToString(); ResubMessage = ircMessage.Message; foreach (var tag in ircMessage.Tags.Keys) { var tagValue = ircMessage.Tags[tag]; switch (tag) { case Tags.Badges: Badges = Common.Helpers.ParseBadges(tagValue); // iterate through badges for special circumstances foreach (var badge in Badges) { if (badge.Key == "partner") { IsPartner = true; } } break; case Tags.BadgeInfo: BadgeInfo = Common.Helpers.ParseBadges(tagValue); break; case Tags.Color: ColorHex = tagValue; if (!string.IsNullOrEmpty(ColorHex)) { Color = ColorTranslator.FromHtml(ColorHex); } break; case Tags.DisplayName: DisplayName = tagValue; break; case Tags.Emotes: EmoteSet = tagValue; break; case Tags.Id: Id = tagValue; break; case Tags.Login: Login = tagValue; break; case Tags.Mod: IsModerator = ConvertToBool(tagValue); break; case Tags.MsgId: MsgId = tagValue; break; case Tags.MsgParamCumulativeMonths: MsgParamCumulativeMonths = tagValue; break; case Tags.MsgParamStreakMonths: MsgParamStreakMonths = tagValue; break; case Tags.MsgParamShouldShareStreak: MsgParamShouldShareStreak = Common.Helpers.ConvertToBool(tagValue); break; case Tags.MsgParamSubPlan: switch (tagValue.ToLower()) { case "prime": SubscriptionPlan = SubscriptionPlan.Prime; break; case "1000": SubscriptionPlan = SubscriptionPlan.Tier1; break; case "2000": SubscriptionPlan = SubscriptionPlan.Tier2; break; case "3000": SubscriptionPlan = SubscriptionPlan.Tier3; break; default: throw new ArgumentOutOfRangeException(nameof(tagValue.ToLower)); } break; case Tags.MsgParamSubPlanName: SubscriptionPlanName = tagValue.Replace("\\s", " "); break; case Tags.RoomId: RoomId = tagValue; break; case Tags.Subscriber: IsSubscriber = ConvertToBool(tagValue); break; case Tags.SystemMsg: SystemMessage = tagValue; SystemMessageParsed = tagValue.Replace("\\s", " "); break; case Tags.TmiSentTs: TmiSentTs = tagValue; break; case Tags.Turbo: IsTurbo = ConvertToBool(tagValue); break; case Tags.UserId: UserId = tagValue; break; case Tags.UserType: switch (tagValue) { case "mod": UserType = UserType.Moderator; break; case "global_mod": UserType = UserType.GlobalModerator; break; case "admin": UserType = UserType.Admin; break; case "staff": UserType = UserType.Staff; break; default: UserType = UserType.Viewer; break; } break; } } }
internal void OnMessage(IrcMessage message) { switch (message.Command) { case "353": foreach (string user in message.Arguments[3].Split(' ')) { users.Add(user); } break; case "366": UsersChanged?.Invoke(this); break; case "PRIVMSG": ReceiveMessage(message); break; case "ROOMSTATE": ReceiveRoomState(message); break; case "USERNOTICE": switch (message.Tags.FirstOrDefault(t => t.Key == "msg-id")?.Value) { case "raid": ReceiveRaidNotice(message); break; case "sub": case "resub": case "charity": ReceiveUserNotice(message); break; default: Logger.Warning(this, "Unknown user message type", message.ToString()); break; } break; case "JOIN": ReceiveJoin(message); break; case "PART": ReceivePart(message); break; case "HOSTTARGET": ReceiveHostTarget(message); break; case "NOTICE": ReceiveNotice(message); break; case "USERSTATE": ReceiveUserState(message); break; } }
/// <summary> /// Broadcasts an <see cref="IRCSharp.IrcMessage"/> to all users listening on this channel. /// </summary> /// <param name="sender">The IIrcUser that sent the message.</param> /// <param name="message">The IrcMessage</param> /// <param name="ignoreSender">Whether to ignore the sender when sending this message.</param> public void SendMessage(IIrcUser sender, IrcMessage message, bool ignoreSender = false) { Users.Where(user => { if (ignoreSender) { return user != sender; } return true; }).ForEach(user => user.Write(message)); IrcServer.Logger.Log(LogLevel.Debug, message.ToString()); }
/// <summary> /// WhisperMessage constructor. /// </summary> /// <param name="ircMessage">Received IRC string from Twitch server.</param> /// <param name="botUsername">Active bot username receiving message.</param> public WhisperMessage(IrcMessage ircMessage, string botUsername) { Username = ircMessage.User; BotUsername = botUsername; RawIrcMessage = ircMessage.ToString(); Message = ircMessage.Message; foreach (var tag in ircMessage.Tags.Keys) { var tagValue = ircMessage.Tags[tag]; switch (tag) { case Tags.Badges: Badges = new List <KeyValuePair <string, string> >(); if (tagValue.Contains('/')) { if (!tagValue.Contains(",")) { Badges.Add(new KeyValuePair <string, string>(tagValue.Split('/')[0], tagValue.Split('/')[1])); } else { foreach (var badge in tagValue.Split(',')) { Badges.Add(new KeyValuePair <string, string>(badge.Split('/')[0], badge.Split('/')[1])); } } } break; case Tags.Color: ColorHex = tagValue; if (!string.IsNullOrEmpty(ColorHex)) { Color = ColorTranslator.FromHtml(ColorHex); } break; case Tags.DisplayName: DisplayName = tagValue; break; case Tags.Emotes: EmoteSet = new EmoteSet(tagValue, Message); break; case Tags.MessageId: MessageId = tagValue; break; case Tags.ThreadId: ThreadId = tagValue; break; case Tags.Turbo: IsTurbo = Common.Helpers.ConvertToBool(tagValue); break; case Tags.UserId: UserId = tagValue; break; case Tags.UserType: switch (tagValue) { case "global_mod": UserType = UserType.GlobalModerator; break; case "admin": UserType = UserType.Admin; break; case "staff": UserType = UserType.Staff; break; default: UserType = UserType.Viewer; break; } break; } } if (EmoteSet == null) { EmoteSet = new EmoteSet(default(string), Message); } }