You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Program.cs 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Threading.Tasks;
  6. using S22.Xmpp;
  7. using S22.Xmpp.Client;
  8. using S22.Xmpp.Im;
  9. namespace RhinoReminds
  10. {
  11. public class ProgramSettings
  12. {
  13. public string AllowedDomain = "*";
  14. public string Filepath = "./reminders.xml";
  15. public string Jid = null;
  16. public string AvatarFilepath = string.Empty;
  17. public string PidFile = null;
  18. public string Password = null;
  19. }
  20. public static class Program
  21. {
  22. private static ProgramSettings settings = new ProgramSettings();
  23. public static int Main(string[] args)
  24. {
  25. List<string> extras = new List<string>();
  26. for (int i = 0; i < args.Length; i++)
  27. {
  28. if (!args[i].StartsWith("-")) {
  29. extras.Add(args[i]);
  30. continue;
  31. }
  32. switch (args[i]) {
  33. case "-h":
  34. case "--help":
  35. Console.WriteLine("--- RhinoReminds ---");
  36. Console.WriteLine("> An XMPP reminder bot");
  37. Console.WriteLine(" By Starbeamrainbowlabs");
  38. Console.WriteLine();
  39. Console.WriteLine("Usage:");
  40. Console.WriteLine(" mono RhinoReminds.exe {options}");
  41. Console.WriteLine();
  42. Console.WriteLine("Options:");
  43. Console.WriteLine(" -h --help Show this message");
  44. Console.WriteLine($" -f --file Specify where to save reminders (default: {settings.Filepath})");
  45. Console.WriteLine(" --domain {domain} Set the domain users are allowed to originate at. Defaults to any domain.");
  46. Console.WriteLine(" --avatar Update the XMPP account's avatar to the specified image. By default the avatar is not updated.");
  47. Console.WriteLine(" --pidfile Save our process ID to the specified file, and delete it on exit");
  48. Console.WriteLine();
  49. Console.WriteLine("Environment Variables:");
  50. Console.WriteLine(" XMPP_JID The JID to login to");
  51. Console.WriteLine(" XMPP_PASSWORD The password to login with");
  52. return 0;
  53. case "--jid":
  54. settings.Jid = args[++i];
  55. break;
  56. case "-d":
  57. case "--domain":
  58. settings.AllowedDomain = args[++i];
  59. break;
  60. case "--avatar":
  61. settings.AvatarFilepath = args[++i];
  62. break;
  63. case "--pidfile":
  64. settings.PidFile = args[++i];
  65. break;
  66. default:
  67. Console.Error.WriteLine($"Error: Unknown argument '{args[i]}'.");
  68. return 14;
  69. }
  70. }
  71. settings.Jid = Environment.GetEnvironmentVariable("XMPP_JID");
  72. settings.Password = Environment.GetEnvironmentVariable("XMPP_PASSWORD");
  73. if (settings.Jid == null) {
  74. Console.Error.WriteLine("Error: No JID specified to login with.");
  75. Console.Error.WriteLine("Do so with the XMPP_JID environment variable!");
  76. return 15;
  77. }
  78. if (settings.Password == null) {
  79. Console.Error.WriteLine("Error: No password specified to login with.");
  80. Console.Error.WriteLine("Do so with the XMPP_PASSWORD environment variable!");
  81. return 16;
  82. }
  83. if (settings.PidFile != null)
  84. setupPidFile();
  85. run();
  86. // We shouldn't ever end up here, but just in case.....
  87. cleanupPidFile();
  88. return 0;
  89. }
  90. private static void setupPidFile()
  91. {
  92. File.WriteAllText(settings.PidFile, Process.GetCurrentProcess().Id.ToString());
  93. AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => cleanupPidFile();
  94. AppDomain.CurrentDomain.DomainUnload += (object sender, EventArgs e) => cleanupPidFile();
  95. }
  96. private static void cleanupPidFile() {
  97. // Make sure we only do cleanup once
  98. if (settings.PidFile == null)
  99. return;
  100. File.Delete(settings.PidFile);
  101. settings.PidFile = null;
  102. }
  103. private static void run()
  104. {
  105. Console.WriteLine("************************************");
  106. Console.WriteLine("***** RhinoReminds is starting *****");
  107. Console.WriteLine("************************************");
  108. ClientListener client = new ClientListener(settings.Jid, settings.Password) {
  109. ReminderFilePath = settings.Filepath
  110. };
  111. client.AllowedDomains.Add(settings.AllowedDomain);
  112. // Update the avatar if appropriate
  113. if (settings.AvatarFilepath != string.Empty) {
  114. OnConnectedHandler handler = null;
  115. handler = (object sender, OnConnectedEventArgs eventArgs) => {
  116. client.SetAvatar(settings.AvatarFilepath);
  117. Console.WriteLine($"[Program] Set avatar to '{settings.AvatarFilepath}'.");
  118. client.OnConnected -= handler;
  119. };
  120. client.OnConnected += handler;
  121. }
  122. // Connect to the server & start listening
  123. // Make sure the program doesn't exit whilst we're connected
  124. try
  125. {
  126. client.Start().Wait();
  127. } catch (Exception) {
  128. // Ensure we tidy up after ourselves by deleting the PID file
  129. if (settings.PidFile != null)
  130. cleanupPidFile();
  131. // Re-throw the error
  132. throw;
  133. }
  134. }
  135. }
  136. }