Example #1
0
    private void Awake()
    {
        client = new Twitch.Client();

        // Transfert events
        client.OnDisconnected       += (s, e) => OnDisconnected?.Invoke(this, e);
        client.OnConnectionError    += (s, e) => OnConnectionError?.Invoke(this, e);
        client.OnChatCleared        += (s, e) => OnChatCleared?.Invoke(this, e);
        client.OnUserTimedout       += (s, e) => OnUserTimedout?.Invoke(this, e);
        client.OnLeftChannel        += (s, e) => OnLeftChannel?.Invoke(this, e);
        client.OnUserBanned         += (s, e) => OnUserBanned?.Invoke(this, e);
        client.OnModeratorsReceived += (s, e) => OnModeratorsReceived?.Invoke(this, e);
        client.OnChatColorChanged   += (s, e) => OnChatColorChanged?.Invoke(this, e);
        client.OnSendReceiveData    += (s, e) => OnSendReceiveData?.Invoke(this, e);
        client.OnNowHosting         += (s, e) => OnNowHosting?.Invoke(this, e);
        //client.OnBeingHosted                        += (s, e) => OnBeingHosted                      ?.Invoke(this, e);
        client.OnRaidNotification              += (s, e) => OnRaidNotification?.Invoke(this, e);
        client.OnGiftedSubscription            += (s, e) => OnGiftedSubscription?.Invoke(this, e);
        client.OnSelfRaidError                 += (s, e) => OnSelfRaidError?.Invoke(this, e);
        client.OnNoPermissionError             += (s, e) => OnNoPermissionError?.Invoke(this, e);
        client.OnRaidedChannelIsMatureAudience += (s, e) => OnRaidedChannelIsMatureAudience?.Invoke(this, e);
        client.OnRitualNewChatter              += (s, e) => OnRitualNewChatter?.Invoke(this, e);
        client.OnHostingStopped                += (s, e) => OnHostingStopped?.Invoke(this, e);
        client.OnHostingStarted                += (s, e) => OnHostingStarted?.Invoke(this, e);
        client.OnUserLeft += (s, e) => OnUserLeft?.Invoke(this, e);
        client.OnExistingUsersDetected += (s, e) => OnExistingUsersDetected?.Invoke(this, e);
        client.OnLog                 += (s, e) => OnLog?.Invoke(this, e);
        client.OnConnected           += (s, e) => OnConnected?.Invoke(this, e);
        client.OnJoinedChannel       += (s, e) => OnJoinedChannel?.Invoke(this, e);
        client.OnIncorrectLogin      += (s, e) => OnIncorrectLogin?.Invoke(this, e);
        client.OnChannelStateChanged += (s, e) => OnChannelStateChanged?.Invoke(this, e);
        client.OnUserStateChanged    += (s, e) => OnUserStateChanged?.Invoke(this, e);
        client.OnMessageReceived     += (s, e) => OnMessageReceived?.Invoke(this, e);
        client.OnWhisperReceived     += (s, e) => OnWhisperReceived?.Invoke(this, e);
        client.OnFailureToReceiveJoinConfirmation += (s, e) => OnFailureToReceiveJoinConfirmation?.Invoke(this, e);
        client.OnMessageSent            += (s, e) => OnMessageSent?.Invoke(this, e);
        client.OnChatCommandReceived    += (s, e) => OnChatCommandReceived?.Invoke(this, e);
        client.OnWhisperCommandReceived += (s, e) => OnWhisperCommandReceived?.Invoke(this, e);
        client.OnUserJoined             += (s, e) => OnUserJoined?.Invoke(this, e);
        client.OnModeratorJoined        += (s, e) => OnModeratorJoined?.Invoke(this, e);
        client.OnModeratorLeft          += (s, e) => OnModeratorLeft?.Invoke(this, e);
        client.OnNewSubscriber          += (s, e) => OnNewSubscriber?.Invoke(this, e);
        client.OnReSubscriber           += (s, e) => OnReSubscriber?.Invoke(this, e);
        client.OnHostLeft       += (s, e) => OnHostLeft?.Invoke(this, e);
        client.OnWhisperSent    += (s, e) => OnWhisperSent?.Invoke(this, e);
        client.OnUnaccountedFor += (s, e) => OnUnaccountedFor?.Invoke(this, e);

        // Log client activity
        client.OnLog           += (s, e) => Debug.Log(e.Data);
        client.OnConnected     += (s, e) => NotificationManager.Instance.PushNotification("Connected to Twitch servers", Color.white, Color.green);
        client.OnJoinedChannel += (s, e) => NotificationManager.Instance.PushNotification($"Joined {e.Channel} channel", Color.white, Color.cyan);
        client.OnLeftChannel   += (s, e) => NotificationManager.Instance.PushNotification($"Left {e.Channel} channel", Color.white, Color.yellow);
        client.OnDisconnected  += (s, e) => NotificationManager.Instance.PushNotification("Disconnected from Twitch servers", Color.white, Color.red);
        client.OnFailureToReceiveJoinConfirmation += (s, e) => NotificationManager.Instance.PushNotification("Failed to join channel", Color.white, Color.magenta);
    }
Example #2
0
        public Client() : base(null)
        {
            ThreadDispatcher.EnsureCreated();

            base.OverrideBeingHostedCheck = true;

            base.OnLog       += (object sender, OnLogArgs e) => { ThreadDispatcher.Enqueue(() => OnLog?.Invoke(sender, e)); };
            base.OnConnected += ((object sender, OnConnectedArgs e) => { ThreadDispatcher.Enqueue(() => OnConnected?.Invoke(sender, e)); });

            base.OnJoinedChannel += ((object sender, OnJoinedChannelArgs e) => {
                ThreadDispatcher.Enqueue(() => OnJoinedChannel?.Invoke(sender, e));

                if (OnBeingHosted == null)
                {
                    return;
                }
                if (e.Channel.ToLower() != TwitchUsername && !OverrideBeingHostedCheck)
                {
                    ThreadDispatcher.Enqueue(() => throw new BadListenException("BeingHosted", "You cannot listen to OnBeingHosted unless you are connected to the broadcaster's channel as the broadcaster. You may override this by setting the TwitchClient property OverrideBeingHostedCheck to true."));
                }
            });

            base.OnIncorrectLogin         += ((object sender, OnIncorrectLoginArgs e) => { ThreadDispatcher.Enqueue(() => OnIncorrectLogin?.Invoke(sender, e)); });
            base.OnChannelStateChanged    += ((object sender, OnChannelStateChangedArgs e) => { ThreadDispatcher.Enqueue(() => OnChannelStateChanged?.Invoke(sender, e)); });
            base.OnUserStateChanged       += ((object sender, OnUserStateChangedArgs e) => { ThreadDispatcher.Enqueue(() => OnUserStateChanged?.Invoke(sender, e)); });
            base.OnMessageReceived        += ((object sender, OnMessageReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnMessageReceived?.Invoke(sender, e)); });
            base.OnWhisperReceived        += ((object sender, OnWhisperReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnWhisperReceived?.Invoke(sender, e)); });
            base.OnMessageSent            += ((object sender, OnMessageSentArgs e) => { ThreadDispatcher.Enqueue(() => OnMessageSent?.Invoke(sender, e)); });
            base.OnWhisperSent            += ((object sender, OnWhisperSentArgs e) => { ThreadDispatcher.Enqueue(() => OnWhisperSent?.Invoke(sender, e)); });
            base.OnChatCommandReceived    += ((object sender, OnChatCommandReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnChatCommandReceived?.Invoke(sender, e)); });
            base.OnWhisperCommandReceived += ((object sender, OnWhisperCommandReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnWhisperCommandReceived?.Invoke(sender, e)); });
            base.OnUserJoined             += ((object sender, OnUserJoinedArgs e) => { ThreadDispatcher.Enqueue(() => OnUserJoined?.Invoke(sender, e)); });
            base.OnModeratorJoined        += ((object sender, OnModeratorJoinedArgs e) => { ThreadDispatcher.Enqueue(() => OnModeratorJoined?.Invoke(sender, e)); });
            base.OnModeratorLeft          += ((object sender, OnModeratorLeftArgs e) => { ThreadDispatcher.Enqueue(() => OnModeratorLeft?.Invoke(sender, e)); });
            base.OnNewSubscriber          += ((object sender, OnNewSubscriberArgs e) => { ThreadDispatcher.Enqueue(() => OnNewSubscriber?.Invoke(sender, e)); });
            base.OnReSubscriber           += ((object sender, OnReSubscriberArgs e) => { ThreadDispatcher.Enqueue(() => OnReSubscriber?.Invoke(sender, e)); });
            base.OnHostLeft += ((object sender, EventArgs arg) => { ThreadDispatcher.Enqueue(() => OnHostLeft?.Invoke(sender, arg)); });
            base.OnExistingUsersDetected += ((object sender, OnExistingUsersDetectedArgs e) => { ThreadDispatcher.Enqueue(() => OnExistingUsersDetected?.Invoke(sender, e)); });
            base.OnUserLeft                         += ((object sender, OnUserLeftArgs e) => { ThreadDispatcher.Enqueue(() => OnUserLeft?.Invoke(sender, e)); });
            base.OnHostingStarted                   += ((object sender, OnHostingStartedArgs e) => { ThreadDispatcher.Enqueue(() => OnHostingStarted?.Invoke(sender, e)); });
            base.OnHostingStopped                   += ((object sender, OnHostingStoppedArgs e) => { ThreadDispatcher.Enqueue(() => OnHostingStopped?.Invoke(sender, e)); });
            base.OnDisconnected                     += ((object sender, OnDisconnectedEventArgs e) => { ThreadDispatcher.Enqueue(() => OnDisconnected?.Invoke(sender, e)); });
            base.OnConnectionError                  += ((object sender, OnConnectionErrorArgs e) => { ThreadDispatcher.Enqueue(() => OnConnectionError?.Invoke(sender, e)); });
            base.OnChatCleared                      += ((object sender, OnChatClearedArgs e) => { ThreadDispatcher.Enqueue(() => OnChatCleared?.Invoke(sender, e)); });
            base.OnUserTimedout                     += ((object sender, OnUserTimedoutArgs e) => { ThreadDispatcher.Enqueue(() => OnUserTimedout?.Invoke(sender, e)); });
            base.OnLeftChannel                      += ((object sender, OnLeftChannelArgs e) => { ThreadDispatcher.Enqueue(() => OnLeftChannel?.Invoke(sender, e)); });
            base.OnUserBanned                       += ((object sender, OnUserBannedArgs e) => { ThreadDispatcher.Enqueue(() => OnUserBanned?.Invoke(sender, e)); });
            base.OnModeratorsReceived               += ((object sender, OnModeratorsReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnModeratorsReceived?.Invoke(sender, e)); });
            base.OnChatColorChanged                 += ((object sender, OnChatColorChangedArgs e) => { ThreadDispatcher.Enqueue(() => OnChatColorChanged?.Invoke(sender, e)); });
            base.OnSendReceiveData                  += ((object sender, OnSendReceiveDataArgs e) => { ThreadDispatcher.Enqueue(() => OnSendReceiveData?.Invoke(sender, e)); });
            base.OnNowHosting                       += ((object sender, OnNowHostingArgs e) => { ThreadDispatcher.Enqueue(() => OnNowHosting?.Invoke(sender, e)); });
            base.OnBeingHosted                      += ((object sender, OnBeingHostedArgs e) => { ThreadDispatcher.Enqueue(() => OnBeingHosted?.Invoke(sender, e)); });
            base.OnRaidNotification                 += ((object sender, OnRaidNotificationArgs e) => { ThreadDispatcher.Enqueue(() => OnRaidNotification?.Invoke(sender, e)); });
            base.OnGiftedSubscription               += ((object sender, OnGiftedSubscriptionArgs e) => { ThreadDispatcher.Enqueue(() => OnGiftedSubscription?.Invoke(sender, e)); });
            base.OnRaidedChannelIsMatureAudience    += ((object sender, EventArgs arg) => { ThreadDispatcher.Enqueue(() => OnRaidedChannelIsMatureAudience?.Invoke(sender, arg)); });
            base.OnRitualNewChatter                 += ((object sender, OnRitualNewChatterArgs e) => { ThreadDispatcher.Enqueue(() => OnRitualNewChatter?.Invoke(sender, e)); });
            base.OnFailureToReceiveJoinConfirmation += ((object sender, OnFailureToReceiveJoinConfirmationArgs e) => { ThreadDispatcher.Enqueue(() => OnFailureToReceiveJoinConfirmation?.Invoke(sender, e)); });
            base.OnUnaccountedFor                   += ((object sender, OnUnaccountedForArgs e) => { ThreadDispatcher.Enqueue(() => OnUnaccountedFor?.Invoke(sender, e)); });
            base.OnSelfRaidError                    += ((object sender, EventArgs e) => { ThreadDispatcher.Enqueue(() => OnSelfRaidError?.Invoke(sender, e)); });
            base.OnNoPermissionError                += ((object sender, EventArgs e) => { ThreadDispatcher.Enqueue(() => OnNoPermissionError?.Invoke(sender, e)); });
            base.OnMessageCleared                   += ((object sender, OnMessageClearedArgs e) => { ThreadDispatcher.Enqueue(() => OnMessageCleared?.Invoke(sender, e)); });
            base.OnReconnected                      += ((object sender, OnReconnectedEventArgs e) => { ThreadDispatcher.Enqueue(() => OnReconnected?.Invoke(sender, e)); });
            base.OnWhisperThrottled                 += ((object sender, OnWhisperThrottledEventArgs e) => { ThreadDispatcher.Enqueue(() => OnWhisperThrottled?.Invoke(sender, e)); });
            base.OnMessageThrottled                 += ((object sender, OnMessageThrottledEventArgs e) => { ThreadDispatcher.Enqueue(() => OnMessageThrottled?.Invoke(sender, e)); });
            base.OnCommunitySubscription            += ((object sender, OnCommunitySubscriptionArgs e) => { ThreadDispatcher.Enqueue(() => OnCommunitySubscription?.Invoke(sender, e)); });
            base.OnError        += ((object sender, OnErrorEventArgs e) => { ThreadDispatcher.Enqueue(() => OnError?.Invoke(sender, e)); });
            base.OnVIPsReceived += ((object sender, OnVIPsReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnVIPsReceived?.Invoke(sender, e)); });
        }
Example #3
0
        private void ParseIrcMessage(string ircMessage)
        {
            #region Chat Parsing
            DetectionReturn response;

            // On Connected
            if (Internal.Parsing.Chat.detectConnected(ircMessage))
            {
                OnConnected?.Invoke(this, new OnConnectedArgs {
                    AutoJoinChannel = _autoJoinChannel != null ? _autoJoinChannel : "", Username = TwitchUsername
                });
                return;
            }

            // On New Subscriber
            response = Internal.Parsing.Chat.detectNewSubscriber(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnNewSubscriber?.Invoke(this, new OnNewSubscriberArgs {
                    Subscriber = new Models.Client.Subscriber(ircMessage), Channel = response.Channel
                });
                return;
            }

            // On Message Received
            response = Internal.Parsing.Chat.detectMessageReceived(ircMessage, JoinedChannels);
            bool foundMessage = false;
            if (response.Successful)
            {
                foundMessage = true;
                var chatMessage = new ChatMessage(TwitchUsername, ircMessage, ref _channelEmotes, WillReplaceEmotes);
                foreach (var joinedChannel in JoinedChannels.Where(x => x.Channel.ToLower() == response.Channel.ToLower()))
                {
                    joinedChannel.HandleMessage(chatMessage);
                }
                OnMessageReceived?.Invoke(this, new OnMessageReceivedArgs {
                    ChatMessage = chatMessage
                });
                // purposely drop through without return
            }

            // On Command Received (PURPOSELY DROP THROUGH WITHOUT RETURN)
            response = Internal.Parsing.Chat.detectCommandReceived(TwitchUsername, ircMessage, JoinedChannels, ChannelEmotes, WillReplaceEmotes, _chatCommandIdentifiers);
            if (response.Successful)
            {
                var chatMessage = new ChatMessage(TwitchUsername, ircMessage, ref _channelEmotes, WillReplaceEmotes);
                OnChatCommandReceived?.Invoke(this, new OnChatCommandReceivedArgs {
                    Command = new ChatCommand(ircMessage, chatMessage)
                });
                return;
            }
            // We don't want to continue checking if we already found a chat message
            else if (foundMessage)
            {
                return;
            }

            // On Viewer Joined
            response = Internal.Parsing.Chat.detectUserJoined(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                if (TwitchUsername.ToLower() == ircMessage.Split('!')[1].Split('@')[0].ToLower())
                {
                    OnJoinedChannel?.Invoke(this, new OnJoinedChannelArgs {
                        Channel = response.Channel, Username = ircMessage.Split('!')[1].Split('@')[0]
                    });
                    if (OnBeingHosted != null)
                    {
                        if (response.Channel.ToLower() != TwitchUsername && !OverrideBeingHostedCheck)
                        {
                            throw new BadListenException("BeingHosted", "You cannot listen to OnBeingHosted unless you are connected to the broadcaster's channel as the broadcaster. You may override this by setting the TwitchClient property OverrideBeingHostedCheck to true.");
                        }
                    }
                }
                else
                {
                    OnUserJoined?.Invoke(this, new OnUserJoinedArgs {
                        Username = ircMessage.Split('!')[1].Split('@')[0], Channel = response.Channel
                    });
                }
                return;
            }

            // On Viewer Left
            response = Internal.Parsing.Chat.detectedUserLeft(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                string username = ircMessage.Split(':')[1].Split('!')[0];
                if (username.ToLower() == TwitchUsername)
                {
                    JoinedChannels.Remove(JoinedChannels.FirstOrDefault(x => x.Channel.ToLower() == response.Channel));
                    _hasSeenJoinedChannels.Remove(response.Channel.ToLower());
                    OnLeftChannel?.Invoke(this, new OnLeftChannelArgs {
                        BotUsername = username, Channel = response.Channel
                    });
                }
                else
                {
                    OnUserLeft?.Invoke(this, new OnUserLeftArgs {
                        Username = username, Channel = response.Channel
                    });
                }
                return;
            }

            // On Moderator Joined
            response = Internal.Parsing.Chat.detectedModeratorJoined(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnModeratorJoined?.Invoke(this, new OnModeratorJoinedArgs {
                    Username = ircMessage.Split(' ')[4], Channel = response.Channel
                });
                return;
            }

            // On Moderator Left
            response = Internal.Parsing.Chat.detectedModeatorLeft(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnModeratorLeft?.Invoke(this, new OnModeratorLeftArgs {
                    Username = ircMessage.Split(' ')[4], Channel = response.Channel
                });
                return;
            }

            // On Incorrect login
            response = Internal.Parsing.Chat.detectedIncorrectLogin(ircMessage);
            if (response.Successful)
            {
                Disconnect();
                OnIncorrectLogin?.Invoke(this, new OnIncorrectLoginArgs {
                    Exception = new ErrorLoggingInException(ircMessage, _credentials.TwitchUsername)
                });
                return;
            }

            // On Malformed OAuth
            response = Internal.Parsing.Chat.detectedMalformedOAuth(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                Disconnect();
                OnIncorrectLogin?.Invoke(this, new OnIncorrectLoginArgs {
                    Exception = new ErrorLoggingInException("Invalid OAuth key. Remember to add 'oauth:' as a prefix. Example: oauth:19nds9sbnga9asd", _credentials.TwitchUsername)
                });
                return;
            }

            // On Host Left
            response = Internal.Parsing.Chat.detectedHostLeft(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnHostLeft?.Invoke(this, null);
                return;
            }

            // On Channel State Changed
            response = Internal.Parsing.Chat.detectedChannelStateChanged(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnChannelStateChanged?.Invoke(this, new OnChannelStateChangedArgs {
                    ChannelState = new ChannelState(ircMessage), Channel = response.Channel
                });
                return;
            }

            // On User State Changed
            response = Internal.Parsing.Chat.detectedUserStateChanged(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                var userState = new UserState(ircMessage);
                if (!_hasSeenJoinedChannels.Contains(userState.Channel.ToLower()))
                {
                    // UserState fired from joining channel
                    _hasSeenJoinedChannels.Add(userState.Channel.ToLower());
                    OnUserStateChanged?.Invoke(this, new OnUserStateChangedArgs {
                        UserState = userState
                    });
                }
                else
                {
                    // UserState fired from sending a message
                    OnMessageSent?.Invoke(this, new OnMessageSentArgs {
                        SentMessage = new SentMessage(userState, _lastMessageSent)
                    });
                }
                return;
            }

            // On ReSubscriber
            response = Internal.Parsing.Chat.detectedReSubscriber(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                var resub = new Models.Client.Subscriber(ircMessage);
                OnReSubscriber?.Invoke(this, new OnReSubscriberArgs {
                    ReSubscriber = resub
                });
                return;
            }

            // On PING received
            response = Internal.Parsing.Chat.detectedPing(ircMessage);
            if (response.Successful && !DisableAutoPong)
            {
                SendRaw("PONG");
                return;
            }

            // On PONG received (don't do anything)
            response = Internal.Parsing.Chat.detectedPong(ircMessage);
            if (response.Successful)
            {
                return;
            }

            // On Hosting Stopped
            if (Internal.Parsing.Chat.detectedHostingStopped(ircMessage))
            {
                int viewers;
                int.TryParse(ircMessage.Split(' ')[4], out viewers);
                OnHostingStopped?.Invoke(this, new OnHostingStoppedArgs()
                {
                    Viewers = viewers, HostingChannel = ircMessage.Split(' ')[2].Remove(0, 1)
                });
                return;
            }

            // On Hosting Started
            if (Internal.Parsing.Chat.detectedHostingStarted(ircMessage))
            {
                int viewers;
                int.TryParse(ircMessage.Split(' ')[4], out viewers);
                OnHostingStarted?.Invoke(this, new OnHostingStartedArgs()
                {
                    Viewers = viewers, HostingChannel = ircMessage.Split(' ')[2].Remove(0, 1), TargetChannel = ircMessage.Split(' ')[3].Remove(0, 1)
                });
                return;
            }

            // On Existing Users Detected
            response = Internal.Parsing.Chat.detectedExistingUsers(ircMessage, _credentials.TwitchUsername, JoinedChannels);
            if (response.Successful)
            {
                OnExistingUsersDetected?.Invoke(this, new OnExistingUsersDetectedArgs {
                    Channel = response.Channel,
                    Users   = ircMessage.Replace($":{_credentials.TwitchUsername}.tmi.twitch.tv 353 {_credentials.TwitchUsername} = #{response.Channel} :", "").Split(' ').ToList <string>()
                });
                return;
            }

            // On Now Hosting
            response = Internal.Parsing.Chat.detectedNowHosting(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnNowHosting?.Invoke(this, new OnNowHostingArgs {
                    Channel       = response.Channel,
                    HostedChannel = ircMessage.Split(' ')[6].Replace(".", "")
                });
                return;
            }

            // On channel join completed with all existing names
            response = Internal.Parsing.Chat.detectedJoinChannelCompleted(ircMessage);
            if (response.Successful)
            {
                currentlyJoiningChannels = false;
                queueingJoinCheck();
                return;
            }

            // On another channel hosts this broadcaster's channel
            response = Internal.Parsing.Chat.detectedBeingHosted(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                var hostedBy = ircMessage.Split(':')[2].Split(' ')[0];
                var viewers  = ((ircMessage.Contains("hosting you for") && ircMessage.Split(' ').Count() >= 9) ? int.Parse(ircMessage.Split(' ')[8]) : -1);
                var isAuto   = ircMessage.Contains("now autohosting");
                OnBeingHosted?.Invoke(this, new OnBeingHostedArgs {
                    Channel = response.Channel, BotUsername = TwitchUsername, HostedByChannel = hostedBy,
                    Viewers = viewers, IsAutoHosted = isAuto
                });
                return;
            }
            #endregion

            #region Clear Chat, Timeouts, and Bans
            // On clear chat detected
            response = Internal.Parsing.Chat.detectedClearedChat(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnChatCleared?.Invoke(this, new OnChatClearedArgs {
                    Channel = response.Channel
                });
                return;
            }

            // On timeout detected
            response = Internal.Parsing.Chat.detectedUserTimedout(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnUserTimedout?.Invoke(this, new OnUserTimedoutArgs
                {
                    Channel         = response.Channel,
                    TimeoutDuration = int.Parse(ircMessage.Split(';')[0].Split('=')[1]),
                    TimeoutReason   = ircMessage.Split(' ')[0].Split('=')[2].Replace("\\s", " "),
                    Username        = ircMessage.Split(':')[2]
                });
                return;
            }

            // On ban detected
            response = Internal.Parsing.Chat.detectedUserBanned(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnUserBanned?.Invoke(this, new OnUserBannedArgs
                {
                    Channel   = response.Channel,
                    BanReason = ircMessage.Split(' ')[0].Split('=')[1].Replace("\\s", " "),
                    Username  = ircMessage.Split(':')[2]
                });
                return;
            }

            // On moderators received detected
            response = Internal.Parsing.Chat.detectedModeratorsReceived(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnModeratorsReceived?.Invoke(this, new OnModeratorsReceivedArgs
                {
                    Channel    = ircMessage.Split('#')[1].Split(' ')[0],
                    Moderators = ircMessage.Replace(" ", "").Split(':')[3].Split(',').ToList <string>()
                });
                return;
            }
            #endregion

            #region Others
            // On chat color changed detected
            response = Internal.Parsing.Chat.detectedChatColorChanged(ircMessage, JoinedChannels);
            if (response.Successful)
            {
                OnChatColorChanged?.Invoke(this, new OnChatColorChangedArgs
                {
                    Channel = ircMessage.Split('#')[1].Split(' ')[0]
                });
                return;
            }
            #endregion

            #region Whisper Parsing
            if (ircMessage.Split(' ').Count() > 2 && (ircMessage.Split(' ')[1] == "WHISPER" || ircMessage.Split(' ')[2] == "WHISPER"))
            {
                // On Whisper Message Received
                WhisperMessage receivedMessage = null;
                if (Internal.Parsing.Whisper.detectedWhisperReceived(ircMessage, _credentials.TwitchUsername))
                {
                    receivedMessage = new WhisperMessage(ircMessage, _credentials.TwitchUsername);
                    PreviousWhisper = receivedMessage;
                    OnWhisperReceived?.Invoke(this, new OnWhisperReceivedArgs {
                        WhisperMessage = receivedMessage
                    });
                    // Fall through to detect command as well
                }

                // On Whisper Command Received
                if (Internal.Parsing.Whisper.detectedWhisperCommandReceived(ircMessage, _credentials.TwitchUsername, _whisperCommandIdentifiers))
                {
                    var    whisperMessage    = new WhisperMessage(ircMessage, _credentials.TwitchUsername);
                    string command           = whisperMessage.Message.Split(' ')?[0].Substring(1, whisperMessage.Message.Split(' ')[0].Length - 1) ?? whisperMessage.Message.Substring(1, whisperMessage.Message.Length - 1);
                    var    argumentsAsList   = whisperMessage.Message.Split(' ')?.Where(arg => arg != whisperMessage.Message[0] + command).ToList <string>() ?? new List <string>();
                    string argumentsAsString = whisperMessage.Message.Replace(whisperMessage.Message.Split(' ')?[0] +" ", "") ?? "";
                    OnWhisperCommandReceived?.Invoke(this, new OnWhisperCommandReceivedArgs {
                        Command = command, WhisperMessage = whisperMessage, ArgumentsAsList = argumentsAsList, ArgumentsAsString = argumentsAsString
                    });
                    return;
                }

                // Return if whisper message was parsed successfully
                if (receivedMessage != null)
                {
                    return;
                }
            }
            #endregion

            // Any other messages here
            log($"Unaccounted for: {ircMessage}");
        }
Example #4
0
 public TwitchClientUnity(ILogger <TwitchClientUnity> logger) : base(logger)
 {
     CoroutineHost.PrepareCrossThread();
     // client = new TwitchClient(credentials, channel, chatCommandIdentifier,whisperCommandIdentifier,logging,logger,autoReListenOnExceptions);
     base.OnLog                              += ((object sender, OnLogArgs e) => { CoroutineHost.Host(() => OnLog?.Invoke(sender, e)); });
     base.OnConnected                        += ((object sender, OnConnectedArgs e) => { CoroutineHost.Host(() => OnConnected?.Invoke(sender, e)); });
     base.OnJoinedChannel                    += ((object sender, OnJoinedChannelArgs e) => { CoroutineHost.Host(() => OnJoinedChannel?.Invoke(sender, e)); });
     base.OnIncorrectLogin                   += ((object sender, OnIncorrectLoginArgs e) => { CoroutineHost.Host(() => OnIncorrectLogin?.Invoke(sender, e)); });
     base.OnChannelStateChanged              += ((object sender, OnChannelStateChangedArgs e) => { CoroutineHost.Host(() => OnChannelStateChanged?.Invoke(sender, e)); });
     base.OnUserStateChanged                 += ((object sender, OnUserStateChangedArgs e) => { CoroutineHost.Host(() => OnUserStateChanged?.Invoke(sender, e)); });
     base.OnMessageReceived                  += ((object sender, OnMessageReceivedArgs e) => { CoroutineHost.Host(() => OnMessageReceived?.Invoke(sender, e)); });
     base.OnWhisperReceived                  += ((object sender, OnWhisperReceivedArgs e) => { CoroutineHost.Host(() => OnWhisperReceived?.Invoke(sender, e)); });
     base.OnMessageSent                      += ((object sender, OnMessageSentArgs e) => { CoroutineHost.Host(() => OnMessageSent?.Invoke(sender, e)); });
     base.OnWhisperSent                      += ((object sender, OnWhisperSentArgs e) => { CoroutineHost.Host(() => OnWhisperSent?.Invoke(sender, e)); });
     base.OnChatCommandReceived              += ((object sender, OnChatCommandReceivedArgs e) => { CoroutineHost.Host(() => OnChatCommandReceived?.Invoke(sender, e)); });
     base.OnWhisperCommandReceived           += ((object sender, OnWhisperCommandReceivedArgs e) => { CoroutineHost.Host(() => OnWhisperCommandReceived?.Invoke(sender, e)); });
     base.OnUserJoined                       += ((object sender, OnUserJoinedArgs e) => { CoroutineHost.Host(() => OnUserJoined?.Invoke(sender, e)); });
     base.OnModeratorJoined                  += ((object sender, OnModeratorJoinedArgs e) => { CoroutineHost.Host(() => OnModeratorJoined?.Invoke(sender, e)); });
     base.OnModeratorLeft                    += ((object sender, OnModeratorLeftArgs e) => { CoroutineHost.Host(() => OnModeratorLeft?.Invoke(sender, e)); });
     base.OnNewSubscriber                    += ((object sender, OnNewSubscriberArgs e) => { CoroutineHost.Host(() => OnNewSubscriber?.Invoke(sender, e)); });
     base.OnReSubscriber                     += ((object sender, OnReSubscriberArgs e) => { CoroutineHost.Host(() => OnReSubscriber?.Invoke(sender, e)); });
     base.OnHostLeft                         += ((object sender, EventArgs arg) => { CoroutineHost.Host(() => OnHostLeft(sender, arg)); });
     base.OnExistingUsersDetected            += ((object sender, OnExistingUsersDetectedArgs e) => { CoroutineHost.Host(() => OnExistingUsersDetected?.Invoke(sender, e)); });
     base.OnUserLeft                         += ((object sender, OnUserLeftArgs e) => { CoroutineHost.Host(() => OnUserLeft?.Invoke(sender, e)); });
     base.OnHostingStarted                   += ((object sender, OnHostingStartedArgs e) => { CoroutineHost.Host(() => OnHostingStarted?.Invoke(sender, e)); });
     base.OnHostingStopped                   += ((object sender, OnHostingStoppedArgs e) => { CoroutineHost.Host(() => OnHostingStopped?.Invoke(sender, e)); });
     base.OnDisconnected                     += ((object sender, OnDisconnectedArgs e) => { CoroutineHost.Host(() => OnDisconnected?.Invoke(sender, e)); });
     base.OnConnectionError                  += ((object sender, OnConnectionErrorArgs e) => { CoroutineHost.Host(() => OnConnectionError?.Invoke(sender, e)); });
     base.OnChatCleared                      += ((object sender, OnChatClearedArgs e) => { CoroutineHost.Host(() => OnChatCleared?.Invoke(sender, e)); });
     base.OnUserTimedout                     += ((object sender, OnUserTimedoutArgs e) => { CoroutineHost.Host(() => OnUserTimedout?.Invoke(sender, e)); });
     base.OnLeftChannel                      += ((object sender, OnLeftChannelArgs e) => { CoroutineHost.Host(() => OnLeftChannel?.Invoke(sender, e)); });
     base.OnUserBanned                       += ((object sender, OnUserBannedArgs e) => { CoroutineHost.Host(() => OnUserBanned?.Invoke(sender, e)); });
     base.OnModeratorsReceived               += ((object sender, OnModeratorsReceivedArgs e) => { CoroutineHost.Host(() => OnModeratorsReceived?.Invoke(sender, e)); });
     base.OnChatColorChanged                 += ((object sender, OnChatColorChangedArgs e) => { CoroutineHost.Host(() => OnChatColorChanged?.Invoke(sender, e)); });
     base.OnSendReceiveData                  += ((object sender, OnSendReceiveDataArgs e) => { CoroutineHost.Host(() => OnSendReceiveData?.Invoke(sender, e)); });
     base.OnNowHosting                       += ((object sender, OnNowHostingArgs e) => { CoroutineHost.Host(() => OnNowHosting?.Invoke(sender, e)); });
     base.OnBeingHosted                      += ((object sender, OnBeingHostedArgs e) => { CoroutineHost.Host(() => OnBeingHosted?.Invoke(sender, e)); });
     base.OnRaidNotification                 += ((object sender, OnRaidNotificationArgs e) => { CoroutineHost.Host(() => OnRaidNotification?.Invoke(sender, e)); });
     base.OnGiftedSubscription               += ((object sender, OnGiftedSubscriptionArgs e) => { CoroutineHost.Host(() => OnGiftedSubscription?.Invoke(sender, e)); });
     base.OnRaidedChannelIsMatureAudience    += ((object sender, EventArgs arg) => { CoroutineHost.Host(() => OnRaidedChannelIsMatureAudience(sender, arg)); });
     base.OnRitualNewChatter                 += ((object sender, OnRitualNewChatterArgs e) => { CoroutineHost.Host(() => OnRitualNewChatter?.Invoke(sender, e)); });
     base.OnFailureToReceiveJoinConfirmation += ((object sender, OnFailureToReceiveJoinConfirmationArgs e) => { CoroutineHost.Host(() => OnFailureToReceiveJoinConfirmation?.Invoke(sender, e)); });
     base.OnUnaccountedFor                   += ((object sender, OnUnaccountedForArgs e) => { CoroutineHost.Host(() => OnUnaccountedFor?.Invoke(sender, e)); });
 }
Example #5
0
        private void ParseIrcMessage(string ircMessage)
        {
            // Hack to accomodate at least cyrillic characters, possibly more
            string decodedMessage = Encoding.UTF8.GetString(Encoding.Default.GetBytes(ircMessage));

            #region Chat Parsing
            DetectionReturn response;

            // On Connected
            if (ChatParsing.detectConnected(decodedMessage))
            {
                IsConnected = true;
                OnConnected?.Invoke(this, new OnConnectedArgs {
                    AutoJoinChannel = "", Username = TwitchUsername
                });
                return;
            }

            // On New Subscriber
            response = ChatParsing.detectNewSubscriber(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnNewSubscriber?.Invoke(this, new OnNewSubscriberArgs {
                    Subscriber = new NewSubscriber(decodedMessage), Channel = response.Channel
                });
                return;
            }

            // On Command Received (PURPOSELY DROP THROUGH WITHOUT RETURN)
            response = ChatParsing.detectCommandReceived(TwitchUsername, decodedMessage, JoinedChannels, ChannelEmotes, WillReplaceEmotes, _chatCommandIdentifiers);
            if (response.Successful)
            {
                var chatMessage = new ChatMessage(TwitchUsername, decodedMessage, ref _channelEmotes, WillReplaceEmotes);
                OnChatCommandReceived?.Invoke(this, new OnChatCommandReceivedArgs {
                    Command = new ChatCommand(decodedMessage, chatMessage)
                });
                // purposely drop through without return
            }

            // On Message Received
            response = ChatParsing.detectMessageReceived(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                var chatMessage = new ChatMessage(TwitchUsername, decodedMessage, ref _channelEmotes, WillReplaceEmotes);
                foreach (var joinedChannel in JoinedChannels.Where(x => x.Channel.ToLower() == response.Channel.ToLower()))
                {
                    joinedChannel.HandleMessage(chatMessage);
                }
                OnMessageReceived?.Invoke(this, new OnMessageReceivedArgs {
                    ChatMessage = chatMessage
                });
                return;
            }

            // On Viewer Joined
            response = ChatParsing.detectUserJoined(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                if (TwitchUsername.ToLower() == decodedMessage.Split('!')[1].Split('@')[0].ToLower())
                {
                    OnJoinedChannel?.Invoke(this, new OnJoinedChannelArgs {
                        Channel = response.Channel, Username = decodedMessage.Split('!')[1].Split('@')[0]
                    });
                }
                else
                {
                    OnUserJoined?.Invoke(this, new OnUserJoinedArgs {
                        Username = decodedMessage.Split('!')[1].Split('@')[0], Channel = response.Channel
                    });
                }
                return;
            }

            // On Viewer Left
            response = ChatParsing.detectedUserLeft(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                string username = decodedMessage.Split(':')[1].Split('!')[0];
                if (username.ToLower() == TwitchUsername)
                {
                    JoinedChannels.Remove(JoinedChannels.FirstOrDefault(x => x.Channel.ToLower() == response.Channel));
                    _hasSeenJoinedChannels.Remove(response.Channel.ToLower());
                    OnClientLeftChannel?.Invoke(this, new OnClientLeftChannelArgs {
                        BotUsername = username, Channel = response.Channel
                    });
                }
                else
                {
                    OnUserLeft?.Invoke(this, new OnUserLeftArgs {
                        Username = username, Channel = response.Channel
                    });
                }
                return;
            }

            // On Moderator Joined
            response = ChatParsing.detectedModeratorJoined(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnModeratorJoined?.Invoke(this, new OnModeratorJoinedArgs {
                    Username = decodedMessage.Split(' ')[4], Channel = response.Channel
                });
                return;
            }

            // On Moderator Left
            response = ChatParsing.detectedModeatorLeft(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnModeratorLeft?.Invoke(this, new OnModeratorLeftArgs {
                    Username = decodedMessage.Split(' ')[4], Channel = response.Channel
                });
                return;
            }

            // On Incorrect login
            response = ChatParsing.detectedIncorrectLogin(decodedMessage);
            if (response.Successful)
            {
                Disconnect();
                OnIncorrectLogin?.Invoke(this, new OnIncorrectLoginArgs {
                    Exception = new ErrorLoggingInException(decodedMessage, _credentials.TwitchUsername)
                });
                return;
            }

            // On Malformed OAuth
            response = ChatParsing.detectedMalformedOAuth(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                Disconnect();
                OnIncorrectLogin?.Invoke(this, new OnIncorrectLoginArgs {
                    Exception = new ErrorLoggingInException("Invalid OAuth key. Remember to add 'oauth:' as a prefix. Example: oauth:19nds9sbnga9asd", _credentials.TwitchUsername)
                });
                return;
            }

            // On Host Left
            response = ChatParsing.detectedHostLeft(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnHostLeft?.Invoke(this, null);
                return;
            }

            // On Channel State Changed
            response = ChatParsing.detectedChannelStateChanged(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnChannelStateChanged?.Invoke(this, new OnChannelStateChangedArgs {
                    ChannelState = new ChannelState(decodedMessage), Channel = response.Channel
                });
                return;
            }

            // On User State Changed
            response = ChatParsing.detectedUserStateChanged(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                var userState = new UserState(decodedMessage);
                if (!_hasSeenJoinedChannels.Contains(userState.Channel.ToLower()))
                {
                    // UserState fired from joining channel
                    _hasSeenJoinedChannels.Add(userState.Channel.ToLower());
                    OnUserStateChanged?.Invoke(this, new OnUserStateChangedArgs {
                        UserState = userState
                    });
                }
                else
                {
                    // UserState fired from sending a message
                    OnMessageSent?.Invoke(this, new OnMessageSentArgs {
                        SentMessage = new SentMessage(userState, _lastMessageSent)
                    });
                }
                return;
            }

            // On ReSubscriber
            response = ChatParsing.detectedReSubscriber(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                var resub = new ReSubscriber(decodedMessage);
                OnReSubscriber?.Invoke(this, new OnReSubscriberArgs {
                    ReSubscriber = resub
                });
                return;
            }

            // On PING received
            response = ChatParsing.detectedPing(decodedMessage);
            if (response.Successful && !DisableAutoPong)
            {
                SendRaw("PONG");
                return;
            }

            // On PONG received (don't do anything)
            response = ChatParsing.detectedPong(decodedMessage);
            if (response.Successful)
            {
                return;
            }

            // On Hosting Stopped
            if (ChatParsing.detectedHostingStopped(decodedMessage))
            {
                int viewers;
                int.TryParse(decodedMessage.Split(' ')[4], out viewers);
                OnHostingStopped?.Invoke(this, new OnHostingStoppedArgs()
                {
                    Viewers = viewers, HostingChannel = decodedMessage.Split(' ')[2].Remove(0, 1)
                });
                return;
            }

            // On Hosting Started
            if (ChatParsing.detectedHostingStarted(decodedMessage))
            {
                int viewers;
                int.TryParse(decodedMessage.Split(' ')[4], out viewers);
                OnHostingStarted?.Invoke(this, new OnHostingStartedArgs()
                {
                    Viewers = viewers, HostingChannel = decodedMessage.Split(' ')[2].Remove(0, 1), TargetChannel = decodedMessage.Split(' ')[3].Remove(0, 1)
                });
                return;
            }

            // On Existing Users Detected
            response = ChatParsing.detectedExistingUsers(decodedMessage, _credentials.TwitchUsername, JoinedChannels);
            if (response.Successful)
            {
                OnExistingUsersDetected?.Invoke(this, new OnExistingUsersDetectedArgs {
                    Channel = response.Channel,
                    Users   = decodedMessage.Replace($":{_credentials.TwitchUsername}.tmi.twitch.tv 353 {_credentials.TwitchUsername} = #{response.Channel} :", "").Split(' ').ToList <string>()
                });
                return;
            }

            // On Now Hosting
            response = ChatParsing.detectedNowHosting(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnNowHosting?.Invoke(this, new OnNowHostingArgs {
                    Channel       = response.Channel,
                    HostedChannel = decodedMessage.Split(' ')[6].Replace(".", "")
                });
                return;
            }

            // On channel join completed with all existing names
            response = ChatParsing.detectedJoinChannelCompleted(decodedMessage);
            if (response.Successful)
            {
                currentlyJoiningChannels = false;
                queueingJoinCheck();
            }
            #endregion

            #region Clear Chat, Timeouts, and Bans
            // On clear chat detected
            response = ChatParsing.detectedClearedChat(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnChatCleared?.Invoke(this, new OnChatClearedArgs {
                    Channel = response.Channel
                });
                return;
            }

            // On timeout detected
            response = ChatParsing.detectedUserTimedout(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnUserTimedout?.Invoke(this, new OnUserTimedoutArgs
                {
                    Channel         = response.Channel,
                    TimeoutDuration = int.Parse(decodedMessage.Split(';')[0].Split('=')[1]),
                    TimeoutReason   = decodedMessage.Split(' ')[0].Split('=')[2].Replace("\\s", " "),
                    Username        = decodedMessage.Split(':')[2]
                });
                return;
            }

            // On ban detected
            response = ChatParsing.detectedUserBanned(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnUserBanned?.Invoke(this, new OnUserBannedArgs
                {
                    Channel   = response.Channel,
                    BanReason = decodedMessage.Split(' ')[0].Split('=')[1].Replace("\\s", " "),
                    Username  = decodedMessage.Split(':')[2]
                });
                return;
            }

            // On moderators received detected
            response = ChatParsing.detectedModeratorsReceived(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnModeratorsReceived?.Invoke(this, new OnModeratorsReceivedArgs
                {
                    Channel    = decodedMessage.Split('#')[1].Split(' ')[0],
                    Moderators = decodedMessage.Replace(" ", "").Split(':')[3].Split(',').ToList <string>()
                });
                return;
            }
            #endregion

            #region Others
            // On chat color changed detected
            response = ChatParsing.detectedChatColorChanged(decodedMessage, JoinedChannels);
            if (response.Successful)
            {
                OnChatColorChanged?.Invoke(this, new OnChatColorChangedArgs
                {
                    Channel = decodedMessage.Split('#')[1].Split(' ')[0]
                });
                return;
            }
            #endregion

            #region Whisper Parsing
            if (decodedMessage.Split(' ').Count() > 2 && (decodedMessage.Split(' ')[1] == "WHISPER" || decodedMessage.Split(' ')[2] == "WHISPER"))
            {
                // On Whisper Message Received
                WhisperMessage receivedMessage = null;
                if (WhisperParsing.detectedWhisperReceived(decodedMessage, _credentials.TwitchUsername))
                {
                    receivedMessage = new WhisperMessage(decodedMessage, _credentials.TwitchUsername);
                    PreviousWhisper = receivedMessage;
                    OnWhisperReceived?.Invoke(this, new OnWhisperReceivedArgs {
                        WhisperMessage = receivedMessage
                    });
                    // Fall through to detect command as well
                }

                // On Whisper Command Received
                if (WhisperParsing.detectedWhisperCommandReceived(decodedMessage, _credentials.TwitchUsername, _whisperCommandIdentifiers))
                {
                    var    whisperMessage    = new WhisperMessage(decodedMessage, _credentials.TwitchUsername);
                    string command           = whisperMessage.Message.Split(' ')?[0].Substring(1, whisperMessage.Message.Split(' ')[0].Length - 1) ?? whisperMessage.Message.Substring(1, whisperMessage.Message.Length - 1);
                    var    argumentsAsList   = whisperMessage.Message.Split(' ')?.Where(arg => arg != whisperMessage.Message[0] + command).ToList <string>() ?? new List <string>();
                    string argumentsAsString = whisperMessage.Message.Replace(whisperMessage.Message.Split(' ')?[0] +" ", "") ?? "";
                    OnWhisperCommandReceived?.Invoke(this, new OnWhisperCommandReceivedArgs {
                        Command = command, WhisperMessage = whisperMessage, ArgumentsAsList = argumentsAsList, ArgumentsAsString = argumentsAsString
                    });
                    return;
                }

                // Return if whisper message was parsed successfully
                if (receivedMessage != null)
                {
                    return;
                }
            }
            #endregion

            // Any other messages here
            if (_logging)
            {
                Common.Log($"Unaccounted for: {decodedMessage}");
            }
        }
Example #6
0
        public Client() : base(null)
        {
            _threadDispatcher = new GameObject("TwitchClientUnityDispatcher");
            _threadDispatcher.AddComponent <ThreadDispatcher>();
            UnityEngine.Object.DontDestroyOnLoad(_threadDispatcher);

            base.OnLog                              += ((object sender, OnLogArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnLog?.Invoke(sender, e)); });
            base.OnConnected                        += ((object sender, OnConnectedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnConnected?.Invoke(sender, e)); });
            base.OnJoinedChannel                    += ((object sender, OnJoinedChannelArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnJoinedChannel?.Invoke(sender, e)); });
            base.OnIncorrectLogin                   += ((object sender, OnIncorrectLoginArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnIncorrectLogin?.Invoke(sender, e)); });
            base.OnChannelStateChanged              += ((object sender, OnChannelStateChangedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnChannelStateChanged?.Invoke(sender, e)); });
            base.OnUserStateChanged                 += ((object sender, OnUserStateChangedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnUserStateChanged?.Invoke(sender, e)); });
            base.OnMessageReceived                  += ((object sender, OnMessageReceivedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnMessageReceived?.Invoke(sender, e)); });
            base.OnWhisperReceived                  += ((object sender, OnWhisperReceivedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnWhisperReceived?.Invoke(sender, e)); });
            base.OnMessageSent                      += ((object sender, OnMessageSentArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnMessageSent?.Invoke(sender, e)); });
            base.OnWhisperSent                      += ((object sender, OnWhisperSentArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnWhisperSent?.Invoke(sender, e)); });
            base.OnChatCommandReceived              += ((object sender, OnChatCommandReceivedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnChatCommandReceived?.Invoke(sender, e)); });
            base.OnWhisperCommandReceived           += ((object sender, OnWhisperCommandReceivedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnWhisperCommandReceived?.Invoke(sender, e)); });
            base.OnUserJoined                       += ((object sender, OnUserJoinedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnUserJoined?.Invoke(sender, e)); });
            base.OnModeratorJoined                  += ((object sender, OnModeratorJoinedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnModeratorJoined?.Invoke(sender, e)); });
            base.OnModeratorLeft                    += ((object sender, OnModeratorLeftArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnModeratorLeft?.Invoke(sender, e)); });
            base.OnNewSubscriber                    += ((object sender, OnNewSubscriberArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnNewSubscriber?.Invoke(sender, e)); });
            base.OnReSubscriber                     += ((object sender, OnReSubscriberArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnReSubscriber?.Invoke(sender, e)); });
            base.OnHostLeft                         += ((object sender, EventArgs arg) => { ThreadDispatcher.Instance().Enqueue(() => OnHostLeft(sender, arg)); });
            base.OnExistingUsersDetected            += ((object sender, OnExistingUsersDetectedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnExistingUsersDetected?.Invoke(sender, e)); });
            base.OnUserLeft                         += ((object sender, OnUserLeftArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnUserLeft?.Invoke(sender, e)); });
            base.OnHostingStarted                   += ((object sender, OnHostingStartedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnHostingStarted?.Invoke(sender, e)); });
            base.OnHostingStopped                   += ((object sender, OnHostingStoppedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnHostingStopped?.Invoke(sender, e)); });
            base.OnDisconnected                     += ((object sender, OnDisconnectedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnDisconnected?.Invoke(sender, e)); });
            base.OnConnectionError                  += ((object sender, OnConnectionErrorArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnConnectionError?.Invoke(sender, e)); });
            base.OnChatCleared                      += ((object sender, OnChatClearedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnChatCleared?.Invoke(sender, e)); });
            base.OnUserTimedout                     += ((object sender, OnUserTimedoutArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnUserTimedout?.Invoke(sender, e)); });
            base.OnLeftChannel                      += ((object sender, OnLeftChannelArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnLeftChannel?.Invoke(sender, e)); });
            base.OnUserBanned                       += ((object sender, OnUserBannedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnUserBanned?.Invoke(sender, e)); });
            base.OnModeratorsReceived               += ((object sender, OnModeratorsReceivedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnModeratorsReceived?.Invoke(sender, e)); });
            base.OnChatColorChanged                 += ((object sender, OnChatColorChangedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnChatColorChanged?.Invoke(sender, e)); });
            base.OnSendReceiveData                  += ((object sender, OnSendReceiveDataArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnSendReceiveData?.Invoke(sender, e)); });
            base.OnNowHosting                       += ((object sender, OnNowHostingArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnNowHosting?.Invoke(sender, e)); });
            base.OnBeingHosted                      += ((object sender, OnBeingHostedArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnBeingHosted?.Invoke(sender, e)); });
            base.OnRaidNotification                 += ((object sender, OnRaidNotificationArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnRaidNotification?.Invoke(sender, e)); });
            base.OnGiftedSubscription               += ((object sender, OnGiftedSubscriptionArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnGiftedSubscription?.Invoke(sender, e)); });
            base.OnRaidedChannelIsMatureAudience    += ((object sender, EventArgs arg) => { ThreadDispatcher.Instance().Enqueue(() => OnRaidedChannelIsMatureAudience(sender, arg)); });
            base.OnRitualNewChatter                 += ((object sender, OnRitualNewChatterArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnRitualNewChatter?.Invoke(sender, e)); });
            base.OnFailureToReceiveJoinConfirmation += ((object sender, OnFailureToReceiveJoinConfirmationArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnFailureToReceiveJoinConfirmation?.Invoke(sender, e)); });
            base.OnUnaccountedFor                   += ((object sender, OnUnaccountedForArgs e) => { ThreadDispatcher.Instance().Enqueue(() => OnUnaccountedFor?.Invoke(sender, e)); });
        }