public CreeperCarl(ICarl carl) { s_instance = this; m_carl = carl; m_userChecker = new Thread(ChannelUserCheckerThread); m_userChecker.IsBackground = false; m_userChecker.Start(); }
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); }
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"); } } }