From ac3b998da9876197a9969a5529b5772e826e5a21 Mon Sep 17 00:00:00 2001 From: "Adam R. Grey" Date: Fri, 3 Sep 2021 03:38:21 -0400 Subject: [PATCH] poc check for responding agents seems to work, need to test telefranzing them --- HumanCommunication.cs | 59 +++++++++++++++++ Log.cs | 20 ------ Program.cs | 8 ++- schedulable/Show.cs | 14 ++++- showHandlers/ShowHandler.cs | 1 + showHandlers/TwitchStreamHandler.cs | 1 + showHandlers/YoutubeHandler.cs | 98 ++++++++++++++++++++++------- 7 files changed, 153 insertions(+), 48 deletions(-) create mode 100644 HumanCommunication.cs delete mode 100644 Log.cs diff --git a/HumanCommunication.cs b/HumanCommunication.cs new file mode 100644 index 0000000..a9c14d8 --- /dev/null +++ b/HumanCommunication.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using System.Net; + +namespace Director +{ + public class HumanCommunication + { + private static string call_for_humans_discord_webhook{get;set;} + private static HumanCommunication _instance = null; + private static readonly object createLock = new object(); + public static void Configure(string call_for_humans_discord_webhook) + { + lock (createLock) + { + if (_instance == null) + { + _instance = new HumanCommunication(call_for_humans_discord_webhook); + } + } + } + public static HumanCommunication Instance + { + get + { + lock (createLock) + { + if (_instance == null) + { + throw new NotInitializedException("Configure me first"); + } + } + return _instance; + } + } + private HumanCommunication(string discord_webhook) + { + HumanCommunication.call_for_humans_discord_webhook = discord_webhook; + } + public void Say(string message, LogLevel logLevel = LogLevel.Info) + { + Console.WriteLine($"[{DateTime.Now.ToLongTimeString()}] [{logLevel.ToString()}] {message}"); + + var httpWebRequest = (HttpWebRequest)WebRequest.Create(call_for_humans_discord_webhook); + httpWebRequest.ContentType = "application/json"; + httpWebRequest.Method = "POST"; + using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) + { + streamWriter.Write($"{{\"content\":\"[{DateTime.Now.ToLongTimeString()}] [{logLevel.ToString()}] {message}\"}}"); + } + httpWebRequest.GetResponse(); + } + public enum LogLevel { Trace, Verbose, Info, Warning, Error, Showstopper } + } + public class NotInitializedException : Exception + { + public NotInitializedException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/Log.cs b/Log.cs deleted file mode 100644 index 137d9d2..0000000 --- a/Log.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.IO; -using System.Net; - -public class Log -{ - public static string call_for_humans_discord_webhook{get;set;} - public static void Panic(string message) - { - Console.Error.WriteLine(message); - var httpWebRequest = (HttpWebRequest)WebRequest.Create(call_for_humans_discord_webhook); - httpWebRequest.ContentType = "application/json"; - httpWebRequest.Method = "POST"; - using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) - { - streamWriter.Write("{\"content\":\"" + message + "\"}"); - } - httpWebRequest.GetResponse(); - } -} \ No newline at end of file diff --git a/Program.cs b/Program.cs index 806f2bf..7e8765e 100644 --- a/Program.cs +++ b/Program.cs @@ -8,6 +8,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; +using Director; using franz; using Newtonsoft.Json; using ShowHandlers; @@ -34,7 +35,7 @@ namespace director return; } conf = JsonConvert.DeserializeObject(File.ReadAllText("appsettings.json")); - Log.call_for_humans_discord_webhook = conf.call_for_humans_discord_webhook; + HumanCommunication.Configure(conf.call_for_humans_discord_webhook); httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String( @@ -94,7 +95,7 @@ namespace director } Console.WriteLine("calendars checked"); #if (DEBUG) - for (int i = 0; i < 3; i++) + for (int i = 0; i < 1; i++) { var psuedo = new Schedulable.Schedulable(); psuedo.Showtime = DateTime.Now + TimeSpan.FromSeconds(30); @@ -156,6 +157,7 @@ namespace director { Task.WaitAll(Task.Delay(napLength)); } + Console.WriteLine("places, everyone!"); try { @@ -173,7 +175,7 @@ namespace director } catch (Exception e) { - Log.Panic($"error in show handler! Panicking!\n{JsonConvert.SerializeObject(e)}"); + HumanCommunication.Instance.Say($"error in show handler! Panicking!\n{JsonConvert.SerializeObject(e)}", HumanCommunication.LogLevel.Showstopper); } break; } diff --git a/schedulable/Show.cs b/schedulable/Show.cs index ae83493..632e649 100644 --- a/schedulable/Show.cs +++ b/schedulable/Show.cs @@ -12,12 +12,12 @@ namespace Schedulable.Show public class TaskList { public IEnumerable Manual { get; set; } - public IEnumerable Commands { get; set; } + public IEnumerable Commands { get; set; } } public class PreshowTaskList : TaskList { public IEnumerable AgentsNeeded { get; set; } - public IEnumerable Checks { get; set; } + public IEnumerable Checks { get; set; } } public class Checklistable { @@ -25,9 +25,17 @@ namespace Schedulable.Show public string Label { get; set; } public IEnumerable Items { get; set; } //if no items, just throw up a checkbox } + public class CommandLine + { + public string cmd { get; set; } + public string args { get; set; } + } + public class CommandLineCheck : CommandLine + { + public string target { get; set; } + } #endregion } - public class TwitchStream : Show { public string TwitchTitle { get; set; } diff --git a/showHandlers/ShowHandler.cs b/showHandlers/ShowHandler.cs index 39b64c6..a214784 100644 --- a/showHandlers/ShowHandler.cs +++ b/showHandlers/ShowHandler.cs @@ -5,6 +5,7 @@ namespace ShowHandlers { public abstract class ShowHandler { + protected abstract TimeSpan AgentsRespondingBuffer { get; } public abstract void Handle(iCalHoopJumping.CalendarOccurrence evt); } } \ No newline at end of file diff --git a/showHandlers/TwitchStreamHandler.cs b/showHandlers/TwitchStreamHandler.cs index 7b8761c..f211bbb 100644 --- a/showHandlers/TwitchStreamHandler.cs +++ b/showHandlers/TwitchStreamHandler.cs @@ -5,6 +5,7 @@ namespace ShowHandlers { public class TwitchStreamHandler : ShowHandler { + protected override TimeSpan AgentsRespondingBuffer { get { return TimeSpan.FromHours(1); } } public override void Handle(iCalHoopJumping.CalendarOccurrence evt) { Console.WriteLine("I am a twitch stream handler, it falls to me to..."); diff --git a/showHandlers/YoutubeHandler.cs b/showHandlers/YoutubeHandler.cs index 7a4cbf3..6bf338f 100644 --- a/showHandlers/YoutubeHandler.cs +++ b/showHandlers/YoutubeHandler.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using director; +using Director; using franz; using Newtonsoft.Json; using Schedulable.Show; @@ -14,57 +16,109 @@ namespace ShowHandlers { private YoutubeRelease config; private List agentsPresent = new List(); - private bool essentialChecksPassed = false; - private bool allChecksPassed = false; + private Dictionary checksProgress = new Dictionary(); private readonly AutoResetEvent checkSignal = new AutoResetEvent(false); + + protected override TimeSpan AgentsRespondingBuffer { get { return TimeSpan.FromHours(1); } } + public override void Handle(iCalHoopJumping.CalendarOccurrence evt) { - config = JsonConvert.DeserializeObject(Program.conf.show_template_yt_release); - config.PreShow.AgentsNeeded = config.PreShow.AgentsNeeded.Select(s => s.ToLower()); - Telefranz.Instance.addHandler(agentReports); + Console.WriteLine($"begin youtube handler. current time {DateTime.Now.ToLongTimeString()}"); + Console.WriteLine(JsonConvert.SerializeObject(evt)); + var ytConfig = File.ReadAllText(Program.conf.show_template_yt_release); + config = JsonConvert.DeserializeObject(ytConfig); + config.PreShow.AgentsNeeded = config.PreShow.AgentsNeeded.Select(s => s.ToLower()).ToList(); Task.Run(() => PreShow(evt)); - if(evt.OccurrenceStart > DateTime.Now) + Console.WriteLine("kicked off the pre-show"); + if (evt.OccurrenceStart > DateTime.Now) { Task.WaitAll(Task.Delay(evt.OccurrenceStart - DateTime.Now)); } + //youtube releases in particular jump right to post-show PostShow(evt); } ~YoutubeHandler() { - Telefranz.Instance.removeHandler(agentReports); + //Telefranz.Instance.removeHandler(agentReports); } protected void PreShow(iCalHoopJumping.CalendarOccurrence evt) { Console.WriteLine($"it's the pre-show, showtime at: {evt.OccurrenceStart}"); + + preShow_GetAgents(evt); + preShow_RunChecks(evt); + preShow_RunCommands(evt); + } + protected void preShow_GetAgents(iCalHoopJumping.CalendarOccurrence evt) + { + Console.WriteLine($"preshow agents needed: {string.Join(", ", config.PreShow.AgentsNeeded)}"); agentsPresent.Clear(); - essentialChecksPassed = false; - allChecksPassed = false; - Task.WaitAny( - Task.Delay(10) - ); - Telefranz.Instance.ProduceMessage(new silver_messages.global.sound_off()); - while(agentsPresent.Where(ap => !config.PreShow.AgentsNeeded.Contains(ap))?.Count() > 0) + + //TODO: actual telefranz + //Telefranz.Instance.addHandler(agentReports); + //Telefranz.Instance.ProduceMessage(new silver_messages.global.sound_off()); + while (config.PreShow.AgentsNeeded.Where(ap => !agentsPresent.Contains(ap))?.Count() > 0) + { + checkSignal.WaitOne(TimeSpan.FromMinutes(1)); + if(DateTime.Now > evt.OccurrenceStart - AgentsRespondingBuffer) + { + var miaAgents = string.Join(", ", config.PreShow.AgentsNeeded.Where(ap => !agentsPresent.Contains(ap))); + HumanCommunication.Instance.Say($"Youtube handler getting antsy and going forward. mia agents: {miaAgents}", + HumanCommunication.LogLevel.Error); + break; + } + } + Console.WriteLine("going forward"); + } + protected void preShow_RunChecks(iCalHoopJumping.CalendarOccurrence evt) + { + Console.WriteLine("pre show: run checks:"); + //TODO + checksProgress.Clear(); + var argsList = new List() { JsonConvert.SerializeObject(evt) }; + //Telefranz.Instance.addHandler() + foreach (var c in config.PreShow.Checks) + { + checksProgress.Add(c.cmd, false); + Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_check() + { + check = c.cmd, + args = argsList.Append(c.args).ToList() + }); + } + while (true) { checkSignal.WaitOne(TimeSpan.FromSeconds(45)); + } - // //await sound offs for some timeout - // config.PreShow.AgentsNeeded; - // //once that's ok, await checks - // config.PreShow.Checks; - // //once that's ok, await first command, then start running them - // config.PreShow.Commands; + } + protected void preShow_RunCommands(iCalHoopJumping.CalendarOccurrence evt) + { + Console.WriteLine("pre show: run commands"); } protected void agentReports(silver_messages.global.report r) { - if(config.PreShow.AgentsNeeded?.FirstOrDefault(an => an.ToLower() == r.name.ToLower()) != null) + if (config.PreShow.AgentsNeeded?.FirstOrDefault(an => an.ToLower() == r.name.ToLower()) != null) { - lock(agentsPresent) + lock (agentsPresent) { agentsPresent.Add(r.name.ToLower()); checkSignal.Set(); } } } + protected void checkReports(silver_messages.directorial.check_complete check) + { + var myCheck = config.PreShow.Checks.FirstOrDefault(psc => psc.cmd == check.check); + if (myCheck != null) + { + lock (checksProgress) + { + checksProgress[myCheck.cmd] = check.result == myCheck.target; + } + checkSignal.Set(); + } + } protected void PostShow(iCalHoopJumping.CalendarOccurrence evt) { Console.WriteLine("can't do this bit without understanding when a show ends, sooo.");