def load_users(self, yaml_data): users = {} if 'users' in yaml_data: for user_name in yaml_data['users'].keys(): user = User(user_name) yaml_obj = yaml_data['users'][user_name] if 'roles' in yaml_obj: roles_list = yaml_obj['roles'] splits = roles_list.split(",") for role_name in splits: role_name = role_name.strip() if role_name not in user.roles: user.roles.append(role_name) else: YLogger.debug(self, "Role [%s] already exists in user [%s]", role_name, user_name) if 'groups' in yaml_obj: groups_list = yaml_obj['groups'] splits = groups_list.split(",") for group_name in splits: group_name = group_name.strip() if group_name not in user.groups: user.groups.append(group_name) else: YLogger.debug(self, "Group [%s] already exists in user [%s]", group_name, user_name) users[user.userid] = user return users
def parse_oob_xml(self, oob: ET.Element): if oob is not None and oob.text is not None: self._command = oob.text return True else: YLogger.error(self, "Unvalid camera oob command - missing command") return False
def replace_by_pattern(self, replacable): alreadys = [] for key, pair in self._pairs.items(): try: pattern = pair[0] if pattern.findall(" " + replacable + " "): found = False for already in alreadys: stripped = key.strip() if stripped in already: found = True if found is not True: if pair[1].endswith("."): replacable = pattern.sub(pair[1], replacable) else: # replacable = pattern.sub(pair[1]+" ", replacable) replacable = pattern.sub(replacable, pair[1] + " ") alreadys.append(pair[1]) except Exception as excep: YLogger.exception( self, "Invalid regular expression [%s]" % str(pair[0]), excep) return re.sub(' +', ' ', replacable.strip())
def resolve_to_string(self, client_context): conversation = client_context.bot.get_conversation(client_context) question = conversation.previous_nth_question(self.index) resolved = question.combine_answers() YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), resolved) return resolved
def resolve_to_string(self, client_context): name = self.name.resolve(client_context) value = self.resolve_children(client_context) if self.local is True: YLogger.debug(client_context, "[%s] resolved to local: [%s] => [%s]", self.to_string(), name, value) client_context.bot.get_conversation( client_context).current_question().set_property(name, value) else: if client_context.bot.override_properties is False and client_context.brain.properties.has_property( name): YLogger.error( client_context, "Global property already exists for name [%s], ignoring set!", name) value = client_context.brain.properties.property(name) else: if client_context.brain.properties.has_property(name): YLogger.warning( client_context, "Global property already exists for name [%s], over writing!", name) YLogger.debug(client_context, "[%s] resolved to global: [%s] => [%s]", self.to_string(), name, value) client_context.bot.get_conversation( client_context).set_property(name, value) YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), value) return value
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_file_contents(self, id, filename, userid="*"): try: return self._aiml_parser.parse_from_file(filename, userid=userid) except Exception as excep: YLogger.exception( self, "Failed to load contents of file from [%s]" % filename, excep)
def wait_and_answer(self, ): running = True try: self._client_connection = self._server_socket.accept_connection() receive_payload = self._client_connection.receive_data() question = self.extract_question(receive_payload) userid = self.extract_userid(receive_payload) service_name = self.extract_servicename(receive_payload) client_context = self.create_client_context(userid) answer = self.ask_question_from_service(service_name, question) self.render_response(client_context, answer) except KeyboardInterrupt: running = False YLogger.debug(self, "Cleaning up and exiting...") except Exception as e: if self._client_connection is not None: self._client_connection.send_error(e) finally: if self._client_connection is not None: self._client_connection.close() return running
def send_error(self, error): if hasattr(error, 'message') is True: return_payload = { "result": { "status": "ERROR", "message": error.message } } elif hasattr(error, 'msg') is True: return_payload = { "result": { "status": "ERROR", "message": error.msg } } else: return_payload = { "result": { "status": "ERROR", "message": str(error) } } json_data = json.dumps(return_payload) YLogger.debug(self, "Sent: %s", json_data) self._clientsocket.send(json_data.encode('utf-8'))
def create_conversation(self, question, answer): question_sentence_text = "" for question_sentence in question: try: if question_sentence.words[-1].endswith( '?') or question_sentence.words[-1].endswith(')'): end_sign = "" else: end_sign = ". " except Exception as e: YLogger.exception(self, "Failed to get end_sign ", e) question_sentence_text += " ".join( question_sentence.words) + end_sign answer_sentence_text = "" for answer_sentence in answer: try: if answer_sentence.words[-1].endswith( '?') or answer_sentence.words[-1].endswith(')'): end_sign = "" else: end_sign = ". " except Exception as e: YLogger.exception(self, "Failed to get end_sign ", e) answer_sentence_text += " ".join(answer_sentence.words) + end_sign return question_sentence_text, answer_sentence_text
def _get_response_as_json(self, url): YLogger.debug(self, "GoogleMaps Request = [%s]", url) response = urllib.request.urlopen(url) content = response.read() decoded = content.decode('utf8') YLogger.debug(self, "GoogleMaps Response = [%s]", decoded) return json.loads(decoded)
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 execute(self, client_context, data): YLogger.debug(client_context, "RDF Admin - [%s]", data) rdf = "" segments = data.split() if segments[0] == 'SUBJECTS': subjects = client_context.brain.rdf.subjects() if segments[1] == 'LIST': rdf += "<ul>" for subject in subjects: rdf += "<li>%s</li>" % subject rdf += "</ul>" else: return str(len(subjects)) elif segments[0] == "PREDICATES": subject = segments[1] predicates = client_context.brain.rdf.predicates(subject) rdf += "<ul>" for predicate in predicates: rdf += "<li>%s</li>" % predicate rdf += "</ul>" elif segments[0] == "OBJECT": subject = segments[1] predicate = segments[2] objects = client_context.brain.rdf.objects(subject, predicate) rdf += "<ul>" for object in objects: rdf += "<li>%s</li>" % object rdf += "</ul>" return rdf
def load_config_section(self, configuration_file, configuration, bot_root): Conversations = configuration_file.get_section(self._section_name, configuration) if Conversations is not None: self._max_histories = configuration_file.get_int_option( Conversations, "max_histories", missing_value=100) self._initial_topic = configuration_file.get_option( Conversations, "initial_topic", missing_value="*") self._restore_last_topic = configuration_file.get_bool_option( Conversations, "restore_last_topic", missing_value=False) self._type = configuration_file.get_option(Conversations, "type", missing_value=None) config_name = configuration_file.get_option(Conversations, "config_name", missing_value=None) self._empty_on_start = configuration_file.get_bool_option( Conversations, "empty_on_start", missing_value=False) self._storage = ConversationStorageFactory.get_storage_config( self._type, config_name, configuration_file, configuration, bot_root) else: YLogger.warning( self, "'Conversations' section missing from bot config, using defaults" )
def get_property_value(client_context, local, name): if local is True: value = None #TODO Why would you need this test, when is get_conversation(clientid) == None ? if client_context.bot.get_conversation(client_context) is not None: if client_context.bot.get_conversation(client_context).has_current_question(): value = client_context.bot.get_conversation(client_context).current_question().property(name) else: if name is not None and client_context.brain.dynamics.is_dynamic_var(name) is True: value = client_context.brain.dynamics.dynamic_var(client_context, name) else: value = client_context.bot.get_conversation(client_context).property(name) #if value is None: # value = bot.brain.properties.property(name) if value is None: YLogger.error(client_context, "No property for [%s]", name) value = TemplateGetNode.get_default_value(client_context.bot) return value
def resolve_to_string(self, client_context): YLogger.debug(client_context, "Removing all learn nodes created by [%s]", client_context.userid) root = client_context.brain.aiml_parser.pattern_parser.root root.remove_children_with_userid(client_context.userid) return ""
def add_set(self, name, the_set): # Set names always stored in upper case to handle ambiquity set_name = name.upper() if set_name in self._sets: raise Exception("Set %s already exists" % set_name) YLogger.debug(self, "Adding set [%s[ to set group", set_name) self._sets[set_name] = the_set
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 load_aiml(self, configuration: BrainConfiguration): if configuration.files.aiml_files is not None: self.create_debug_storage(configuration) if configuration.files.aiml_files.has_multiple_files(): self.load_files_from_directory(configuration) self.load_learnf_files_from_directory(configuration) elif configuration.files.aiml_files.has_single_file(): self.load_single_file(configuration) self.load_learnf_files_from_directory(configuration) else: YLogger.info( self, "No AIML files or file defined in configuration to load") self.save_debug_files(configuration) self.display_debug_info(configuration) else: YLogger.info( self, "No AIML files or file defined in configuration to load")
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 parse_topic(self, topic_element, namespace): if 'name' in topic_element.attrib: name = topic_element.attrib['name'] if name is None or not name: raise ParserException("Topic name empty or null", xml_element=topic_element) xml = "<topic>%s</topic>" % name YLogger.info(self, "Topic attrib converted to %s", xml) topic_pattern = ET.fromstring(xml) else: raise ParserException("Missing name attribute for topic", xml_element=topic_element) category_found = False num_category = 0 for child in topic_element: tag_name, _ = self.tag_and_namespace_from_text(child.tag) if tag_name == 'category': self.parse_category(child, namespace, topic_pattern) category_found = True num_category += 1 else: raise ParserException("Unknown child node of topic, %s" % child.tag, xml_element=topic_element) if category_found is False: raise ParserException("No categories in topic", xml_element=topic_element) return num_category
def get_question(self, client_context, input_func=input): try: ask = "%s " % self.get_client_configuration().prompt return input_func(ask) except Exception as excep: YLogger.debug(client_context, "Exception caught in get_question !", excep)
def parse_expression(self, graph, expression): self._parse_node_with_attrib(graph, expression, "index", "1") if self.children: YLogger.warning( self, "<response> node should not contain child text, use <response /> or <response></response> only" )
def execute(self, context, data): YLogger.debug(context, "GeoCode [%s]", data) words = data.split(" ") if words[0] == 'POSTCODE1': location = words[1] elif words[0] == 'POSTCODE2': location = words[1] + words[2] elif words[0] == 'LOCATION': location = " ".join(words[1:]) else: return None googlemaps = self.get_geo_locator() latlng = googlemaps.get_latlong_for_location(location) if latlng is not None: str_lat = str(latlng.latitude) str_lng = str(latlng.longitude) lats = str_lat.split(".") lngs = str_lng.split(".") return "LATITUDE DEC %s FRAC %s LONGITUDE DEC %s FRAC %s" % ( lats[0], lats[1], lngs[0], lngs[1]) return None
def resolve(self, client_context): try: str = self.resolve_to_string(client_context) return str except Exception as excep: YLogger.exception(client_context, "Failed to resolve", excep) return ""
def get_storage_config(type, config_name, configuration_file, configuration, bot_root): if type == 'file': storage = BotConversationsFileStorageConfiguration( config_name=config_name) storage.load_config_section(configuration_file, configuration, bot_root) return storage elif type == 'redis': storage = BotConversationsRedisStorageConfiguration( config_name=config_name) storage.load_config_section(configuration_file, configuration, bot_root) return storage elif type == "mongodb": storage = BotConversationsMongodbStorageConfiguration( config_name=config_name) storage.load_config_section(configuration_file, configuration, bot_root) return storage YLogger.warning(None, "Invalid Conversations file storage type [%s]", type) return None
def execute(self, client_context, data): YLogger.debug(client_context, "Scheduler - [%s]", data) # SCHEDULE IN|EVERY X SECONDS|MINUTES|HOURS|DAYS|WEEKS TEXT|SRAI ........... try: words = data.split() if words[0].upper() == 'SCHEDULE': action = words[1].upper() if action in ['IN', 'EVERY']: return self.execute_schedule(client_context, words) elif action == 'PAUSE': return self.execute_pause(client_context, words) elif action == 'RESUME': return self.execute_resume(client_context, words) elif action == 'STOP': return self.execute_stop(client_context, words) elif action == 'LIST': return self.execute_lists(client_context, words) else: raise Exception ("Scheduler invalid action %s"% action) else: raise Exception ("Scheduler invalid command, must start with SCHEDULE") except Exception as excep: YLogger.exception(client_context, "Failed to parse Scheduler command", excep) return 'ERR'
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 load_config_section(self, configuration_file, configuration, bot_root): conversations_mongodb_storage = configuration_file.get_section( self._section_name, configuration) if conversations_mongodb_storage is not None: self._host = configuration_file.get_option( conversations_mongodb_storage, "host", missing_value="localhost") self._port = configuration_file.get_int_option( conversations_mongodb_storage, "port", missing_value=27017) self._password = configuration_file.get_option( conversations_mongodb_storage, "password", missing_value=None) self._root = configuration_file.get_option( conversations_mongodb_storage, "root", missing_value=None) self._name = configuration_file.get_option( conversations_mongodb_storage, "name", missing_value=None) self._collection_name = configuration_file.get_option( conversations_mongodb_storage, "collection_name", missing_value=None) else: YLogger.warning( self, "'BotConversationsMongodbStorageConfiguration' section missing from bot config, using defaults" )
def load_conversation(self, conversation, clientid, restore_last_topic=False): YLogger.debug(self, "Loading Conversation from file for %s" % clientid) h_key = "{prefix}:{clientid}:props".format(prefix=self._prefix, clientid=clientid) try: # Check if clientid in sessions set if not self._redis.is_member(self._sessions_set_key, clientid): return # Fetch properties props = self._redis.get(h_key) props = { k.decode('utf-8'): v.decode('utf-8') for k, v in props.items() } last_topic = props["topic"] # Update conversation conversation._properties.update(props) # Load last topic if required if restore_last_topic and last_topic: conversation._properties["topic"] = last_topic except Exception as e: YLogger.exception( self, "Failed to load conversation from redis for clientid [%s]" % clientid, e)