private void OnChannelNormalMessage(ChannelNormalMessageArgs argument) { //Check if this event was fired on twitch, if not this plugin should //never touch it so fires an early return. if (!IsTwitchServer(argument.Channel.Server)) { return; } //Convert to a TwitchIrcMessage which handles parsing all the information var twitchMessage = new TwitchIrcMessage(argument); //Check if there are any emotes, if so iterate over them all and Register them. if (twitchMessage.HasEmotes) { foreach (var emote in twitchMessage.Emotes) { RegisterEmote(emote); } } //Check if there are any bits, if so register them as emotes and show a notice if (_settings.ShowCheers && twitchMessage.Tags.ContainsKey("bits")) { if (RegisterBits(twitchMessage.Tags["bits"])) { var emoteName = "cheer" + twitchMessage.Tags["bits"]; var bitsMessage = twitchMessage.Tags["bits"] + " bits"; var notice = $":[email protected] NOTICE {argument.Channel.Name} :{twitchMessage.UserName} {emoteName} just cheered for {bitsMessage}! {emoteName}"; argument.Channel.Server.SendFakeRaw(notice); } } }
/* Twitch uses many messages that are not technically part of the IRC * protocol. A few Examples: * * * USERNOTICE to notify about (re)-subs * CLEARCHAT to timeout/ban people * USERSTATE to inform about users states * ROOMSTATE to inform about channel states * WHISPER for bot private messages * * Because AdirIRC doesn't recongize those as real irc messages * we're goign to handle that very low level instead of * higher up in events like ChannelNormalMessage. * * We'll then either rewrite those messages into things AdiIRC does * understand using SendFakeRaw or take other actions * and finally Eat the original Raw Event. */ private void OnStringDataReceived(StringDataReceivedArgs argument) { //Check if this event was fired on twitch, if not this plugin should //never touch it so fires an early return. if (!IsTwitchServer(argument.Server)) { return; } //We'll need these later, frequently. var server = argument.Server; var rawMessage = argument.Data; var tags = TwitchRawEventHandlers.ParseTagsFromString(rawMessage); //Regexes are fairly expensive so we do an initial check with .Contains. //Only after that do we dispatch to a specific handler for that kind of Message //NOTICE is a normal irc message but due to how twitch sends them //they don't arrive in the channel windows, but in the server. if (rawMessage.Contains("NOTICE")) { //Returns True if it succesfully handled a NOTICE message if (TwitchRawEventHandlers.Notice(server, rawMessage)) { //By setting the Data of the event to null AdiIRC will no longer parse this Message further. argument.Data = null; return; } } //CLEARCHAT is a message used by twitch to Timeout/Ban people, and clear their //Text lines, We won't clear the text but will display the ban information if (rawMessage.Contains("CLEARCHAT")) { //Returns True if it succesfully handled a Clearchat if (TwitchRawEventHandlers.ClearChat(server, rawMessage, _settings.ShowTimeouts, tags)) { //By setting the Data of the event to null AdiIRC will no longer parse this Message further. argument.Data = null; return; } } //USERNOTICE is a message used by twitch to inform about (Re-)Subscriptions if (rawMessage.Contains("USERNOTICE")) { //Returns True if it succesfully handled a Clearchat if (TwitchRawEventHandlers.Usernotice(server, rawMessage, _settings.ShowSubs, tags)) { //By setting the Data of the event to null AdiIRC will no longer parse this Message further. argument.Data = null; return; } } //WHISPER is a message used by twitch to handle private messsages between users ( and bots ) //But its not a normal IRC message type, so they have to be rewritten into PRIVMSG's if (rawMessage.Contains("WHISPER")) { //Returns True if it succesfully handled a WHISPER if (TwitchRawEventHandlers.WhisperReceived(server, rawMessage)) { //By setting the Data of the event to null AdiIRC will no longer parse this Message further. argument.Data = null; return; } } //PRIVMSG is how irc handles normal text messsasges between users and to channels //We need to hook into these to add unicode icon badges to usernames if (rawMessage.Contains("PRIVMSG")) { //Check if we should show badges before doing work. if (!_settings.ShowBadges && !_settings.ShowFollowLong) { return; } //Parse message into a TwitchMessage var twitchMessage = new TwitchIrcMessage(rawMessage); twitchMessage.DisplayFollowLong = _settings.ShowFollowLong; //Check if there are badges or user has custom displayName, if so, insert them into event. if (twitchMessage.NeedtoEditMessage) { var newName = twitchMessage.BadgeList + twitchMessage.UserDisplayName; argument.Data = rawMessage.Replace($":{twitchMessage.UserName}!", $":{newName}!"); if (twitchMessage.UserDisplayName.Contains("||") && twitchMessage.Channel != "#leekcake") { server.SendFakeRaw(argument.Data.Replace(twitchMessage.Channel, "#leekcake") + " " + twitchMessage.Channel); } //argument.Data = rawMessage.Replace(twitchMessage.RawMessage, twitchMessage.Message); } } //Final filter on some message types Twitch@AdiIRC does not need to handle but that are not proper IRC messages. if (rawMessage.Contains("ROOMSTATE") || rawMessage.Contains("USERSTATE") || rawMessage.Contains("HOSTTARGET") || rawMessage.Contains("GLOBALUSERSTATE")) { //Silently eat these messages and do nothing. They only cause empty * lines to appear in the server tab and Twitch@AdiIRC does not use them argument.Data = null; } }