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-10-13 09:25:03 -04:00
using System.Text.RegularExpressions ;
2021-08-20 01:48:35 -04:00
using System.Threading ;
2021-08-18 23:16:57 -04:00
using System.Threading.Tasks ;
2021-10-13 09:25:03 -04:00
using DirectorConfiguration ;
2021-08-18 23:16:57 -04:00
using franz ;
using Newtonsoft.Json ;
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-10-26 07:36:25 -04:00
private static Telefranz tf ;
2021-10-13 09:25:03 -04:00
public static Config directorConf ;
2021-08-18 23:16:57 -04:00
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-10-13 09:25:03 -04:00
private static readonly ConcurrentQueue < schedulable . Scheduled > workQueue = new ConcurrentQueue < schedulable . Scheduled > ( ) ;
2021-08-20 01:48:35 -04:00
private static readonly AutoResetEvent _signal = new AutoResetEvent ( false ) ;
2021-10-07 08:51:52 -04:00
private const int concurrentWorkers = 5 ;
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-10-13 09:25:03 -04:00
directorConf = new DirectorConfiguration . Config ( ) ;
File . WriteAllText ( "appsettings.json" , JsonConvert . SerializeObject ( directorConf , Formatting . Indented ) ) ;
2021-08-18 23:16:57 -04:00
return ;
}
2021-10-13 09:25:03 -04:00
directorConf = JsonConvert . DeserializeObject < Config > ( File . ReadAllText ( "appsettings.json" ) ) ;
HumanCommunication . Configure ( directorConf . call_for_humans_discord_webhook ) ;
2021-08-20 01:48:35 -04:00
2021-08-18 23:16:57 -04:00
httpClient = new HttpClient ( ) ;
httpClient . DefaultRequestHeaders . Authorization = new AuthenticationHeaderValue ( "Basic" , Convert . ToBase64String (
2021-10-13 09:25:03 -04:00
System . Text . Encoding . ASCII . GetBytes ( $"{directorConf.webdav_username}:{directorConf.webdav_password}" ) ) ) ;
2021-09-03 11:33:28 -04:00
2021-10-13 09:25:03 -04:00
Telefranz . Configure ( "scheduler" , directorConf . kafka_bootstrap ) ;
2021-10-26 07:36:25 -04:00
tf = Telefranz . Instance ;
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-10-13 09:25:03 -04:00
var calChecks = new List < Task > ( ) ;
foreach ( var calendar in directorConf . webdav_calendars )
{
calChecks . Add ( checkCalendar ( calendar ) ) ;
}
Task . WaitAll ( calChecks . ToArray ( ) ) ;
2021-10-26 07:36:25 -04:00
scratch . agenda = scratch . agenda . OrderBy ( s = > s . Showtime ) . ToList ( ) ;
2021-10-13 09:25:03 -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-09-03 07:18:38 -04:00
//todo: find the perfect lead time.
if ( ( s . Showtime - TimeSpan . FromDays ( 1 ) ) - DateTime . Now < = calendarNaptime )
2021-08-20 00:26:00 -04:00
{
2021-10-13 09:25:03 -04:00
var copy = JsonConvert . DeserializeObject < schedulable . Scheduled > ( JsonConvert . SerializeObject ( s ) ) ;
2021-08-20 01:48:35 -04:00
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-10-26 07:45:15 -04:00
// #if (DEBUG)
// //if(true)
// {
// Console.WriteLine("debug test");
2021-10-07 08:51:52 -04:00
2021-10-26 07:45:15 -04:00
// var psuedo = new schedulable.Scheduled();
// psuedo.Showtime = DateTime.Now + TimeSpan.FromMinutes(30);
// // foreach(var a in scratch.agenda){
// // Console.WriteLine(a.Occurrence._event.Summary);
// // }
// var partiallyCopiable = scratch.agenda?.First(a => a.Occurrence._event.Summary == "Good Morning, Phyrexia (in the morning)!");
// psuedo.Occurrence = partiallyCopiable.Occurrence;
// psuedo.Occurrence.OccurrenceStart = psuedo.Showtime;
// psuedo.Occurrence.OccurrenceEnd = psuedo.Showtime;
// workQueue.Enqueue(psuedo);
// _signal.Set();
// }
// #endif
2021-08-18 23:16:57 -04:00
}
2021-08-19 08:44:38 -04:00
2021-10-13 09:25:03 -04:00
private static async Task checkCalendar ( string calendarUri )
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-10-13 09:25:03 -04:00
Console . WriteLine ( calendarUri ) ;
var calString = await httpClient . GetStringAsync ( directorConf . webdav_uri + calendarUri + "?export" ) ;
2021-10-26 07:36:25 -04:00
2021-08-19 08:44:38 -04:00
lock ( scratch )
{
2021-10-13 09:25:03 -04:00
var calName = iCalHoopJumping . LoadCalendar ( calString ) ;
scratch . Calendars [ calName ] = calString ;
2021-10-26 07:36:25 -04:00
//todo: make sure I'm getting things in the present.
2021-10-13 09:25:03 -04:00
foreach ( var occurrence in iCalHoopJumping . getOccurrences ( calName ) )
2021-08-19 08:44:38 -04:00
{
2021-10-13 09:25:03 -04:00
var newSchedulable = new schedulable . Scheduled ( )
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
} ;
2021-10-13 09:25:03 -04:00
var asActualEvent = iCalHoopJumping . parseEvent ( calName , occurrence . Event ) ;
if ( scratch . agenda . FirstOrDefault ( s = > iCalHoopJumping . parseEvent ( calName , s . Occurrence . Event ) ? . Uid = = asActualEvent . Uid ) = = null )
2021-09-03 11:44:44 -04:00
{
2021-10-13 09:25:03 -04:00
//createSchedulable(ref newSchedulable);
2021-09-03 11:44:44 -04:00
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 ( )
{
2021-10-13 09:25:03 -04:00
schedulable . Scheduled todo = null ;
2021-08-20 01:48:35 -04:00
while ( true )
{
_signal . WaitOne ( calendarNaptime ) ;
if ( ! workQueue . TryDequeue ( out todo ) ) { continue ; }
2021-10-13 09:25:03 -04:00
Console . WriteLine ( $"threadwork consumes! showtime at {todo.Showtime}, {todo.Occurrence._event.Summary} on {todo.Occurrence.CalendarSourceName}" ) ;
2021-09-01 01:16:29 -04:00
2021-10-13 09:25:03 -04:00
todo . Configuration = findConfig ( todo . Occurrence . CalendarSourceName , todo . Occurrence . _event . Summary ) ;
if ( todo . Configuration = = null )
2021-08-21 00:15:37 -04:00
{
2021-10-13 09:25:03 -04:00
Console . WriteLine ( "configuration not found, skipping :(" ) ;
continue ;
2021-08-21 00:15:37 -04:00
}
2021-10-13 09:25:03 -04:00
Console . WriteLine ( "configuration found" ) ;
2021-09-03 07:18:38 -04:00
2021-10-26 07:36:25 -04:00
var handler = new ShowHandler ( todo , directorConf . workingDirectory + todo . Showtime . ToString ( "_yyyy-MM-dd" ) , ( ) = > {
//tf.ProduceMessage(new silver_messages.directorial.execute_command(){command = "directors_datasync", timeout = TimeSpan.Zero});
} ) ;
2021-10-13 09:25:03 -04:00
handler . StartHandling ( ) ;
}
}
2021-09-01 01:16:29 -04:00
2021-10-13 09:25:03 -04:00
private static schedulable . Schedulable findConfig ( string CalendarSourceName , string eventName )
{
foreach ( var locator in directorConf . scheduleConfigs )
{
if ( locator . Calendar = = CalendarSourceName )
2021-09-01 01:16:29 -04:00
{
2021-10-13 09:25:03 -04:00
if ( locator . EventName . IsMatch ( eventName ) )
{
var configurationName = locator . EventName . Replace ( eventName , locator . SchedulableConfiguration ) ;
Console . WriteLine ( $"found match good enough, I guess. going to load {configurationName} for {eventName}" ) ;
try
{
return JsonConvert . DeserializeObject < schedulable . Schedulable > ( File . ReadAllText ( configurationName ) ) ;
}
catch ( Exception e )
{
Console . Error . WriteLine ( $"error btw. not sure who's not throwing one. {e.Message}" ) ;
return null ;
}
}
2021-08-20 01:48:35 -04:00
}
}
2021-10-13 09:25:03 -04:00
//HumanCommunication.Instance.forwardToDiscord($"couldn't find suitable configuration for {eventName} within {CalendarSourceName}", HumanCommunication.LogLevel.Info);
return null ;
2021-08-20 01:48:35 -04:00
}
2021-08-17 04:21:48 -04:00
}
}