2020-06-28 11:15:51 +00:00

491 lines
17 KiB
Python

#!/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: <hotword file path>
example: "/usr/local/aion-<aion_version>/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: <language locale>
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: <listening mode>
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: <pid manipulation number>
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: <speech-to-text engine>
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: <time format>
example: 24
:since: 0.1.0
"""
for value_list in self._aion_cfg_reader.get_infos(["time_format"]).values():
for config in value_list:
if config["parent"]["tag"] == "aion":
return int(config["text"])
def get_tts_engine(self) -> str:
"""
get set text-to-speech engine
:return: str
returns text-to-speech engine
syntax: <text-to-speech engine>
example: "espeak"
:since: 0.1.0
"""
for value_list in self._aion_cfg_reader.get_infos(["tts_engine"]).values():
for config in value_list:
if config["parent"]["tag"] == "aion":
return config["text"]
@staticmethod
def reset() -> None:
"""
resets the aion config values
:return: None
:since: 0.1.0
"""
from locale import getdefaultlocale
_BaseXMLWriter(config_file).remove("config", "aion")
aion_cfg_writer = _BaseXMLWriter(config_file)
aion_cfg_writer.add("config", "aion")
aion_cfg_writer.add("aion", "hotword_file", text="/usr/local/aion-*/etc/Aion.pmdl")
aion_cfg_writer.add("aion", "language", text=str(getdefaultlocale()[0]))
aion_cfg_writer.add("aion", "listening_mode", text="auto")
aion_cfg_writer.add("aion", "pid_manipulation_number", text="4")
aion_cfg_writer.add("aion", "stt_engine", text="pocketsphinx")
aion_cfg_writer.add("aion", "time_format", text="12")
aion_cfg_writer.add("aion", "tts_engine", text="espeak")
aion_cfg_writer.write()
def set_hotword_file(self, hotword_file: str) -> None:
"""
sets the hotword file
:param hotword_file: str
location from the new hotword file
syntax: <hotword_file>
example: "/usr/local/aion-*/etc/Aion.pmdl"
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_no_hotword_file_file
except ImportError:
from _error_codes import config_no_hotword_file_file
from os.path import isfile
if isfile(hotword_file):
self._aion_cfg_writer.update("aion", "hotword_file", text=str(hotword_file))
self._aion_cfg_writer.write()
else:
raise FileNotFoundError("Errno: " + config_no_hotword_file_file + " - Couldn't find file '" + hotword_file + "'")
def set_language(self, language: str) -> None:
"""
sets the language locale
:param language: str
new language locale
syntax: <language locale>
example: "en_US"
:return: None
:since: 0.1.0
"""
from colorama import Fore
if language in self.supported_languages:
self._aion_cfg_writer.update("aion", "language", text=str(language))
self._aion_cfg_writer.write()
else:
print(Fore.RED + "'" + language + "' isn't an official supported language for speech output (type 'aion.Config.supported_languages' to see all supported languages).\n"
"The complete speech output is now in English. You have to create your own '.lng' file to support your language.\n" +
str(self.supported_languages) + " are the supported languages" + Fore.RESET)
self._aion_cfg_writer.update("aion", "language", text=str(language))
self._aion_cfg_writer.write()
def set_listening_mode(self, listening_mode: str) -> None:
"""
sets the listening mode
:param listening_mode: str
new listening mode
syntax: <listening mode>
example: "auto"
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_no_supported_listening_mode
except ImportError:
from _error_codes import config_no_supported_listening_mode
if listening_mode in self.all_listening_modes:
self._aion_cfg_writer.update("aion", "listening_mode", text=str(listening_mode))
self._aion_cfg_writer.write()
else:
raise ValueError("Errno: " + config_no_supported_listening_mode + " - " + str(listening_mode) + " isn't a supported listening mode. Please choose from these: " + str(self.all_listening_modes))
def set_pid_manipulation_number(self, pid_manipulation_number: int) -> None:
"""
sets the pid manipulation number
:param pid_manipulation_number: int
new pid manipulation number
syntax: <pid manipulation number>
example: 4
:return: None
:since: 0.1.0
"""
self._aion_cfg_writer.update("aion", "listening_mode", text=str(pid_manipulation_number))
self._aion_cfg_writer.write()
def set_stt_engine(self, stt_engine: str) -> None:
"""
sets the speech-to-text engine
:param stt_engine: str
new speech-to-text engine
syntax: <speech-to-text engine>
example: "pocketsphinx"
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_no_supported_listening_source
except ImportError:
from _error_codes import config_no_supported_listening_source
if stt_engine in self.all_stt_engines:
self._aion_cfg_writer.update("aion", "stt_engine", text=str(stt_engine))
self._aion_cfg_writer.write()
else:
raise ValueError("Errno: " + config_no_supported_listening_source + " - " + str(stt_engine) + " isn't a supported listening source. Please choose from these: " + str(self.all_stt_engines))
def set_time_format(self, time_format: str) -> None:
"""
sets the time format
:param time_format: str
new time format
syntax: <time format>
example: "24"
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_no_supported_time_format
except ImportError:
from _error_codes import config_no_supported_time_format
if str(time_format) in self.all_time_formats:
self._aion_cfg_writer.update("aion", "time_format", text=str(time_format))
self._aion_cfg_writer.write()
else:
raise ValueError("Error: " + config_no_supported_time_format + " - " + str(time_format) + " isn't a supported time format. Please choose from these: " + str(self.all_time_formats))
def set_tts_engine(self, tts_engine: str) -> None:
"""
sets the text-to-speech engine
:param tts_engine: str
new text-to-speech engine
syntax: <text-to-speech engine>
example: "espeak"
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_no_supported_tts_engine
except ImportError:
from _error_codes import config_no_supported_tts_engine
if tts_engine in self.all_tts_engines:
self._aion_cfg_writer.update("aion", "tts_engine", text=str(tts_engine))
self._aion_cfg_writer.write()
else:
raise ValueError("Errno: " + config_no_supported_tts_engine + " - " +str(tts_engine) + " isn't a supported tts engine. Please choose from these: " + str(self.all_tts_engines))
def add_entry(name: str, text: str = None, attrib: dict = {}, parent_name: str = "config", parent_attrib: dict = {}) -> None:
"""
adds an entry from the config file
:param name: str
name of the new entry
syntax: <name>
example: "test_entry"
:param text: str, optional
text of the new entry
syntax: <text>
example: "Test"
:param attrib: dict, optional
attributes of the new entry
syntax: {<attribute name>: <attribute value>}
example: {"test_attrib", "test"}
:param parent_name: str, optional
name of the parent entry to which the entry is added
syntax: <parent name>
example: "test_parent"
:param parent_attrib: dict, optional
attributes of the parent entry
syntax: {<parent attribute name>: <parent attribute value>}
example: {"version": "1.0.0"}
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_name_config_is_used_as_root_name, config_character_must_be_in_alphabet
except ImportError:
from _error_codes import config_name_config_is_used_as_root_name, config_character_must_be_in_alphabet
cfg_writer = _BaseXMLWriter(config_file)
if name == "config":
raise NameError("Errno: " + config_name_config_is_used_as_root_name + " - Name 'config' is already used as root name")
for char in name:
if char not in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_":
raise IndexError("Errno: " + config_character_must_be_in_alphabet + " - " + char + " in " + name + " must be in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_'")
cfg_writer.add(parent_name, name, text, attrib, parent_attrib=parent_attrib)
cfg_writer.write()
def delete_entry(name: str, parent_name: str = "config", parent_attrib: dict = {}) -> None:
"""
deletes an entry from the config file
:param name: str
name of the entry to be deleted
syntax: <name>
example: "test_entry"
:param parent_name: str, optional
name of the parent entry of the entry to be deleted
syntax: <parent name>
example: "test_parent"
:param parent_attrib: dict, optional
attributes of the parent entry from the entry to be searched
syntax: {<attribute name>: <attribute value>}
example: {"test_attrib", "test"}
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_root_tag_cannot_be_removed
except ImportError:
from _error_codes import config_root_tag_cannot_be_removed
cfg_writer = _BaseXMLWriter(config_file)
if name == "config":
raise NameError("Errno: " + config_root_tag_cannot_be_removed + " - The root tag cannot be removed")
cfg_writer.remove(parent_name, name, parent_attrib)
cfg_writer.write()
def get_entry(name: str, parent_name: str = None, parent_attrib: dict = None) -> dict:
"""
get infos about an entry
:param name: str
name of the entry to be searched
syntax: <name>
example: "test_entry"
:param parent_name: str, optional
name of the parent entry of the entry to be deleted
syntax: <parent name>
example: "test_parent"
:param parent_attrib: dict, optional
attributes of the parent entry
syntax: {<attribute name>: <attribute value>}
example: {"test_attrib", "test"}
:return: dict
returns the infos about the given entry
syntax: {"text": <text of entry>, "attrib": <attributes of entry>}
e.g.: {"text": "entry text", "attrib": {"version": "1.0.0"}}
:since: 0.1.0
"""
cfg_reader = _BaseXMLReader(config_file)
return_dict = {}
if parent_name:
for value_list in cfg_reader.get_infos([name]).values():
for entry in value_list:
if entry["parent"] == parent_name:
if parent_attrib:
if entry["attrib"] == parent_attrib:
return_dict["text"] = entry["text"]
return_dict["attrib"] = entry["attrib"]
break
else:
return_dict["text"] = entry["text"]
return_dict["attrib"] = entry["attrib"]
break
else:
return_dict["text"] = cfg_reader.get_infos([name]).items().index(0)["text"]
return_dict["attrib"] = cfg_reader.get_infos([name]).items().index(0)["attrib"]
return return_dict
def update_entry(name: str, text: str = None, attrib: dict = {}, parent_name: str = "config", **extra: str) -> None:
"""
updates an entry
:param name: str
name of the entry to be updated
syntax: <name>
example: "test_entry"
:param text: str, optional
new text of the entry to be updated
syntax: <text>
example: "new test text"
:param attrib: dict, optional
new attributes of the entry to be updated
syntax: {<attribute name>: <attribute value>}
example: {"new_test_attrib", "new_test"}
:param parent_name: str, optional
parent entry of the entry to be updated
syntax: <parent name>
example: "test_parent"
:return: None
:since: 0.1.0
"""
try:
from ._error_codes import config_root_tag_cannot_be_updated
except ImportError:
from _error_codes import config_root_tag_cannot_be_updated
cfg_writer = _BaseXMLWriter(config_file)
if name == "config":
raise NameError("Errno: " + config_root_tag_cannot_be_updated + " - Can't update root name")
if extra:
cfg_writer.update(parent_name, name, text, {**attrib, **extra})
else:
cfg_writer.update(parent_name, name, text, attrib)