RhinoReminds/RhinoReminds/Program.cs

178 line
5.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using RhinoReminds.Utilities;
using S22.Xmpp;
using S22.Xmpp.Client;
using S22.Xmpp.Im;
using SBRL.Utilities;
namespace RhinoReminds
{
public class ProgramSettings
{
public string AllowedDomain = "*";
public string Filepath = "./reminders.xml";
public string Jid = null;
public string AvatarFilepath = string.Empty;
public string PidFile = null;
public bool ExitOnModify = false;
public string Password = null;
}
public static class Program
{
public static string Version {
get {
return $"v{Assembly.GetExecutingAssembly().GetName().Version}" +
$"-{EmbeddedFiles.ReadAllText("RhinoReminds.git-hash.txt").Substring(0, 7)}";
}
}
private static ProgramSettings settings = new ProgramSettings();
public static int Main(string[] args)
{
List<string> extras = new List<string>();
for (int i = 0; i < args.Length; i++)
{
if (!args[i].StartsWith("-")) {
extras.Add(args[i]);
continue;
}
switch (args[i]) {
case "-h":
case "--help":
Console.WriteLine($"--- RhinoReminds {Version} ---");
Console.WriteLine("> An XMPP reminder bot");
Console.WriteLine(" By Starbeamrainbowlabs");
Console.WriteLine();
Console.WriteLine("Usage:");
Console.WriteLine(" mono RhinoReminds.exe {options}");
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine(" -h --help Show this message");
Console.WriteLine($" -f --file Specify where to save reminders (default: {settings.Filepath})");
Console.WriteLine(" --domain {domain} Set the domain users are allowed to originate at. Defaults to any domain.");
Console.WriteLine(" --avatar Update the XMPP account's avatar to the specified image. By default the avatar is not updated.");
Console.WriteLine(" --pidfile Save our process ID to the specified file, and delete it on exit");
Console.WriteLine(" --auto-exit Watch for changes to the executable on disk and automatically quit with an exit code of 0 if a modification is detected. Useful for integration with a service manager and continuous deployment.");
Console.WriteLine();
Console.WriteLine("Environment Variables:");
Console.WriteLine(" XMPP_JID The JID to login to");
Console.WriteLine(" XMPP_PASSWORD The password to login with");
return 0;
case "--jid":
settings.Jid = args[++i];
break;
case "-d":
case "--domain":
settings.AllowedDomain = args[++i];
break;
case "--avatar":
settings.AvatarFilepath = args[++i];
break;
case "--pidfile":
settings.PidFile = args[++i];
break;
case "--auto-exit":
settings.ExitOnModify = true;
break;
default:
Console.Error.WriteLine($"Error: Unknown argument '{args[i]}'.");
return 14;
}
}
settings.Jid = Environment.GetEnvironmentVariable("XMPP_JID");
settings.Password = Environment.GetEnvironmentVariable("XMPP_PASSWORD");
if (settings.Jid == null) {
Console.Error.WriteLine("Error: No JID specified to login with.");
Console.Error.WriteLine("Do so with the XMPP_JID environment variable!");
return 15;
}
if (settings.Password == null) {
Console.Error.WriteLine("Error: No password specified to login with.");
Console.Error.WriteLine("Do so with the XMPP_PASSWORD environment variable!");
return 16;
}
if (settings.PidFile != null)
setupPidFile();
run();
// We shouldn't ever end up here, but just in case.....
cleanupPidFile();
return 0;
}
private static void setupPidFile()
{
File.WriteAllText(settings.PidFile, Process.GetCurrentProcess().Id.ToString());
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => cleanupPidFile();
AppDomain.CurrentDomain.DomainUnload += (object sender, EventArgs e) => cleanupPidFile();
}
private static void cleanupPidFile() {
// Make sure we only do cleanup once
if (settings.PidFile == null)
return;
File.Delete(settings.PidFile);
settings.PidFile = null;
}
private static void run()
{
Console.WriteLine("************************************");
Console.WriteLine("***** RhinoReminds is starting *****");
Console.WriteLine("************************************");
Console.WriteLine($"[Program] Running {Version}");
if (settings.ExitOnModify) {
ExitWatcher.EnableExitOnModify();
}
ClientListener client = new ClientListener(settings.Jid, settings.Password) {
ReminderFilePath = settings.Filepath
};
client.AllowedDomains.Add(settings.AllowedDomain);
// Update the avatar if appropriate
if (settings.AvatarFilepath != string.Empty) {
OnConnectedHandler handler = null;
handler = (object sender, OnConnectedEventArgs eventArgs) => {
client.SetAvatar(settings.AvatarFilepath);
Console.WriteLine($"[Program] Set avatar to '{settings.AvatarFilepath}'.");
client.OnConnected -= handler;
};
client.OnConnected += handler;
}
// Connect to the server & start listening
// Make sure the program doesn't exit whilst we're connected
try {
client.Start().Wait();
} catch (Exception) {
// Ensure we tidy up after ourselves by deleting the PID file
if (settings.PidFile != null)
cleanupPidFile();
// Re-throw the error
throw;
}
}
}
}