Beispiel #1
0
        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);
        }
Beispiel #2
0
        /// <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);
            }
        }