public bool parseExpectedReplies(message m) { //are we expecteing this? bool processed = false; Modules.RobotoModuleTemplate pluginToCall = null; ExpectedReply er = null; try { foreach (ExpectedReply e in expectedReplies) { //we are looking for direct messages from the user where c_id = m_id, OR reply messages where m_id = reply_id //could trigger twice if we f****d something up - dont think this is an issue but checking processed flag for safety if (!processed && e.isSent() && m.userID == e.userID) { if (m.chatID == e.userID || m.replyMessageID == e.outboundMessageID) { //find the plugin, send the expectedreply to it foreach (Modules.RobotoModuleTemplate plugin in settings.plugins) { if (e.isOfType(plugin.GetType())) { //stash these for calling outside of the "foreach" loop. This is so we can be sure it is called ONCE only, and so that we can remove //the expected reply before calling the method, so any post-processing works smoother. pluginToCall = plugin; er = e; } } processed = true; } } } } catch (Exception e) { Roboto.log.log("Error matching incoming message to plugin - " + e.ToString(), logging.loglevel.critical); } if (processed) { expectedReplies.Remove(er); //now send it to the plugin (remove first, so any checks can be done) try { bool pluginProcessed = pluginToCall.replyReceived(er, m); if (pluginProcessed) { //reset our chat timer chat c = getChat(er.chatID); c.resetLastUpdateTime(); } else { throw new InvalidProgramException("Plugin didnt process the message it expected a reply to!"); } } catch (Exception e) { Roboto.log.log("Error calling plugin " + pluginToCall.GetType().ToString() + " with expected reply. " + e.ToString(), logging.loglevel.critical); } /*/are there any more messages for the user? If so, find & send * ExpectedReply messageToSend = null; * foreach (ExpectedReply e in expectedReplies) * { * if (e.userID == m.userID) * { * if (messageToSend == null || e.timeLogged < messageToSend.timeLogged) * { * messageToSend = e; * } * * } * } * * //send it * //note that the plugin might send an urgent message during this processing that may have jumped the queue (using trySendImmediate param) * if ( !userHasOutstandingMessages(m.userID) && messageToSend != null) * { * messageToSend.sendMessage(); * //make sure we are in a safe state. This will make sure if we sent a message-only, that the next message(s) are processed. * expectedReplyHousekeeping(); * } */ expectedReplyHousekeeping(); } return(processed); }
/// <summary> /// Main Roboto process. Connects to Telegram and processes any updates. /// </summary> private static void Process() { DateTime lastUpdate = DateTime.MinValue; while (!endLoop) { //store the time to prevent hammering the service when its down if (lastUpdate > DateTime.Now.Subtract(TimeSpan.FromSeconds(10))) { Console.WriteLine("Too quick, sleeping"); Thread.Sleep(10000); } lastUpdate = DateTime.Now; string updateURL = Settings.telegramAPIURL + Settings.telegramAPIKey + "/getUpdates" + "?offset=" + Settings.getUpdateID() + "&timeout=" + Settings.waitDuration + "&limit=5"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(updateURL); Console.WriteLine("getUpdate, ID " + Settings.getUpdateID()); request.Method = "GET"; request.ContentType = "application/json"; try { WebResponse webResponse = request.GetResponse(); using (Stream webStream = webResponse.GetResponseStream()) { if (webStream != null) { using (StreamReader responseReader = new StreamReader(webStream)) { string response = responseReader.ReadToEnd(); JObject jo = JObject.Parse(response); //success? string path = jo.First.Path; string result = jo.First.First.Value<string>(); if (path != "ok" || result != "True") { endLoop = true; throw new WebException("Failure code from web service"); } else { //open the response and parse it using JSON. Probably only one result, but should be more? foreach (JToken token in jo.SelectTokens("result.[*]"))//jo.Children()) //) records[*].data.importedPath" { Console.WriteLine(token.ToString()); //Find out what kind of message this is. //TOP LEVEL TOKENS JToken updateID_TK = token.First; JToken update_TK = updateID_TK.Next.First; //Flag the update ID as processed. int updateID = updateID_TK.First.Value<int>(); Settings.lastUpdate = updateID; //is this for a group chat? int chatID = update_TK.SelectToken("chat.id").Value<int>(); chat chatData = null; if (chatID < 0) { //find the chat chatData = Settings.getChat(chatID); //new chat, add if (chatData == null) { chatData = Settings.addChat(chatID); } if (chatData == null) { throw new DataMisalignedException("Something went wrong creating the new chat data"); } } //Do we have an incoming message? if (update_TK.Path == "result[0].message" && update_TK.SelectToken(".text") != null) { //prevent delays - its sent something valid back to us so we are probably OK. lastUpdate = DateTime.MinValue; message m = new message(update_TK); //now decide what to do with this stuff. bool processed = false; //TODO - do this in priority order :( foreach (Modules.RobotoModuleTemplate plugin in settings.plugins) { if (plugin.chatHook && (!processed || plugin.chatEvenIfAlreadyMatched)) { plugin.chatEvent(m, chatData); } } } //dont know what other update types we want to monitor? } } } } } } catch (Exception e) { Console.Out.WriteLine("-----------------"); Console.Out.WriteLine(e.Message); } //TODO - process background actions foreach (Modules.RobotoModuleTemplate plugin in settings.plugins) { if (plugin.backgroundHook) { plugin.callBackgroundProcessing(); } } } }
/// <summary> /// Main Roboto process. Connects to Telegram and processes any updates. /// </summary> private static void Process() { DateTime lastUpdate = DateTime.MinValue; while (!endLoop) { //store the time to prevent hammering the service when its down. Pause for a couple of seconds if things are getting toasty if (lastUpdate > DateTime.Now.Subtract(TimeSpan.FromSeconds(10))) { Roboto.Settings.stats.logStat(new statItem("Hammering Prevention", typeof(Roboto))); log.log("Too quick, sleeping", logging.loglevel.warn); Thread.Sleep(2000); } lastUpdate = DateTime.Now; //TODO - move this code to the webADI class string updateURL = Settings.telegramAPIURL + Settings.telegramAPIKey + "/getUpdates" + "?offset=" + Settings.getUpdateID() + "&timeout=" + Settings.waitDuration + "&limit=10"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(updateURL); log.log(".", logging.loglevel.low, ConsoleColor.White, true); request.Method = "GET"; request.ContentType = "application/json"; try { WebResponse webResponse = request.GetResponse(); using (Stream webStream = webResponse.GetResponseStream()) { if (webStream != null) { using (StreamReader responseReader = new StreamReader(webStream)) { string response = responseReader.ReadToEnd(); JObject jo = JObject.Parse(response); //success? string path = jo.First.Path; string result = jo.First.First.Value <string>(); if (path != "ok" || result != "True") { endLoop = true; log.log("Failure code from web service", logging.loglevel.high); throw new WebException("Failure code from web service"); } else { int resultID = 0; //open the response and parse it using JSON. Probably only one result, but should be more? foreach (JToken token in jo.SelectTokens("result.[*]"))//jo.Children()) //) records[*].data.importedPath" { string logText = Regex.Replace(token.ToString(), @"(\s|\n|\r|\r\n)+", " "); log.log(logText, logging.loglevel.verbose); //Find out what kind of message this is. //TOP LEVEL TOKENS JToken updateID_TK = token.First; JToken update_TK = updateID_TK.Next.First; //Flag the update ID as processed. int updateID = updateID_TK.First.Value <int>(); Settings.lastUpdate = updateID; //is this for a group chat? long chatID = update_TK.SelectToken("chat.id").Value <long>(); chat chatData = null; if (chatID < 0) { //find the chat chatData = Settings.getChat(chatID); string chatTitle = update_TK.SelectToken("chat.title").Value <string>(); //new chat, add if (chatData == null) { chatData = Settings.addChat(chatID, chatTitle); } if (chatData == null) { throw new DataMisalignedException("Something went wrong creating the new chat data"); } chatData.setTitle(chatTitle); } //Do we have an incoming message? if (update_TK.Path == "result[" + resultID.ToString() + "].message" && update_TK.SelectToken(".text") != null) { //prevent delays - its sent something valid back to us so we are probably OK. lastUpdate = DateTime.MinValue; if (chatData != null) { chatData.resetLastUpdateTime(); } message m = new message(update_TK); //now decide what to do with this stuff. bool processed = false; //check if this is an expected reply, and if so route it to the Settings.parseExpectedReplies(m); //TODO - call plugins in some kind of priority order foreach (Modules.RobotoModuleTemplate plugin in settings.plugins) { //Skip this message if the chat is muted. if (plugin.chatHook && (chatData == null || (chatData.muted == false || plugin.chatIfMuted))) { if ((!processed || plugin.chatEvenIfAlreadyMatched)) { processed = plugin.chatEvent(m, chatData); } } } } else { log.log("No text in update", logging.loglevel.verbose); } //dont know what other update types we want to monitor? //TODO - leave / kicked / chat deleted resultID++; } //housekeeping //check that all players have been sent a message, if there is one in the stack. This is to double check that if e.g. a game is cancelled the player doesnt get stuck Settings.expectedReplyHousekeeping(); } } } } } catch (System.Net.WebException e) { log.log("Web Service Timeout during getUpdates: " + e.ToString(), logging.loglevel.high); Settings.stats.logStat(new statItem("BotAPI Timeouts", typeof(Roboto))); } catch (Exception e) { try { log.log("Exception caught at main loop. " + e.ToString(), logging.loglevel.critical, ConsoleColor.White, false, false, false, false, 2); } catch (Exception ex) { Console.Out.WriteLine("-----------------"); Console.Out.WriteLine("Error During LOGGING! Original Error was"); Console.Out.WriteLine(e.Message); Console.Out.WriteLine("Logging Error was"); Console.Out.WriteLine(ex.Message); } } Settings.backgroundProcessing(false); } }
/// <summary> /// Main Roboto process. Connects to Telegram and processes any updates. /// </summary> private static void Process() { DateTime lastUpdate = DateTime.MinValue; while (!endLoop) { //store the time to prevent hammering the service when its down. Pause for a couple of seconds if things are getting toasty if (lastUpdate > DateTime.Now.Subtract(TimeSpan.FromSeconds(10))) { Roboto.Settings.stats.logStat(new statItem("Hammering Prevention", typeof(Roboto))); log.log("Too quick, sleeping", logging.loglevel.warn ); Thread.Sleep(2000); } lastUpdate = DateTime.Now; //TODO - move this code to the webADI class string updateURL = Settings.telegramAPIURL + Settings.telegramAPIKey + "/getUpdates" + "?offset=" + Settings.getUpdateID() + "&timeout=" + Settings.waitDuration + "&limit=1"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(updateURL); log.log(".", logging.loglevel.low, ConsoleColor.White, true ); request.Method = "GET"; request.ContentType = "application/json"; try { WebResponse webResponse = request.GetResponse(); using (Stream webStream = webResponse.GetResponseStream()) { if (webStream != null) { using (StreamReader responseReader = new StreamReader(webStream)) { string response = responseReader.ReadToEnd(); JObject jo = JObject.Parse(response); //success? string path = jo.First.Path; string result = jo.First.First.Value<string>(); if (path != "ok" || result != "True") { endLoop = true; log.log("Failure code from web service", logging.loglevel.high); throw new WebException("Failure code from web service"); } else { //open the response and parse it using JSON. Probably only one result, but should be more? foreach (JToken token in jo.SelectTokens("result.[*]"))//jo.Children()) //) records[*].data.importedPath" { string logText = Regex.Replace(token.ToString(), @"(\s|\n|\r|\r\n)+", " "); log.log(logText, logging.loglevel.verbose); //Find out what kind of message this is. //TOP LEVEL TOKENS JToken updateID_TK = token.First; JToken update_TK = updateID_TK.Next.First; //Flag the update ID as processed. int updateID = updateID_TK.First.Value<int>(); Settings.lastUpdate = updateID; //is this for a group chat? long chatID = update_TK.SelectToken("chat.id").Value<long>(); chat chatData = null; if (chatID < 0) { //find the chat chatData = Settings.getChat(chatID); string chatTitle = update_TK.SelectToken("chat.title").Value<string>(); //new chat, add if (chatData == null) { chatData = Settings.addChat(chatID, chatTitle); } if (chatData == null) { throw new DataMisalignedException("Something went wrong creating the new chat data"); } chatData.setTitle(chatTitle); } //Do we have an incoming message? if (update_TK.Path == "result[0].message" && update_TK.SelectToken(".text") != null) { //prevent delays - its sent something valid back to us so we are probably OK. lastUpdate = DateTime.MinValue; if (chatData != null) { chatData.resetLastUpdateTime(); } message m = new message(update_TK); //now decide what to do with this stuff. bool processed = false; //check if this is an expected reply, and if so route it to the Settings.parseExpectedReplies(m); //TODO - call plugins in some kind of priority order foreach (Modules.RobotoModuleTemplate plugin in settings.plugins) { //Skip this message if the chat is muted. if (plugin.chatHook && (chatData == null || (chatData.muted == false || plugin.chatIfMuted))) { if ((!processed || plugin.chatEvenIfAlreadyMatched)) { processed = plugin.chatEvent(m, chatData); } } } } //dont know what other update types we want to monitor? //TODO - leave / kicked / chat deleted } //housekeeping //check that all players have been sent a message, if there is one in the stack. This is to double check that if e.g. a game is cancelled the player doesnt get stuck Settings.expectedReplyHousekeeping(); } } } } } catch (System.Net.WebException e) { log.log("Web Service Timeout during getUpdates: " + e.ToString(), logging.loglevel.high); Settings.stats.logStat(new statItem("BotAPI Timeouts", typeof(Roboto))); } catch (Exception e) { try { log.log("Exception caught at main loop. " + e.ToString(), logging.loglevel.critical, ConsoleColor.White, false, false, false, false, 2); } catch (Exception ex) { Console.Out.WriteLine("-----------------"); Console.Out.WriteLine("Error During LOGGING! Original Error was"); Console.Out.WriteLine(e.Message); Console.Out.WriteLine("Logging Error was"); Console.Out.WriteLine(ex.Message); } } Settings.backgroundProcessing(false); } }