using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using S22.Xmpp; using S22.Xmpp.Client; using S22.Xmpp.Im; namespace XmppBotDemo { public static class MainClass { private static XmppClient client; private static Jid ourJid = null; private static string password = null; public static int Main(string[] args) { // Read in the environment variables ourJid = new Jid(Environment.GetEnvironmentVariable("XMPP_JID")); password = Environment.GetEnvironmentVariable("XMPP_PASSWORD"); // Ensure they are present if (ourJid == null || password == null) { Console.Error.WriteLine("XMPP Bot Demo"); Console.Error.WriteLine("============="); Console.Error.WriteLine(""); Console.Error.WriteLine("Usage:"); Console.Error.WriteLine(" ./XmppBotDemo.exe"); Console.Error.WriteLine(""); Console.Error.WriteLine("Environment Variables:"); Console.Error.WriteLine(" XMPP_JID Required. Specifies the JID to login with."); Console.Error.WriteLine(" XMPP_PASSWORD Required. Specifies the password to login with."); return 1; } // Create the client instance client = new XmppClient(ourJid.Domain, ourJid.Node, password); client.Error += errorHandler; client.SubscriptionRequest += subscriptionRequestHandler; client.Message += messageHandler; client.Connect(); // Wait for a connection while (!client.Connected) Thread.Sleep(100); Console.WriteLine($"[Main] Connected as {ourJid}."); // Wait forever. Thread.Sleep(Timeout.Infinite); // TODO: Automatically reconnect to the server when we get disconnected. return 0; } #region Event Handlers /// /// Handles requests to talk to us. /// /// /// Only allow people to talk to us if they are on the same domain we are. /// You probably don't want this for production, but for developmental purposes /// it offers some measure of protection. /// /// The JID of the remote user who wants to talk to us. /// Whether we're going to allow the requester to talk to us or not. public static bool subscriptionRequestHandler(Jid from) { Console.WriteLine($"[Handler/SubscriptionRequest] {from} is requesting access, I'm saying {(from.Domain == ourJid.Domain?"yes":"no")}"); return from.Domain == ourJid.Domain; } /// /// Handles incoming messages. /// private static void messageHandler(object sender, MessageEventArgs eventArgs) { Console.WriteLine($"[Handler/Message] {eventArgs.Message.Body.Length} chars from {eventArgs.Jid}"); char[] messageCharArray = eventArgs.Message.Body.ToCharArray(); Array.Reverse(messageCharArray); sendChatReply( eventArgs.Message, new string(messageCharArray) ); } /// /// Handles any errors thrown by the XMPP client engine. /// private static void errorHandler(object sender, ErrorEventArgs eventArgs) { Console.Error.WriteLine($"Error: {eventArgs.Reason}"); Console.Error.WriteLine(eventArgs.Exception); } #endregion #region Message Senders /// /// Sends a chat message to the specified JID. /// /// The JID to send the message to. /// The messaage to send. private static void sendChatMessage(Jid to, string message) { //Console.WriteLine($"[Rhino/Send/Chat] Sending {message} -> {to}"); client.SendMessage( to, message, null, null, MessageType.Chat ); } /// /// Sends a chat message in direct reply to a given incoming message. /// /// Original message. /// Reply. private static void sendChatReply(Message originalMessage, string reply) { //Console.WriteLine($"[Rhino/Send/Reply] Sending {reply} -> {originalMessage.From}"); client.SendMessage( originalMessage.From, reply, null, originalMessage.Thread, MessageType.Chat ); } #endregion } }