2021-06-19 04:49:08 -04:00
|
|
|
|
using franz;
|
|
|
|
|
using Newtonsoft.Json;
|
2021-07-23 01:51:40 -04:00
|
|
|
|
using silver_messages.directorial;
|
2021-06-09 07:51:25 -04:00
|
|
|
|
using System;
|
2021-06-19 04:49:08 -04:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
2021-07-23 01:51:40 -04:00
|
|
|
|
using System.Net;
|
2021-06-19 04:49:08 -04:00
|
|
|
|
using System.Net.Http;
|
2021-07-23 01:51:40 -04:00
|
|
|
|
using System.Text;
|
2021-06-09 07:51:25 -04:00
|
|
|
|
using System.Threading;
|
2021-06-19 04:49:08 -04:00
|
|
|
|
using System.Threading.Tasks;
|
2021-06-08 07:02:34 -04:00
|
|
|
|
|
|
|
|
|
namespace directors_assistant
|
|
|
|
|
{
|
|
|
|
|
class Program
|
|
|
|
|
{
|
2021-06-19 04:49:08 -04:00
|
|
|
|
public static Config conf;
|
|
|
|
|
public static Telefranz telefranz;
|
|
|
|
|
static async Task Main(string[] args)
|
2021-07-23 01:51:40 -04:00
|
|
|
|
{
|
2021-06-19 04:49:08 -04:00
|
|
|
|
conf = JsonConvert.DeserializeObject<Config>(File.ReadAllText("appsettings.json"));
|
2021-10-15 11:04:49 -04:00
|
|
|
|
Telefranz.Configure(name: conf.name, bootstrap_servers: conf.bootstrap_servers,
|
|
|
|
|
commands: conf.commands.Select(c => c.name).ToList());
|
|
|
|
|
telefranz = Telefranz.Instance;
|
2021-07-23 01:51:40 -04:00
|
|
|
|
telefranz.addHandler((silver_messages.directorial.execute_command ec) =>
|
|
|
|
|
{
|
|
|
|
|
var matchedCommands = conf.commands.Where(c => c.name == ec.command)?.ToList();
|
|
|
|
|
//I swear I have a vague memory of foreach in linq'd query throwing an exception when results empty.
|
|
|
|
|
if (matchedCommands != null && matchedCommands.Count > 0)
|
2021-06-09 07:51:25 -04:00
|
|
|
|
{
|
2021-07-23 01:51:40 -04:00
|
|
|
|
foreach (var cmd in matchedCommands)
|
|
|
|
|
{
|
2021-07-23 04:18:21 -04:00
|
|
|
|
Console.WriteLine($"executing {cmd.name}{(ec.args != null ? ", given args " + string.Join(' ', ec.args) : "")} with timeout {ec.timeout}");
|
2021-07-23 01:51:40 -04:00
|
|
|
|
|
|
|
|
|
var cmdAndArgs = cmd.shell.Split(' ');
|
|
|
|
|
var justArgs = cmdAndArgs.Skip(1).ToList();
|
|
|
|
|
justArgs.AddRange(ec.args);
|
|
|
|
|
var commandPath = cmdAndArgs[0];
|
|
|
|
|
var commandArguments = String.Join(' ', justArgs);
|
2021-10-15 11:04:49 -04:00
|
|
|
|
if (ec.timeout > TimeSpan.Zero)
|
2021-07-23 01:51:40 -04:00
|
|
|
|
{
|
|
|
|
|
executeTimed(cmd.name, commandPath, commandArguments, ec.timeout);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
executeUntimed(cmd.name, commandPath, commandArguments);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-09 07:51:25 -04:00
|
|
|
|
}
|
2021-06-19 04:49:08 -04:00
|
|
|
|
});
|
2021-07-23 01:51:40 -04:00
|
|
|
|
await Task.Delay(1000);
|
|
|
|
|
telefranz.ProduceMessage(new silver_messages.global.sound_off());
|
2021-06-09 07:51:25 -04:00
|
|
|
|
|
2021-07-23 04:18:21 -04:00
|
|
|
|
await Task.Delay(-1);
|
2021-06-08 07:02:34 -04:00
|
|
|
|
}
|
2021-07-23 01:51:40 -04:00
|
|
|
|
|
2021-10-15 11:04:49 -04:00
|
|
|
|
private static void executeTimed(string commandName, string commandPath, string commandArguments, TimeSpan? timeout)
|
2021-07-23 01:51:40 -04:00
|
|
|
|
{
|
|
|
|
|
var process = readableProcess(commandPath, commandArguments);
|
|
|
|
|
var outputs = new List<string>();
|
|
|
|
|
var errors = new List<string>();
|
|
|
|
|
process.OutputDataReceived += new DataReceivedEventHandler((s, e) => { outputs.Add(e.Data); });
|
|
|
|
|
process.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { errors.Add(e.Data); });
|
|
|
|
|
|
|
|
|
|
var stopwatch = new Stopwatch();
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
process.Start();
|
|
|
|
|
process.BeginErrorReadLine();
|
|
|
|
|
process.BeginOutputReadLine();
|
2021-10-15 11:04:49 -04:00
|
|
|
|
if (timeout > TimeSpan.Zero)
|
|
|
|
|
{
|
|
|
|
|
Task.WaitAny(
|
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
process.WaitForExit();
|
|
|
|
|
}),
|
|
|
|
|
Task.Delay(timeout.Value)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
process.WaitForExit();
|
|
|
|
|
}
|
2021-07-23 01:51:40 -04:00
|
|
|
|
if (process.HasExited)
|
|
|
|
|
{
|
|
|
|
|
stopwatch.Stop();
|
2021-07-23 04:18:21 -04:00
|
|
|
|
Console.WriteLine($"{commandName} completed");
|
2021-07-23 01:51:40 -04:00
|
|
|
|
telefranz.ProduceMessage(new silver_messages.directorial.command_completed()
|
|
|
|
|
{
|
|
|
|
|
command = commandName,
|
2021-07-23 04:18:21 -04:00
|
|
|
|
runtimeMilliseconds = stopwatch.ElapsedMilliseconds,
|
2021-07-23 01:51:40 -04:00
|
|
|
|
exit_code = process.ExitCode,
|
|
|
|
|
stdout = string.Join('\n', outputs),
|
|
|
|
|
stderr = string.Join('\n', errors)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
process.Kill();
|
2021-07-23 04:18:21 -04:00
|
|
|
|
Console.WriteLine($"{commandName} expired");
|
2021-07-23 01:51:40 -04:00
|
|
|
|
telefranz.ProduceMessage(new silver_messages.directorial.command_expired()
|
|
|
|
|
{
|
2021-10-15 11:04:49 -04:00
|
|
|
|
command = commandName,
|
2021-07-23 04:18:21 -04:00
|
|
|
|
stdout = string.Join('\n', outputs),
|
|
|
|
|
stderr = string.Join('\n', errors)
|
2021-07-23 01:51:40 -04:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void executeUntimed(string commandName, string commandPath, string commandArguments)
|
|
|
|
|
{
|
2021-07-23 04:18:21 -04:00
|
|
|
|
var stopwatch = new Stopwatch();
|
2021-07-23 01:51:40 -04:00
|
|
|
|
var process = readableProcess(commandPath, commandArguments);
|
2021-10-15 11:04:49 -04:00
|
|
|
|
process.OutputDataReceived += new DataReceivedEventHandler((s, e) =>
|
|
|
|
|
{
|
2021-07-23 04:18:21 -04:00
|
|
|
|
Console.WriteLine($"{commandName} output: {e.Data}");
|
2021-10-15 11:04:49 -04:00
|
|
|
|
if (string.IsNullOrWhiteSpace(e.Data))
|
2021-07-23 04:18:21 -04:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-10-15 11:04:49 -04:00
|
|
|
|
telefranz.ProduceMessage(new silver_messages.directorial.command_output()
|
|
|
|
|
{
|
2021-07-23 04:18:21 -04:00
|
|
|
|
stdout = e.Data,
|
|
|
|
|
command = commandName,
|
|
|
|
|
runtime = (uint)stopwatch.ElapsedMilliseconds
|
2021-07-23 01:51:40 -04:00
|
|
|
|
});
|
|
|
|
|
});
|
2021-10-15 11:04:49 -04:00
|
|
|
|
process.ErrorDataReceived += new DataReceivedEventHandler((s, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(e.Data))
|
2021-07-23 04:18:21 -04:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Console.Error.WriteLine($"{commandName} err (but not necessarily dead?): {e.Data}");
|
2021-10-15 11:04:49 -04:00
|
|
|
|
telefranz.ProduceMessage(new silver_messages.directorial.command_error()
|
|
|
|
|
{
|
2021-07-23 04:18:21 -04:00
|
|
|
|
stderr = e.Data,
|
|
|
|
|
command = commandName,
|
|
|
|
|
runtime = (uint)stopwatch.ElapsedMilliseconds
|
2021-07-23 01:51:40 -04:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
process.Start();
|
|
|
|
|
process.BeginErrorReadLine();
|
|
|
|
|
process.BeginOutputReadLine();
|
|
|
|
|
process.WaitForExit();
|
2021-07-23 04:18:21 -04:00
|
|
|
|
stopwatch.Stop();
|
|
|
|
|
Console.WriteLine($"{commandName} returned {process.ExitCode} after {stopwatch.ElapsedMilliseconds}ms");
|
2021-07-23 01:51:40 -04:00
|
|
|
|
telefranz.ProduceMessage(new silver_messages.directorial.command_completed()
|
|
|
|
|
{
|
|
|
|
|
command = commandName,
|
2021-07-23 04:18:21 -04:00
|
|
|
|
runtimeMilliseconds = stopwatch.ElapsedMilliseconds,
|
2021-07-23 01:51:40 -04:00
|
|
|
|
exit_code = process.ExitCode
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Process readableProcess(string commandPath, string commandArguments)
|
|
|
|
|
{
|
|
|
|
|
var pi = new ProcessStartInfo(commandPath, commandArguments);
|
|
|
|
|
pi.UseShellExecute = false;
|
|
|
|
|
pi.CreateNoWindow = true;
|
|
|
|
|
pi.RedirectStandardError = true;
|
|
|
|
|
pi.RedirectStandardOutput = true;
|
|
|
|
|
var process = new Process();
|
|
|
|
|
process.StartInfo = pi;
|
|
|
|
|
return process;
|
|
|
|
|
}
|
2021-06-08 07:02:34 -04:00
|
|
|
|
}
|
|
|
|
|
}
|