예제 #1
0
 public CreeperCarl(ICarl carl)
 {
     s_instance    = this;
     m_carl        = carl;
     m_userChecker = new Thread(ChannelUserCheckerThread);
     m_userChecker.IsBackground = false;
     m_userChecker.Start();
 }
예제 #2
0
        public bool Run(string[] args)
        {
            CarlConfig config = CarlConfig.Get();

            if (config != null)
            {
                m_chatBotUserId     = config.ChatBotUserId;
                m_chatBotoAuthToken = config.ChatBotOAuthToken;
                m_viewerCountLimit  = config.ViewerCountLimit;
            }
            else
            {
                Logger.Info("Checking Args...");
                if (args.Length < 2)
                {
                    Logger.Info("Usage: carl <chat bot user Id> <chat bot oauth> (channel viewer count limit - default is 5)");
                    Logger.Info("User info can be found here: https://dev.mixer.com/tutorials/chatbot.html");
                    return(false);
                }

                if (!int.TryParse(args[0], out m_chatBotUserId))
                {
                    Logger.Error("Failed to parse chat bot user id.");
                    return(false);
                }
                m_chatBotoAuthToken = args[1];
                if (args.Length > 2)
                {
                    if (!int.TryParse(args[2], out m_viewerCountLimit))
                    {
                        Logger.Error("Failed to parse viewer count limit.");
                        return(false);
                    }
                }
            }

            Logger.Info($"Starting! Viewer Count Limit:{m_viewerCountLimit}.");

            // Set the oauth token
            MixerUtils.SetMixerCreds(m_chatBotoAuthToken);

            Logger.Info("Setting up discovery");
            // Start the discovery process.
            ChannelDiscover dis = new ChannelDiscover(m_viewerCountLimit, m_channelOverrides);

            dis.OnChannelOnlineUpdate += OnChannelOnlineUpdate;
            dis.Run();

            Logger.Info("Setting up work master");
            // Setup the work master
            m_masterWorker = new Thread(WorkMasterThread);
            m_masterWorker.IsBackground = true;
            m_masterWorker.Start();

            Logger.Info("Setting up worker threads");
            // Setup the worker threads.
            int i = 0;

            while (i < m_workerLimit)
            {
                i++;
                Thread t = new Thread(WorkerThread);
                t.IsBackground = true;
                t.Start();
                m_workers.Add(t);
            }

            // Create our creeper.
            m_creeperCarl = new CreeperCarl(this);

            Logger.Info("Running!");
            return(true);
        }
예제 #3
0
        private void WorkMasterThread()
        {
            while (true)
            {
                DateTime   workStart         = DateTime.Now;
                int        connectedChannels = 0;
                int        eligibleChannels  = 0;
                List <int> toRemove          = new List <int>();
                lock (m_channelMap)
                {
                    foreach (KeyValuePair <int, ChannelEntry> ent in m_channelMap)
                    {
                        if (m_lastChannelUpdateTime.HasValue && (m_lastChannelUpdateTime.Value - ent.Value.LastFoundTime).TotalSeconds > 180)
                        {
                            toRemove.Add(ent.Value.Channel.Id);
                        }
                        else
                        {
                            // If there isn't a chat setup, add it to the queue to get spun up.
                            eligibleChannels++;
                            if (ent.Value.Chat == null)
                            {
                                lock (m_channelProcessQueue)
                                {
                                    if (!m_channelProcessQueue.ContainsKey(ent.Value.Channel.Id))
                                    {
                                        m_channelProcessQueue.Add(ent.Value.Channel.Id, false);
                                    }
                                }
                            }
                            else
                            {
                                // If the chat gets stuck in a disconnected state, clear the chat object.
                                if (ent.Value.Chat.IsDisconnected())
                                {
                                    ent.Value.Chat = null;
                                }
                                else
                                {
                                    connectedChannels++;
                                }
                            }
                        }
                    }
                }

                Logger.Info($"{connectedChannels}/{eligibleChannels} ({(eligibleChannels == 0 ? 0 : Math.Round(((double)connectedChannels / (double)eligibleChannels)*100, 2))}%) connected channels; tracking {CreeperCarl.GetViewerCount().ToString("n0", Culture)} viewers. Work time was: {(DateTime.Now - workStart).TotalMilliseconds}ms");

                foreach (int id in toRemove)
                {
                    RemoveChannel(id, "the channel is offline or under the viewer limit.").ConfigureAwait(false);
                }

                DateTime sleepStart = DateTime.Now;
                Thread.Sleep(m_workMasterTimeMs);
                double time = (DateTime.Now - sleepStart).TotalMilliseconds;
                if (time > 2100)
                {
                    Logger.Info($"Master work thread slept for {time}ms");
                }
            }
        }