flow of youtube release seems to make sense

This commit is contained in:
Adam R. Grey 2021-09-03 07:18:38 -04:00
parent 57be4c1f47
commit 8614b42e47
8 changed files with 105 additions and 114 deletions

View File

@ -13,8 +13,6 @@ namespace director
public string calendar_youtube { get; set; } public string calendar_youtube { get; set; }
public string calendar_twitch { get; set; } public string calendar_twitch { get; set; }
public string calendar_other { get; set; } public string calendar_other { get; set; }
public TimeSpan preshowBufferTime { get; set; }
public string show_template_yt_release { get; set; }
public string show_template_twitch_streams { get; set; } public string show_template_twitch_streams { get; set; }
public Dictionary<string, string> phase_handlers { get; set; } public Dictionary<string, string> phase_handlers { get; set; }
} }

View File

@ -6,7 +6,7 @@ namespace Director
{ {
public class HumanCommunication public class HumanCommunication
{ {
private static string call_for_humans_discord_webhook{get;set;} private static string call_for_humans_discord_webhook { get; set; }
private static HumanCommunication _instance = null; private static HumanCommunication _instance = null;
private static readonly object createLock = new object(); private static readonly object createLock = new object();
public static void Configure(string call_for_humans_discord_webhook) public static void Configure(string call_for_humans_discord_webhook)
@ -42,7 +42,7 @@ namespace Director
Console.WriteLine($"[{DateTime.Now.ToLongTimeString()}] [{logLevel.ToString()}] {message}"); Console.WriteLine($"[{DateTime.Now.ToLongTimeString()}] [{logLevel.ToString()}] {message}");
//if(logLevel >= LogLevel.Warning && false) //if(logLevel >= LogLevel.Warning && false)
if(false) //TODO: re-enable if (false) //TODO: re-enable
{ {
var httpWebRequest = (HttpWebRequest)WebRequest.Create(call_for_humans_discord_webhook); var httpWebRequest = (HttpWebRequest)WebRequest.Create(call_for_humans_discord_webhook);
httpWebRequest.ContentType = "application/json"; httpWebRequest.ContentType = "application/json";
@ -54,7 +54,15 @@ namespace Director
httpWebRequest.GetResponse(); httpWebRequest.GetResponse();
} }
} }
public enum LogLevel { Trace, Verbose, Info, Warning, Error, Showstopper } public enum LogLevel
{
Trace, //development
Verbose,
Info, //archival purposes, status checking, curiosity satisfaciton
Warning,
Error, //it's going to go up, but look bad. The bar is (currently) low enough that this won't necessarily damage the brand, but for better creators it would.
Showstopper //it's not going to go up
}
} }
public class NotInitializedException : Exception public class NotInitializedException : Exception
{ {

View File

@ -86,7 +86,8 @@ namespace director
foreach (var s in scratch.agenda) foreach (var s in scratch.agenda)
{ {
if ((s.Showtime - conf.preshowBufferTime) - DateTime.Now <= calendarNaptime) //todo: find the perfect lead time.
if ((s.Showtime - TimeSpan.FromDays(1)) - DateTime.Now <= calendarNaptime)
{ {
var copy = JsonConvert.DeserializeObject<Schedulable.Schedulable>(JsonConvert.SerializeObject(s)); var copy = JsonConvert.DeserializeObject<Schedulable.Schedulable>(JsonConvert.SerializeObject(s));
workQueue.Enqueue(copy); workQueue.Enqueue(copy);
@ -121,6 +122,7 @@ namespace director
{ {
scratch.Calendars[calLabel] = calString; scratch.Calendars[calLabel] = calString;
iCalHoopJumping.LoadCalendar(calLabel, calString); iCalHoopJumping.LoadCalendar(calLabel, calString);
//todo: I'm pretty sure some library is returning me only things in the future. Verify, and also make sure it's returning things in the present.
foreach (var occurrence in iCalHoopJumping.getOccurrences(calLabel)) foreach (var occurrence in iCalHoopJumping.getOccurrences(calLabel))
{ {
var newSchedulable = new Schedulable.Schedulable() var newSchedulable = new Schedulable.Schedulable()
@ -142,17 +144,24 @@ namespace director
if (!workQueue.TryDequeue(out todo)) { continue; } if (!workQueue.TryDequeue(out todo)) { continue; }
var napLength = (todo.Showtime - conf.preshowBufferTime) - DateTime.Now; ShowHandler handler = null;
Console.WriteLine($"threadwork consumes! showtime at {todo.Showtime}; napping until {todo.Showtime - conf.preshowBufferTime} ({napLength})");
switch (todo.ScedulableType) switch (todo.ScedulableType)
{ {
case Schedulable.ScedulableType.TwitchStream: case Schedulable.ScedulableType.TwitchStream:
Console.WriteLine("it's a twitch stream"); Console.WriteLine("it's a twitch stream");
handler = new TwitchStreamHandler();
break; break;
case Schedulable.ScedulableType.YTRelease: case Schedulable.ScedulableType.YTRelease:
Console.WriteLine("it's a yt release"); Console.WriteLine("it's a yt release");
handler = new YoutubeHandler();
break; break;
default:
HumanCommunication.Instance.Say($"unknown schedulable type!\n{JsonConvert.SerializeObject(todo)}", HumanCommunication.LogLevel.Showstopper);
continue;
} }
var napLength = (todo.Showtime - handler.LeadTimeDesired) - DateTime.Now;
Console.WriteLine($"threadwork consumes! showtime at {todo.Showtime}; napping until {todo.Showtime - handler.LeadTimeDesired} ({napLength})");
if (napLength.TotalMinutes > 0) if (napLength.TotalMinutes > 0)
{ {
Task.WaitAll(Task.Delay(napLength)); Task.WaitAll(Task.Delay(napLength));
@ -161,17 +170,7 @@ namespace director
try try
{ {
switch (todo.ScedulableType) handler.Handle(todo.Occurrence);
{
case Schedulable.ScedulableType.TwitchStream:
new TwitchStreamHandler().Handle(todo.Occurrence);
break;
case Schedulable.ScedulableType.YTRelease:
new YoutubeHandler().Handle(todo.Occurrence);
break;
default:
throw new NotImplementedException($"unknown schedulable type!\n{JsonConvert.SerializeObject(todo)}");
}
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -7,7 +7,6 @@
"calendar_youtube": "calendars/1wingedangle/youtube-channel_shared_by_adam", "calendar_youtube": "calendars/1wingedangle/youtube-channel_shared_by_adam",
"calendar_twitch": "calendars/1wingedangle/twitch-channel_shared_by_adam", "calendar_twitch": "calendars/1wingedangle/twitch-channel_shared_by_adam",
"calendar_other": "calendars/1wingedangle/other_shared_by_adam", "calendar_other": "calendars/1wingedangle/other_shared_by_adam",
"preshowBufferTime": "04:00:00",
"show_template_yt_release": "./yt release/config.json", "show_template_yt_release": "./yt release/config.json",
"show_template_twitch_streams": "./twitch stream configs/" "show_template_twitch_streams": "./twitch stream configs/"
} }

View File

@ -48,6 +48,7 @@ namespace director
internal static string Event_ToString(CalendarEvent asEvent) internal static string Event_ToString(CalendarEvent asEvent)
{ {
//return asEvent.ToString(); //lol no //return asEvent.ToString(); //lol no
if(asEvent == null){return null;}
return ser.SerializeToString(asEvent); return ser.SerializeToString(asEvent);
} }
public static IEnumerable<CalendarOccurrence> getOccurrences(string calLabel) public static IEnumerable<CalendarOccurrence> getOccurrences(string calLabel)

View File

@ -6,5 +6,6 @@ namespace ShowHandlers
public abstract class ShowHandler public abstract class ShowHandler
{ {
public abstract void Handle(iCalHoopJumping.CalendarOccurrence evt); public abstract void Handle(iCalHoopJumping.CalendarOccurrence evt);
public abstract TimeSpan LeadTimeDesired { get; }
} }
} }

View File

@ -5,11 +5,54 @@ namespace ShowHandlers
{ {
public class TwitchStreamHandler : ShowHandler public class TwitchStreamHandler : ShowHandler
{ {
public override TimeSpan LeadTimeDesired => TimeSpan.FromHours(4);
public override void Handle(iCalHoopJumping.CalendarOccurrence evt) public override void Handle(iCalHoopJumping.CalendarOccurrence evt)
{ {
Console.WriteLine("I am a twitch stream handler, it falls to me to..."); Console.WriteLine("I am a twitch stream handler, it falls to me to...");
Console.WriteLine(" H A N D L E "); Console.WriteLine(" H A N D L E ");
Console.WriteLine($"current time is {DateTime.Now}"); Console.WriteLine($"current time is {DateTime.Now}");
} }
protected void preShow_RunCommands(iCalHoopJumping.CalendarOccurrence evt)
{
// Console.WriteLine($"pre show: run commands: {string.Join(", ", PreShowCommands.Select(c => c.cmd))}");
// foreach (var cmd in PreShowCommands.OrderByDescending(cmd => cmd.leadTime))
// {
// if (DateTime.Now < evt.OccurrenceStart - cmd.leadTime)
// {
// var waitTime = evt.OccurrenceStart - cmd.leadTime - DateTime.Now;
// Console.WriteLine($"waiting {waitTime} before executing {cmd.cmd}");
// Task.WaitAll(Task.Delay(waitTime));
// }
// var argsList = new List<string>() { JsonConvert.SerializeObject(evt) }.Append(cmd.args).ToList();
// Console.WriteLine($"telefranzing execution: {cmd.cmd} with args {string.Join(' ', argsList)}");
// // Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_command()
// // {
// // command = cmd.cmd,
// // args = argsList,
// // timeout = (int)cmd.timeout.TotalMilliseconds //TODO: update when franz gets updated
// // });
// }
// Console.WriteLine("seems all pre-show commands have been issued, but to be fair I wasn't listening for output.");
}
protected void PostShow(iCalHoopJumping.CalendarOccurrence evt)
{
// Console.WriteLine($"post show: run commands: {string.Join(", ", config.PostShow.Commands.Select(c => c.cmd))}");
// foreach (var cmd in config.PostShow.Commands)
// {
// var argsList = new List<string>() { JsonConvert.SerializeObject(evt) }.Append(cmd.args).ToList();
// Console.WriteLine($"telefranzing execution: {cmd.cmd} with args {string.Join(' ', argsList)}");
// // Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_command()
// // {
// // command = cmd.cmd,
// // args = argsList,
// // timeout = (int)cmd.timeout.TotalMilliseconds //TODO: update when franz gets updated
// // });
// }
// Console.WriteLine("seems all post-show commands have been issued, but to be fair I wasn't listening for output.");
}
} }
} }

View File

@ -14,17 +14,16 @@ namespace ShowHandlers
{ {
public class YoutubeHandler : ShowHandler public class YoutubeHandler : ShowHandler
{ {
private YoutubeRelease config;
private List<string> agentsPresent = new List<string>();
private Dictionary<string, bool> checksProgress = new Dictionary<string, bool>();
private readonly AutoResetEvent checkSignal = new AutoResetEvent(false); private readonly AutoResetEvent checkSignal = new AutoResetEvent(false);
private static string[] AgentsNeeded { get; set; } = { "youtube" };
private List<string> agentsPresent {get;set;} = new List<string>();
public override TimeSpan LeadTimeDesired { get => TimeSpan.FromDays(1); }
private silver_messages.youtube.yt_metadata metadataSoFar = new silver_messages.youtube.yt_metadata();
public override void Handle(iCalHoopJumping.CalendarOccurrence evt) public override void Handle(iCalHoopJumping.CalendarOccurrence evt)
{ {
Console.WriteLine($"begin youtube handler. current time {DateTime.Now.ToLongTimeString()}"); Console.WriteLine($"begin youtube handler. current time {DateTime.Now.ToLongTimeString()}");
Console.WriteLine(JsonConvert.SerializeObject(evt)); Console.WriteLine(JsonConvert.SerializeObject(evt));
var ytConfig = File.ReadAllText(Program.conf.show_template_yt_release);
config = JsonConvert.DeserializeObject<YoutubeRelease>(ytConfig);
Task.Run(() => PreShow(evt)); Task.Run(() => PreShow(evt));
Console.WriteLine("kicked off the pre-show"); Console.WriteLine("kicked off the pre-show");
if (evt.OccurrenceStart > DateTime.Now) if (evt.OccurrenceStart > DateTime.Now)
@ -42,104 +41,57 @@ namespace ShowHandlers
protected void PreShow(iCalHoopJumping.CalendarOccurrence evt) protected void PreShow(iCalHoopJumping.CalendarOccurrence evt)
{ {
Console.WriteLine($"it's the pre-show, showtime at: {evt.OccurrenceStart}"); Console.WriteLine($"it's the pre-show, showtime at: {evt.OccurrenceStart}");
config.PreShow.AgentsNeeded = config.PreShow.AgentsNeeded.Select(s => s.ToLower()).ToList();
var commandLeadNeeded = TimeSpan.FromMinutes(15); preShow_GetAgents(evt, TimeSpan.FromMinutes(10));
foreach(var cl in config.PreShow.Commands) preShow_RunChecks(evt, TimeSpan.FromMinutes(10));
{
if(cl.leadTime > commandLeadNeeded){
commandLeadNeeded = cl.leadTime;
}
}
preShow_GetAgents(evt, commandLeadNeeded + TimeSpan.FromMinutes(10));
preShow_RunChecks(evt, commandLeadNeeded);
preShow_RunCommands(evt);
Console.WriteLine("pre show seems to be set."); Console.WriteLine("pre show seems to be set.");
} }
protected void preShow_GetAgents(iCalHoopJumping.CalendarOccurrence evt, TimeSpan leadNeeded) protected void preShow_GetAgents(iCalHoopJumping.CalendarOccurrence evt, TimeSpan leadNeeded)
{ {
Console.WriteLine($"preshow agents needed: {string.Join(", ", config.PreShow.AgentsNeeded)}"); Console.WriteLine($"preshow agents needed: {string.Join(", ", AgentsNeeded)}");
agentsPresent.Clear(); agentsPresent.Clear();
//TODO: actual telefranz //TODO: actual telefranz
//Telefranz.Instance.addHandler<silver_messages.global.report>(agentReports); //Telefranz.Instance.addHandler<silver_messages.global.report>(agentReports);
//Telefranz.Instance.ProduceMessage(new silver_messages.global.sound_off()); //Telefranz.Instance.ProduceMessage(new silver_messages.global.sound_off());
while (config.PreShow.AgentsNeeded.Where(ap => !agentsPresent.Contains(ap))?.Count() > 0) while (AgentsNeeded.Where(ap => !agentsPresent.Contains(ap))?.Count() > 0)
{ {
checkSignal.WaitOne(TimeSpan.FromSeconds(15)); checkSignal.WaitOne(TimeSpan.FromSeconds(15));
if(DateTime.Now > evt.OccurrenceStart - leadNeeded) if (DateTime.Now > evt.OccurrenceStart - leadNeeded)
{ {
var miaAgents = string.Join(", ", config.PreShow.AgentsNeeded.Where(ap => !agentsPresent.Contains(ap))); var miaAgents = string.Join(", ", AgentsNeeded.Where(ap => !agentsPresent.Contains(ap)));
HumanCommunication.Instance.Say($"Youtube handler getting antsy and going forward. mia agents: {miaAgents}", HumanCommunication.Instance.Say($"Youtube handler getting antsy and going forward. mia agents: {miaAgents}",
HumanCommunication.LogLevel.Error); HumanCommunication.LogLevel.Warning);
break; break;
} }
} }
Console.WriteLine("going forward");
} }
protected void preShow_RunChecks(iCalHoopJumping.CalendarOccurrence evt, TimeSpan leadNeeded) protected void preShow_RunChecks(iCalHoopJumping.CalendarOccurrence evt, TimeSpan leadNeeded)
{ {
checksProgress.Clear();
var argsList = new List<string>() { JsonConvert.SerializeObject(evt) }; var argsList = new List<string>() { JsonConvert.SerializeObject(evt) };
//Telefranz.Instance.addHandler() //Telefranz.Instance.addHandler<silver_messages.youtube.metadata_needed>(youtubeAgentReports);
foreach (var c in config.PreShow.Checks) Console.WriteLine($"pre show: run check. It's just going to be \"is the metadata set\".");
Action issueChecks = () =>
{ {
checksProgress.Add(c.cmd, false); //Telefranz.Instance.ProduceMessage(new silver_messages.youtube.request_metadata_needed());
}
Console.WriteLine($"pre show: run checks: {string.Join(", ", config.PreShow.Checks.Select(c => c.cmd))}");
Action issueChecks = () => {
foreach (var checkCmd in checksProgress.Where(cp => cp.Value == false).Select(kvp => kvp.Key))
{
var check = config.PreShow.Checks.First(clc => clc.cmd == checkCmd);
// Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_check()
// {
// check = check.cmd,
// args = argsList.Append(check.args).ToList()
// });
}
}; };
issueChecks(); issueChecks();
while (checksProgress.ContainsValue(false)) while (metadataUnset(metadataSoFar))
{ {
//checkSignal.WaitOne(TimeSpan.FromHours(6));
checkSignal.WaitOne(TimeSpan.FromSeconds(15)); checkSignal.WaitOne(TimeSpan.FromSeconds(15));
if(DateTime.Now > evt.OccurrenceStart - leadNeeded) if (DateTime.Now > evt.OccurrenceStart - leadNeeded)
{ {
var stillFailing = string.Join(", ", checksProgress.Where(cp => cp.Value == false).Select(cp => cp.Key)); HumanCommunication.Instance.Say($"Youtube handler reports no metadata in time! too late now though. {JsonConvert.SerializeObject(metadataSoFar)}",
HumanCommunication.Instance.Say($"Youtube handler getting antsy and going forward. checks still failing: {stillFailing}",
HumanCommunication.LogLevel.Error); HumanCommunication.LogLevel.Error);
break; break;
} }
issueChecks(); issueChecks();
} }
Console.WriteLine("going forward");
}
protected void preShow_RunCommands(iCalHoopJumping.CalendarOccurrence evt)
{
Console.WriteLine($"pre show: run commands: {string.Join(", ", config.PreShow.Commands.Select(c => c.cmd))}");
foreach(var cmd in config.PreShow.Commands.OrderByDescending(cmd => cmd.leadTime))
{
if(DateTime.Now < evt.OccurrenceStart - cmd.leadTime)
{
var waitTime = evt.OccurrenceStart - cmd.leadTime - DateTime.Now;
Console.WriteLine($"waiting {waitTime} before executing {cmd.cmd}");
Task.WaitAll(Task.Delay(waitTime));
}
var argsList = new List<string>() { JsonConvert.SerializeObject(evt) }.Append(cmd.args).ToList();
Console.WriteLine($"telefranzing execution: {cmd.cmd} with args {string.Join(' ', argsList)}");
// Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_command()
// {
// command = cmd.cmd,
// args = argsList,
// timeout = (int)cmd.timeout.TotalMilliseconds //TODO: update when franz gets updated
// });
}
Console.WriteLine("seems all pre-show commands have been issued, but to be fair I wasn't listening for output.");
} }
protected void agentReports(silver_messages.global.report r) protected void agentReports(silver_messages.global.report r)
{ {
if (config.PreShow.AgentsNeeded?.FirstOrDefault(an => an.ToLower() == r.name.ToLower()) != null) if (AgentsNeeded?.FirstOrDefault(an => an.ToLower() == r.name.ToLower()) != null)
{ {
lock (agentsPresent) lock (agentsPresent)
{ {
@ -148,35 +100,25 @@ namespace ShowHandlers
} }
} }
} }
protected void checkReports(silver_messages.directorial.check_complete check) protected void youtubeAgentReports(silver_messages.youtube.metadata_needed neededmsg)
{ {
var myCheck = config.PreShow.Checks.FirstOrDefault(psc => psc.cmd == check.check); metadataSoFar = neededmsg.needed.Where(kvp => kvp.Key == "key")?.Select(kvp => kvp.Value)?.FirstOrDefault();
if (myCheck != null) checkSignal.Set();
{ }
lock (checksProgress) protected bool metadataUnset(silver_messages.youtube.yt_metadata metadata)
{ {
checksProgress[myCheck.cmd] = check.result == myCheck.target; return (
} string.IsNullOrWhiteSpace(metadata.playlist)
checkSignal.Set(); || metadata.recording == null
} || metadata.release == null
|| string.IsNullOrWhiteSpace(metadata.thumbnail)
|| string.IsNullOrWhiteSpace(metadata.title)
);
} }
protected void PostShow(iCalHoopJumping.CalendarOccurrence evt) protected void PostShow(iCalHoopJumping.CalendarOccurrence evt)
{ {
Console.WriteLine("there really isn't a post-show atm, but in future would be cool to pester matrix/discord/twitter");
Console.WriteLine($"post show: run commands: {string.Join(", ", config.PostShow.Commands.Select(c => c.cmd))}"); //Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_command("advertise"));
foreach(var cmd in config.PostShow.Commands)
{
var argsList = new List<string>() { JsonConvert.SerializeObject(evt) }.Append(cmd.args).ToList();
Console.WriteLine($"telefranzing execution: {cmd.cmd} with args {string.Join(' ', argsList)}");
// Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_command()
// {
// command = cmd.cmd,
// args = argsList,
// timeout = (int)cmd.timeout.TotalMilliseconds //TODO: update when franz gets updated
// });
}
Console.WriteLine("seems all post-show commands have been issued, but to be fair I wasn't listening for output.");
} }
} }
} }