diff --git a/aion-0.1.0_alpha/Aion_Logo.png b/aion-0.1.0_alpha/Aion_Logo.png new file mode 100644 index 0000000..9d0e67f Binary files /dev/null and b/aion-0.1.0_alpha/Aion_Logo.png differ diff --git a/aion-0.1.0_alpha/aion_core/__init__.py b/aion-0.1.0_alpha/aion_core/__init__.py new file mode 100644 index 0000000..04a0d91 --- /dev/null +++ b/aion-0.1.0_alpha/aion_core/__init__.py @@ -0,0 +1,143 @@ +#!/usr/bin/python3 + +__author__ = "blueShard" +__license__ = "GPL-3.0" +__version__ = "0.1.0" + +try: + from .utils import aion_data_path, aion_path +except ImportError: + from utils import aion_data_path, aion_path + + +def speech_output(speech_output: str) -> None: + """ + plays a output of an artificial voice from the given words + + :param speech_output: str + the words to be said + syntax: + example: "This is an test" + :return: None + + :since: 0.1.0 + """ + try: + from .config import Aion + except ImportError: + from config import Aion + from os import system + + try: + tts_engine = Aion().get_tts_engine() + except IndexError: + Aion().reset() + tts_engine = Aion().get_tts_engine() + + if tts_engine == "espeak": + system("espeak -v" + Aion().get_language().split("_")[0] + " " + str(speech_output) + " stdout | aplay") + print("Sayed '" + str(speech_output) + "'") + elif tts_engine == "pico2wave": + system('pico2wave --lang=' + Aion().get_language().split("_")[0] + '-' + Aion().get_language().split("_")[1] + ' --wave=/tmp/aion.wav "' + str(speech_output) + "." + '"; aplay /tmp/aion.wav; rm /tmp/aion.wav') + print("Sayed '" + str(speech_output) + "'") + + +def start(sudo: bool = False) -> None: + """ + starts aion + + :param sudo: bool + says if 'aion' should run as sudo (True) or not (False) + syntax: + example: False + :return: None + + :since: 0.1.0 + """ + from os import system + if sudo is True: + system("sudo python3 " + aion_path + "/main.py") + else: + system("python3 " + aion_path + "/main.py") + + +class ExecuteAionFile: + + """ + base class for execution '.aion' files + + :since: 0.1.0 + """ + + def __init__(self, fname: str) -> None: + """ + makes the file available for all functions in this class and calls the '_main()' function + + :param fname: str + path of the file + syntax: + example: "/home/pi/test.aion" + :return: None + + :since: 0.1.0 + """ + self.fname = fname + + self._main() + + def _main(self) -> None: + """ + checks which type of an 'aion' file is the given file + + :return: None + + :since: 0.1.0 + """ + try: + from ._error_codes import init_no_file_type + from .utils import remove_space + except ImportError: + from _error_codes import init_no_file_type + from utils import remove_space + + for line in open(self.fname, "r"): + if line.isspace(): + continue + elif line.startswith("#"): + line = remove_space(line, "") + if line.startswith("#type:"): + line = line.replace("#type:", "") + if line.strip() == "skill": + self._skill() + elif "plugin" in line.strip(): + self._plugin() + else: + raise IndexError("Errno: " + init_no_file_type + " - Couldn't find file type in " + self.fname) + + def _plugin(self) -> None: + """ + execute the given file as plugin type + + :return: None + + :since: 0.1.0 + """ + try: + from .plugin import execute_aion_file_type_plugin + except ImportError: + from plugin import execute_aion_file_type_plugin + execute_aion_file_type_plugin(self.fname) + + def _skill(self) -> None: + """ + execute the given file as skill type + + :return: None + + :since: 0.1.0 + """ + try: + from .skill import execute_aion_file_type_skill + except ImportError: + from skill import execute_aion_file_type_skill + execute_aion_file_type_skill(self.fname) diff --git a/aion-0.1.0_alpha/aion_core/_error_codes.py b/aion-0.1.0_alpha/aion_core/_error_codes.py new file mode 100644 index 0000000..bc4c47e --- /dev/null +++ b/aion-0.1.0_alpha/aion_core/_error_codes.py @@ -0,0 +1,120 @@ +# __init__.py (01) + +init_no_file_type = "01792" + +# _error_codes.py (07) + +# _errors.py (04) + +# acph.py (57) + +acph_activate_phrase_exist = "57042" + +# config.py (40) + +config_no_hotword_file_file = "40863" +config_no_supported_listening_mode = "40518" +config_no_supported_listening_source = "40801" +config_no_supported_time_format = "40014" +config_no_supported_tts_engine = "40744" +config_name_config_is_used_as_root_name = "40026" +config_character_must_be_in_alphabet = "40955" + +config_root_tag_cannot_be_removed = "40471" +config_root_tag_cannot_be_updated = "40849" + +# language.py (68) + +language_lng_file_doesnt_exist = "16898" +language_entry_already_exist = "66873" +language_lng_file_already_exist = "68481" + +# logging.py (87) + +# save.py (83) + +save_save_not_found = "83160" +save_save_name_already_exist = "83923" + +# plugin.py (36) + +plugin_aion_plugin_file_not_found = "36134" +plugin_to_much_aion_files = "36278" +plugin_couldnt_find_key = "36896" +plugin_couldnt_find_plugin_type = "36132" +plugin_illegal_run_after_pseudonym = "36987" +plugin_run_after_pseudonym_already_exist = "36059" +plugin_illegal_run_before_pseudonym = "36165" +plugin_run_before_pseudonym_already_exist = "36919" +plugin_file_doesnt_exist_in_setup_dir = "36713" +plugin_directory_doesnt_exist_in_setup_dir = "36426" +plugin_run_after_additional_directories_already_exist = "36550" +plugin_run_before_additional_directories_already_exist = "36635" +plugin_python3_module_not_found = "36277" + +plugin_couldnt_find_plugin_dot_aion = "36184" + +plugin_author_must_be_str = "36534" +plugin_plugin_name_must_be_str = "36370" +plugin_main_file_must_be_str = "36938" +plugin_main_file_not_found = "36430" +plugin_main_file_name_must_be_plugin_name = "36276" +plugin_skill_must_be_dict = "36261" +plugin_plugin_methods_must_be_dict = "36358" +plugin_version_must_be_str = "36184" +plugin_additional_directories_must_be_list_or_tuple = "36512" +plugin_couldnt_find_additional_directories_directory = "36606" +plugin_description_must_be_str = "36716" +plugin_language_locales_must_be_list_or_tuple = "36351" +plugin_language_dict_must_be_dict = "36297" +plugin_language_dict_character_must_be_in_alphabet = "36756" +plugin_license_must_be_str = "36333" +plugin_required_python3_package_must_be_list_or_tuple = "36054" + +# skill.py (25) + +skill_author_must_be_str = "25662" +skill_language_locales_must_be_list_or_tuple = "25351" +skill_skill_name_must_be_str = "25432" +skill_main_file_must_be_str = "25586" +skill_main_file_not_found = "25439" +skill_main_file_name_must_be_skill_name = "25737" +skill_version_must_be_str = "25133" +skill_additional_directories_must_be_list_or_tuple = "25902" +skill_couldnt_find_additional_directories_directory = "25271" +skill_description_must_be_str = "25367" +skill_language_dict_must_be_dict = "25487" +skill_language_dict_character_must_be_in_alphabet = "25540" +skill_license_must_be_str = "25248" +skill_required_python3_package_must_be_list_or_tuple = "25780" +skill_activate_phrases_must_be_dict = "25161" +skill_activate_phrases_character_must_be_in_alphabet = "25559" + +skill_package_couldnt_find_directory = "25816" +skill_package_couldnt_find_aion_file = "25505" +skill_package_expected_one_aion_file = "25253" + +skill_couldnt_find_key = "25319" +skill_skill_already_exist = "25045" +skill_file_doesnt_exist = "25174" +skill_directory_doesnt_exist = "25974" +skill_directory_already_exist = "25819" +skill_couldnt_install_python3_package = "25082" + +skill_couldnt_find_skill_dot_aion = "25184" + +# usb.py (99) + +# utils.py (92) + +utils_unexpected_error = "92700" +utils_fname_doesnt_exist = "92029" +utils_couldnt_find_parent = "92613" +utils_dict_index_out_of_range = "92743" + +# variable.py (20) + +variable_get_value_variable_file_variable_doesnt_exist = "92481" +variable_get_value_user_variables_variable_doesnt_exist = "92255" +variable_remove_variable_variable_doesnt_exist = "92010" +variable_set_value_variable_doesnt_exist = "92603" diff --git a/aion-0.1.0_alpha/aion_core/acph.py b/aion-0.1.0_alpha/aion_core/acph.py new file mode 100644 index 0000000..f486ecd --- /dev/null +++ b/aion-0.1.0_alpha/aion_core/acph.py @@ -0,0 +1,158 @@ +#!/usr/bin/python3 + +try: + from .config import Aion as _Aion + from .utils import aion_data_path as _aion_data_path +except ImportError: + from config import Aion as _Aion + from utils import aion_data_path as _aion_data_path + + +def _acph_file() -> str: + """ + gets the activate phrase file for the current language + + :return: None + + :since: 0.1.0 + """ + from colorama import Fore + from os.path import isfile + if isfile(acph_directory + "/" + language + ".acph") is False: + print(Fore.RED + "didn't found acph file in your language. Using the default acph file (en_US)" + Fore.RESET) + return acph_directory + "/en_US.acph" + else: + return acph_directory + "/" + language + ".acph" + + +language = _Aion().get_language() +acph_directory = _aion_data_path + "/language" +acph_file = _acph_file() +supported_languages = ["de_DE", "en_US"] + + +def add_acph(language_locale: str, skill: str, acph_dict: dict = {}) -> None: + """ + adds an new entry(s) to from argument 'language_locale' given language + + :param language_locale: str + language locale from the language to which the entry(s) is/are to be added + syntax: + example: "de_DE" + :param skill: str + skill name to which the acph belongs + syntax: "" + example: "test_skill" + :param acph_dict: dict, optional + defines a word or a sentence from which a method is called + syntax: {: } + example: {"start test": "MyTestMethod"} + NOTE: in key 'activate_phrase' you can use the '__and__' statement. This checks if the words before and after '__and__' are in the sentence that the user has spoken in + :return: None + + :since: 0.1.0 + """ + try: + from ._error_codes import acph_activate_phrase_exist + from .utils import BaseXMLWriter + except ImportError: + from _error_codes import acph_activate_phrase_exist + from utils import BaseXMLWriter + + acph_writer = BaseXMLWriter(acph_directory + "/" + language_locale + ".acph") + for acph, method in acph_dict: + if exist_acph(language_locale, acph): + raise IndexError("Errno: " + acph_activate_phrase_exist + " - The activate phrase " + acph + " already exist") + acph_writer.add("", acph, skill=skill, method=method) + acph_writer.write() + + +def create_acph_file(language_locale: str, skill_acph_dict_dict: dict = {}) -> None: + """ + creates a new '.acph' file for given language locale with given skill_acph_dict_dict + + :param language_locale: str + language locale of language from which the new file is to be created + syntax: + example: "en_US" + :param skill_acph_dict_dict: dict, optional + skill name you want to add specific entries + syntax: {: {: }} + example: {"test_skill": {"start test": "MyTestMethod"}} + NOTE: in key 'activate_phrase' you can use the '__and__' statement. This checks if the words before and after '__and__' are in the sentence that the user has spoken in + :return: None + + :since: 0.1.0 + """ + try: + from .utils import BaseXMLBuilder + except ImportError: + from utils import BaseXMLBuilder + + acph_builder = BaseXMLBuilder(language_locale) + for skill, acph_dict in skill_acph_dict_dict.items(): + for acph, method in acph_dict.items(): + acph_builder.create_root_element(acph, skill=skill, method=method) + + acph_builder.write(acph_directory + "/" + language_locale + ".acph") + + +def delete_acph(language_locale: str, acph_list: list = []) -> None: + """ + deletes entries from '.acph' + + :param language_locale: str + language locale from (file) which the activate phases is being deleted + syntax: + example: "en_US" + :param acph_list: list, optional + name of the activate phases you want to remove + syntax: [] + example: ["test_acph"] + :return: None + + :since: 0.1.0 + """ + try: + from .utils import BaseXMLWriter + except ImportError: + from utils import BaseXMLWriter + + acph_writer = BaseXMLWriter(acph_directory + "/" + language_locale + ".acph") + for item in acph_list: + acph_writer.remove("", str(item)) + acph_writer.write() + + +def exist_acph(language_locale: str, acph: str) -> bool: + """ + checks if a entry exist + + :param language_locale: str + language locale from (file) which the activate phrase should be search + syntax: + example: "en_US" + :param acph: str + activate phrase you want to check if exists + syntax: + example: "start test" + :return: bool + returns True if acph exist / False if not + syntax: + example: False + + :since: 0.1.0 + """ + try: + from .utils import BaseXMLReader + except ImportError: + from utils import BaseXMLReader + + acph = acph.replace(" ", "_") + + acph_reader = BaseXMLReader(acph_directory + "/" + language_locale + ".acph") + for item in acph_reader.get_infos([""]).items().index(0): + if acph in item["childs"]: + return True + else: + return False diff --git a/aion-0.1.0_alpha/aion_core/config.py b/aion-0.1.0_alpha/aion_core/config.py new file mode 100644 index 0000000..6cf8cf4 --- /dev/null +++ b/aion-0.1.0_alpha/aion_core/config.py @@ -0,0 +1,490 @@ +#!/usr/bin/python3 + +try: + from .utils import aion_data_path as _aion_data_path, BaseXMLReader as _BaseXMLReader, BaseXMLWriter as _BaseXMLWriter +except ImportError: + from utils import aion_data_path as _aion_data_path, BaseXMLReader as _BaseXMLReader, BaseXMLWriter as _BaseXMLWriter + + +config_file = _aion_data_path + "/config.xml" + + +class Aion: + """ + get infos about all aion internal configs (and change them) + + :since: 0.1.0 + """ + + def __init__(self) -> None: + """ + set all class values + + :return: None + + :since: 0.1.0 + """ + self.all_listening_modes = ["auto", "manual"] + self.all_stt_engines = ["google", "pocketsphinx"] + self.all_time_formats = ["12", "24"] + self.all_tts_engines = ["pico2wave", "espeak"] + self.supported_languages = ["de_DE", "en_US"] + + self._aion_cfg_reader = _BaseXMLReader(config_file) + self._aion_cfg_writer = _BaseXMLWriter(config_file) + + def get_hotword_file(self) -> str: + """ + get set hotword file path + + :return: str + returns path of the hotword file + syntax: + example: "/usr/local/aion-/etc/Aion.pmdl" + + :since: 0.1.0 + """ + from glob import glob + for value_list in self._aion_cfg_reader.get_infos(["hotword_file"]).values(): + for config in value_list: + if config["parent"]["tag"] == "aion": + return glob(config["text"])[0] + + def get_language(self) -> str: + """ + get set language locale + + :return: str + returns language locale + syntax: + example: "en_US" + + :since: 0.1.0 + """ + for value_list in self._aion_cfg_reader.get_infos(["language"]).values(): + for config in value_list: + if config["parent"]["tag"] == "aion": + return config["text"] + + def get_listening_mode(self) -> str: + """ + get set listening mode + + :return: str + returns listening mode + syntax: + example: "auto" + + :since: 0.1.0 + """ + for value_list in self._aion_cfg_reader.get_infos(["listening_mode"]).values(): + for config in value_list: + if config["parent"]["tag"] == "aion": + return config["text"] + + def get_pid_manipulation_number(self) -> int: + """ + get set pid manipulation number + + :return: int + returns the pid manipulation number + syntax: + example: 4 + + :since: 0.1.0 + """ + for value_list in self._aion_cfg_reader.get_infos(["pid_manipulation_number"]).values(): + for config in value_list: + if config["parent"]["tag"] == "aion": + return int(config["text"]) + + def get_stt_engine(self) -> str: + """ + get set speech-to-text engine + + :return: str + returns speech-to-text engine + syntax: + example: "google" + + :since: 0.1.0 + """ + for value_list in self._aion_cfg_reader.get_infos(["listening_source"]).values(): + for config in value_list: + if config["parent"]["tag"] == "aion": + return config["text"] + + def get_time_format(self) -> int: + """ + get set time format + + :return: str + returns time format + syntax: