2021-08-17 04:21:48 -04:00
|
|
|
|
using System;
|
2021-08-20 01:48:35 -04:00
|
|
|
|
using System.Collections.Concurrent;
|
2021-08-19 08:44:38 -04:00
|
|
|
|
using System.Collections.Generic;
|
2021-08-18 23:16:57 -04:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
2021-08-20 01:48:35 -04:00
|
|
|
|
using System.Net;
|
2021-08-18 23:16:57 -04:00
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Net.Http.Headers;
|
2021-08-20 01:48:35 -04:00
|
|
|
|
using System.Threading;
|
2021-08-18 23:16:57 -04:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using franz;
|
|
|
|
|
using Newtonsoft.Json;
|
2021-08-20 01:48:35 -04:00
|
|
|
|
using ShowHandlers;
|
2021-08-17 04:21:48 -04:00
|
|
|
|
|
|
|
|
|
namespace director
|
|
|
|
|
{
|
2021-08-21 00:15:37 -04:00
|
|
|
|
public class Program
|
2021-08-17 04:21:48 -04:00
|
|
|
|
{
|
2021-08-18 23:16:57 -04:00
|
|
|
|
//private static Telefranz tf;
|
|
|
|
|
public static Config conf;
|
|
|
|
|
private static TimeSpan calendarNaptime = TimeSpan.FromHours(1);
|
2021-08-21 00:15:37 -04:00
|
|
|
|
public static Scratch scratch;
|
2021-08-18 23:16:57 -04:00
|
|
|
|
private static HttpClient httpClient;
|
2021-08-20 01:48:35 -04:00
|
|
|
|
private static readonly ConcurrentQueue<Schedulable.Schedulable> workQueue = new ConcurrentQueue<Schedulable.Schedulable>();
|
|
|
|
|
private static readonly AutoResetEvent _signal = new AutoResetEvent(false);
|
|
|
|
|
private const int concurrentWorkers = 2;
|
2021-08-17 04:21:48 -04:00
|
|
|
|
static void Main(string[] args)
|
|
|
|
|
{
|
2021-08-18 23:16:57 -04:00
|
|
|
|
if (!File.Exists("appsettings.json"))
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine("appsettings.json was not found!");
|
2021-08-20 01:48:35 -04:00
|
|
|
|
conf = new Config();
|
|
|
|
|
File.WriteAllText("appsettings.json", JsonConvert.SerializeObject(conf, Formatting.Indented));
|
2021-08-18 23:16:57 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
conf = JsonConvert.DeserializeObject<Config>(File.ReadAllText("appsettings.json"));
|
2021-08-20 01:48:35 -04:00
|
|
|
|
Log.call_for_humans_discord_webhook = conf.call_for_humans_discord_webhook;
|
|
|
|
|
|
2021-08-18 23:16:57 -04:00
|
|
|
|
httpClient = new HttpClient();
|
|
|
|
|
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(
|
|
|
|
|
System.Text.Encoding.ASCII.GetBytes($"{conf.webdav_username}:{conf.webdav_password}")));
|
|
|
|
|
//tf = new Telefranz("scheduler", conf.kafka_bootstrap);
|
2021-08-19 08:44:38 -04:00
|
|
|
|
|
2021-08-18 23:16:57 -04:00
|
|
|
|
scratch = Scratch.LoadScratch();
|
2021-08-19 08:44:38 -04:00
|
|
|
|
|
2021-08-20 01:48:35 -04:00
|
|
|
|
for (var i = 0; i < concurrentWorkers; i++)
|
|
|
|
|
{
|
|
|
|
|
Task.Run(threadwork);
|
|
|
|
|
}
|
2021-08-18 23:16:57 -04:00
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
Task.WaitAll(
|
2021-08-21 00:23:14 -04:00
|
|
|
|
Task.Run(checkCalendars),
|
2021-08-18 23:16:57 -04:00
|
|
|
|
Task.Delay(calendarNaptime)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-21 00:23:14 -04:00
|
|
|
|
private static void checkCalendars()
|
2021-08-18 23:16:57 -04:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-08-20 00:26:00 -04:00
|
|
|
|
lock (scratch)
|
|
|
|
|
{
|
|
|
|
|
scratch.agenda.Clear();
|
|
|
|
|
}
|
2021-08-18 23:16:57 -04:00
|
|
|
|
Task.WaitAll(
|
2021-08-21 00:15:37 -04:00
|
|
|
|
checkCalendar(conf.calendar_youtube, "youtube", (ref Schedulable.Schedulable n) =>
|
2021-08-20 00:26:00 -04:00
|
|
|
|
{
|
|
|
|
|
n.ScedulableType = Schedulable.ScedulableType.YTRelease;
|
|
|
|
|
}),
|
|
|
|
|
checkCalendar(conf.calendar_twitch, "twitch", (ref Schedulable.Schedulable n) =>
|
|
|
|
|
{
|
|
|
|
|
n.ScedulableType = Schedulable.ScedulableType.TwitchStream;
|
|
|
|
|
})
|
2021-08-18 23:16:57 -04:00
|
|
|
|
);
|
2021-08-20 00:26:00 -04:00
|
|
|
|
lock (scratch)
|
|
|
|
|
{
|
|
|
|
|
scratch.Save();
|
|
|
|
|
}
|
2021-08-18 23:16:57 -04:00
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine(e);
|
|
|
|
|
}
|
2021-08-20 00:26:00 -04:00
|
|
|
|
|
|
|
|
|
foreach (var s in scratch.agenda)
|
|
|
|
|
{
|
2021-08-20 01:48:35 -04:00
|
|
|
|
if ((s.Showtime - conf.preshowBufferTime) - DateTime.Now <= calendarNaptime)
|
2021-08-20 00:26:00 -04:00
|
|
|
|
{
|
2021-08-20 01:48:35 -04:00
|
|
|
|
var copy = JsonConvert.DeserializeObject<Schedulable.Schedulable>(JsonConvert.SerializeObject(s));
|
|
|
|
|
workQueue.Enqueue(copy);
|
|
|
|
|
_signal.Set();
|
2021-08-20 00:26:00 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-21 00:15:37 -04:00
|
|
|
|
Console.WriteLine("calendars checked");
|
2021-09-01 01:16:29 -04:00
|
|
|
|
#if (DEBUG)
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
var psuedo = new Schedulable.Schedulable();
|
|
|
|
|
psuedo.Showtime = DateTime.Now + TimeSpan.FromSeconds(30);
|
|
|
|
|
var partiallyCopiable = scratch.agenda?.FirstOrDefault(s => s.ScedulableType == Schedulable.ScedulableType.YTRelease);
|
|
|
|
|
psuedo.Occurrence = partiallyCopiable.Occurrence;
|
|
|
|
|
psuedo.Occurrence.OccurrenceStart = psuedo.Showtime;
|
|
|
|
|
psuedo.Occurrence.OccurrenceEnd = psuedo.Showtime;
|
|
|
|
|
psuedo.ScedulableType = Schedulable.ScedulableType.YTRelease;
|
|
|
|
|
workQueue.Enqueue(psuedo);
|
|
|
|
|
_signal.Set();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2021-08-18 23:16:57 -04:00
|
|
|
|
}
|
2021-08-19 08:44:38 -04:00
|
|
|
|
|
2021-08-20 00:26:00 -04:00
|
|
|
|
private delegate void schedulableCreate(ref Schedulable.Schedulable creating);
|
|
|
|
|
private static async Task checkCalendar(string calendarUri, string calLabel, schedulableCreate createSchedulable)
|
2021-08-18 23:16:57 -04:00
|
|
|
|
{
|
2021-08-19 08:44:38 -04:00
|
|
|
|
//?export is a hack to allow me to access the calendar
|
2021-08-20 00:26:00 -04:00
|
|
|
|
//it likes to throw an error saying "this is the webDAV interface, use webDAV" at my webDAV client, stopping me from using webDAV.
|
2021-08-19 08:44:38 -04:00
|
|
|
|
var calString = await httpClient.GetStringAsync(conf.webdav_uri + calendarUri + "?export");
|
|
|
|
|
var knownChecklist = new List<Schedulable.Schedulable>();
|
|
|
|
|
lock (scratch)
|
|
|
|
|
{
|
|
|
|
|
scratch.Calendars[calLabel] = calString;
|
2021-08-21 00:15:37 -04:00
|
|
|
|
iCalHoopJumping.LoadCalendar(calLabel, calString);
|
|
|
|
|
foreach (var occurrence in iCalHoopJumping.getOccurrences(calLabel))
|
2021-08-19 08:44:38 -04:00
|
|
|
|
{
|
2021-08-20 00:26:00 -04:00
|
|
|
|
var newSchedulable = new Schedulable.Schedulable()
|
2021-08-19 08:44:38 -04:00
|
|
|
|
{
|
2021-08-21 00:15:37 -04:00
|
|
|
|
Occurrence = occurrence,
|
|
|
|
|
Showtime = occurrence.OccurrenceStart
|
2021-08-20 00:26:00 -04:00
|
|
|
|
};
|
|
|
|
|
createSchedulable(ref newSchedulable);
|
|
|
|
|
scratch.agenda.Add(newSchedulable);
|
2021-08-19 08:44:38 -04:00
|
|
|
|
}
|
2021-08-18 23:16:57 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-20 01:48:35 -04:00
|
|
|
|
private static void threadwork()
|
|
|
|
|
{
|
|
|
|
|
Schedulable.Schedulable todo = null;
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
_signal.WaitOne(calendarNaptime);
|
|
|
|
|
|
|
|
|
|
if (!workQueue.TryDequeue(out todo)) { continue; }
|
2021-09-01 01:16:29 -04:00
|
|
|
|
|
2021-08-21 01:04:44 -04:00
|
|
|
|
var napLength = (todo.Showtime - conf.preshowBufferTime) - DateTime.Now;
|
|
|
|
|
Console.WriteLine($"threadwork consumes! showtime at {todo.Showtime}; napping until {todo.Showtime - conf.preshowBufferTime} ({napLength})");
|
2021-09-01 01:16:29 -04:00
|
|
|
|
switch (todo.ScedulableType)
|
2021-08-21 00:15:37 -04:00
|
|
|
|
{
|
|
|
|
|
case Schedulable.ScedulableType.TwitchStream:
|
|
|
|
|
Console.WriteLine("it's a twitch stream");
|
|
|
|
|
break;
|
|
|
|
|
case Schedulable.ScedulableType.YTRelease:
|
|
|
|
|
Console.WriteLine("it's a yt release");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-09-01 01:16:29 -04:00
|
|
|
|
if (napLength.TotalMinutes > 0)
|
2021-08-21 01:04:44 -04:00
|
|
|
|
{
|
|
|
|
|
Task.WaitAll(Task.Delay(napLength));
|
|
|
|
|
}
|
2021-09-01 01:16:29 -04:00
|
|
|
|
|
|
|
|
|
try
|
2021-08-20 01:48:35 -04:00
|
|
|
|
{
|
2021-09-01 01:16:29 -04:00
|
|
|
|
switch (todo.ScedulableType)
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
Log.Panic($"error in show handler! Panicking!\n{JsonConvert.SerializeObject(e)}");
|
2021-08-20 01:48:35 -04:00
|
|
|
|
}
|
2021-09-01 01:16:29 -04:00
|
|
|
|
break;
|
2021-08-20 01:48:35 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-17 04:21:48 -04:00
|
|
|
|
}
|
|
|
|
|
}
|