2018-11-09 22:45:59 +00:00
using System ;
using System.Collections.Generic ;
2018-12-27 13:36:55 +00:00
using System.Diagnostics ;
2018-11-10 18:15:30 +00:00
using System.IO ;
2019-03-28 20:03:10 +00:00
using System.Reflection ;
2018-11-23 17:55:23 +00:00
using System.Threading.Tasks ;
2019-03-28 23:04:52 +00:00
using RhinoReminds.Utilities ;
2018-11-10 18:15:30 +00:00
using S22.Xmpp ;
2018-11-09 22:45:59 +00:00
using S22.Xmpp.Client ;
using S22.Xmpp.Im ;
2019-03-28 20:03:10 +00:00
using SBRL.Utilities ;
2018-11-09 22:45:59 +00:00
namespace RhinoReminds
{
public class ProgramSettings
{
2018-11-10 21:16:39 +00:00
public string AllowedDomain = "*" ;
2018-11-10 19:58:45 +00:00
public string Filepath = "./reminders.xml" ;
2018-11-09 22:45:59 +00:00
public string Jid = null ;
2018-11-23 17:55:23 +00:00
public string AvatarFilepath = string . Empty ;
2018-12-27 13:36:55 +00:00
public string PidFile = null ;
2018-11-23 17:55:23 +00:00
2019-03-28 23:04:52 +00:00
public bool ExitOnModify = false ;
2018-11-09 22:45:59 +00:00
public string Password = null ;
}
public static class Program
{
2019-03-28 20:03:10 +00:00
public static string Version {
get {
return $"v{Assembly.GetExecutingAssembly().GetName().Version}" +
$"-{EmbeddedFiles.ReadAllText(" RhinoReminds . git - hash . txt ").Substring(0, 7)}" ;
}
}
2018-11-09 22:45:59 +00:00
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 ] ) {
2018-11-10 21:16:39 +00:00
case "-h" :
2018-11-09 22:45:59 +00:00
case "--help" :
2019-03-28 20:03:10 +00:00
Console . WriteLine ( $"--- RhinoReminds {Version} ---" ) ;
2018-11-09 22:45:59 +00:00
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:" ) ;
2019-03-28 23:04:52 +00:00
Console . WriteLine ( " -h --help Show this message" ) ;
Console . WriteLine ( $" -f --file Specify where to save reminders (default: {settings.Filepath})" ) ;
2018-11-10 21:16:39 +00:00
Console . WriteLine ( " --domain {domain} Set the domain users are allowed to originate at. Defaults to any domain." ) ;
2019-03-28 23:04:52 +00:00
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." ) ;
2018-11-09 22:45:59 +00:00
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 ;
2018-11-10 21:16:39 +00:00
case "-d" :
case "--domain" :
settings . AllowedDomain = args [ + + i ] ;
break ;
2018-11-23 17:55:23 +00:00
case "--avatar" :
settings . AvatarFilepath = args [ + + i ] ;
break ;
2018-12-27 13:36:55 +00:00
case "--pidfile" :
settings . PidFile = args [ + + i ] ;
break ;
2018-12-27 13:38:23 +00:00
2019-03-28 23:04:52 +00:00
case "--auto-exit" :
settings . ExitOnModify = true ;
break ;
2018-12-27 13:38:23 +00:00
default :
Console . Error . WriteLine ( $"Error: Unknown argument '{args[i]}'." ) ;
return 14 ;
2018-11-09 22:45:59 +00:00
}
}
settings . Jid = Environment . GetEnvironmentVariable ( "XMPP_JID" ) ;
settings . Password = Environment . GetEnvironmentVariable ( "XMPP_PASSWORD" ) ;
2018-12-27 13:36:55 +00:00
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 ;
}
2018-11-10 01:19:54 +00:00
2018-12-27 13:36:55 +00:00
if ( settings . PidFile ! = null )
setupPidFile ( ) ;
run ( ) ;
// We shouldn't ever end up here, but just in case.....
cleanupPidFile ( ) ;
2018-11-09 22:45:59 +00:00
return 0 ;
}
2018-12-27 13:36:55 +00:00
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 ( )
2018-11-09 22:45:59 +00:00
{
2019-02-08 11:02:52 +00:00
Console . WriteLine ( "************************************" ) ;
Console . WriteLine ( "***** RhinoReminds is starting *****" ) ;
Console . WriteLine ( "************************************" ) ;
2019-03-28 20:03:10 +00:00
Console . WriteLine ( $"[Program] Running {Version}" ) ;
2019-02-08 11:02:52 +00:00
2019-03-28 23:04:52 +00:00
if ( settings . ExitOnModify ) {
ExitWatcher . EnableExitOnModify ( ) ;
}
2018-11-10 18:15:30 +00:00
ClientListener client = new ClientListener ( settings . Jid , settings . Password ) {
ReminderFilePath = settings . Filepath
} ;
2018-11-10 21:16:39 +00:00
client . AllowedDomains . Add ( settings . AllowedDomain ) ;
2018-11-23 17:55:23 +00:00
// Update the avatar if appropriate
2018-12-05 23:18:38 +00:00
if ( settings . AvatarFilepath ! = string . Empty ) {
2018-12-21 10:58:14 +00:00
OnConnectedHandler handler = null ;
handler = ( object sender , OnConnectedEventArgs eventArgs ) = > {
2018-12-05 23:18:38 +00:00
client . SetAvatar ( settings . AvatarFilepath ) ;
Console . WriteLine ( $"[Program] Set avatar to '{settings.AvatarFilepath}'." ) ;
2018-12-21 10:58:14 +00:00
client . OnConnected - = handler ;
2018-12-05 23:18:38 +00:00
} ;
2018-12-21 10:58:14 +00:00
client . OnConnected + = handler ;
2018-12-05 23:18:38 +00:00
}
// Connect to the server & start listening
2018-11-23 17:55:23 +00:00
// Make sure the program doesn't exit whilst we're connected
2019-03-28 23:04:52 +00:00
try {
2018-12-27 13:36:55 +00:00
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 ;
}
2018-11-09 22:45:59 +00:00
}
}
}