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 save_braintree(self, client_context, filename, content): if content == 'txt': with open(filename, "w+", encoding="utf-8") as dump_file: self.dump(output_func=dump_file.write, eol="\n") elif content == 'xml': braintree = '<?xml version="1.0" encoding="UTF-8"?>\n' braintree += '<aiml>\n' braintree += self.root.to_xml(client_context) braintree += '</aiml>\n' with open(filename, "w+", encoding="utf-8") as dump_file: dump_file.write(braintree) else: YLogger.error(client_context, "Unknown braintree content type [%s]", content)
def check_api_key(self, request): if self.configuration.client_configuration.use_api_keys is True: api_key = self.get_api_key(request) if api_key is None: YLogger.error( self, "Unauthorised access - api required but missing") return self.unauthorised_access_response() if self.is_apikey_valid(api_key) is False: YLogger.error(self, "'Unauthorised access - invalid api key") return self.unauthorised_access_response() return None
def valid_config_line(self, line): if not line: return False if line.startswith('#'): return False if "=" not in line: YLogger.error(self, "Config line missing '=' [%s]", line) return False return True
def map_value(self, client_context, input_value): try: int_value = int(input_value) str_value = str(int_value - 1) YLogger.debug(client_context, "PredecessorMap converted %s to %s", input_value, str_value) return str_value except Exception: YLogger.error( client_context, "PredecessorMap could not convert %s to integer string", input_value) return ""
def get_question(self, rest_request): # YLogger.debug(self, f"In get_question, rest_request.data: {rest_request.data.decode('utf-8')}") # YLogger.debug(self, f"rest_request type: {type(rest_request)}") # TODO: Save userid to MongoDB with rest of user info rest_request = json.loads(rest_request.data.decode('utf-8')) # YLogger.debug(self, f"after json.loads, rest_request: {rest_request}") if "question" not in rest_request or rest_request["question"] is None: YLogger.error(self, "'question' missing from request") self.server_abort(400) return rest_request["question"]
def consume(self, client_context, context, words, word_no, match_type, depth): tabs = self.get_tabs(client_context, depth) if context.search_depth_exceeded(depth) is True: YLogger.error(client_context, "%sMax search depth [%d]exceeded", tabs, context.max_search_depth) return None if words.word(word_no) == PatternTopicNode.TOPIC: YLogger.debug(client_context, "%sTopic matched %s", tabs, words.word(word_no)) return super(PatternTopicNode, self).consume(client_context, context, words, word_no+1, match_type, depth+1) YLogger.debug(client_context, "%sTopic NOT matched %s", tabs, words.word(word_no)) return None
def verify_api_key_usage(self, request): if self.configuration.client_configuration.use_api_keys is True: apikey = self.get_api_key(request) if apikey is None: YLogger.error( self, "Unauthorised access - api required but missing") return {'error': 'Unauthorized access'}, 401 if self.is_apikey_valid(apikey) is False: YLogger.error(self, "'Unauthorised access - invalid api key") return {'error': 'Unauthorized access'}, 401 return None, None
def get_news(self, context, source, max_num, sort, reverse): newsapi = self.get_news_api_api(context) headlines = newsapi.get_headlines(source, max_num, sort, reverse) if headlines is None: YLogger.error(context, "NewsAPIExtension no headlines found!") return "" results = newsapi.to_program_y_text(headlines) if results is None: YLogger.error(context, "NewsAPIExtension no results returned!") return "" return results
def find_files(self, path, subdir=False, extension=None): found_files = [] try: if subdir is False: paths = os.listdir(path) for filename in paths: if filename.endswith(extension): found_files.append((filename, os.path.join(path, filename))) else: for dirpath, _, filenames in os.walk(path): for filename in [f for f in filenames if f.endswith(extension)]: found_files.append((filename, os.path.join(dirpath, filename))) except FileNotFoundError: YLogger.error(self, "No directory found [%s]", path) return sorted(found_files, key=lambda element: (element[1], element[0]))
def load(self, filename, *args, **kw): YLogger.debug(self, "Loading processors from file [%s]", filename) count = 0 try: with open(filename, "r", encoding="utf-8") as file: for line in file: line = line.strip() if line: if line[0] != '#': new_class = ClassLoader.instantiate_class(line) if new_class is not None: self.processors.append(new_class(*args, **kw)) count += 1 except FileNotFoundError: YLogger.error(self, "File not found [%s]", filename) return count
def ask_question(self, client_context, question: str): try: if client_context.client.license_keys.has_key('PANDORA_BOTID'): botid = client_context.client.license_keys.get_key( 'PANDORA_BOTID') else: YLogger.error( client_context, "No variable PANDORA_BOTID found in license key file") return "" return self.api.ask_question(self._config.url, question, botid) except Exception as excep: YLogger.error(client_context, str(excep)) return ""
def ask_question(self, client_context, question: str): try: if client_context.client.license_keys.has_key('PANNOUS_LOGIN'): login = client_context.client.license_keys.get_key( 'PANNOUS_LOGIN') else: YLogger.error( client_context, "No variable PANNOUS_LOGIN found in license key file") return "" return self.api.ask_question(self.url, question, login) except Exception as excep: YLogger.error(client_context, str(excep)) return ""
def equals(self, client_context, words, word_no): if self.userid != '*': if self.userid != client_context.userid: return EqualsMatch(False, word_no) word = words.word(word_no) if word is not None: word = word.upper() for set_word in self._words: if word == set_word: YLogger.debug(client_context, "Found word [%s] in iset", word) return EqualsMatch(True, word_no, word) YLogger.error(client_context, "No word [%s] found in iset", word) return EqualsMatch(False, word_no)
def handle_aiml_error(self, parser_excep, filename, expression): if self._errors is not None: if logging.getLogger().isEnabledFor(logging.ERROR): parser_excep.filename = filename msg = parser_excep.format_message() YLogger.error(self, msg) startline = None if hasattr(expression, "_start_line_number"): startline = str(expression._start_line_number) endline = None if hasattr(expression, "_end_line_number"): endline = str(expression._end_line_number) self._errors.save_entry(parser_excep.message, filename, startline, endline)
def load_regex_templates(self, configuration): if configuration.files.regex_templates is not None: collection = PropertiesCollection() total = collection.load_from_filename( configuration.files.regex_templates) YLogger.info(self, "Loaded a total of %d regex templates", total) self._regex_templates.clear() for pair in collection.pairs: name = pair[0] pattern = pair[1] try: self._regex_templates[name] = re.compile( pattern, re.IGNORECASE) except Exception: YLogger.error(self, "Invalid regex template [%s]", pattern)
def load(self, configuration): loader = SetLoader() if configuration.files is not None: self._sets = {} for file in configuration.files: sets, file_sets = loader.load_dir_contents( file, configuration.directories, configuration.extension) for key in sets.keys(): if key in self._sets: YLogger.error(self, "Duplicate set [%s] found in [%s]", key, file) self._sets[key] = sets[key] for key in file_sets.keys(): self._files[key] = file_sets[key] else: self._sets = {} return len(self._sets)
def resolve_to_string(self, client_context): resolved = self.resolve_children_to_string(client_context) YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), resolved) if self._service is not None: bot_service = ServiceFactory.get_service(self._service) response = bot_service.ask_question(client_context, resolved) YLogger.debug(client_context, "SRAIX service [%s] return [%s]", self._service, response) return response else: YLogger.error( client_context, "Sorry SRAIX does not currently have an implementation for [%s]", self._service) return ""
def resolve_to_string(self, client_context): format_str = self._interval_format.resolve(client_context) from_str = self.interval_from.resolve(client_context) from_time = datetime.datetime.strptime(from_str, format_str) to_str = self.interval_to.resolve(client_context) to_time = datetime.datetime.strptime(to_str, format_str) style = self._style.resolve(client_context) diff = to_time - from_time difference = relativedelta(to_time, from_time) if style == "years": resolved = str(difference.years) elif style == "months": resolved = str(difference.months) elif style == "weeks": resolved = str(difference.weeks) elif style == "days": resolved = str(diff.days) elif style == "hours": resolved = str(difference.hours) elif style == "minutes": resolved = str(difference.minutes) elif style == "seconds": resolved = str(difference.seconds) elif style == "microseconds": resolved = str(difference.microseconds) elif style == "ymd": resolved = "%d years, %d months, %d days" % \ (difference.years, difference.months, difference.days) elif style == "hms": resolved = "%d hours, %d minutes, %d seconds" % \ (difference.hours, difference.minutes, difference.seconds) elif style == "ymdhms": resolved = "%d years, %d months, %d days, %d hours, %d minutes, %d seconds" % \ (difference.years, difference.months, difference.days, difference.hours, difference.minutes, difference.seconds) else: YLogger.error(client_context, "Unknown interval style [%s]", style) resolved = "" YLogger.debug(client_context, "[INTERVAL] resolved to [%s]", resolved) return resolved
def load(self, configuration): loader = MapLoader(split_char=self._split_char, eol=self._eol) if configuration.files is not None: self._maps = {} for file in configuration.files: maps, file_maps = loader.load_dir_contents( file, configuration.directories, configuration.extension) for key in maps.keys(): if key in self._maps: YLogger.error(self, "Duplicate map [%s] found in [%s]", key, file) self._maps[key] = maps[key] for key in file_maps.keys(): self._files[key] = file_maps[key] else: self._maps = {} return len(self._maps)
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 parse_oob_xml(self, oob: ET.Element): if oob is not None: for child in oob: if child.tag == 'recipient': self._recipient = child.text elif child.tag == 'message': self._message = child.text else: YLogger.error(self, "Unknown child element [%s] in sms oob", child.tag) if self._recipient is not None and self._message is not None: return True YLogger.error(self, "Invalid sms oob command") return False
def resolve_to_string(self, client_context): fullname = "AIMLBot" if client_context.brain.properties.has_property("fullname") is True: fullname = client_context.brain.properties.property("fullname") else: YLogger.error(client_context, "Fullname property missing") version = "" if client_context.brain.properties.has_property("version") is True: version = client_context.brain.properties.property("version") else: YLogger.error(client_context, "Version property missing") resolved = "%s %s" % (fullname, version) YLogger.debug(self, "[%s] resolved to [%s]", self.to_string(), resolved) return resolved
def __init__(self, spelling_config=None): SpellingChecker.__init__(self, spelling_config) self.words = [] self.sum_of_words = 0 if spelling_config is None: corpus_filename = os.path.dirname(__file__) + os.sep + "corpus.txt" else: corpus_filename = spelling_config.corpus if os.path.exists(corpus_filename) is True: YLogger.info(self, "Loading spelling corpus [%s]", corpus_filename) self.words = Counter(self._all_words(open(corpus_filename, encoding="utf-8").read())) self.sum_of_words = sum(self.words.values()) else: YLogger.error(self, "No spelling corpus found[%s]", corpus_filename)
def parse_oob_xml(self, oob: ET.Element): if oob is not None: for child in oob: if child.tag == 'title': self._title = child.text elif child.tag == 'description': self._description = child.text else: YLogger.error( self, "Unknown child element [%s] in schedule oob", child.tag) if self._title is not None and \ self._description is not None: return True YLogger.error(self, "Invalid email schedule command") return False
def parse_oob_xml(self, oob: ET.Element): if oob is not None: for child in oob: if child.tag == 'title': self._title = child.text elif child.tag == 'list': self._list = child.text else: YLogger.error(self, "Unknown child element [%s] in dialog oob", child.tag) if self._title is not None and \ self._list is not None: return True YLogger.error(self, "Invalid dialog oob command") return False
def load_config_section(self, configuration_file, configuration, bot_root): files_config = configuration_file.get_section("files", configuration) if files_config is not None: self._aiml_files.load_config_section(configuration_file, files_config, bot_root) self._set_files.load_config_section(configuration_file, files_config, bot_root) self._map_files.load_config_section(configuration_file, files_config, bot_root) self._rdf_files.load_config_section(configuration_file, files_config, bot_root) self._denormal = self._get_file_option(configuration_file, "denormal", files_config, bot_root) self._normal = self._get_file_option(configuration_file, "normal", files_config, bot_root) self._gender = self._get_file_option(configuration_file, "gender", files_config, bot_root) self._person = self._get_file_option(configuration_file, "person", files_config, bot_root) self._person2 = self._get_file_option(configuration_file, "person2", files_config, bot_root) self._properties = self._get_file_option(configuration_file, "properties", files_config, bot_root) self._variables = self._get_file_option(configuration_file, "variables", files_config, bot_root) self._triples = self._get_file_option(configuration_file, "triples", files_config, bot_root) self._preprocessors = self._get_file_option( configuration_file, "preprocessors", files_config, bot_root) self._postprocessors = self._get_file_option( configuration_file, "postprocessors", files_config, bot_root) self._regex_templates = self._get_file_option( configuration_file, "regex_templates", files_config, bot_root) else: YLogger.error( self, "Config section [files] missing from Brain, default values not appropriate" )
def resolve_to_string(self, client_context): resolved = self.resolve_children_to_string(client_context) if self._output == "logging": YLogger.debug(client_context, "[%s] resolved to [%s]", self.to_string(), resolved) if self._level == "debug": YLogger.debug(client_context, resolved) elif self._level == "warning": YLogger.warning(client_context, resolved) elif self._level == "error": YLogger.error(client_context, resolved) elif self._level == "info": YLogger.info(client_context, resolved) else: YLogger.info(client_context, resolved) else: print(resolved) return ""
def failed_authentication(self, client_context): YLogger.error(client_context, "[%s] failed authentication!") # If we have an SRAI defined, then use that if self.authentication.configuration.denied_srai is not None: match_context = self._aiml_parser.match_sentence( client_context, Sentence(self._bot.brain.nlp.tokenizer, self.authentication.configuration.denied_srai), topic_pattern="*", that_pattern="*") # If the SRAI matched then return the result if match_context is not None: return self.resolve_matched_template(client_context, match_context) # Otherswise return the static text, which is either # User defined via config.yaml # Or use the default value BrainSecurityConfiguration.DEFAULT_ACCESS_DENIED return self.authentication.configuration.denied_text
def _load_libraries(self, nltk_data_dir): if nltk_data_dir and os.path.isdir(nltk_data_dir): if nltk_data_dir not in nltk.data.path: nltk.data.path.append(nltk_data_dir) try: nltk.download("popular", download_dir=nltk_data_dir, quiet=True) except Exception as excp: #install data in home directory due to problems in provided dir nltk.download("popular", quiet=True) YLogger.exception( self, "wrong nltk directory. Install in home directory", excp) else: nltk.download("popular", quiet=True) YLogger.error(self, "No nltk directory. Install in home directory")