def receive_message(self, request): api_key_response = self.check_api_key(request) if api_key_response is not None: return api_key_response question = self.get_question(request) if question is None: YLogger.error(self, "'question' missing from request") abort(400) userid = self.get_userid(request) userid_expire_date = self.get_userid_cookie_expirary_date(self.configuration.client_configuration.cookie_expires) client_context = self.create_client_context(userid) try: answer = self.get_answer(client_context, question) rendered = self._renderer.render(client_context, answer) response_data = self.create_success_response_data(question, rendered) except Exception as excep: YLogger.exception(self, "Failed receving message", excep) response_data = self.create_error_response_data(client_context, question, str(excep)) return self.create_response(response_data, userid, userid_expire_date)
def resolve(self, client_context): try: data = self.resolve_to_string(client_context) return data except Exception as excep: YLogger.exception(client_context, "Failed to resolve", excep) return ""
def load_conversation(self, conversation, clientid, restore_last_topic=False): try: if self._config._dir is not None: if os.path.exists(self._config._dir): filename = self.create_filename(clientid) if os.path.exists(filename): should_open = True last_modified = time.ctime(os.path.getmtime(filename)) if self._last_modified is not None: if self._last_modified >= last_modified: should_open = False self._last_modified = last_modified if should_open is True: YLogger.debug(self, "Loading Conversation from file") with open(filename, "r", encoding="utf-8") as convo_file: for line in convo_file: if ':' in line: splits = line.split(":") name = splits[0].strip() value = splits[1].strip() if name == "topic": if restore_last_topic is True: YLogger.debug(self, "Loading stored property [%s]=[%s] for %s", name, value, clientid) conversation._properties[name] = value else: YLogger.debug(self, "Loading stored property [%s]=[%s] for %s", name, value, clientid) conversation._properties[name] = value except Exception as e: YLogger.exception(self, "Failed to load conversation for clientid [%s]"%clientid, e)
def handle_message(self, message): try: if self.configuration.client_configuration.debug is True: self.dump_request(message) self.renderer.print_payload("Incoming", message) # Facebook Messenger ID for user so we know where to send response back to recipient_id = self.get_recipitent_id(message) if recipient_id: client_context = self.create_client_context(recipient_id) message_text = self.get_message_text(message) # We have been send a text message, we can respond if message_text is not None: response_text = self.handle_text_message(client_context, message_text) # else if user sends us a GIF, photo,video, or any other non-text item elif self.has_attachements(message): response_text = self.handle_attachement(client_context, message) # otherwise its a general error else: YLogger.error(client_context, "Facebook general error handling message") response_text = "Sorry, I do not understand you!" YLogger.debug(client_context, "Facebook message response: [%s]", response_text) self.render_response(client_context, response_text) except Exception as e: YLogger.exception(None, "Error handling facebook message", e)
def resolve(self, client_context): try: client_context.bot.load_conversation(client_context.userid) return self.resolve_to_string(client_context) except Exception as excep: YLogger.exception(client_context, "Failed to resolve", excep) return ""
def resolve_type3_condition(self, client_context): try: for condition in self.children: value = self.get_condition_variable_value(client_context, condition.var_type, condition.name) if condition.value is not None: condition_value = condition.value.resolve(client_context) # Condition comparison is always case insensetive if value.upper() == condition_value.upper(): resolved = client_context.brain.tokenizer.words_to_texts([child_node.resolve(client_context) for child_node in condition.children]) YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), resolved) if condition.loop is True: resolved = resolved.strip() + " " + self.resolve(client_context).strip() return resolved default = self.get_default() if default is not None: resolved = client_context.brain.tokenizer.words_to_texts([child_node.resolve(client_context) for child_node in default.children]) if default.loop is True: resolved = resolved.strip() + " " + self.resolve(client_context).strip() else: resolved = "" YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), resolved) return resolved except Exception as excep: YLogger.exception(client_context, "Failed to resolve type3 condition", excep) return ""
def receive_message(): try: return WEB_CLIENT.receive_message(request) except Exception as e: print(e) YLogger.exception(None, "Web client error", e) return "500"
def poll_and_answer(self): running = True try: (last_direct_message_id, last_status_id) = self._get_last_message_ids() self._poll(last_direct_message_id, last_status_id) except KeyboardInterrupt: running = False except RateLimitError: if self._configuration.client_configuration.rate_limit_sleep != -1: rate_limit_sleep = self._configuration.client_configuration.rate_limit_sleep else: rate_limit_sleep = self.FIFTEEN_MINUTES YLogger.error(self, "Rate limit exceeded, sleeping for %d seconds", rate_limit_sleep) self.sleep(rate_limit_sleep) except Exception as excep: YLogger.exception(self, "Poll and answer error", excep) return running
def load_security_services(self, configuration): if configuration.security is not None: if configuration.security.authentication is not None: if configuration.security.authentication.classname is not None: try: classobject = ClassLoader.instantiate_class( configuration.security.authentication.classname) self._authentication = classobject(configuration.security.authentication) except Exception as excep: YLogger.exception(self, "Failed to load security services", excep) else: YLogger.debug(self, "No authentication configuration defined") if configuration.security.authorisation is not None: if configuration.security.authorisation.classname is not None: try: classobject = ClassLoader.instantiate_class( configuration.security.authorisation.classname) self._authorisation = classobject(configuration.security.authorisation) except Exception as excep: YLogger.exception(self, "Failed to instatiate authorisation class", excep) else: YLogger.debug(self, "No authorisation configuration defined") else: YLogger.debug(self, "No security configuration defined, running open...")
def set_attrib(self, attrib_name, attrib_value): if attrib_name != 'index': raise ParserException("Invalid attribute name [%s] for this node" % (attrib_name)) if isinstance(attrib_value, int): int_val = attrib_value self._sentence = int_val else: splits = attrib_value.split(",") if len(splits) == 1: try: self._sentence = int(splits[0]) except Exception as excep: YLogger.exception(self, "Failed to split string", excep) raise ParserException("None numeric format [%s] for this node [%s], either 'x' or 'x,y'", attrib_value, attrib_name) elif len(splits) == 2: try: self._question = int(splits[0]) if splits[1] == '*': self._sentence = -1 else: self._sentence = int(splits[1]) except Exception as excep: YLogger.exception(self, "Failed to split string", excep) raise ParserException("None numeric format [%s] for this node [%s], either 'x', 'x,y', or 'x,*'", attrib_value, attrib_name) if self._sentence == 0: raise ParserException("Sentence values are 1 based, cannot be 0") if self._question == 0: raise ParserException("Question values are 1 based, cannot be 0")
def resolve(self, client_context): try: resolved = self.resolve_children_to_string(client_context) YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), resolved) return resolved except Exception as excep: YLogger.exception(client_context, "Failed to resolve", excep) return ""
def load_renderer(self): try: if self.get_client_configuration().renderer is not None: clazz = ClassLoader.instantiate_class(self.get_client_configuration().renderer.renderer) return clazz(self) except Exception as e: YLogger.exception(None, "Failed to load config specified renderer", e) return self.get_default_renderer()
def empty(self): YLogger.debug(self, "Deleting Conversation redis data") try: self._redis.delete(self._sessions_set_key) except Exception as e: YLogger.exception(self, "Failed deleting conversation redis data", e)
def remove_conversation(self, clientid): YLogger.debug("Deleting Conversation redis data") try: self._redis.remove(self._sessions_set_key, clientid) except Exception as e: YLogger.exception(self, "Failed deleting conversation redis data for clientid [%s]"%clientid, e)
def unknown(self, telegram_bot, update): try: unknown_response = self.get_unknown_command(update.message.chat_id) if unknown_response: telegram_bot.send_message(chat_id=update.message.chat_id, text=unknown_response) YLogger.error(self, "No response to return in unknown()") except Exception as e: YLogger.exception(self, "Failed to handle unknown", e)
def start(self, telegram_bot, update): try: initial_question = self.get_initial_question(update) if initial_question: telegram_bot.send_message(chat_id=update.message.chat_id, text=initial_question) else: YLogger.error(self, "Not initial question to return in start()") except Exception as e: YLogger.exception(self, "Failed to start", e)
def listener_event(event): try: message = ProgramyScheduler.get_event_str(event) if message is not None: YLogger.debug(None, message) else: YLogger.error(None, "Unknown APSchedulerEvent! %s", str(event)) except Exception as e: YLogger.exception(None, "APScheduler Listener Error", e)
def message(self, telegram_bot, update): try: response = self.ask_question(update.message.chat_id, update.message.text) if response: telegram_bot.send_message(chat_id=update.message.chat_id, text=response) else: YLogger.error(self, "Not response to return in message()") except Exception as e: YLogger.exception(self, "Failed to handle message", e)
def load_single_file_contents(self, filename): just_filename = self.get_just_filename_from_filepath(filename) collection = {} try: collection[just_filename] = self.load_file_contents(just_filename, filename) except Exception as excep: YLogger.exception(self, "Failed to load file contents for file [%s]"%filename, excep) return collection
def handle_attachement(self, client_context, payload): try: message = payload.get('message') attachements = message.get('attachments') for attachment in attachements: if attachment.get('type') == 'location': return self.handle_location_attachment(client_context, attachment) except Exception as e: YLogger.exception(client_context, "Unable to handle attachment", e) return "Sorry, I cannot handle that type of attachement right now!"
def handle_location_attachment(self, client_context, attachment): try: payload = attachment.get('payload') coordinates = payload.get('coordinates') lat = coordinates.get('lat') long = coordinates.get('long') question = "RCS XLATLONG LOCATION XLAT %s XLONG %s" % (lat, long) return self.ask_question(client_context, question) except Exception as e: YLogger.exception(client_context, "Unable to handle location attachment", e) return "Error processing location!"
def resolve(self, client_context): try: resolved = self.resolve_to_string(client_context) YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), resolved) return resolved except LimitOverException: raise except Exception as excep: YLogger.exception(client_context, "Template node failed to resolve", excep) raise
def remove_conversation(self, clientid): YLogger.debug("Deleting Conversation redis data") try: self._redis.remove(self._sessions_set_key, clientid) except Exception as e: YLogger.exception( self, "Failed deleting conversation redis data for clientid [%s]" % clientid, e)
def reload(self, storage_factory, set_name): if storage_factory.entity_storage_engine_available( StorageFactory.SETS) is True: set_engine = storage_factory.entity_storage_engine( StorageFactory.SETS) if set_engine: try: sets_store = set_engine.sets_store() sets_store.reload(self, set_name) except Exception as e: YLogger.exception(self, "Failed to load set from storage", e)
def load_from_file(self, filename, client_configuration, bot_root): configuration = ProgramyConfiguration(client_configuration) try: with open(filename, 'r+', encoding="utf-8") as json_data_file: self.json_data = json.load(json_data_file) configuration.load_config_data(self, bot_root) except Exception as excep: YLogger.exception(self, "Failed to open json config file [%s]", excep, filename) return configuration
def load_conversation(self, client_context, conversation): conversation_filepath = self._conversations_filename(self._storage_engine.configuration.conversation_storage.dirs[0], client_context.client.id, client_context.userid) if self._file_exists(conversation_filepath): try: with open(conversation_filepath, "r+", encoding="utf-8") as convo_file: json_text = convo_file.read() json_data = json.loads(json_text) conversation.from_json(client_context, json_data) except Exception as excep: YLogger.exception(self, "Failed to read conversation file [%s]", excep, conversation_filepath)
def initiate_spellchecker(self): # TODO Move this to Spelling bass class if self.configuration is not None: if self.configuration.spelling.classname is not None: try: YLogger.info(self, "Loading spelling checker from class [%s]", self.configuration.spelling.classname) spell_class = ClassLoader.instantiate_class(self.configuration.spelling.classname) self._spell_checker = spell_class(self.configuration.spelling) except Exception as excep: YLogger.exception(self, "Failed to initiate spellcheker", excep) else: YLogger.warning(self, "No configuration setting for spelling checker!")
def _upload_usergroup_as_yaml(self, filename): try: with open(filename, 'r+', encoding="utf-8") as yaml_data_file: yaml_data = yaml.load(yaml_data_file) return yaml_data except Exception as e: YLogger.exception(self, "Failed to load usergroups yaml file [%s]", e, filename) return {}
def _write_properties(self, property_filepath, properties): try: with open(property_filepath, "w+") as props_file: for key, value in properties.items(): props_file.write( "%s%s%s\n" % (key, FilePropertyStore.SPLIT_CHAR, value)) props_file.write("\n") except Exception as excep: YLogger.exception(self, "Failed to write properties file [%s]", excep, property_filepath)
def _write_variables(self, variables_filepath, variables): try: with open(variables_filepath, "w+") as vars_file: for key, value in variables.items(): vars_file.write( "%s%s%s\n" % (key, FileVariablesStore.SPLIT_CHAR, value)) vars_file.write("\n") except Exception as e: YLogger.exception(None, "Failed to write variables [%s]", e, variables_filepath)
def load_single_file_contents(self, filename): just_filename = self.get_just_filename_from_filepath(filename) collection = {} try: collection[just_filename] = self.load_file_contents(filename) except Exception as excep: YLogger.exception( self, "Failed to load file contents for file [%s]" % filename, excep) return collection
def wait_and_answer(self): running = True try: client_context = self.create_client_context(self._configuration.client_configuration.default_userid) self.process_question_answer(client_context) except KeyboardInterrupt as keye: running = False client_context = self.create_client_context(self._configuration.client_configuration.default_userid) self._renderer.render(client_context, client_context.bot.get_exit_response(client_context)) except Exception as excep: YLogger.exception(self, "Oops something bad happened !", excep) return running
def reload(self, storage_factory, map_name): if storage_factory.entity_storage_engine_available( StorageFactory.MAPS) is True: map_engine = storage_factory.entity_storage_engine( StorageFactory.MAPS) if map_engine: try: maps_store = map_engine.maps_store() maps_store.reload(self, map_name) except Exception as e: YLogger.exception(self, "Failed to load map from storage", e)
def wait_and_answer(self): running = True try: client_context = self.create_client_context(self._configuration.client_configuration.default_userid) self.process_question_answer(client_context) except KeyboardInterrupt as keye: running = False client_context = self.create_client_context(self._configuration.client_configuration.default_userid) self._renderer.render(client_context, client_context.bot.get_exit_response(client_context)) except Exception as excep: YLogger.exception(self, "Oops something bad happened !", e) return running
def test_ylogger_exception(self): client_context = ClientContext(TestClient(), "testid") YLogger.reset_snapshot() YLogger.exception(client_context, "Test Message", Exception("Test error")) snapshot = YLogger.snapshot() self.assertIsNotNone(snapshot) self.assertEqual( str(snapshot), "Critical(0) Fatal(0) Error(0) Exception(1) Warning(0) Info(0), Debug(0)" )
def empty(self): YLogger.debug(self, "Emptying Conversation Folder") try: if self._config._dir is not None: if os.path.exists(self._config._dir): convo_files = [f for f in listdir(self._config._dir) if isfile(join(self._config._dir, f))] for file in convo_files: fullpath = self._config._dir + os.sep + file YLogger.debug(self, "Removing conversation file: [%s]", fullpath) os.remove(fullpath) except Exception as e: YLogger.exception(self, "Failed emptying conversation directory [%s]"%self._config._dir, e)
def _ask_question(self, client_context, question): reply = "" try: reply = client_context.bot.ask_question(client_context, question, responselogger=self) except Exception as e: YLogger.exception(client_context, "Error getting reply from bot", e) return reply
def _store_last_message_ids(self, last_direct_message_id, last_status_id): if self._configuration.client_configuration.storage == 'file': try: YLogger.debug(self, "Storing Last Messaged ID: %s", last_direct_message_id) YLogger.debug(self, "Storing Last Status ID: %s", last_status_id) with open(self._configuration.client_configuration.storage_location, "w+", encoding="utf-8") as idfile: idfile.write("%d\n"%last_direct_message_id) idfile.write("%d\n"%last_status_id) except Exception as excep: YLogger.exception(self, "Failed to store last message ids", excep)
def save_conversation(self, conversation, clientid): YLogger.debug(self, "Saving conversation to file") try: if self._config._dir is not None: if os.path.exists(self._config._dir): filename = self.create_filename(clientid) with open(filename, "w+", encoding="utf-8") as convo_file: for name, value in conversation._properties.items(): convo_file.write("%s:%s\n"%(name, value)) convo_file.write("\n") except Exception as e: YLogger.exception(self, "Failed to save conversation for clientid [%s]"% clientid, e)
def reload(self, storage_factory, map_name): if storage_factory.entity_storage_engine_available( StorageFactory.MAPS) is True: maps_store_engine = storage_factory.entity_storage_engine( StorageFactory.MAPS) try: self._reload_collection(maps_store_engine, map_name) except Exception as e: YLogger.exception(self, "Failed to load map from storage", e) return len(self._maps)
def reload(self, storage_factory): if storage_factory.entity_storage_engine_available( StorageFactory.REST_TEMPLATES) is True: templates_engine = storage_factory.entity_storage_engine( StorageFactory.REST_TEMPLATES) if templates_engine: try: templates_store = templates_engine.rest_templates_store() templates_store.reload(self) except Exception as e: YLogger.exception( self, "Failed to load REST-Template from storage", e)
def load(self, storage_factory): if storage_factory.entity_storage_engine_available( StorageFactory.DENORMAL) is True: lookups_engine = storage_factory.entity_storage_engine( StorageFactory.DENORMAL) if lookups_engine: try: lookups_store = lookups_engine.denormal_store() lookups_store.load_all(self) except Exception as e: YLogger.exception(self, "Failed to load lookups from storage", e)
def load(self, storage_factory): if storage_factory.entity_storage_engine_available( self.get_storage_name()) is True: lookups_engine = storage_factory.entity_storage_engine( self.get_storage_name()) if lookups_engine: try: lookups_store = self.get_lookups_store(lookups_engine) lookups_store.load_all(self) except Exception as e: YLogger.exception(self, "Failed to load lookups from storage", e)
def create_learnf_file_if_missing(learnf_path): if os.path.isfile(learnf_path) is False: try: with open(learnf_path, "w+", encoding="utf-8") as file: file.write('<?xml version="1.0" encoding="UTF-8"?>\n') file.write('<aiml>\n') file.write('</aiml>\n') file.close() except Exception as excep: YLogger.exception(None, "Error Writing learnf to %s", excep, learnf_path)
def load_renderer(self): try: if self.get_client_configuration().renderer is not None: YLogger.debug(None, "Loading Renderer") clazz = ClassLoader.instantiate_class(self.get_client_configuration().renderer.renderer) self._renderer = clazz(self) return except Exception as e: YLogger.exception(None, "Failed to load config specified renderer", e) self._renderer = self.get_default_renderer()
def ask_question(self, client_context, question): response = "" try: self._questions += 1 response = client_context.bot.ask_question(client_context, question, responselogger=self) except Exception as e: YLogger.exception(client_context, "Error asking Facebook:", e) return response
def initiate_logging(self, arguments): if arguments.logging is not None: try: with open(arguments.logging, 'r+', encoding="utf-8") as yml_data_file: logging_config = yaml.load(yml_data_file, Loader=yaml.SafeLoader) logging.config.dictConfig(logging_config) YLogger.debug(self, "Now logging under configuration") except Exception as excep: YLogger.exception(self, "Failed to open logging configuration [%s]", excep, arguments.logging) else: print("Warning. No logging configuration file defined, using defaults...")
def load_bot_selector(self, configuration): if configuration.bot_selector is None: self._bot_selector = DefaultBotSelector(configuration, self._bots) else: try: self._bot_selector = ClassLoader.instantiate_class( configuration.bot_selector)(configuration, self._bots) except Exception as excep: YLogger.exception(self, "Failed to loadbot selector [%s]", excep) self._bot_selector = DefaultBotSelector( configuration, self._bots)
def load(self, storage_factory): if storage_factory.entity_storage_engine_available( StorageFactory.SETS) is True: storage_engine = storage_factory.entity_storage_engine( StorageFactory.SETS) try: self._load_collection(storage_engine) except Exception as e: YLogger.exception(self, "Failed to load set from storage", e) return len(self._sets)
def upload_from_file(self, filename, fileformat=Store.TEXT_FORMAT, commit=True, verbose=False): try: count, success = self._load_nodes_from_file(filename, verbose) self.commit(commit) return count, success except Exception as error: YLogger.exception(self, "Failed to load nodes from [%s]", error, filename) return 0, 0
def load_trigger_manager(config: TriggerConfiguration): if config.manager is not None: try: return ClassLoader.instantiate_class(config.manager)(config) except Exception as e: YLogger.exception(None, "Failed to load trigger manager [%s]", e, config.manager) else: YLogger.error(None, "No Trigger Manager defined in configuration") return None
def process_config_line(self, line): if self.valid_config_line(line): splits = line.split("=") node_name = splits[0].strip() if node_name in self._nodes_config: YLogger.error(self, "Node already exists in config [%s]", line) return class_name = splits[1].strip() YLogger.debug(self, "Pre-instantiating %s Node [%s]", self._type, class_name) try: self._nodes_config[node_name] = ClassLoader.instantiate_class(class_name) except Exception as e: YLogger.exception(self, "Failed pre-instantiating %s Node [%s]"%(self._type, class_name), e)
def save_conversation(self, conversation, clientid): YLogger.debug(self, "Saving conversation to Redis for %s"%clientid) h_key = "{prefix}:{clientid}:props".format( prefix = self._prefix, clientid = clientid ) try: self._redis.save(h_key, self._sessions_set_key, clientid, conversation._properties) except Exception as e: YLogger.exception(self, "Failed to save conversation to redis for clientid [%s]"%clientid, e)
def load_nodes_config_from_file(self, filename=None): try: self._nodes_config.clear() if filename is None or os.path.exists(filename) is False: filename = self.default_config_file() with open(filename, "r", encoding="utf-8") as node_file: for line in node_file: line = line.strip() self.process_config_line(line) except Exception as excep: YLogger.exception(self, "Failed to load %s Node Factory config file [%s]"%(self._type, filename), excep)
def poll_and_answer(self): running = True try: self._updater.start_polling() except KeyboardInterrupt as keye: print("Telegram client stopping....") running = False self._updater.stop() except Exception as excep: YLogger.exception(self, "Failed to poll and answer", excep) return running