mirror of
https://github.com/bytedream/aion.git
synced 2025-05-09 20:05:08 +02:00
Add files via upload
This commit is contained in:
parent
b8e3072563
commit
bc65ff575d
BIN
aion-0.1.0_alpha/Aion_Logo.png
Normal file
BIN
aion-0.1.0_alpha/Aion_Logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
143
aion-0.1.0_alpha/aion_core/__init__.py
Normal file
143
aion-0.1.0_alpha/aion_core/__init__.py
Normal file
@ -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: <speech output words>
|
||||
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: <sudo>
|
||||
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: <filename>
|
||||
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)
|
120
aion-0.1.0_alpha/aion_core/_error_codes.py
Normal file
120
aion-0.1.0_alpha/aion_core/_error_codes.py
Normal file
@ -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"
|
158
aion-0.1.0_alpha/aion_core/acph.py
Normal file
158
aion-0.1.0_alpha/aion_core/acph.py
Normal file
@ -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: <language locale>
|
||||
example: "de_DE"
|
||||
:param skill: str
|
||||
skill name to which the acph belongs
|
||||
syntax: "<skill name>"
|
||||
example: "test_skill"
|
||||
:param acph_dict: dict, optional
|
||||
defines a word or a sentence from which a method is called
|
||||
syntax: {<activate phrase>: <method that should get called after the activate phrase was said>}
|
||||
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("<root>", 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: <language_locale>
|
||||
example: "en_US"
|
||||
:param skill_acph_dict_dict: dict, optional
|
||||
skill name you want to add specific entries
|
||||
syntax: {<skill name>: {<activate phrase>: <method that should get called after the activate phrase was said>}}
|
||||
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 '<language_locale>.acph'
|
||||
|
||||
:param language_locale: str
|
||||
language locale from (file) which the activate phases is being deleted
|
||||
syntax: <language locale>
|
||||
example: "en_US"
|
||||
:param acph_list: list, optional
|
||||
name of the activate phases you want to remove
|
||||
syntax: [<activate phase name>]
|
||||
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("<root>", 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: <language locale>
|
||||
example: "en_US"
|
||||
:param acph: str
|
||||
activate phrase you want to check if exists
|
||||
syntax: <acph name>
|
||||
example: "start test"
|
||||
:return: bool
|
||||
returns True if acph exist / False if not
|
||||
syntax: <boolean>
|
||||
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(["<root>"]).items().index(0):
|
||||
if acph in item["childs"]:
|
||||
return True
|
||||
else:
|
||||
return False
|
490
aion-0.1.0_alpha/aion_core/config.py
Normal file
490
aion-0.1.0_alpha/aion_core/config.py
Normal file
@ -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: <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)
|
231
aion-0.1.0_alpha/aion_core/language.py
Normal file
231
aion-0.1.0_alpha/aion_core/language.py
Normal file
@ -0,0 +1,231 @@
|
||||
#!/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 _language_file() -> str:
|
||||
"""
|
||||
gets the language file for the current language
|
||||
|
||||
:return: str
|
||||
return the language file for the current language
|
||||
syntax: "<language file>"
|
||||
example: "en_US"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
from os.path import isfile
|
||||
if isfile(language_directory + "/" + language + ".lng") is False:
|
||||
print(Fore.RED + "didn't found language file in your language. Using the default language file (en_US)" + Fore.RESET)
|
||||
return language_directory + "/en_US.lng"
|
||||
else:
|
||||
return language_directory + "/" + language + ".lng"
|
||||
|
||||
|
||||
language = _Aion().get_language()
|
||||
language_directory = _aion_data_path + "/language"
|
||||
language_file = _language_file()
|
||||
supported_languages = ["de_DE", "en_US"]
|
||||
|
||||
|
||||
def add_entry(language_locale: str, skill: str, entry_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: <language locale>
|
||||
example: "de_DE"
|
||||
:param skill: str
|
||||
skill name to which the entry belongs
|
||||
syntax: "<skill name>"
|
||||
example: "test_skill"
|
||||
:param entry_dict: dict, optional
|
||||
all texts for execution of a function
|
||||
syntax: {<entry name>: <text of your entry>}
|
||||
example: {"test_entry": "Test function was executed correctly"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import language_lng_file_doesnt_exist, language_entry_already_exist
|
||||
except ImportError:
|
||||
from _error_codes import language_lng_file_doesnt_exist, language_entry_already_exist
|
||||
|
||||
from os.path import isfile
|
||||
|
||||
lng_file = language_directory + "/" + language_locale + ".lng"
|
||||
if isfile(lng_file) is False:
|
||||
raise FileNotFoundError("Errno: " + language_lng_file_doesnt_exist + " - The file " + lng_file + " doesn't exist")
|
||||
try:
|
||||
from .utils import BaseXMLWriter
|
||||
except ImportError:
|
||||
from utils import BaseXMLWriter
|
||||
|
||||
lng_adder = BaseXMLWriter(lng_file)
|
||||
for entry, text in entry_dict.items():
|
||||
if exist_entry(language_locale, skill, entry) is True:
|
||||
raise IndexError("Errno: " + language_entry_already_exist + " - The entry " + entry + " already exist")
|
||||
lng_adder.add("<root>", skill + "." + str(entry), text=str(text))
|
||||
lng_adder.write()
|
||||
|
||||
|
||||
def create_lng_file(language_locale: str, extra_dict: dict = {}, **extra: dict) -> None:
|
||||
"""
|
||||
creates a new '.lng' file for given language locale with given entry_dict
|
||||
|
||||
:param language_locale: str
|
||||
language locale of language from which the new file is to be created
|
||||
syntax: <language_locale>
|
||||
example: en_US
|
||||
:param extra_dict: dict, optional
|
||||
skill name you want to add specific entries
|
||||
syntax: {<name of the skill you want to add entries>: {{<name of the entry>: <text of the entry>}}
|
||||
example: {"test_skill": {"test_entry": "This is the text for the test text entry"}}
|
||||
:param extra: kwargs, optional
|
||||
skill name you want to add specific entries
|
||||
syntax: <name of the skill you want to add entries>={<name of the entry>: <text of the entry>}
|
||||
example: test_skill={"test_success": "The test was executed successfully", "text_error": "The test wasn't executed successfully"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import language_lng_file_already_exist
|
||||
from .utils import BaseXMLBuilder
|
||||
except ImportError:
|
||||
from _error_codes import language_lng_file_already_exist
|
||||
from utils import BaseXMLBuilder
|
||||
from os.path import isfile
|
||||
|
||||
if isfile(language_directory + "/" + language_locale + ".lng"):
|
||||
raise FileExistsError("Errno: " + language_lng_file_already_exist + " - The language file " + language_locale + ".lng already exist in directory " + language_directory)
|
||||
|
||||
lng_file = BaseXMLBuilder(language_locale)
|
||||
|
||||
for skill, entry_dict in extra_dict.items():
|
||||
for entry_name, entry_text in entry_dict.items():
|
||||
lng_file.create_root_element(language_locale, str(skill) + "." + str(entry_name), text=str(entry_text))
|
||||
|
||||
for skill, entry_dict in extra.items():
|
||||
for entry_name, entry_text in entry_dict.items():
|
||||
lng_file.create_root_element(language_locale, str(skill) + "." + str(entry_name), text=str(entry_text))
|
||||
lng_file.write(language_directory + "/" + language_locale + ".lng")
|
||||
|
||||
|
||||
def delete_entry(language_locale: str, skill: str, entry_list: list = []) -> None:
|
||||
"""
|
||||
deletes entries from '<language_locale>.lng'
|
||||
|
||||
:param language_locale: str
|
||||
language locale from (file) which the entry is being deleted
|
||||
syntax: <language locale>
|
||||
example: "en_US"
|
||||
:param skill : str
|
||||
name of the skill from which the entries should be deleted
|
||||
syntax: <skill name>
|
||||
example: "test"
|
||||
:param entry_list: list, optional
|
||||
name of the entries you want to remove
|
||||
syntax: [<entry name>]
|
||||
example: ["test_entry"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLWriter
|
||||
except ImportError:
|
||||
from utils import BaseXMLWriter
|
||||
|
||||
lng_writer = BaseXMLWriter(language_directory + "/" + language_locale + ".lng")
|
||||
for item in entry_list:
|
||||
lng_writer.remove("<root>", str(skill) + "." + str(item))
|
||||
lng_writer.write()
|
||||
|
||||
|
||||
def exist_entry(language_locale: str, skill: str, entry: str) -> bool:
|
||||
"""
|
||||
checks if a entry exist
|
||||
|
||||
:param language_locale: str
|
||||
language locale from (file) which the entry should be search
|
||||
syntax: <language locale>
|
||||
example: "en_US"
|
||||
:param skill: str
|
||||
skill name from the entry
|
||||
syntax: <skill name>
|
||||
example: "test"
|
||||
:param entry: str
|
||||
entry name of skill (entry)
|
||||
syntax: <entry name>
|
||||
example: "test_entry"
|
||||
:return: bool
|
||||
returns True if entry exist / False if not
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLReader
|
||||
except ImportError:
|
||||
from utils import BaseXMLReader
|
||||
|
||||
entry = entry.replace(" ", "_")
|
||||
|
||||
lng_reader = BaseXMLReader(language_directory + "/" + language_locale + ".lng")
|
||||
for item in lng_reader.get_infos(["<root>"]).items().index(0):
|
||||
if skill + "." + entry in item["childs"]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def start(skill: str, entry: str, format: dict = {}) -> str:
|
||||
"""
|
||||
returns entry from given arguments
|
||||
|
||||
:param skill: str
|
||||
name of the skill from the entry you want to call
|
||||
syntax: <skill name>
|
||||
example: "test_skill"
|
||||
:param entry: str
|
||||
name of the entry you want to call
|
||||
syntax: <entry>
|
||||
example: "test_func_entry"
|
||||
:param format: dict
|
||||
dictionary to format the string in the '.lng' file
|
||||
syntax: <format>
|
||||
example: {"test", "newtest"}: "This is a test" -> "This is a newtest"
|
||||
:return: str
|
||||
returns the (from 'format' formatted) string from the in '/etc/aion_data/config.xml' setted language locale '.lng' file
|
||||
syntax: <return string>
|
||||
example: "This is a test"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from ast import literal_eval
|
||||
from random import choice
|
||||
|
||||
try:
|
||||
from .utils import BaseXMLReader
|
||||
except ImportError:
|
||||
from utils import BaseXMLReader
|
||||
|
||||
lng_reader = BaseXMLReader(language_file)
|
||||
for item in lng_reader.get_infos([skill + "." + entry]).values().index(0):
|
||||
try:
|
||||
if item["text"].startswith("[") and item["text"].endswith("]"):
|
||||
return str(choice(literal_eval(item["text"]))).format(**format)
|
||||
else:
|
||||
return str(item["text"]).format(**format)
|
||||
except SyntaxError:
|
||||
return str(item["text"]).format(**format)
|
775
aion-0.1.0_alpha/aion_core/logging.py
Normal file
775
aion-0.1.0_alpha/aion_core/logging.py
Normal file
@ -0,0 +1,775 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from time import time as _time
|
||||
|
||||
|
||||
class LogAll:
|
||||
"""
|
||||
'LogConsole' and 'LogFile' classes in one class
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, log_fname: str, critical_fname: str = None, debug_fname: str = None, error_fname: str = None, info_fname: str = None, warning_fname: str = None,
|
||||
console_log_format: str = "[{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}",
|
||||
file_log_format: str = "[{year}-{month}-{day} {hour}:{minute}:{second}] - {filename}(line: {lineno}) - {levelname}: {message}") -> None:
|
||||
"""
|
||||
:param log_fname: str
|
||||
filename of the file to which all logging messages should be saved
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test.log"
|
||||
:param critical_fname: str, optional
|
||||
filename of the file to which critical logging messages should be saved
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_critical.log"
|
||||
:param debug_fname: str, optional
|
||||
filename of the file to which debug logging messages should be saved
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_debug.log"
|
||||
:param error_fname: str, optional
|
||||
filename of the file to which error logging messages should be saved
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_error.log"
|
||||
:param info_fname: str, optional
|
||||
filename of the file to which info logging messages should be saved
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_info.log"
|
||||
:param warning_fname: str, optional
|
||||
filename of the file to which warning logging messages should be saved
|
||||
syntax: <fname>
|
||||
example: "/home/pi/test_warning.log"
|
||||
:param console_log_format: str, optional
|
||||
format of the console output
|
||||
syntax: <format>
|
||||
example: [{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}
|
||||
NOTE: in 'format' you can use the following curly bracktes:
|
||||
year gives the year back
|
||||
month gives the month back
|
||||
day gives the day back
|
||||
hour gives the hour back
|
||||
minute gives the minute back
|
||||
second gives the second back
|
||||
microsecond gives the microsecond back
|
||||
runtime gives the back since the logger has started
|
||||
levelname gives the levelname back
|
||||
filename gives the name of the file from which the logger is called back
|
||||
lineno gives the line number back from which the levelname function was called
|
||||
function gives the function back from which the levelname function was called
|
||||
message gives the in levelname function given message back
|
||||
:param file_log_format: str, optional
|
||||
format of the output that should be write to file
|
||||
syntax: <format>
|
||||
example: [{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}
|
||||
NOTE: in 'format' you can use the following curly bracktes:
|
||||
year gives the year back
|
||||
month gives the month back
|
||||
day gives the day back
|
||||
hour gives the hour back
|
||||
minute gives the minute back
|
||||
second gives the second back
|
||||
microsecond gives the microsecond back
|
||||
runtime gives the back since the logger has started
|
||||
levelname gives the levelname back
|
||||
filename gives the name of the file from which the logger is called back
|
||||
lineno gives the line number back from which the levelname function was called
|
||||
function gives the function back from which the levelname function was called
|
||||
message gives the in levelname function given message back
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from datetime import datetime
|
||||
from inspect import getframeinfo, stack
|
||||
|
||||
caller_infos = getframeinfo(stack()[1][0])
|
||||
self.log_fname = log_fname
|
||||
|
||||
self.critical_fname = critical_fname
|
||||
self.debug_fname = debug_fname
|
||||
self.error_fname = error_fname
|
||||
self.info_fname = info_fname
|
||||
self.warning_fname = warning_fname
|
||||
|
||||
self._date = datetime.now()
|
||||
self._filename = caller_infos.filename
|
||||
self._console_log_format = console_log_format
|
||||
self._file_log_format = file_log_format
|
||||
self._function = caller_infos.function
|
||||
self._lineno = caller_infos.lineno
|
||||
self._start_time = _time()
|
||||
|
||||
def _format(self, levelname: str, message: str, lineno: int = None) -> dict:
|
||||
"""
|
||||
returns a dict with custom entries
|
||||
|
||||
:param levelname: str
|
||||
name of the level
|
||||
syntax: <levelname>
|
||||
example: "INFO"
|
||||
:param message: str
|
||||
message in the dict
|
||||
syntax: <message>
|
||||
example: "Test message"
|
||||
:param lineno: int
|
||||
line number in the dict
|
||||
syntax: <line number>
|
||||
example: 34
|
||||
:return: dict
|
||||
syntax: {"year": <year>,
|
||||
"month": <month>,
|
||||
"day": <day>,
|
||||
"hour": <hour>,
|
||||
"minute": <minute>,
|
||||
"second": <second>,
|
||||
"microsecond": <microsecond>,
|
||||
"runtime": <runtime>,
|
||||
"levelname": <level name>,
|
||||
"filename": <filename>,
|
||||
"lineno": <line number>,
|
||||
"function": <function>,
|
||||
"message": <message>}
|
||||
example: {"year": 2000,
|
||||
"month": 1,
|
||||
"day": 1,
|
||||
"hour": 00,
|
||||
"minute": 00,
|
||||
"second": 00,
|
||||
"microsecond": 00000,
|
||||
"runtime": "01:23:45",
|
||||
"levelname": "INFO",
|
||||
"filename": "abc.py",
|
||||
"lineno": 123,
|
||||
"function": "test_function",
|
||||
"message": "This is a test message"}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if lineno:
|
||||
return {"year": self._date.year, "month": self._date.month, "day": self._date.day, "hour": self._date.hour, "minute": self._date.minute, "second": self._date.second, "microsecond": self._date.microsecond,
|
||||
"runtime": self._runtime(), "levelname": levelname, "filename": self._filename, "lineno": lineno, "function": self._function, "message": message}
|
||||
else:
|
||||
return {"year": self._date.year, "month": self._date.month, "day": self._date.day, "hour": self._date.hour, "minute": self._date.minute, "second": self._date.second, "microsecond": self._date.microsecond,
|
||||
"runtime": self._runtime(), "levelname": levelname, "filename": self._filename, "lineno": self._lineno, "function": self._function, "message": message}
|
||||
|
||||
def _runtime(self) -> str:
|
||||
"""
|
||||
returns the runtime
|
||||
|
||||
:return: str
|
||||
returns the runtime
|
||||
syntax: <hour>:<minute>:<day>
|
||||
example: "01:23:45"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
second = int(_time() - self._start_time)
|
||||
minute = 0
|
||||
hour = 0
|
||||
while (second / 60) >= 1:
|
||||
minute += 1
|
||||
second -= 60
|
||||
|
||||
while (minute / 60) >= 1:
|
||||
hour += 1
|
||||
minute -= 60
|
||||
|
||||
if len(str(second)) == 1:
|
||||
second = "0" + str(second)
|
||||
|
||||
if len(str(minute)) == 1:
|
||||
minute = "0" + str(minute)
|
||||
|
||||
if len(str(hour)) == 1:
|
||||
hour = "0" + str(hour)
|
||||
|
||||
return str(str(hour) + ":" + str(minute) + ":" + str(second))
|
||||
|
||||
def critical(self, msg: str, lineno: int = None) -> None:
|
||||
"""
|
||||
prints and write given format with 'critical' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "critical message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
LogFile(self.log_fname, format=self._file_log_format).critical(msg, self._format("CRITICAL", msg, lineno=lineno))
|
||||
if self.critical_fname is not None:
|
||||
LogFile(self.critical_fname, format=self._file_log_format).critical(msg, self._format("CRITICAL", msg, lineno=lineno))
|
||||
LogConsole(self._console_log_format).critical(msg, self._format("CRITICAL", msg, lineno=lineno))
|
||||
|
||||
def debug(self, msg: str, lineno: int = None) -> None:
|
||||
"""
|
||||
prints and write given format with 'debug' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
LogFile(self.log_fname, format=self._file_log_format).debug(msg, self._format("DEBUG", msg, lineno=lineno))
|
||||
if self.debug_fname is not None:
|
||||
LogFile(self.debug_fname, format=self._file_log_format).debug(msg, self._format("DEBUG", msg, lineno=lineno))
|
||||
LogConsole(self._console_log_format).debug(msg, self._format("DEBUG", msg, lineno=lineno))
|
||||
|
||||
def error(self, msg: str, lineno=None) -> None:
|
||||
"""
|
||||
prints and write given format with 'error' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "error message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
LogFile(self.log_fname, format=self._file_log_format).error(msg, self._format("ERROR", msg, lineno=lineno))
|
||||
if self.error_fname is not None:
|
||||
LogFile(self.error_fname, format=self._file_log_format).error(msg, self._format("ERROR", msg, lineno=lineno))
|
||||
LogConsole(self._console_log_format).error(msg, self._format("ERROR", msg, lineno=lineno))
|
||||
|
||||
def info(self, msg: str, lineno=None) -> None:
|
||||
"""
|
||||
prints and write given format with 'info' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "info message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
LogFile(self.log_fname, format=self._file_log_format).info(msg, self._format("INFO", msg, lineno=lineno))
|
||||
if self.info_fname is not None:
|
||||
LogFile(self.log_fname, format=self._file_log_format).info(msg, self._format("INFO", msg, lineno=lineno))
|
||||
LogConsole(self._console_log_format).info(msg, self._format("INFO", msg, lineno=lineno))
|
||||
|
||||
def warning(self, msg: str, lineno=None) -> None:
|
||||
"""
|
||||
prints and write given format with 'warning' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "warning message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
LogFile(self.log_fname, format=self._file_log_format).warning(msg, self._format("WARNING", msg, lineno=lineno))
|
||||
if self.warning_fname is not None:
|
||||
LogFile(self.warning_fname, format=self._file_log_format).warning(msg, self._format("WARNING", msg, lineno=lineno))
|
||||
LogConsole(self._console_log_format).warning(msg, self._format("WARNING", msg, lineno=lineno))
|
||||
|
||||
|
||||
class LogConsole:
|
||||
"""
|
||||
a simple logger for consoles
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, format: str = "[{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}") -> None:
|
||||
"""
|
||||
:param format: str, optional
|
||||
format of the console output
|
||||
syntax: <format>
|
||||
example: [{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}
|
||||
NOTE: in 'format' you can use the following curly bracktes:
|
||||
year gives the year back
|
||||
month gives the month back
|
||||
day gives the day back
|
||||
hour gives the hour back
|
||||
minute gives the minute back
|
||||
second gives the second back
|
||||
microsecond gives the microsecond back
|
||||
runtime gives the back since the logger has started
|
||||
levelname gives the levelname back
|
||||
filename gives the name of the file from which the logger is called back
|
||||
lineno gives the line number back from which the levelname function was called
|
||||
function gives the function back from which the levelname function was called
|
||||
message gives the in levelname function given message back
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from datetime import datetime
|
||||
from inspect import getframeinfo, stack
|
||||
|
||||
self.format = format
|
||||
|
||||
self._caller_infos = getframeinfo(stack()[1][0])
|
||||
self._date = datetime.now()
|
||||
self._start_time = _time()
|
||||
|
||||
def _format(self, levelname: str, message: str) -> dict:
|
||||
"""
|
||||
returns a dict with custom entries
|
||||
|
||||
:param levelname: str
|
||||
name of the level
|
||||
syntax: <levelname>
|
||||
example: "INFO"
|
||||
:param message: str
|
||||
message in the dict
|
||||
syntax: <message>
|
||||
example: "Test message"
|
||||
:return: dict
|
||||
syntax: {"year": <year>,
|
||||
"month": <month>,
|
||||
"day": <day>,
|
||||
"hour": <hour>,
|
||||
"minute": <minute>,
|
||||
"second": <second>,
|
||||
"microsecond": <microsecond>,
|
||||
"runtime": <runtime>,
|
||||
"levelname": <level name>,
|
||||
"filename": <filename>,
|
||||
"lineno": <line number>,
|
||||
"function": <function>,
|
||||
"message": <message>}
|
||||
example: {"year": 2000,
|
||||
"month": 1,
|
||||
"day": 1,
|
||||
"hour": 00,
|
||||
"minute": 00,
|
||||
"second": 00,
|
||||
"microsecond": 00000,
|
||||
"runtime": "01:23:45",
|
||||
"levelname": "INFO",
|
||||
"filename": "abc.py",
|
||||
"lineno": 123,
|
||||
"function": "test_function",
|
||||
"message": "This is a test message"}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
return {"year": self._date.year, "month": self._date.month, "day": self._date.day, "hour": self._date.hour, "minute": self._date.minute, "second": self._date.second, "microsecond": self._date.microsecond,
|
||||
"runtime": self._runtime(), "levelname": levelname, "filename": self._caller_infos.filename, "lineno": self._caller_infos.lineno, "function": self._caller_infos.function, "message": message}
|
||||
|
||||
def _runtime(self) -> str:
|
||||
"""
|
||||
returns the runtime
|
||||
|
||||
:return: str
|
||||
returns the runtime
|
||||
syntax: <hour>:<minute>:<day>
|
||||
example: "01:23:45"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
second = int(_time() - self._start_time)
|
||||
minute = 0
|
||||
hour = 0
|
||||
while (second / 60) >= 1:
|
||||
minute += 1
|
||||
second -= 60
|
||||
|
||||
while (minute / 60) >= 1:
|
||||
hour += 1
|
||||
minute -= 60
|
||||
|
||||
if len(str(second)) == 1:
|
||||
second = "0" + str(second)
|
||||
|
||||
if len(str(minute)) == 1:
|
||||
minute = "0" + str(minute)
|
||||
|
||||
if len(str(hour)) == 1:
|
||||
hour = "0" + str(hour)
|
||||
|
||||
return str(str(hour) + ":" + str(minute) + ":" + str(second))
|
||||
|
||||
def critical(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'critical' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "critical message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="CRITICAL", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def debug(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'debug' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="DEBUG", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def error(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'error' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "error message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="ERROR", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def info(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'info' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "info message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="INFO", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def warning(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'warning' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "warning message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="WARNING", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
|
||||
class LogFile:
|
||||
"""
|
||||
a simple logger for files
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, log_fname: str, mode: str = "a", format: str = "[{year}-{month}-{day} {hour}:{minute}:{second}] - {filename}(line: {lineno}) - {levelname}: {message}") -> None:
|
||||
"""
|
||||
:param log_fname: str
|
||||
filename of the file to which the logging messages should be saved
|
||||
syntax: <fname>
|
||||
example: "/home/pi/test.log"
|
||||
:param mode: str, optional
|
||||
mode to write on file
|
||||
syntax: <mode>
|
||||
example: "a"
|
||||
:param format: str, optional
|
||||
format of the output that should be write to file
|
||||
syntax: <format>
|
||||
example: [{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}
|
||||
NOTE: in 'format' you can use the following curly bracktes:
|
||||
year gives the year back
|
||||
month gives the month back
|
||||
day gives the day back
|
||||
hour gives the hour back
|
||||
minute gives the minute back
|
||||
second gives the second back
|
||||
microsecond gives the microsecond back
|
||||
runtime gives the back since the logger has started
|
||||
levelname gives the levelname back
|
||||
filename gives the name of the file from which the logger is called back
|
||||
lineno gives the line number back from which the levelname function was called
|
||||
function gives the function back from which the levelname function was called
|
||||
message gives the in levelname function given message back
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from datetime import datetime
|
||||
from inspect import getframeinfo, stack
|
||||
|
||||
self.format = format
|
||||
self.log_fname = log_fname
|
||||
self.mode = mode
|
||||
|
||||
self._caller_infos = getframeinfo(stack()[1][0])
|
||||
self._date = datetime.now()
|
||||
self._start_time = _time()
|
||||
|
||||
def _format(self, levelname: str, message: str) -> dict:
|
||||
"""
|
||||
returns a dict with custom entries
|
||||
|
||||
:param levelname: str
|
||||
name of the level
|
||||
syntax: <levelname>
|
||||
example: "INFO"
|
||||
:param message: str
|
||||
message in the dict
|
||||
syntax: <message>
|
||||
example: "Test message"
|
||||
|
||||
:return: dict
|
||||
syntax: {"year": <year>,
|
||||
"month": <month>,
|
||||
"day": <day>,
|
||||
"hour": <hour>,
|
||||
"minute": <minute>,
|
||||
"second": <second>,
|
||||
"microsecond": <microsecond>,
|
||||
"runtime": <runtime>,
|
||||
"levelname": <level name>,
|
||||
"filename": <filename>,
|
||||
"lineno": <line number>,
|
||||
"function": <function>,
|
||||
"message": <message>}
|
||||
example: {"year": 2000,
|
||||
"month": 1,
|
||||
"day": 1,
|
||||
"hour": 00,
|
||||
"minute": 00,
|
||||
"second": 00,
|
||||
"microsecond": 00000,
|
||||
"runtime": "01:23:45",
|
||||
"levelname": "INFO",
|
||||
"filename": "abc.py",
|
||||
"lineno": 123,
|
||||
"function": "test_function",
|
||||
"message": "This is a test message"}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
return {"year": self._date.year, "month": self._date.month, "day": self._date.day, "hour": self._date.hour, "minute": self._date.minute, "second": self._date.second, "microsecond": self._date.microsecond,
|
||||
"runtime": self._runtime(), "levelname": levelname, "filename": self._caller_infos.filename, "lineno": self._caller_infos.lineno, "function": self._caller_infos.function, "message": message}
|
||||
|
||||
def _runtime(self) -> str:
|
||||
"""
|
||||
returns the runtime
|
||||
|
||||
:return: str
|
||||
returns the runtime
|
||||
syntax: <hour>:<minute>:<day>
|
||||
example: "01:23:45"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
second = int(_time() - self._start_time)
|
||||
minute = 0
|
||||
hour = 0
|
||||
while (second / 60) >= 1:
|
||||
minute += 1
|
||||
second -= 60
|
||||
|
||||
while (minute / 60) >= 1:
|
||||
hour += 1
|
||||
minute -= 60
|
||||
|
||||
if len(str(second)) == 1:
|
||||
second = "0" + str(second)
|
||||
|
||||
if len(str(minute)) == 1:
|
||||
minute = "0" + str(minute)
|
||||
|
||||
if len(str(hour)) == 1:
|
||||
hour = "0" + str(hour)
|
||||
|
||||
return str(str(hour) + ":" + str(minute) + ":" + str(second))
|
||||
|
||||
def _write(self, msg: str) -> None:
|
||||
"""
|
||||
writes the given message to the log file
|
||||
|
||||
:param msg: str
|
||||
message that should be write to the file
|
||||
syntax: <message>
|
||||
example: "Test message"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
with open(self.log_fname, self.mode) as file:
|
||||
file.write(msg + "\n")
|
||||
file.close()
|
||||
|
||||
def critical(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'critical' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "critical message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="CRITICAL", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def debug(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'debug' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="DEBUG", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def error(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'debug' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="ERROR", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def info(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'info' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "info message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="INFO", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def warning(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'warning' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "warning message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="WARNING", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
910
aion-0.1.0_alpha/aion_core/plugin.py
Normal file
910
aion-0.1.0_alpha/aion_core/plugin.py
Normal file
@ -0,0 +1,910 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
try:
|
||||
from .utils import aion_data_path as _aion_data_path, BaseXMLReader as _BaseXMLReader
|
||||
except ImportError:
|
||||
from utils import aion_data_path as _aion_data_path, BaseXMLReader as _BaseXMLReader
|
||||
|
||||
|
||||
RUN_AFTER = "run_after"
|
||||
RUN_BEFORE = "run_after"
|
||||
|
||||
|
||||
run_after_path = _aion_data_path + "/plugins/run_after"
|
||||
run_before_path = _aion_data_path + "/plugins/run_before"
|
||||
|
||||
run_after_file = _aion_data_path + "/plugins/run_after/run_after.xml"
|
||||
run_before_file = _aion_data_path + "/plugins/run_before/run_before.xml"
|
||||
|
||||
|
||||
class RunAfter:
|
||||
"""
|
||||
base class to create custom 'run_after' plugins
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, activate_phrase: str, speech_input: str) -> None:
|
||||
"""
|
||||
makes the variables available for all class functions
|
||||
|
||||
:param activate_phrase: str
|
||||
activate phrase from which this class was called
|
||||
syntax: <activate phrase>
|
||||
example: "start plugin test"
|
||||
:param speech_input: str
|
||||
input that the user has spoken in
|
||||
syntax: <speech input>
|
||||
example: "start plugin test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.activate_phrase = activate_phrase
|
||||
self.speech_input = speech_input
|
||||
|
||||
def main(self) -> None:
|
||||
"""
|
||||
gets called if the class get called from the 'run_after_plugin' plugin of the 'Skill' class
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class RunBefore:
|
||||
"""
|
||||
base class to create custom 'run_before' plugins
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, activate_phrase: str, speech_input: str) -> None:
|
||||
"""
|
||||
makes the variables available for all class functions
|
||||
|
||||
:param activate_phrase: str
|
||||
activate phrase from which this class was called
|
||||
syntax: <activate phrase>
|
||||
example: "start plugin test"
|
||||
:param speech_input: str
|
||||
input that the user has spoken in
|
||||
syntax: <speech input>
|
||||
example: "start plugin test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.activate_phrase = activate_phrase
|
||||
self.speech_input = speech_input
|
||||
|
||||
def main(self) -> None:
|
||||
"""
|
||||
gets called if the class get called from the 'run_before_plugin' function of the 'Skill' class
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def create_run_after_plugin_file(author: str,
|
||||
plugin_name: str,
|
||||
main_file: str,
|
||||
skill: str,
|
||||
plugin_methods: dict,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_locales: list = [],
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a 'run_after' plugin can be installed
|
||||
|
||||
:param author: str
|
||||
name of the author from the plugin
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param main_file: str
|
||||
file name of file where all plugin methods are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param plugin_name: str
|
||||
root name of the plugin you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param skill: str
|
||||
name of the skill you want to add the 'run_before' plugin
|
||||
syntax: <skill name>
|
||||
example: "Play"
|
||||
NOTE: be case-sensitive!
|
||||
:param plugin_methods: dict
|
||||
dictionary of plugin pseudonym with plugin method you want to add to given 'skill'
|
||||
syntax: {"<plugin pseudonym>": <plugin methods>}
|
||||
example: ["test_plugin_run_test_2": "TestPlugin"]
|
||||
NOTE: be case-sensitive!
|
||||
NOTE2: the plugins pseudonyms are only pseudonyms for the given methods
|
||||
NOTE3: you can't remove individual plugins via the 'aion' command line command
|
||||
:param version: str
|
||||
version (number) of your plugin
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your plugin
|
||||
syntax: <description>
|
||||
example: "A simple plugin to test the method 'create_run_after_plugin_file'"
|
||||
:param language_locales: list
|
||||
list of language locales for which the 'language_dict' should be stored
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the plugin
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your plugin needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
_create_befater_plugin_file("run_after",
|
||||
author,
|
||||
plugin_name,
|
||||
main_file,
|
||||
skill,
|
||||
plugin_methods,
|
||||
version,
|
||||
additional_directories,
|
||||
description,
|
||||
language_locales,
|
||||
language_dict,
|
||||
license,
|
||||
required_python3_packages)
|
||||
|
||||
|
||||
def create_run_before_plugin_file(author: str,
|
||||
plugin_name: str,
|
||||
main_file: str,
|
||||
skill: str,
|
||||
plugin_methods: dict,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_locales: list = [],
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a 'run_before' plugin can be installed
|
||||
|
||||
:param author: str
|
||||
name of the author from the plugin
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param main_file: str
|
||||
file name of file where all plugin methods are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_run_before_plugin_file' is being executed
|
||||
:param plugin_name: str
|
||||
root name of the plugins you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param skill: str
|
||||
name of the skill you want to add the 'run_before' plugin
|
||||
syntax: <skill name>
|
||||
example: "Play"
|
||||
NOTE: be case-sensitive!
|
||||
:param plugin_methods: dict
|
||||
dictionary of plugin pseudonym with plugin method you want to add to given 'skill'
|
||||
syntax: {"<plugin pseudonyms>": <plugin methods>}
|
||||
example: ["test_plugin_run_test_2": "TestPlugin"]
|
||||
NOTE: be case-sensitive!
|
||||
NOTE2: the plugins pseudonyms are only pseudonyms for the given methods
|
||||
NOTE3: you can't remove individual plugins via the 'aion' command line command
|
||||
:param plugin_name: str
|
||||
name of the plugin you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param version: str
|
||||
version (number) of your plugin
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_run_before_plugin_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your plugin
|
||||
syntax: <description>
|
||||
example: "A simple plugin to test the method 'create_run_after_plugin_file'"
|
||||
:param language_locales: list
|
||||
list of language locales for which the 'language_dict' should be stored
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the plugin
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your plugin needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
_create_befater_plugin_file("run_before",
|
||||
author,
|
||||
plugin_name,
|
||||
main_file,
|
||||
skill,
|
||||
plugin_methods,
|
||||
version,
|
||||
additional_directories,
|
||||
description,
|
||||
language_locales,
|
||||
language_dict,
|
||||
license,
|
||||
required_python3_packages)
|
||||
|
||||
|
||||
def create_plugin_package(dir_name: str) -> None:
|
||||
"""
|
||||
creates a stand alone file ('.plugin') from given directory
|
||||
|
||||
:param dir_name: str
|
||||
directory name of the directory from which you want to create a '.plugin' file
|
||||
syntax: <directory name>
|
||||
example: "/home/pi/test/"
|
||||
:return: None
|
||||
|
||||
:note: 'plugin.aion' file must be in the given directory (see 'create_run_after_plugin_file' / 'create_run_before_plugin_file' to create a 'plugin.aion' file)
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import plugin_aion_plugin_file_not_found, plugin_to_much_aion_files
|
||||
except ImportError:
|
||||
from _error_codes import plugin_aion_plugin_file_not_found, plugin_to_much_aion_files
|
||||
|
||||
from os import listdir, mkdir, rename
|
||||
from os.path import isdir
|
||||
from random import sample
|
||||
from shutil import make_archive, rmtree
|
||||
|
||||
if isdir(dir_name) is False:
|
||||
raise NotADirectoryError("couldn't find the directory '" + dir_name + "'")
|
||||
|
||||
name = ""
|
||||
file_num = 0
|
||||
for file in listdir(dir_name):
|
||||
if file.endswith(".aion"):
|
||||
file_num += 1
|
||||
name = "".join(file.split(".aion")[0])
|
||||
if file_num == 0:
|
||||
raise FileNotFoundError("Errno: " + plugin_aion_plugin_file_not_found + " - Couldn't find .aion file in " + dir_name + ". To create one use the 'create_plugin_file' function in aionlib.skill")
|
||||
elif file_num > 1:
|
||||
raise FileExistsError("Errno: " + plugin_to_much_aion_files + " - Expected one .aion file in " + dir_name + ", got " + str(file_num))
|
||||
|
||||
plugin_dir_name = "plugin_" + name + "".join([str(num) for num in sample(range(1, 10), 5)])
|
||||
mkdir(plugin_dir_name)
|
||||
|
||||
make_archive(name + ".plugin", "zip", plugin_dir_name)
|
||||
rename(plugin_dir_name + ".plugin.zip", plugin_dir_name + ".plugin")
|
||||
|
||||
rmtree(plugin_dir_name)
|
||||
|
||||
|
||||
def execute_aion_file_type_plugin(fname: str) -> None:
|
||||
"""
|
||||
installs custom plugin from '<file name>.aion'
|
||||
|
||||
:param fname: str
|
||||
file name of the '.aion' file
|
||||
syntax: <file name>
|
||||
example: "/home/pi/plugin.aion"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._errors import plugin_couldnt_find_key, plugin_couldnt_find_plugin_type, plugin_illegal_run_after_pseudonym, plugin_run_after_pseudonym_already_exist,\
|
||||
plugin_illegal_run_before_pseudonym, plugin_run_before_pseudonym_already_exist, plugin_file_doesnt_exist_in_setup_dir, plugin_directory_doesnt_exist_in_setup_dir,\
|
||||
plugin_run_after_additional_directories_already_exist, plugin_run_before_additional_directories_already_exist, plugin_python3_module_not_found
|
||||
from .acph import add_acph
|
||||
from .language import add_entry, language_directory
|
||||
from .utils import remove_space, BaseXMLReader, BaseXMLWriter
|
||||
except ImportError:
|
||||
from _error_codes import plugin_couldnt_find_key, plugin_couldnt_find_plugin_type, plugin_illegal_run_after_pseudonym, plugin_run_after_pseudonym_already_exist,\
|
||||
plugin_illegal_run_before_pseudonym, plugin_run_before_pseudonym_already_exist, plugin_file_doesnt_exist_in_setup_dir, plugin_directory_doesnt_exist_in_setup_dir,\
|
||||
plugin_run_after_additional_directories_already_exist, plugin_run_before_additional_directories_already_exist, plugin_python3_module_not_found
|
||||
from acph import add_acph
|
||||
from language import add_entry, language_directory
|
||||
from utils import remove_space, BaseXMLReader, BaseXMLWriter
|
||||
|
||||
from ast import literal_eval
|
||||
from importlib import import_module
|
||||
from os import listdir, path
|
||||
from shutil import copy, copytree
|
||||
from subprocess import call
|
||||
setup_dict = {}
|
||||
setup_dir = path.dirname(path.abspath(fname))
|
||||
|
||||
plugin_type = ""
|
||||
is_skill = True
|
||||
|
||||
for line in open(fname, "r"):
|
||||
if line.startswith("#"):
|
||||
no_space_line = remove_space(line, "")
|
||||
if no_space_line == "#type:run_after_plugin":
|
||||
plugin_type = RUN_AFTER
|
||||
elif no_space_line == "#type:run_before_plugin":
|
||||
plugin_type = RUN_BEFORE
|
||||
continue
|
||||
|
||||
setup_dict[line.split("=")[0].strip()] = line.split("=")[1].strip()
|
||||
try:
|
||||
author = setup_dict["author"]
|
||||
main_file = setup_dict["main_file"]
|
||||
plugin_name = setup_dict["plugin_name"]
|
||||
skill = setup_dict["skill"]
|
||||
plugin_methods = literal_eval(setup_dict["plugin_methods"])
|
||||
version = setup_dict["version"]
|
||||
|
||||
additional_directories = literal_eval(setup_dict["additional_directories"])
|
||||
description = setup_dict["description"]
|
||||
language_locales = literal_eval(setup_dict["language_locales"])
|
||||
language_dict = literal_eval(setup_dict["language_dict"])
|
||||
license = setup_dict["license"]
|
||||
required_python3_packages = literal_eval(setup_dict["required_python3_packages"])
|
||||
except KeyError as error:
|
||||
raise KeyError("Errno: " + plugin_couldnt_find_key + " - Couldn't find key " + str(error) + " in " + fname)
|
||||
|
||||
if plugin_type != RUN_AFTER or plugin_type != RUN_BEFORE:
|
||||
raise NameError("Errno: " + plugin_couldnt_find_plugin_type + " - Couldn't find plugin type ('RUN_AFTER' or 'RUN_BEFORE') in " + fname)
|
||||
|
||||
# ----- #
|
||||
|
||||
if plugin_type == RUN_AFTER:
|
||||
for pseudonym in plugin_methods:
|
||||
if pseudonym == "run_after":
|
||||
raise NameError("Errno: " + plugin_illegal_run_after_pseudonym + " - Illegal name '" + pseudonym + "' in " + str(plugin_methods))
|
||||
try:
|
||||
if pseudonym in get_all_run_after_plugins()[skill]:
|
||||
raise NameError("Errno: " + plugin_run_before_pseudonym_already_exist + " - The plugin pseudonym " + plugin_name + " already exist")
|
||||
except KeyError:
|
||||
is_skill = False
|
||||
pass
|
||||
|
||||
elif plugin_type == RUN_BEFORE:
|
||||
for pseudonym in plugin_methods:
|
||||
if pseudonym == "run_before":
|
||||
raise NameError("Errno: " + plugin_illegal_run_before_pseudonym + " - Illegal name '" + pseudonym + "' in " + str(plugin_methods))
|
||||
try:
|
||||
if pseudonym in get_all_run_before_plugins()[skill]:
|
||||
raise NameError("Errno: " + plugin_run_after_pseudonym_already_exist + " - The plugin pseudonym " + plugin_name + " already exist")
|
||||
except KeyError:
|
||||
is_skill = False
|
||||
pass
|
||||
|
||||
if path.isfile(setup_dir + "/" + main_file) is False:
|
||||
raise FileNotFoundError("Errno: " + plugin_file_doesnt_exist_in_setup_dir + " - The file " + main_file + " doesn't exist in setup dir (" + setup_dir + ")")
|
||||
|
||||
for directory in additional_directories:
|
||||
if path.isdir(setup_dir + "/" + directory) is False:
|
||||
raise NotADirectoryError("Errno: " + plugin_directory_doesnt_exist_in_setup_dir + " - The directory " + directory + " doesn't exist in setup dir (" + setup_dir + ")")
|
||||
if plugin_type == RUN_AFTER:
|
||||
if directory in listdir(run_after_path):
|
||||
raise IsADirectoryError("Errno: " + plugin_run_after_additional_directories_already_exist + " - The directory " + directory + " already exist in " + run_after_path)
|
||||
elif plugin_type == RUN_BEFORE:
|
||||
if directory in listdir(run_before_path):
|
||||
raise IsADirectoryError("Errno: " + plugin_run_before_additional_directories_already_exist + " - The directory " + directory + " already exist in " + run_before_path)
|
||||
|
||||
# ----- #
|
||||
|
||||
for package in required_python3_packages:
|
||||
call("pip3 install " + package, shell=True)
|
||||
try:
|
||||
import_module(package)
|
||||
except ModuleNotFoundError:
|
||||
raise ModuleNotFoundError("Errno: " + plugin_python3_module_not_found + " - Couldn't install the required python3 package '" + package + "'")
|
||||
|
||||
dat_writer = None
|
||||
|
||||
if plugin_type == RUN_AFTER:
|
||||
copy(main_file, run_after_path + "/" + main_file)
|
||||
|
||||
for directory in additional_directories:
|
||||
copytree(directory, run_after_path + "/" + directory)
|
||||
|
||||
for language in language_locales:
|
||||
add_entry(language, plugin_name, language_dict)
|
||||
|
||||
dat_writer = BaseXMLWriter(run_after_file)
|
||||
|
||||
if is_skill is False:
|
||||
dat_writer.add("run_after", skill, type="skill")
|
||||
dat_writer.write()
|
||||
|
||||
elif plugin_type == RUN_BEFORE:
|
||||
copy(main_file, run_after_path + "/" + main_file)
|
||||
|
||||
for directory in additional_directories:
|
||||
copytree(directory, run_after_path + "/" + directory)
|
||||
|
||||
for language in language_locales:
|
||||
add_entry(language, plugin_name, language_dict)
|
||||
|
||||
dat_writer = BaseXMLWriter(run_before_file)
|
||||
|
||||
if is_skill is False:
|
||||
dat_writer.add("run_before", skill, type="skill")
|
||||
dat_writer.write()
|
||||
|
||||
for pseudonym, method in plugin_methods.values():
|
||||
dat_writer.add(skill, str(pseudonym), parent_attrib={"type": "skill"}, method=method, root_plugin=plugin_name)
|
||||
dat_writer.add(str(pseudonym), "additional_directories", str(additional_directories))
|
||||
dat_writer.add(str(pseudonym), "author", str(author))
|
||||
dat_writer.add(str(pseudonym), "description", str(description))
|
||||
dat_writer.add(str(pseudonym), "language_dict", str(language_dict))
|
||||
dat_writer.add(str(pseudonym), "language_locales", str(language_locales))
|
||||
dat_writer.add(str(pseudonym), "license", str(license))
|
||||
dat_writer.add(str(pseudonym), "main_file", str(main_file))
|
||||
dat_writer.add(str(pseudonym), "required_python3_packages", str(required_python3_packages))
|
||||
dat_writer.add(str(pseudonym), "version", str(version))
|
||||
dat_writer.write()
|
||||
|
||||
|
||||
def execute_plugin_file(fname: str) -> None:
|
||||
"""
|
||||
executes a '<name>.plugin' file for installing custom plugins
|
||||
|
||||
:param fname: str
|
||||
file name of the '.plugin' file
|
||||
syntax: <fname>
|
||||
example: "/home/pi/test.plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import plugin_couldnt_find_plugin_dot_aion
|
||||
except ImportError:
|
||||
from _error_codes import plugin_couldnt_find_plugin_dot_aion
|
||||
|
||||
from glob import glob
|
||||
from os.path import isfile
|
||||
from zipfile import ZipFile
|
||||
with ZipFile(fname, "r") as zipfile:
|
||||
zipfile.extractall("/tmp")
|
||||
zipfile.close()
|
||||
if isfile(glob("/tmp/plugin_*/plugin.aion")[0]) is False:
|
||||
raise FileNotFoundError("Errno: " + plugin_couldnt_find_plugin_dot_aion + "couldn't find 'plugin.aion' in " + fname)
|
||||
else:
|
||||
execute_aion_file_type_plugin(glob("/tmp/plugin_*/plugin.aion")[0])
|
||||
|
||||
|
||||
def get_all_run_after_plugins() -> dict:
|
||||
"""
|
||||
get all installed 'run_after' plugins + infos
|
||||
|
||||
:return: dict
|
||||
returns dict of all plugins + infos
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import is_dict_in_dict
|
||||
except ImportError:
|
||||
from utils import is_dict_in_dict
|
||||
|
||||
run_after = {}
|
||||
|
||||
for value in _BaseXMLReader(run_after_file).get_infos("<all>").values():
|
||||
for child in value:
|
||||
attrib = child["attrib"]
|
||||
parent_tag = child["parent"]["tag"]
|
||||
parent_attrib = child["parent"]["attrib"]
|
||||
if is_dict_in_dict({"type": "skill"}, parent_attrib):
|
||||
try:
|
||||
run_after[parent_tag][child["tag"]] = {"method": attrib["method"], "root_plugin": attrib["root_plugin"]}
|
||||
except KeyError:
|
||||
run_after[parent_tag] = {}
|
||||
else:
|
||||
for skill in run_after.values():
|
||||
for plugin in skill:
|
||||
if plugin == parent_tag:
|
||||
run_after[skill][plugin][child["tag"]] = child["text"]
|
||||
break
|
||||
|
||||
return run_after
|
||||
|
||||
|
||||
def get_all_run_before_plugins() -> dict:
|
||||
"""
|
||||
get all installed 'run_before' plugins + infos
|
||||
|
||||
:return: dict
|
||||
returns dict of all plugins + infos
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import is_dict_in_dict
|
||||
except ImportError:
|
||||
from utils import is_dict_in_dict
|
||||
|
||||
run_before = {}
|
||||
|
||||
for value in _BaseXMLReader(run_before_file).get_infos("<all>").values():
|
||||
for child in value:
|
||||
attrib = child["attrib"]
|
||||
parent_tag = child["parent"]["tag"]
|
||||
parent_attrib = child["parent"]["attrib"]
|
||||
if is_dict_in_dict({"type": "skill"}, parent_attrib):
|
||||
try:
|
||||
run_before[parent_tag][child["tag"]] = {"method": attrib["method"], "root_plugin": attrib["root_plugin"]}
|
||||
except KeyError:
|
||||
run_before[parent_tag] = {}
|
||||
else:
|
||||
for skill in run_before.values():
|
||||
for plugin in skill:
|
||||
if plugin == parent_tag:
|
||||
run_before[skill][plugin][child["tag"]] = child["text"]
|
||||
break
|
||||
|
||||
return run_before
|
||||
|
||||
|
||||
def get_run_after_plugin_infos(plugin_name: str) -> dict:
|
||||
"""
|
||||
returns infos about an given 'run_after' plugin
|
||||
|
||||
:param plugin_name: str
|
||||
the name of the 'run_after' plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_plugin"
|
||||
:return: dict
|
||||
returns a dictionary with infos of the 'run_after' plugin
|
||||
syntax: {"author": <author>,
|
||||
"main_file": <main file>,
|
||||
"plugin_root_name": <plugin root name>
|
||||
"plugin_name": <plugin name>,
|
||||
"plugin_method": <plugin method>
|
||||
"version": <version>,
|
||||
"additional_directories": [<additional directories>],
|
||||
"description": <description>,
|
||||
"language_locales": [<language locales>],
|
||||
"language_dict": {<entry>: <text>}
|
||||
"license": <license>,
|
||||
"required_python3_packages": [<python3 packages>]}
|
||||
example: {"author": "blueShard",
|
||||
"main_file": "test.py",
|
||||
"plugin_root_name:": "test_plugin"
|
||||
"plugin_name": "test_plugin_run_after",
|
||||
"plugin_method": "test_plugin_method"
|
||||
"version": "1.0.0",
|
||||
"additional_directories": ["test_directory"],
|
||||
"description": "A simple plugin to test the method 'get_run_after_plugin_infos",
|
||||
"language_locales": ["en_US"],
|
||||
"language_dict": {"test_method": "The test was successful"},
|
||||
"license": "MPL-2.0",
|
||||
"required_python3_packages": ["aionlib"]}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
for skill in get_all_run_after_plugins().values():
|
||||
for plugin, infos in skill.values():
|
||||
if plugin == plugin_name:
|
||||
return infos
|
||||
|
||||
|
||||
def get_run_before_plugin_infos(plugin_name: str) -> dict:
|
||||
"""
|
||||
returns infos about an given 'run_before' plugin
|
||||
|
||||
:param plugin_name: str
|
||||
the name of the 'run_after' plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_plugin"
|
||||
:return: dict
|
||||
returns a dictionary with infos of the 'run_after' plugin
|
||||
syntax: {"author": <author>,
|
||||
"main_file": <main file>,
|
||||
"plugin_root_name": <plugin root name>
|
||||
"plugin_name": <plugin name>,
|
||||
"plugin_method": <plugin method>
|
||||
"version": <version>,
|
||||
"additional_directories": [<additional directories>],
|
||||
"description": <description>,
|
||||
"language_locales": [<language locales>],
|
||||
"language_dict": {<entry>: <text>}
|
||||
"license": <license>,
|
||||
"required_python3_packages": [<python3 packages>]}
|
||||
example: {"author": "blueShard",
|
||||
"main_file": "test.py",
|
||||
"plugin_root_name:": "test_plugin"
|
||||
"plugin_name": "test_plugin_run_before",
|
||||
"plugin_method": "test_plugin_method"
|
||||
"version": "1.0.0",
|
||||
"additional_directories": ["test_directory"],
|
||||
"description": "A simple plugin to test the method 'get_run_before_plugin_infos",
|
||||
"language_locales": ["en_US"],
|
||||
"language_dict": {"test_method": "The test was successful"},
|
||||
"license": "MPL-2.0",
|
||||
"required_python3_packages": ["aionlib"]}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
for skill in get_all_run_before_plugins().values():
|
||||
for plugin, infos in skill.values():
|
||||
if plugin == plugin_name:
|
||||
return infos
|
||||
|
||||
|
||||
def remove_plugin(plugin_name: str, plugin_type: (RUN_AFTER, RUN_BEFORE)) -> None:
|
||||
"""
|
||||
removes given plugin
|
||||
|
||||
:param plugin_name: str
|
||||
name of the plugin you want to remove
|
||||
syntax: <plugin name>
|
||||
example: "test"
|
||||
:param plugin_type: (RUN_AFTER, RUN_BEFORE)
|
||||
type of the plugin
|
||||
syntax: <plugin type>
|
||||
example: RUN_AFTER
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .language import language_directory, delete_entry
|
||||
from .utils import BaseXMLReader, BaseXMLWriter
|
||||
except ImportError:
|
||||
from language import language_directory, delete_entry
|
||||
from utils import BaseXMLReader, BaseXMLWriter
|
||||
|
||||
from ast import literal_eval
|
||||
from os import remove as remove
|
||||
from shutil import rmtree
|
||||
|
||||
if plugin_type == RUN_AFTER:
|
||||
plugin_infos = get_run_after_plugin_infos(plugin_name)
|
||||
remove(run_after_path + "/" + plugin_infos["main_file"])
|
||||
for dir in plugin_infos["additional_directories"]:
|
||||
rmtree(run_after_path + "/" + dir)
|
||||
for language in plugin_infos["language_locales"]:
|
||||
delete_entry(language, plugin_name, entry_list=[key.replace(" ", "_") for key in literal_eval(plugin_infos["language_dict"])])
|
||||
remove_xml = BaseXMLWriter(run_after_file)
|
||||
remove_xml.remove(plugin_infos["method"], plugin_name)
|
||||
remove_xml.write()
|
||||
|
||||
|
||||
def _create_befater_plugin_file(type: (RUN_AFTER, RUN_BEFORE),
|
||||
author: str,
|
||||
plugin_name: str,
|
||||
main_file: str,
|
||||
skill: str,
|
||||
plugin_methods: dict,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_locales: list = [],
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a plugin can be installed
|
||||
|
||||
:param type: (RUN_AFTER, RUN_BEFORE)
|
||||
type of the plugin
|
||||
syntax: <plugin type>
|
||||
example: RUN_AFTER
|
||||
:param author: str
|
||||
name of the author from the plugin
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param main_file: str
|
||||
file name of file where all plugin methods are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param plugin_name: str
|
||||
root name of the plugin you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param skill: str
|
||||
name of the skill you want to add the 'run_before' plugin
|
||||
syntax: <skill name>
|
||||
example: "Play"
|
||||
NOTE: be case-sensitive!
|
||||
:param plugin_methods: dict
|
||||
dictionary of plugin pseudonym with plugin method you want to add to given 'skill'
|
||||
syntax: {"<plugin pseudonym>": <plugin methods>}
|
||||
example: ["test_plugin_run_test_2": "TestPlugin"]
|
||||
NOTE: be case-sensitive!
|
||||
NOTE2: the plugins pseudonyms are only pseudonyms for the given methods
|
||||
NOTE3: you can't remove individual plugins via the 'aion' command line command
|
||||
:param version: str
|
||||
version (number) of your plugin
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your plugin
|
||||
syntax: <description>
|
||||
example: "A simple plugin to test the method 'create_run_after_plugin_file'"
|
||||
:param language_locales: list
|
||||
list of language locales for which the 'language_dict' should be stored
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the plugin
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your plugin needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import plugin_author_must_be_str, plugin_plugin_name_must_be_str, plugin_main_file_must_be_str, plugin_main_file_not_found, plugin_main_file_name_must_be_plugin_name,\
|
||||
plugin_skill_must_be_dict, plugin_plugin_methods_must_be_dict, plugin_version_must_be_str, plugin_additional_directories_must_be_list_or_tuple,\
|
||||
plugin_couldnt_find_additional_directories_directory, plugin_description_must_be_str, plugin_language_locales_must_be_list_or_tuple, plugin_language_dict_must_be_dict,\
|
||||
plugin_language_dict_character_must_be_in_alphabet, plugin_license_must_be_str, plugin_required_python3_package_must_be_list_or_tuple
|
||||
except ImportError:
|
||||
from _error_codes import plugin_author_must_be_str, plugin_plugin_name_must_be_str, plugin_main_file_must_be_str, plugin_main_file_not_found, plugin_main_file_name_must_be_plugin_name,\
|
||||
plugin_skill_must_be_dict, plugin_plugin_methods_must_be_dict, plugin_version_must_be_str, plugin_additional_directories_must_be_list_or_tuple,\
|
||||
plugin_couldnt_find_additional_directories_directory, plugin_description_must_be_str, plugin_language_locales_must_be_list_or_tuple, plugin_language_dict_must_be_dict,\
|
||||
plugin_language_dict_character_must_be_in_alphabet, plugin_license_must_be_str, plugin_required_python3_package_must_be_list_or_tuple
|
||||
|
||||
from os import getcwd, listdir
|
||||
|
||||
write_dict = {}
|
||||
|
||||
if isinstance(author, str) is False:
|
||||
raise TypeError("Errno: " + plugin_author_must_be_str + " - Argument 'author' must be str, got " + type(author).__name__)
|
||||
write_dict["author"] = author
|
||||
|
||||
if isinstance(plugin_name, str) is False:
|
||||
raise TypeError("Errno: " + plugin_plugin_name_must_be_str + " - Argument 'plugin_name' must be str, got " + type(plugin_name).__name__)
|
||||
write_dict["plugin_name"] = plugin_name
|
||||
|
||||
if isinstance(main_file, str) is False:
|
||||
raise TypeError("Errno: " + plugin_main_file_must_be_str + " - argument 'main_file' must be str, got " + type(author).__name__)
|
||||
if main_file not in listdir(getcwd()):
|
||||
raise FileNotFoundError("Errno: " + plugin_main_file_not_found + " - Couldn't find the file " + main_file + " in current directory")
|
||||
if main_file[:-3] == plugin_name is False:
|
||||
raise NameError("Errno: " + plugin_main_file_name_must_be_plugin_name + " - The file name from " + main_file + " must be same as the argument 'plugin_name' (" + plugin_name + ")")
|
||||
write_dict["main_file"] = main_file
|
||||
|
||||
if isinstance(skill, str) is False:
|
||||
raise TypeError("Errno: " + plugin_skill_must_be_dict + " - Argument 'skill' must be dict, got " + type(plugin_methods).__name__)
|
||||
write_dict["skill"] = skill
|
||||
|
||||
if isinstance(plugin_methods, dict) is False:
|
||||
raise TypeError("Errno: " + plugin_plugin_methods_must_be_dict + " - Argument 'plugin_methods' must be dict, got " + type(plugin_methods).__name__)
|
||||
write_dict["plugin_methods"] = plugin_methods
|
||||
|
||||
if isinstance(version, str) is False:
|
||||
raise TypeError("Errno: " + plugin_version_must_be_str + " - Argument 'version' must be str, got " + type(version).__name__)
|
||||
write_dict["version"] = version
|
||||
|
||||
# ----- #
|
||||
|
||||
if isinstance(additional_directories, (list, tuple)) is False:
|
||||
raise TypeError("Errno: " + plugin_additional_directories_must_be_list_or_tuple + " - Argument 'additional_directories' must be list or tuple, got " + type(additional_directories).__name__)
|
||||
for directory in additional_directories:
|
||||
if directory not in listdir(getcwd()):
|
||||
raise NotADirectoryError("Errno: " + plugin_couldnt_find_additional_directories_directory + " - Couldn't find the directory " + directory + " in current directory")
|
||||
write_dict["additional_directories"] = additional_directories
|
||||
|
||||
if isinstance(description, str) is False:
|
||||
raise TypeError("Errno: " + plugin_description_must_be_str+ " - Argument 'description' must be str, got " + type(description).__name__)
|
||||
write_dict["description"] = description
|
||||
|
||||
if isinstance(language_locales, (list, tuple)) is False:
|
||||
raise TypeError("Errno: " + plugin_language_locales_must_be_list_or_tuple + " - Argument 'language_locales' must be list or tuple, got " + type(language_locales).__name__)
|
||||
write_dict["language_locales"] = language_locales
|
||||
|
||||
if isinstance(language_dict, dict) is False:
|
||||
raise TypeError("Errno: " + plugin_language_locales_must_be_list_or_tuple + " - Argument 'language_dict' must be dict, got " + type(language_dict).__name__)
|
||||
for key in language_dict.keys():
|
||||
tmp_string = ""
|
||||
for char in key:
|
||||
if char == " ":
|
||||
char = "_"
|
||||
if char.lower() not in "abcdefghijklmnopqrstuvwxyz_":
|
||||
raise ValueError("Errno: " + plugin_language_dict_character_must_be_in_alphabet + " - Letter " + str(char) + " in " + str(key) + " must be in 'ABCDEFGHIJLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz_'")
|
||||
tmp_string = tmp_string + char
|
||||
language_dict[tmp_string] = language_dict.pop(key)
|
||||
write_dict["language_dict"] = language_dict
|
||||
|
||||
if isinstance(license, str) is False:
|
||||
raise TypeError("Errno: " + plugin_license_must_be_str + " - Argument 'license' must be str, got " + type(license).__name__)
|
||||
write_dict["license"] = license
|
||||
|
||||
if isinstance(required_python3_packages, (list, tuple)) is False:
|
||||
raise TypeError("Errno: " + plugin_required_python3_package_must_be_list_or_tuple + " - Argument 'required_python3_packages' must be list or tuple, got " + type(required_python3_packages).__name__)
|
||||
write_dict["required_python3_packages"] = required_python3_packages
|
||||
|
||||
# ----- #
|
||||
|
||||
with open("plugin.aion", "w") as file:
|
||||
file.write("#type: " + type.lower() + "_plugin\n")
|
||||
for key, value in write_dict.items():
|
||||
file.write(key + " = " + str(value) + "\n")
|
||||
file.close()
|
||||
|
||||
|
||||
def _run_befater_plugin(type: (RUN_AFTER, RUN_BEFORE), fname: str, plugin_name: str, activate_phrase: str, speech_input: str) -> None:
|
||||
"""
|
||||
runs a plugin
|
||||
|
||||
:param type: (RUN_AFTER, RUN_BEFORE)
|
||||
type of the plugin
|
||||
syntax: <plugin type>
|
||||
example: RUN_AFTER
|
||||
:param fname: str
|
||||
file path of the plugin file
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test.py"
|
||||
:param plugin_name: str
|
||||
name of the plugin
|
||||
syntax: <plugin name>
|
||||
example: "TestPlugin"
|
||||
:param activate_phrase: str
|
||||
activate phrase, which calls the skill class to which the plugin belongs
|
||||
syntax: <activate phrase>
|
||||
example: "Start test plugin"
|
||||
:param speech_input: str
|
||||
speech input, which calls the skill class to which the plugin belongs
|
||||
syntax: <speech input>
|
||||
example: "Start test plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from sys import path
|
||||
path.insert(1, _aion_data_path + "/" + type.lower())
|
||||
exec("__import__('" + fname + "')." + plugin_name + "(" + activate_phrase + ", " + speech_input + ").main()")
|
91
aion-0.1.0_alpha/aion_core/save.py
Normal file
91
aion-0.1.0_alpha/aion_core/save.py
Normal file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
try:
|
||||
from .utils import aion_data_path as _aion_data_path
|
||||
except ImportError:
|
||||
from utils import aion_data_path as _aion_data_path
|
||||
|
||||
|
||||
save_path = _aion_data_path + "/saves"
|
||||
|
||||
|
||||
def load_save(name: str, current_save_name: str = None) -> None:
|
||||
"""
|
||||
loads a saved aion_data
|
||||
|
||||
:param name: str
|
||||
name of the new aion_data save
|
||||
syntax: "<name>"
|
||||
example: "test save"
|
||||
:param current_save_name: str, optional
|
||||
if not None, the current aion_data get saved under this name
|
||||
syntax: "<current save name>"
|
||||
example: "test save2"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import save_save_not_found
|
||||
except ImportError:
|
||||
from _error_codes import save_save_not_found
|
||||
|
||||
from os import listdir
|
||||
from shutil import copytree, rmtree
|
||||
|
||||
if name not in listdir(save_path):
|
||||
raise NotADirectoryError("Errno: " + save_save_not_found + " - Couldn't find the save '" + name + "'")
|
||||
else:
|
||||
if current_save_name:
|
||||
save(current_save_name)
|
||||
rmtree(_aion_data_path)
|
||||
copytree(save_path + "/" + name, _aion_data_path)
|
||||
|
||||
|
||||
def save(name: str) -> None:
|
||||
"""
|
||||
saves the current aion_data directory
|
||||
|
||||
:param name: str
|
||||
name of the save
|
||||
syntax: "<name>"
|
||||
example: "test save"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import save_save_name_already_exist
|
||||
from .utils import BaseXMLWriter
|
||||
except ImportError:
|
||||
from _error_codes import save_save_name_already_exist
|
||||
from utils import BaseXMLWriter
|
||||
|
||||
from os import listdir
|
||||
from shutil import copytree
|
||||
|
||||
if name in listdir(save_path):
|
||||
raise NameError("Errno: " + save_save_name_already_exist + " - The save name '" + name + "' already exists")
|
||||
else:
|
||||
copytree(_aion_data_path, save_path + "/" + name)
|
||||
|
||||
|
||||
def saves() -> list:
|
||||
"""
|
||||
get all aion_data saves
|
||||
|
||||
:return: list
|
||||
returns a list of the names of the aion_data saves
|
||||
syntax: [<saves>]
|
||||
example: ["test save", "test save2"]
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import listdir
|
||||
|
||||
return_list = []
|
||||
|
||||
for file in listdir(save_path):
|
||||
return_list.append(file)
|
||||
|
||||
return return_list
|
BIN
aion-0.1.0_alpha/aion_core/shell/Aion_Logo.ico
Normal file
BIN
aion-0.1.0_alpha/aion_core/shell/Aion_Logo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
228
aion-0.1.0_alpha/aion_core/shell/shell.py
Normal file
228
aion-0.1.0_alpha/aion_core/shell/shell.py
Normal file
@ -0,0 +1,228 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from shell_utils import *
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, "..")
|
||||
|
||||
|
||||
help = """
|
||||
Usage:
|
||||
aion [command]
|
||||
|
||||
Commands:
|
||||
start starts aion
|
||||
run runs aion
|
||||
|
||||
install <skill / plugin> installs a skill or plugin
|
||||
uninstall <skill / plugin> uninstalls a skill or plugin
|
||||
remove <skill / plugin> removes a skill or plugin
|
||||
update <skill / plugin> updates a skill or plugin
|
||||
version <skill / plugin> version of a skill or plugin
|
||||
|
||||
save <name> saves the current aion_data directory (with a name)
|
||||
load <version> [name] loads a saved aion_data directory (add optional name to save the current aion_data directory with this name)
|
||||
saves shows all saved aion_data directory
|
||||
|
||||
pid shows the pid from the running aion process
|
||||
kill kills aion
|
||||
stop stops aion
|
||||
|
||||
pack <custom skill / plugin directory> packs the given directory with a custom skill or plugin into one standalone file for installation
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
from argparse import ArgumentParser, RawTextHelpFormatter
|
||||
import os
|
||||
|
||||
parser = ArgumentParser(description="Command line support for the 'aion' project", formatter_class=RawTextHelpFormatter, add_help=False)
|
||||
|
||||
parser.add_argument("command", nargs="+")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
command = args.command[0].strip()
|
||||
|
||||
if os.path.isfile(command):
|
||||
import __init__
|
||||
__init__.ExecuteAionFile(command)
|
||||
|
||||
elif command == "help" or command == "-help" or command == "--help":
|
||||
print(help)
|
||||
|
||||
elif command == "start" or command == "run":
|
||||
os.system("python3 " + atils.aion_path + "/main.py")
|
||||
|
||||
elif command == "install":
|
||||
errno = "77227"
|
||||
arglen_check(args.command, 2)
|
||||
package = args.command[1]
|
||||
if package == "aion":
|
||||
must_be_sudo()
|
||||
Install.aion()
|
||||
print("Installed aion")
|
||||
elif package == "respeaker":
|
||||
must_be_sudo()
|
||||
Install.respeaker(yesno("Install in compatibility mode? (installs older kernel version)? (y/n): "))
|
||||
print("Installed respeaker")
|
||||
elif os.path.exists(package):
|
||||
if package.strip() == "skill.aion":
|
||||
Install.skill_from_aion_file(package)
|
||||
elif package.strip() == "plugin.aion":
|
||||
Install.plugin_from_aion_file(package)
|
||||
elif package.endswith(".skill"):
|
||||
Install.skill_from_skill_file(package)
|
||||
elif package.endswith(".plugin"):
|
||||
Install.plugin_from_plugin_file(package)
|
||||
else:
|
||||
AionShellError(package + " is an unknowing skill / plugin. Type 'aion help' for help", errno)
|
||||
else:
|
||||
AionShellError(package + " is an unknowing skill / plugin. Type 'aion help' for help", errno)
|
||||
|
||||
elif args.command in ["kill", "stop"]: # kist
|
||||
arglen_check(args.command, 1)
|
||||
is_aion_running(command)
|
||||
import variable
|
||||
import signal
|
||||
avar = variable.Variable()
|
||||
os.kill(int(avar.get_value("AION_PID")), signal.SIGKILL)
|
||||
|
||||
elif command == "load":
|
||||
arglen_check(args.command, 2, 3)
|
||||
import save as asave
|
||||
if len(args.command) == 3:
|
||||
asave.load_save(str(args.command[1]), str(args.command[2]))
|
||||
else:
|
||||
asave.load_save(str(args.command[1]))
|
||||
|
||||
elif command == "pack":
|
||||
no_skill_plugin_file_errno = "27177"
|
||||
no_dir_errno = "27178"
|
||||
arglen_check(args.command, 2)
|
||||
dir = args.command[1]
|
||||
if os.path.isdir(dir):
|
||||
if os.path.isfile(dir + "/skill.aion"):
|
||||
Pack.skill(dir)
|
||||
elif os.path.isfile(dir + "/plugin.aion"):
|
||||
Pack.plugin(dir)
|
||||
else:
|
||||
AionShellError("couldn't find 'skill.aion' or 'plugin.aion' in " + dir + ". See 'create_skill_file' function in 'aionlib.skill' to create a 'skill.aion' file"
|
||||
"or 'create_plugin_file' function in 'aionlib.plugin' to create a 'plugin.aion' file", no_skill_plugin_file_errno)
|
||||
else:
|
||||
AionShellError("couldn't find directory " + dir, no_dir_errno)
|
||||
|
||||
elif command == "pid":
|
||||
arglen_check(args.command, 1)
|
||||
is_aion_running(command)
|
||||
import variable
|
||||
avar = variable.Variable()
|
||||
print(avar.get_value("AION_PID"))
|
||||
|
||||
elif command == "save":
|
||||
arglen_check(args.command, 2)
|
||||
import save as asave
|
||||
asave.save(args.command[1])
|
||||
|
||||
elif command == "saves":
|
||||
arglen_check(args.command, 1)
|
||||
import save as asave
|
||||
print(" ".join(asave.saves()))
|
||||
|
||||
elif command in ["remove", "uninstall"]: # UnRem
|
||||
errno = "07340"
|
||||
arglen_check(args.command, 2)
|
||||
package = args.command[1]
|
||||
if command == "uninstall":
|
||||
name = "Uninstall"
|
||||
else:
|
||||
name = "Remove"
|
||||
question = yesno(name + " " + package + "? (y/n): ")
|
||||
if package == "aion":
|
||||
if question is True:
|
||||
question = yesno("Should your personal data ('/etc/aion_data/': custom skills / plugins, version saves, language files, ...) deleted as well? (y/n): ")
|
||||
UnRem.aion(question)
|
||||
print(name + "ed aion")
|
||||
print("You should reboot now to complete the " + name.lower() + " process")
|
||||
elif package == "aionlib":
|
||||
if question is True:
|
||||
UnRem.aionlib()
|
||||
print(name + "ed aionlib")
|
||||
elif package == "respeaker":
|
||||
if question is True:
|
||||
UnRem.respeaker()
|
||||
print(name + "ed respeaker")
|
||||
else:
|
||||
package_type = which_package(package, "Type in the number of your package type: ")
|
||||
if package_type == -1:
|
||||
AionShellError("couldn't find skill / plugin " + package, errno)
|
||||
elif package_type == 0:
|
||||
UnRem.skill(package)
|
||||
elif package_type == 1:
|
||||
UnRem.run_after_plugin(package)
|
||||
elif package_type == 2:
|
||||
UnRem.run_before_plugin(package)
|
||||
|
||||
elif command in ["run", "start"]:
|
||||
arglen_check(args.command, 1)
|
||||
import start
|
||||
from os import geteuid
|
||||
if geteuid() == 0:
|
||||
start(True)
|
||||
elif geteuid() == 1000:
|
||||
start(False)
|
||||
|
||||
elif command == "update":
|
||||
errno = "43503"
|
||||
arglen_check(args.command, 2)
|
||||
package = args.command[1]
|
||||
if package == "aion":
|
||||
Update.aion()
|
||||
elif package == "aionlib":
|
||||
Update.aionlib()
|
||||
else:
|
||||
package_type = which_package(package, "Type in the number of your package type: ")
|
||||
if package_type == -1:
|
||||
AionShellError("couldn't find skill / plugin " + package, errno)
|
||||
elif package_type == 0:
|
||||
Update.skill(package)
|
||||
elif package_type == 1:
|
||||
Update.run_after_plugin(package)
|
||||
elif package_type == 2:
|
||||
Update.run_before_plugin(package)
|
||||
|
||||
elif command == "variable":
|
||||
arglen_check(args.command, 2)
|
||||
command_variable = args.command[1]
|
||||
import variable
|
||||
avar = variable.Variable()
|
||||
print(avar.get_value(command_variable))
|
||||
|
||||
elif command == "version":
|
||||
errno = "56297"
|
||||
arglen_check(args.command, 2)
|
||||
package = args.command[1]
|
||||
if package == "aion":
|
||||
Version.aion()
|
||||
elif package == "aionlib":
|
||||
Version.aionlib()
|
||||
else:
|
||||
package_type = which_package(package, "Type in the number of your package type: ")
|
||||
if package_type == -1:
|
||||
AionShellError("couldn't find skill / plugin " + package, errno)
|
||||
elif package_type == 0:
|
||||
Version.skill(package)
|
||||
elif package_type == 1:
|
||||
Version.run_after_plugin(package)
|
||||
elif package_type == 2:
|
||||
Version.run_before_plugin(package)
|
||||
|
||||
else:
|
||||
errno = "12345"
|
||||
AionShellError(" ".join(args.command) + " isn't a command. Type 'aion help' to get help", errno)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
exit(-1)
|
612
aion-0.1.0_alpha/aion_core/shell/shell_utils.py
Normal file
612
aion-0.1.0_alpha/aion_core/shell/shell_utils.py
Normal file
@ -0,0 +1,612 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
from glob import glob
|
||||
|
||||
sys.path.insert(1, glob("/usr/local/aion-*/aion_core/")[0])
|
||||
|
||||
import utils as atils
|
||||
|
||||
|
||||
class AionShellError:
|
||||
"""
|
||||
base class for errors while using the 'aion' shell command (for the exact identification of the error)
|
||||
"""
|
||||
|
||||
def __init__(self, errormsg: str, errno: str = "00000") -> None:
|
||||
"""
|
||||
the error 'function'
|
||||
|
||||
:param errormsg: str
|
||||
message that should be printed out
|
||||
syntax: <error message>
|
||||
example: "An example error occured"
|
||||
:param errno: str
|
||||
error number
|
||||
syntax: <error number>
|
||||
example: "11112"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
|
||||
print(Fore.RED + "AionShellError: [Errno " + str(errno) + "]: " + str(errormsg) + Fore.RESET)
|
||||
|
||||
|
||||
def arglen_check(arg_list: list, arg_len: int, max_arg_len: int = None) -> None:
|
||||
"""
|
||||
checks if the length of a list is equal to a given length
|
||||
|
||||
:param arg_list: list
|
||||
list you want to check if the length is equal to the given length
|
||||
syntax: [<list content>]
|
||||
example: ["example1", "example2"]
|
||||
:param arg_len: int
|
||||
length you want to check
|
||||
syntax: <length>
|
||||
example: 2
|
||||
:param max_arg_len: int
|
||||
if not None, it checks if the arg list length is between 'arg_len' and 'max_arg_len
|
||||
syntax: <max length>
|
||||
example: 4
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if max_arg_len is None:
|
||||
max_arg_len = arg_len
|
||||
if len(arg_list) < arg_len or len(arg_list) > max_arg_len:
|
||||
from colorama import Fore
|
||||
if arg_len == max_arg_len:
|
||||
if arg_len == 1:
|
||||
print(Fore.RED + "Expected 1 argument, got " + str(len(arg_list)) + " (" + ", ".join(arg_list) + "). Type 'aion help' for help" + Fore.RESET)
|
||||
else:
|
||||
print(Fore.RED + "Expected " + str(arg_len) + " arguments, got " + str(len(arg_list)) + " (" + ", ".join(arg_list) + "). Type 'aion help' for help" + Fore.RESET)
|
||||
else:
|
||||
print(Fore.RED + "Expected " + str(arg_len) + " to " + str(max_arg_len) + " arguments, got " + str(len(arg_list)) + " (" + ", ".join(arg_list) + "). Type 'aion help' for help" + Fore.RESET)
|
||||
exit(-1)
|
||||
|
||||
|
||||
def which_package(package: str, input_sentence: str) -> int:
|
||||
"""
|
||||
if a user want to uninstall (or something else) a skill or plugin and there are more than one plugin / skill with this name, this function get called
|
||||
|
||||
:param package: str
|
||||
name of the package
|
||||
syntax: <package name>
|
||||
example: "test_package
|
||||
|
||||
:param input_sentence: str
|
||||
sentence the user should be asked for input
|
||||
syntax: <input sentence>
|
||||
example: "Type in the number of your package type: "
|
||||
:return: int
|
||||
returns the type of the package (0 = skill; 1 = run after plugin; 2 = run before plugin)
|
||||
syntax: <package type>
|
||||
example: 2
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from plugin import get_all_run_after_plugins, get_all_run_before_plugins
|
||||
from skill import get_all_skills
|
||||
|
||||
in_package = []
|
||||
|
||||
if package in get_all_skills():
|
||||
in_package.append("Skill: " + str(len(in_package)))
|
||||
else:
|
||||
for plugin in get_all_run_after_plugins().values():
|
||||
if package in plugin:
|
||||
in_package.append("Run after plugin: " + str(len(in_package)))
|
||||
|
||||
for plugin in get_all_run_before_plugins().values():
|
||||
if package in plugin:
|
||||
in_package.append("Run before plugin: " + str(len(in_package)))
|
||||
|
||||
if len(in_package) == 0:
|
||||
return -1
|
||||
elif len(in_package) == 1:
|
||||
choose = 0
|
||||
else:
|
||||
for pa in in_package:
|
||||
print(pa)
|
||||
print("Found package '" + str(package) + "' multiple times")
|
||||
while True:
|
||||
input_choose = input(input_sentence)
|
||||
if str(input_choose) not in [str(l) for l in range(len(in_package))]:
|
||||
print("Your number must be in " + ", ".join([str(l) for l in range(len(in_package))]))
|
||||
else:
|
||||
choose = input_choose
|
||||
break
|
||||
|
||||
if in_package[choose].startswith("Skill"):
|
||||
return 0
|
||||
elif in_package[choose].startswith("Run after"):
|
||||
return 1
|
||||
elif in_package[choose].startswith("Run before"):
|
||||
return 2
|
||||
|
||||
|
||||
def is_aion_running(command: str) -> None:
|
||||
"""
|
||||
checks if aion is running
|
||||
|
||||
:param command: str
|
||||
command that the user has typed in
|
||||
syntax: <command>
|
||||
example: "pid"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
import variable
|
||||
from ast import literal_eval
|
||||
from colorama import Fore
|
||||
if literal_eval(variable.Variable().get_value(variable.IS_AION_RUNNING)) is False:
|
||||
print(Fore.RED + command + " can only used if aion is running. Type 'aion run' or 'aion start' to start aion" + Fore.RESET)
|
||||
exit(-1)
|
||||
|
||||
|
||||
def must_be_sudo() -> None:
|
||||
"""
|
||||
checks if the user is root and if not it prints an warning message
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
if atils.is_root() is False:
|
||||
print(Fore.RED + "to execute the command, aion must be run as sudo" + Fore.RESET)
|
||||
exit(-1)
|
||||
|
||||
|
||||
def yesno(question: str) -> bool:
|
||||
"""
|
||||
asks a yes no question
|
||||
|
||||
:param question: str
|
||||
question you want to ask
|
||||
syntax: <question>
|
||||
example: "Execute test command? (y/n): "
|
||||
:return: bool
|
||||
returns if the user entered y / yes (True) or n / no (False)
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
while True:
|
||||
yn = input(question)
|
||||
if yn.lower().strip() == "y" or yn.lower().strip() == "yes":
|
||||
return True
|
||||
elif yn.lower().strip() == "n" or yn.lower().strip() == "no":
|
||||
return False
|
||||
else:
|
||||
print("Please choose 'y' or 'n'")
|
||||
|
||||
|
||||
class Install:
|
||||
|
||||
"""
|
||||
base class for installation
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def aion() -> None:
|
||||
"""
|
||||
installs aion
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from os import system
|
||||
from shutil import rmtree
|
||||
system("git clone https://github.com/blueShard/aion_project /tmp/aion_project")
|
||||
system("bash /tmp/aion_project/install.sh")
|
||||
rmtree("/tmp/aion_project", ignore_errors=True)
|
||||
|
||||
@staticmethod
|
||||
def plugin_from_aion_file(fname: str) -> None:
|
||||
"""
|
||||
installs a plugin from a 'plugin.aion' file
|
||||
|
||||
:param fname: str
|
||||
path of the file
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_plugin/plugin.aion"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from plugin import execute_aion_file_type_plugin
|
||||
execute_aion_file_type_plugin(fname)
|
||||
|
||||
@staticmethod
|
||||
def plugin_from_plugin_file(fname: str) -> None:
|
||||
"""
|
||||
installs a plugin from a '.plugin' package
|
||||
|
||||
:param fname: str
|
||||
path of the file
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_plugin/test.plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from plugin import execute_plugin_file
|
||||
execute_plugin_file(fname)
|
||||
|
||||
@staticmethod
|
||||
def skill_from_aion_file(fname: str) -> None:
|
||||
"""
|
||||
installs a skill from a 'skill.aion' file
|
||||
|
||||
:param fname: str
|
||||
path of the file
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_skill/skill.aion"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from skill import execute_aion_file_type_skill
|
||||
execute_aion_file_type_skill(fname)
|
||||
|
||||
@staticmethod
|
||||
def skill_from_skill_file(fname: str) -> None:
|
||||
"""
|
||||
installs a skill from a '.skill' package
|
||||
|
||||
:param fname: str
|
||||
path of the file
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_skill/test.skill"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from skill import execute_skill_file
|
||||
execute_skill_file(fname)
|
||||
|
||||
@staticmethod
|
||||
def respeaker(compatibility_mode: bool = False) -> None:
|
||||
"""
|
||||
installs respeaker
|
||||
|
||||
:param compatibility_mode:
|
||||
installs an old kernel version which is definitely compatible with respeaker
|
||||
(the current version may contain patches etc. which make respeaker not work properly anymore and to which the developers of respeaker have to adapt the software first)
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from os import system
|
||||
from shutil import copy, rmtree
|
||||
system("git clone https://github.com/respeaker/seeed-voicecard.git /tmp/seeed-voicecard")
|
||||
copy("/tmp/seeed-voicecard/uninstall.sh", atils.aion_path + "/etc/respeaker_uninstall.sh")
|
||||
if compatibility_mode:
|
||||
system("cd /tmp/seeed-voicecard/; ./install.sh --compat-kernel")
|
||||
else:
|
||||
system("cd /tmp/seeed-voicecard/; ./install.sh")
|
||||
system("amixer cset numid=3 2")
|
||||
rmtree("/tmp/seeed-voicecard", ignore_errors=True)
|
||||
|
||||
|
||||
class Pack:
|
||||
|
||||
"""
|
||||
base class for packing plugin or skill directories to '.plugin' or '.skill' packages
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def skill(directory: str) -> None:
|
||||
"""
|
||||
creates a skill package from given directory
|
||||
|
||||
:param directory: str
|
||||
path of the directory
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_skill.skill"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from skill import create_skill_package
|
||||
|
||||
create_skill_package(directory)
|
||||
|
||||
@staticmethod
|
||||
def plugin(directory: str) -> None:
|
||||
"""
|
||||
creates a plugin package from given directory
|
||||
|
||||
:param directory: str
|
||||
path of the directory
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test_plugin.plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from plugin import create_plugin_package
|
||||
|
||||
create_plugin_package(directory)
|
||||
|
||||
|
||||
class UnRem: # this class name combine the word uninstall and remove
|
||||
|
||||
@staticmethod
|
||||
def aion(personal_data: bool = False) -> None:
|
||||
"""
|
||||
deletes aion
|
||||
|
||||
:param personal_data: bool
|
||||
checks if all personal data should be deleted as well
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from glob import glob
|
||||
from os import system
|
||||
if personal_data is True:
|
||||
system("bash " + glob("/usr/local/aion-*/etc/uninstall.sh")[0] + " --all")
|
||||
else:
|
||||
system("bash " + glob("/usr/local/aion-*/etc/uninstall.sh")[0])
|
||||
|
||||
@staticmethod
|
||||
def aionlib() -> None:
|
||||
"""
|
||||
uninstalls aionlib
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from os import system
|
||||
system("yes | pip3 uninstall aionlib")
|
||||
|
||||
@staticmethod
|
||||
def run_after_plugin(name: str) -> None:
|
||||
"""
|
||||
uninstalls a run after plugin
|
||||
|
||||
:param name: str
|
||||
name of the run after plugin
|
||||
syntax: <run after plugin>
|
||||
example: "test_run_after_plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from plugin import RUN_AFTER, remove_plugin
|
||||
remove_plugin(name, RUN_AFTER)
|
||||
|
||||
@staticmethod
|
||||
def run_before_plugin(name: str) -> None:
|
||||
"""
|
||||
uninstalls a run before plugin
|
||||
|
||||
:param name: str
|
||||
name of the run before plugin
|
||||
syntax: <run before plugin>
|
||||
example: "test_run_before_plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from plugin import RUN_BEFORE, remove_plugin
|
||||
remove_plugin(name, RUN_BEFORE)
|
||||
|
||||
@staticmethod
|
||||
def skill(name: str) -> None:
|
||||
"""
|
||||
uninstalls a skill
|
||||
|
||||
:param name: str
|
||||
name of the skill
|
||||
syntax: <skill>
|
||||
example: "test_skill"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from skill import remove_skill
|
||||
remove_skill(name)
|
||||
|
||||
@staticmethod
|
||||
def respeaker() -> None:
|
||||
"""
|
||||
uninstalls respeaker (if installed)
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from os import path, system
|
||||
if path.isfile(atils.aion_path + "/etc/respeaker_uninstall.sh") is False:
|
||||
raise FileNotFoundError("can't find file '" + atils.aion_path + "/etc/respeaker_uninstall.sh' to uninstall respeaker")
|
||||
else:
|
||||
system("bash " + atils.aion_path + "/etc/respeaker_uninstall.sh")
|
||||
|
||||
|
||||
class Update:
|
||||
|
||||
@staticmethod
|
||||
def aion() -> None:
|
||||
"""
|
||||
updates aion
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
print(Fore.RED + "The update command for aion isn't created yet" + Fore.RESET)
|
||||
|
||||
@staticmethod
|
||||
def aionlib() -> None:
|
||||
"""
|
||||
updates aionlib
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
must_be_sudo()
|
||||
from os import system
|
||||
system("yes | pip3 install --upgrade aionlib")
|
||||
|
||||
@staticmethod
|
||||
def run_after_plugin(name: str) -> None:
|
||||
"""
|
||||
updates a run after plugin
|
||||
|
||||
:param name: str
|
||||
name of the plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_run_after_plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
print(Fore.RED + "The update command for 'run_after_plugin' isn't created yet")
|
||||
|
||||
@staticmethod
|
||||
def run_before_plugin(name: str) -> None:
|
||||
"""
|
||||
updates a run before plugin
|
||||
|
||||
:param name: str
|
||||
name of the run before plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_run_before_plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
print(Fore.RED + "The update command for 'run_before_plugin' isn't created yet")
|
||||
|
||||
@staticmethod
|
||||
def skill(name: str) -> None:
|
||||
"""
|
||||
updates a skill
|
||||
|
||||
:param name: str
|
||||
name if the skill
|
||||
syntax: <skill name>
|
||||
example: "test_skill"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
print(Fore.RED + "The update command for 'skill' isn't created yet")
|
||||
|
||||
|
||||
class Version:
|
||||
|
||||
@staticmethod
|
||||
def aion() -> None:
|
||||
"""
|
||||
prints the version of 'aion'
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from glob import glob
|
||||
print("".join(glob("/usr/local/aion-*").remove("/usr/local/aion-")))
|
||||
|
||||
@staticmethod
|
||||
def aionlib() -> None:
|
||||
"""
|
||||
prints the version of aionlib (if installed)
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from aionlib import __version__ as aionlib_version
|
||||
print(aionlib_version)
|
||||
except ImportError:
|
||||
print("'aionlib' isn't installed. To install aionlib, type 'sudo pip3 install aionlib'")
|
||||
|
||||
@staticmethod
|
||||
def run_after_plugin(name: str) -> None:
|
||||
"""
|
||||
prints the version of a run after plugin
|
||||
|
||||
:param name: str
|
||||
name of the plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_run_after_plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from plugin import get_run_after_plugin_infos
|
||||
for key, item in get_run_after_plugin_infos(name):
|
||||
if key == "version":
|
||||
print(item)
|
||||
break
|
||||
|
||||
@staticmethod
|
||||
def run_before_plugin(name: str) -> None:
|
||||
"""
|
||||
prints the version of a run before plugin
|
||||
|
||||
:param name: str
|
||||
name of the plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_run_before_plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from plugin import get_run_before_plugin_infos
|
||||
for key, item in get_run_before_plugin_infos(name):
|
||||
if key == "version":
|
||||
print(item)
|
||||
break
|
||||
|
||||
@staticmethod
|
||||
def skill(name: str) -> None:
|
||||
"""
|
||||
prints the version of a skill
|
||||
|
||||
:param name: str
|
||||
name of the skill
|
||||
syntax: <plugin name>
|
||||
example: "test_skill"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from skill import get_skill_infos
|
||||
for key, item in get_skill_infos(name):
|
||||
if key == "version":
|
||||
print(item)
|
||||
break
|
585
aion-0.1.0_alpha/aion_core/skill.py
Normal file
585
aion-0.1.0_alpha/aion_core/skill.py
Normal file
@ -0,0 +1,585 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
try:
|
||||
from .utils import aion_data_path as _aion_data_path
|
||||
except ImportError:
|
||||
from utils import aion_data_path as _aion_data_path
|
||||
|
||||
|
||||
skills_path = _aion_data_path + "/skills"
|
||||
skills_file = skills_path + "/skills.xml"
|
||||
|
||||
|
||||
class Skill:
|
||||
"""
|
||||
base class for use custom skills
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, activate_phrase: str, speech_input: str, run_after_plugins: dict, run_before_plugins: dict) -> None:
|
||||
"""
|
||||
:param activate_phrase: str
|
||||
activate phrase that called this class
|
||||
syntax: "<activate phrase>"
|
||||
example: "test"
|
||||
:param speech_input: str
|
||||
complete spoken words
|
||||
syntax: "<speech input>"
|
||||
example: "Start the test"
|
||||
:param run_after_plugins: dict
|
||||
all run after plugins
|
||||
:param run_before_plugins: dict
|
||||
all run before plugins
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.activate_phrase = activate_phrase
|
||||
self.speech_input = speech_input
|
||||
|
||||
try:
|
||||
self.run_after_plugins = run_after_plugins[self.__class__.__name__]
|
||||
except KeyError:
|
||||
self.run_after_plugins = {}
|
||||
try:
|
||||
self.run_before_plugins = run_before_plugins[self.__class__.__name__]
|
||||
except KeyError:
|
||||
self.run_before_plugins = {}
|
||||
|
||||
def main(self) -> None:
|
||||
"""
|
||||
gets called if user says the defined activate_phrase
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
def run_after(self) -> None:
|
||||
"""
|
||||
gets called after the 'main' function was executed
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
def run_before(self) -> None:
|
||||
"""
|
||||
gets called before the 'main' function was executed
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
def start_run_after_plugin(self, plugin_name: str) -> None:
|
||||
"""
|
||||
calls a 'run_after' plugin (all plugins are in at the root of 'run_after_plugins' dict)
|
||||
|
||||
:param plugin_name: str
|
||||
name of the plugin that should called (all plugins are in at the root of 'run_after_plugins' dict)
|
||||
syntax: "<plugin name>"
|
||||
example: "ExampleClass
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .plugin import _run_befater_plugin, RUN_AFTER
|
||||
except ImportError:
|
||||
from plugin import _run_befater_plugin, RUN_AFTER
|
||||
|
||||
if plugin_name in self.run_after_plugins:
|
||||
_run_befater_plugin(RUN_AFTER, plugin_name, self.run_after_plugins[plugin_name]["method"], self.activate_phrase, self.speech_input)
|
||||
|
||||
def start_run_before_plugin(self, plugin_name: str) -> None:
|
||||
"""
|
||||
calls a 'run_before' plugin (all plugins are in at the root of 'run_before_plugins' dict)
|
||||
|
||||
:param plugin_name: str
|
||||
name of the plugin that should called (all plugins are in at the root of 'run_before_plugins' dict)
|
||||
syntax: "<plugin name>"
|
||||
example: "ExampleClass"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .plugin import _run_befater_plugin, RUN_BEFORE
|
||||
except ImportError:
|
||||
from plugin import _run_befater_plugin, RUN_BEFORE
|
||||
|
||||
if plugin_name in self.run_before_plugins:
|
||||
_run_befater_plugin(RUN_BEFORE, plugin_name, self.run_before_plugins[plugin_name]["method"], self.activate_phrase, self.speech_input)
|
||||
|
||||
def speech_output(self, 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: "<speech output words>"
|
||||
example: "This is an test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from . import speech_output as _speech_output
|
||||
except ImportError:
|
||||
from .__init__ import speech_output as _speech_output
|
||||
|
||||
_speech_output(speech_output)
|
||||
|
||||
|
||||
def create_skill_file(activate_phrases: dict,
|
||||
author: str,
|
||||
language_locales: list,
|
||||
skill_name: str,
|
||||
main_file: str,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a skill can be installed
|
||||
|
||||
:param activate_phrases: dict
|
||||
defines a word or a sentence from which a method is called
|
||||
syntax: {<activate phrase>: <method that should get called after the activate phrase was said>}
|
||||
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
|
||||
:param author: str
|
||||
name of the author from the skill
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param language_locales: list
|
||||
list of language locales for which the skill is available
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param main_file: str
|
||||
file name of file where all methods for the activate_phrases are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_skill_file' is being executed
|
||||
:param skill_name: str
|
||||
name of the skill you create
|
||||
syntax: <skill name>
|
||||
example: "text_skill"
|
||||
:param version: str
|
||||
version (number) of your skill
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_skill_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your skill
|
||||
syntax: <description>
|
||||
example: "A simple skill to test the method 'create_skill_file'"
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the skill
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your package needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import skill_author_must_be_str, skill_language_locales_must_be_list_or_tuple, skill_skill_name_must_be_str, skill_main_file_must_be_str, skill_main_file_not_found,\
|
||||
skill_main_file_name_must_be_skill_name, skill_version_must_be_str, skill_additional_directories_must_be_list_or_tuple, skill_couldnt_find_additional_directories_directory,\
|
||||
skill_description_must_be_str, skill_language_dict_must_be_dict, skill_language_dict_character_must_be_in_alphabet, skill_license_must_be_str,\
|
||||
skill_required_python3_package_must_be_list_or_tuple, skill_activate_phrases_must_be_dict, skill_activate_phrases_character_must_be_in_alphabet
|
||||
except ImportError:
|
||||
from _error_codes import skill_author_must_be_str, skill_language_locales_must_be_list_or_tuple, skill_skill_name_must_be_str, skill_main_file_must_be_str, skill_main_file_not_found,\
|
||||
skill_main_file_name_must_be_skill_name, skill_version_must_be_str, skill_additional_directories_must_be_list_or_tuple, skill_couldnt_find_additional_directories_directory,\
|
||||
skill_description_must_be_str, skill_language_dict_must_be_dict, skill_language_dict_character_must_be_in_alphabet, skill_license_must_be_str,\
|
||||
skill_required_python3_package_must_be_list_or_tuple, skill_activate_phrases_must_be_dict, skill_activate_phrases_character_must_be_in_alphabet
|
||||
|
||||
from os import getcwd, listdir
|
||||
|
||||
write_dict = {}
|
||||
|
||||
if isinstance(author, str) is False:
|
||||
raise TypeError("Errno: " + skill_author_must_be_str + " - Argument 'author' must be str, got " + type(author).__name__)
|
||||
write_dict["author"] = author
|
||||
|
||||
if isinstance(language_locales, (list, tuple)) is False:
|
||||
raise TypeError("Errno: " + skill_language_locales_must_be_list_or_tuple + " - Argument 'language_locales' must be list or tuple, got " + type(language_locales).__name__)
|
||||
write_dict["language_locales"] = language_locales
|
||||
|
||||
if isinstance(skill_name, str) is False:
|
||||
raise TypeError("Errno: " + skill_skill_name_must_be_str + " - Argument 'skill_name' must be str, got " + type(skill_name).__name__)
|
||||
write_dict["skill_name"] = skill_name
|
||||
|
||||
if isinstance(main_file, str) is False:
|
||||
raise TypeError("Errno: " + skill_main_file_must_be_str + " - Argument 'main_file' must be str, got " + type(author).__name__)
|
||||
if main_file not in listdir(getcwd()):
|
||||
raise FileNotFoundError("Errno: " + skill_main_file_not_found + " - Couldn't find the file " + main_file + " in current directory")
|
||||
if main_file[:-3] == skill_name is False:
|
||||
raise NameError("Errno: " + skill_main_file_name_must_be_skill_name + " - The file name from " + main_file + " must be same as the argument 'name' (" + skill_name + ")")
|
||||
write_dict["main_file"] = main_file
|
||||
|
||||
if isinstance(version, str) is False:
|
||||
raise TypeError("Errno: " + skill_version_must_be_str + " - Argument 'version' must be str, got " + type(version).__name__)
|
||||
write_dict["version"] = version
|
||||
|
||||
# ----- #
|
||||
|
||||
if isinstance(additional_directories, (list, tuple)) is False:
|
||||
raise TypeError("Errno: " + skill_additional_directories_must_be_list_or_tuple + " - Argument 'additional_directories' must be list or tuple, got " + type(additional_directories).__name__)
|
||||
for directory in additional_directories:
|
||||
if directory not in listdir(getcwd()):
|
||||
raise NotADirectoryError("Errno: " + skill_couldnt_find_additional_directories_directory + " - Couldn't find the directory " + directory + " in current directory")
|
||||
write_dict["additional_directories"] = additional_directories
|
||||
|
||||
if isinstance(description, str) is False:
|
||||
raise TypeError("Errno: " + skill_description_must_be_str + " - Argument 'description' must be str, got " + type(description).__name__)
|
||||
write_dict["description"] = description
|
||||
|
||||
if isinstance(language_dict, dict) is False:
|
||||
raise TypeError("Errno: " + skill_language_dict_must_be_dict + " - Argument 'language_success' must be dict, got " + type(language_dict).__name__)
|
||||
for key in language_dict.keys():
|
||||
tmp_string = ""
|
||||
for char in key:
|
||||
if char == " ":
|
||||
char = "_"
|
||||
if char.lower() not in "abcdefghijklmnopqrstuvwxyz_":
|
||||
raise ValueError("Errno: " + skill_language_dict_character_must_be_in_alphabet + " - Setter " + str(char) + " in " + str(key) + " must be in 'ABCDEFGHIJLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz_'")
|
||||
tmp_string = tmp_string + char
|
||||
language_dict[tmp_string] = language_dict.pop(key)
|
||||
write_dict["language_dict"] = language_dict
|
||||
|
||||
if isinstance(license, str) is False:
|
||||
raise TypeError("Errno: " + skill_license_must_be_str + " - Argument 'license' must be str, got " + type(license).__name__)
|
||||
write_dict["license"] = license
|
||||
|
||||
if isinstance(required_python3_packages, (list, tuple)) is False:
|
||||
raise TypeError("Errno: " + skill_required_python3_package_must_be_list_or_tuple + " - Argument 'required_python3_packages' must be list or tuple, got " + type(required_python3_packages).__name__)
|
||||
write_dict["required_python3_packages"] = required_python3_packages
|
||||
|
||||
# ----- #
|
||||
|
||||
if isinstance(activate_phrases, dict) is False:
|
||||
raise TypeError("Errno: " + skill_activate_phrases_must_be_dict + " - Argument 'activate_phrases' must be dict, got " + type(activate_phrases).__name__)
|
||||
for item in activate_phrases:
|
||||
tmp_string = ""
|
||||
for char in item:
|
||||
if char == " ":
|
||||
char = "_"
|
||||
if char.lower() not in "abcdefghijklmnopqrstuvwxyz-_":
|
||||
raise ValueError("Errno: " + skill_activate_phrases_character_must_be_in_alphabet + " - Letter " + str(char) + " in " + str(item) + " must be in 'ABCDEFGHIJLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz-_'")
|
||||
tmp_string = tmp_string + char
|
||||
activate_phrases[tmp_string] = activate_phrases.pop(item)
|
||||
write_dict["activate_phrases"] = activate_phrases
|
||||
|
||||
# ----- #
|
||||
|
||||
with open("skill.aion", "w") as file:
|
||||
file.write("#type: skill\n")
|
||||
for key, value in write_dict.items():
|
||||
file.write(key + " = " + str(value) + "\n")
|
||||
file.close()
|
||||
|
||||
|
||||
def create_skill_package(dir_name: str) -> None:
|
||||
"""
|
||||
creates a stand alone file ('.skill') from given directory
|
||||
|
||||
:param dir_name: str
|
||||
directory name of the directory from which you want to create a '.skill' file
|
||||
syntax: <directory name>
|
||||
example: "/home/pi/test/"
|
||||
:return: None
|
||||
|
||||
:note: 'skill.aion' file must be in the given directory (see 'create_skill_file' to create a 'skill.aion' file)
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import skill_package_couldnt_find_directory, skill_package_couldnt_find_aion_file, skill_package_expected_one_aion_file
|
||||
except ImportError:
|
||||
from _error_codes import skill_package_couldnt_find_directory, skill_package_couldnt_find_aion_file, skill_package_expected_one_aion_file
|
||||
|
||||
from os import listdir, mkdir, rename
|
||||
from os.path import isdir
|
||||
from random import sample
|
||||
from shutil import make_archive, rmtree
|
||||
|
||||
if isdir(dir_name) is False:
|
||||
raise NotADirectoryError("Errno: " + skill_package_couldnt_find_directory + " - Couldn't find the directory '" + dir_name + "'")
|
||||
|
||||
name = ""
|
||||
file_num = 0
|
||||
for file in listdir(dir_name):
|
||||
if file.endswith(".aion"):
|
||||
file_num += 1
|
||||
name = "".join(file.split(".aion")[0])
|
||||
if file_num == 0:
|
||||
raise FileNotFoundError("Errno: " + skill_package_couldnt_find_aion_file + " - Couldn't find .aion file in " + dir_name + ". To create one use the 'create_skill_file' function in aionlib.skill")
|
||||
elif file_num > 1:
|
||||
raise FileExistsError("Errno: " + skill_package_expected_one_aion_file + " - Expected one .aion file in " + dir_name + ", got " + str(file_num))
|
||||
|
||||
skill_dir_name = "skill_" + name + "".join([str(num) for num in sample(range(1, 10), 5)])
|
||||
mkdir(skill_dir_name)
|
||||
|
||||
make_archive(name + ".skill", "zip", skill_dir_name)
|
||||
rename(skill_dir_name + ".skill.zip", skill_dir_name + ".skill")
|
||||
|
||||
rmtree(skill_dir_name)
|
||||
|
||||
|
||||
def execute_aion_file_type_skill(fname: str) -> None:
|
||||
"""
|
||||
installs custom skill from '<file name>.aion'
|
||||
|
||||
:param fname: str
|
||||
file name of the '.aion' file
|
||||
syntax: <file name>
|
||||
example: "/home/pi/skill.aion"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import skill_couldnt_find_key, skill_skill_already_exist, skill_file_doesnt_exist, skill_directory_doesnt_exist, skill_directory_already_exist, \
|
||||
skill_couldnt_install_python3_package
|
||||
from .acph import add_acph
|
||||
from .language import add_entry, language_directory
|
||||
from .utils import BaseXMLReader, BaseXMLWriter
|
||||
except ImportError:
|
||||
from acph import add_acph
|
||||
from language import add_entry, language_directory
|
||||
from utils import BaseXMLReader, BaseXMLWriter
|
||||
from _error_codes import skill_couldnt_find_key, skill_skill_already_exist, skill_file_doesnt_exist, skill_directory_doesnt_exist, skill_directory_already_exist, \
|
||||
skill_couldnt_install_python3_package
|
||||
|
||||
from ast import literal_eval
|
||||
from importlib import import_module
|
||||
from os import listdir, path
|
||||
from shutil import copy, copytree
|
||||
from subprocess import call
|
||||
setup_dict = {}
|
||||
setup_dir = path.dirname(path.abspath(fname))
|
||||
for line in open(fname, "r"):
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
setup_dict[line.split("=")[0].strip()] = line.split("=")[1].strip()
|
||||
try:
|
||||
activate_phrases = literal_eval(setup_dict["activate_phrases"])
|
||||
author = setup_dict["author"]
|
||||
language_locales = literal_eval(setup_dict["language_locales"])
|
||||
main_file = setup_dict["main_file"]
|
||||
skill_name = setup_dict["skill_name"]
|
||||
version = setup_dict["version"]
|
||||
|
||||
additional_directories = literal_eval(setup_dict["additional_directories"])
|
||||
description = setup_dict["description"]
|
||||
language_dict = literal_eval(setup_dict["language_dict"])
|
||||
license = setup_dict["license"]
|
||||
required_python3_packages = literal_eval(setup_dict["required_python3_packages"])
|
||||
except KeyError as error:
|
||||
raise KeyError("Errno: " + skill_couldnt_find_key + " - Couldn't find key " + str(error) + " in " + fname)
|
||||
|
||||
# ----- #
|
||||
|
||||
if skill_name in get_all_skills():
|
||||
raise NameError("Errno: " + skill_skill_already_exist + " - The skill " + skill_name + " already exist")
|
||||
|
||||
if path.isfile(setup_dir + "/" + main_file) is False:
|
||||
raise FileNotFoundError("Errno: " + skill_file_doesnt_exist + " - The file " + main_file + " doesn't exist in setup dir (" + setup_dir + ")")
|
||||
|
||||
for directory in additional_directories:
|
||||
if path.isdir(setup_dir + "/" + directory) is False:
|
||||
raise NotADirectoryError("Errno: " + skill_directory_doesnt_exist + " - The directory " + directory + " doesn't exist in setup dir (" + setup_dir + ")")
|
||||
if directory in listdir(skills_path):
|
||||
raise IsADirectoryError("Errno: " + skill_directory_already_exist + " - The directory " + directory + " already exist in " + skills_path)
|
||||
|
||||
# ----- #
|
||||
|
||||
for package in required_python3_packages:
|
||||
call("pip3 install " + package, shell=True)
|
||||
try:
|
||||
import_module(package)
|
||||
except ModuleNotFoundError:
|
||||
raise ModuleNotFoundError("Errno: " + skill_couldnt_install_python3_package + " - Couldn't install the required python3 package '" + package + "'")
|
||||
|
||||
copy(main_file, skills_path + "/" + main_file)
|
||||
|
||||
for directory in additional_directories:
|
||||
copytree(directory, skills_path + "/" + directory)
|
||||
|
||||
for language in language_locales:
|
||||
add_acph(language, skill_name, activate_phrases)
|
||||
add_entry(language, skill_name, language_dict)
|
||||
|
||||
dat_writer = BaseXMLWriter(skills_file)
|
||||
|
||||
dat_writer.add("<root>", str(skill_name), author=str(author))
|
||||
dat_writer.add(str(skill_name), "activate_phrases", str(activate_phrases))
|
||||
dat_writer.add(str(skill_name), "additional_directories", str(additional_directories))
|
||||
dat_writer.add(str(skill_name), "description", str(description))
|
||||
dat_writer.add(str(skill_name), "language_dict", str(language_dict))
|
||||
dat_writer.add(str(skill_name), "language_locales", str(language_locales))
|
||||
dat_writer.add(str(skill_name), "license", str(license))
|
||||
dat_writer.add(str(skill_name), "main_file", str(main_file))
|
||||
dat_writer.add(str(skill_name), "required_python3_packages", str(required_python3_packages))
|
||||
dat_writer.add(str(skill_name), "version", str(version))
|
||||
dat_writer.write()
|
||||
|
||||
|
||||
def execute_skill_file(fname: str) -> None:
|
||||
"""
|
||||
executes a '<name>.skill' file for installing custom skills
|
||||
|
||||
:param fname: str
|
||||
file name of the '.skill' file
|
||||
syntax: <fname>
|
||||
example: "/home/pi/test.skill"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import skill_couldnt_find_skill_dot_aion
|
||||
except ImportError:
|
||||
from _error_codes import skill_couldnt_find_skill_dot_aion
|
||||
|
||||
from glob import glob
|
||||
from os.path import isfile
|
||||
from zipfile import ZipFile
|
||||
with ZipFile(fname, "r") as zipfile:
|
||||
zipfile.extractall("/tmp")
|
||||
zipfile.close()
|
||||
if isfile(glob("/tmp/skill_*/skill.aion")[0]) is False:
|
||||
raise FileNotFoundError("Errno: " + skill_couldnt_find_skill_dot_aion + " - ouldn't find 'skill.aion' in " + fname)
|
||||
else:
|
||||
execute_aion_file_type_skill(glob("/tmp/skill_*/skill.aion")[0])
|
||||
|
||||
|
||||
def get_all_skills() -> list:
|
||||
"""
|
||||
returns all installed skills
|
||||
|
||||
:return: list
|
||||
returns list of all installed skills
|
||||
syntax: [<skill>]
|
||||
example: ["skills"]
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLReader
|
||||
except ImportError:
|
||||
from utils import BaseXMLReader
|
||||
return BaseXMLReader(skills_file).get_infos("<root>").items().index(0)[0]["childs"]
|
||||
|
||||
|
||||
def get_skill_infos(skill_name: str) -> dict:
|
||||
"""
|
||||
returns infos about an given skill
|
||||
|
||||
:param skill_name: str
|
||||
name of the skill you want to get infos about
|
||||
syntax: <skill name>
|
||||
example: "test_skill"
|
||||
:return: dict
|
||||
returns a dictionary with infos of the skill
|
||||
syntax: {"activate_phrases": {<activate phrases>},
|
||||
"author": <author>,
|
||||
"language_locales": [<language locales>],
|
||||
"main_file": <main file>,
|
||||
"skill_name": <skill name>,
|
||||
"version": <version>,
|
||||
"additional_directories": [<additional directories>],
|
||||
"description": <description>,
|
||||
"language_dict": {<entry>: <text>}
|
||||
"license": <license>,
|
||||
"required_python3_packages": [<python3 packages>]}
|
||||
example: {"activate_phrases": {"start test": "test_method_start"}},
|
||||
"author": "blueShard",
|
||||
"language_locales": ["en_US"],
|
||||
"main_file": "test.py",
|
||||
"skill_name": "text_skill",
|
||||
"version": "1.0.0",
|
||||
"additional_directories": ["test_directory"],
|
||||
"description": "A simple skill to test the function 'get_skill_infos",
|
||||
"language_dict": {"test_func": "The test was successful"},
|
||||
"license": "MPL-2.0",
|
||||
"required_python3_packages": ["aionlib"]}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLReader
|
||||
except ImportError:
|
||||
from utils import BaseXMLReader
|
||||
|
||||
from ast import literal_eval
|
||||
skill_reader = BaseXMLReader(skills_file)
|
||||
return_dict = {"skill_name": skill_name}
|
||||
for value_list in skill_reader.get_infos("<all>").values():
|
||||
for skill in value_list:
|
||||
try:
|
||||
if skill["parent"]["tag"] == skill_name:
|
||||
try:
|
||||
return_dict[skill["tag"]] = literal_eval(skill["text"])
|
||||
except (EOFError, SyntaxError, ValueError):
|
||||
return_dict[skill["tag"]] = skill["text"]
|
||||
except KeyError:
|
||||
pass
|
||||
return return_dict
|
||||
|
||||
|
||||
def remove_skill(skill_name: str) -> None:
|
||||
"""
|
||||
removes given skill
|
||||
|
||||
:param skill_name: str
|
||||
name of the skill you want to remove
|
||||
syntax: <skill name>
|
||||
example: "test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .acph import delete_acph
|
||||
from .language import language_directory, delete_entry
|
||||
from .utils import BaseXMLReader, BaseXMLWriter
|
||||
except ImportError:
|
||||
from acph import delete_acph
|
||||
from language import language_directory, delete_entry
|
||||
from utils import BaseXMLReader, BaseXMLWriter
|
||||
|
||||
from os import remove as os_remove
|
||||
from shutil import rmtree
|
||||
skill_infos = get_skill_infos(skill_name)
|
||||
os_remove(skills_path + "/" + skill_infos["main_file"])
|
||||
for dir in skill_infos["additional_directories"]:
|
||||
rmtree(skills_path + "/" + dir)
|
||||
for language in skill_infos["language_locales"]:
|
||||
delete_acph(language, [acph_dict["activate_phrase"] for acph_dict in skill_infos["activate_phrases"]])
|
||||
delete_entry(language, skill_name, entry_list=[key.replace(" ", "_") for key in skill_infos["language_dict"]])
|
||||
remove_xml = BaseXMLWriter(skills_file)
|
||||
remove_xml.remove("<root>", skill_name)
|
||||
remove_xml.write()
|
102
aion-0.1.0_alpha/aion_core/usb.py
Normal file
102
aion-0.1.0_alpha/aion_core/usb.py
Normal file
@ -0,0 +1,102 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import pyudev, psutil
|
||||
from os import system
|
||||
|
||||
|
||||
class USB:
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
class _DeviceInfos:
|
||||
"""
|
||||
base class for usb infos
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, action: str) -> None:
|
||||
"""
|
||||
:param action: str
|
||||
name of the action
|
||||
syntax: <action name>
|
||||
example: "add"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.action = action
|
||||
self.add = False
|
||||
self.remove = False
|
||||
|
||||
if self.action == "add":
|
||||
self.add = True
|
||||
self.remove = False
|
||||
elif action == "remove":
|
||||
self.remove = True
|
||||
self.add = False
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
@staticmethod
|
||||
def mount() -> None:
|
||||
"""
|
||||
mounts a usb device
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
def listen(self) -> _DeviceInfos:
|
||||
"""
|
||||
listen permanent to usb ports for actions etc.
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
context = pyudev.Context()
|
||||
monitor = pyudev.Monitor.from_netlink(context)
|
||||
monitor.filter_by(subsystem="usb")
|
||||
|
||||
removable = [device for device in context.list_devices(subsystem='block', DEVTYPE='disk') if device.attributes.asstring('removable') == "1"]
|
||||
for device in removable:
|
||||
partitions = [device.device_node for device in context.list_devices(subsystem='block', DEVTYPE='partition', parent=device)]
|
||||
print("All removable partitions: {}".format(", ".join(partitions)))
|
||||
print("Mounted removable partitions:")
|
||||
for p in psutil.disk_partitions():
|
||||
if p.device in partitions:
|
||||
print(" {}: {}".format(p.device, p.mountpoint))
|
||||
|
||||
for device in iter(monitor.poll, None):
|
||||
if device.action == "add":
|
||||
yield self._DeviceInfos("add")
|
||||
elif device.action == "remove":
|
||||
yield self._DeviceInfos("remove")
|
||||
print([device.device_node for device in context.list_devices(subsystem='block', DEVTYPE='partition')])
|
||||
|
||||
@staticmethod
|
||||
def umount() -> None:
|
||||
"""
|
||||
unmount usb device
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
system("sudo umount /mnt/usbstick")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print([device.device_node for device in pyudev.Context().list_devices(subsystem='block', DEVTYPE='partition')])
|
||||
for action in USB().listen():
|
||||
pass
|
1204
aion-0.1.0_alpha/aion_core/utils.py
Normal file
1204
aion-0.1.0_alpha/aion_core/utils.py
Normal file
File diff suppressed because it is too large
Load Diff
200
aion-0.1.0_alpha/aion_core/variable.py
Normal file
200
aion-0.1.0_alpha/aion_core/variable.py
Normal file
@ -0,0 +1,200 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
_aion_variable_file = "/tmp/aion39ewefv90erfte25"
|
||||
|
||||
_default_variables = {"IS_AION_RUNNING": False}
|
||||
|
||||
IS_AION_RUNNING = "IS_AION_RUNNING"
|
||||
|
||||
|
||||
class Variable:
|
||||
"""
|
||||
base class for aion variables
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
set all class variables
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os.path import isfile as _isfile
|
||||
|
||||
self._user_variables = {}
|
||||
|
||||
if _isfile(_aion_variable_file):
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
else:
|
||||
self._aion_open_variable_file = None
|
||||
|
||||
def add_variable(self, variable_name: str, value: str) -> None:
|
||||
"""
|
||||
adds a variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable you want to add
|
||||
syntax: <variable name>
|
||||
example: "test_variable"
|
||||
:param value: str
|
||||
value of the variable
|
||||
syntax: <value>
|
||||
example: "test_value"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if self._aion_open_variable_file is not None:
|
||||
file = open(_aion_variable_file, "a")
|
||||
file.write(variable_name + "=" + value)
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
self._user_variables[variable_name] = value
|
||||
|
||||
def close(self) -> None:
|
||||
"""
|
||||
remove the file with the saved variables
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import remove
|
||||
|
||||
if self._aion_open_variable_file is not None:
|
||||
remove(_aion_variable_file)
|
||||
self._aion_open_variable_file = None
|
||||
|
||||
def get_value(self, variable_name: str) -> str:
|
||||
"""
|
||||
get the value of an variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable you want to get the value
|
||||
syntax: <variable name>
|
||||
example: "test_variable"
|
||||
:return: str
|
||||
return the value of the variable
|
||||
syntax: <value>
|
||||
example: <text_variable_value>
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import variable_get_value_variable_file_variable_doesnt_exist, variable_get_value_user_variables_variable_doesnt_exist
|
||||
except ImportError:
|
||||
from _error_codes import variable_get_value_variable_file_variable_doesnt_exist, variable_get_value_user_variables_variable_doesnt_exist
|
||||
|
||||
if self._aion_open_variable_file is not None:
|
||||
for value in self._aion_open_variable_file:
|
||||
if value.strip().startswith("#"):
|
||||
continue
|
||||
elif value.split("=")[0].strip() == variable_name:
|
||||
return value.split("=")[1].strip()
|
||||
raise KeyError("Errno: " + variable_get_value_variable_file_variable_doesnt_exist + " - The variable " + variable_name + " doesn't exists")
|
||||
else:
|
||||
try:
|
||||
return str(_default_variables[variable_name])
|
||||
except KeyError:
|
||||
if variable_name in self._user_variables:
|
||||
return self._user_variables[variable_name]
|
||||
raise KeyError("Errno: " + variable_get_value_user_variables_variable_doesnt_exist + " - The variable " + variable_name + " doesn't exists")
|
||||
|
||||
def inititalize_variables(self, additional_variables: dict = {}) -> None:
|
||||
"""
|
||||
creates a new file for the variables to store
|
||||
|
||||
:param additional_variables: dict, optional
|
||||
variables that should be added ('add_variable' could be used instead)
|
||||
syntax: {"key": "value"}
|
||||
example: {"test": "True"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
write_list = [variable + "=" + str(value) for variable, value in _default_variables.items()]
|
||||
write_list = write_list + [str(additional_variable) + "=" + str(additional_value) for additional_variable, additional_value in additional_variables.items()]
|
||||
write_list = write_list + [str(user_variable) + "=" + str(user_value) for user_variable, user_value in self._user_variables]
|
||||
self._aion_open_variable_file.writelines(write_list)
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
|
||||
def remove_variable(self, variable_name: str) -> None:
|
||||
"""
|
||||
removes a variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable
|
||||
syntax: <variable name>
|
||||
example: "test_variable"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import variable_remove_variable_variable_doesnt_exist
|
||||
from .utils import remove_space, replace_line
|
||||
except ImportError:
|
||||
from _error_codes import variable_remove_variable_variable_doesnt_exist
|
||||
from utils import remove_space, replace_line
|
||||
|
||||
found = False
|
||||
|
||||
if variable_name in self._user_variables:
|
||||
del self._user_variables[variable_name]
|
||||
found = True
|
||||
|
||||
if self._aion_open_variable_file is not None:
|
||||
line_number = -1
|
||||
for line in self._aion_open_variable_file:
|
||||
line_number = line_number + 1
|
||||
if remove_space(line, "").split("=")[0] == variable_name:
|
||||
replace_line(_aion_variable_file, line_number, "")
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
return
|
||||
|
||||
if found is False:
|
||||
raise KeyError("Errno: " + variable_remove_variable_variable_doesnt_exist + " - The variable " + variable_name + " doesn't exists")
|
||||
|
||||
def set_value(self, variable_name: str, value: str) -> None:
|
||||
"""
|
||||
set a new value to a variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable you want to change the value
|
||||
syntax: "<variable name>"
|
||||
example: "test_variable"
|
||||
:param value: str
|
||||
new value
|
||||
syntax: "<new value>"
|
||||
example: "new_test_value"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from ._error_codes import variable_set_value_variable_doesnt_exist
|
||||
from .utils import remove_space, replace_line
|
||||
except ImportError:
|
||||
from _error_codes import variable_set_value_variable_doesnt_exist
|
||||
from utils import remove_space, replace_line
|
||||
|
||||
found = False
|
||||
|
||||
if variable_name in self._user_variables:
|
||||
self._user_variables[variable_name] = value
|
||||
found = True
|
||||
|
||||
if self._aion_open_variable_file is not None:
|
||||
line_number = -1
|
||||
for line in self._aion_open_variable_file:
|
||||
line_number = line_number + 1
|
||||
if remove_space(line, " ").split("=")[0] == variable_name:
|
||||
replace_line(_aion_variable_file, line_number, variable_name + "=" + value)
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
return
|
||||
|
||||
if found is False:
|
||||
raise KeyError("Errno: " + variable_set_value_variable_doesnt_exist + " - The variable " + variable_name + " doesn't exists")
|
445
aion-0.1.0_alpha/etc/ACC/Aion Command Creator.py
Normal file
445
aion-0.1.0_alpha/etc/ACC/Aion Command Creator.py
Normal file
@ -0,0 +1,445 @@
|
||||
from tkinter import *
|
||||
from tkinter import scrolledtext
|
||||
from tkinter import filedialog
|
||||
from tkinter import messagebox
|
||||
from tkinter.ttk import *
|
||||
|
||||
|
||||
root = Tk()
|
||||
menu = Menu(root)
|
||||
root.config(menu=menu)
|
||||
filemenu = Menu(menu, tearoff=FALSE)
|
||||
helpmenu = Menu(menu, tearoff=FALSE)
|
||||
ACC = Menu(menu, tearoff=FALSE)
|
||||
|
||||
active_window = ""
|
||||
|
||||
|
||||
def info():
|
||||
info = Tk()
|
||||
|
||||
info.title("Info")
|
||||
info.resizable(width=0, height=0)
|
||||
|
||||
text = """Aion Command Creator
|
||||
Version 1.0
|
||||
|
||||
Offizielles Programm zum erstellen von eigenen Befehlen für die Aion Platform"""
|
||||
|
||||
Label(info, text=text).pack()
|
||||
|
||||
info.mainloop()
|
||||
|
||||
|
||||
def command_window():
|
||||
def start_config_creator():
|
||||
global root
|
||||
global menu
|
||||
global filemenu
|
||||
global helpmenu
|
||||
global ACC
|
||||
root.destroy()
|
||||
root = Tk()
|
||||
menu = Menu(root)
|
||||
root.config(menu=menu)
|
||||
filemenu = Menu(menu, tearoff=FALSE)
|
||||
helpmenu = Menu(menu, tearoff=FALSE)
|
||||
ACC = Menu(menu, tearoff=FALSE)
|
||||
config_window()
|
||||
|
||||
def anwser_extension():
|
||||
global global_answer
|
||||
global active_window
|
||||
active_window = "answer_extension"
|
||||
|
||||
try:
|
||||
for variable in global_command:
|
||||
variable.destroy()
|
||||
except:
|
||||
pass
|
||||
|
||||
separator = Frame(height=2, relief=SUNKEN)
|
||||
separator.pack(fill=X, padx=5, pady=5)
|
||||
|
||||
answer_extension_choose = Combobox(root, values=["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaggggggggggnjmrjrzhzaaaaaaaaaaaaa", "b"], width=100)
|
||||
answer_extension_choose.pack()
|
||||
answer_extension_choose.current(0)
|
||||
|
||||
free_space = Label(root)
|
||||
free_space.pack()
|
||||
|
||||
answer = Text(root, width=80, height=5)
|
||||
answer.pack()
|
||||
|
||||
global_answer = [separator, answer_extension_choose, free_space, answer]
|
||||
|
||||
def own_command():
|
||||
global global_command
|
||||
global active_window
|
||||
active_window = "own_command"
|
||||
|
||||
try:
|
||||
for variable in global_answer:
|
||||
variable.destroy()
|
||||
except:
|
||||
pass
|
||||
|
||||
separator = Frame(height=2, relief=SUNKEN)
|
||||
separator.pack(fill=X, padx=5, pady=5)
|
||||
|
||||
|
||||
|
||||
global_command = [separator]
|
||||
|
||||
def command_event(event):
|
||||
global active_window
|
||||
if command_choose.get() == "----------------------------":
|
||||
new()
|
||||
active_window = ""
|
||||
elif command_choose.get() == "Antwort Erweiterung":
|
||||
if active_window == "answer_extension":
|
||||
pass
|
||||
else:
|
||||
anwser_extension()
|
||||
elif command_choose.get() == "Eigener Befehl":
|
||||
if active_window == "own_command":
|
||||
pass
|
||||
else:
|
||||
own_command()
|
||||
|
||||
def new():
|
||||
try:
|
||||
for variable in global_answer:
|
||||
variable.destroy()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
for variable in global_command:
|
||||
variable.destroy()
|
||||
except:
|
||||
pass
|
||||
|
||||
command_choose.current(0)
|
||||
|
||||
root.title("ACC | Aion Command Creator | command Creator")
|
||||
root.resizable(width=0, height=0)
|
||||
|
||||
menu.add_cascade(label="Datei", menu=filemenu)
|
||||
filemenu.add_command(label="Neu", command=new)
|
||||
filemenu.add_command(label="Öffnen...")
|
||||
filemenu.add_command(label="Speichern")
|
||||
filemenu.add_command(label="Speichern unter...")
|
||||
filemenu.add_separator()
|
||||
filemenu.add_command(label="Beenden", command=root.destroy)
|
||||
menu.add_cascade(label="Hilfe", menu=helpmenu)
|
||||
helpmenu.add_command(label="Hilfe anzeigen")
|
||||
helpmenu.add_separator()
|
||||
helpmenu.add_command(label="Info", command=info)
|
||||
menu.add_cascade(label="ACC", menu=ACC)
|
||||
ACC.add_command(label="Zum config Creator", command=start_config_creator)
|
||||
|
||||
Label(root, text="Was für eine Art soll dein Befehls sein?").pack()
|
||||
command_choose = Combobox(root, values=["----------------------------", "Antwort Erweiterung", "Eigener Befehl"])
|
||||
command_choose.pack()
|
||||
command_choose.current(0)
|
||||
command_choose.bind("<<ComboboxSelected>>", command_event)
|
||||
|
||||
root.mainloop()
|
||||
|
||||
def config_window():
|
||||
|
||||
def acc_file_search(file_name, search_element):
|
||||
not_needed_informations = ["author=", "version=", "command_type="]
|
||||
no_square_bracket = ["name=", "author=", "version=", "command_type="]
|
||||
if "=" not in search_element:
|
||||
search_element = search_element + "="
|
||||
fileprint = open(file_name).read().splitlines()
|
||||
acc_search_line = acc_search_file_element(file_name, search_element)
|
||||
acc_file_search = fileprint[acc_search_line]
|
||||
acc_file_line = []
|
||||
if search_element in acc_file_search:
|
||||
acc_file_search = acc_file_search.replace(search_element, "")
|
||||
if "\n" in acc_file_search:
|
||||
acc_file_search = acc_file_search.replace("\n", "")
|
||||
acc_file_line.append(acc_file_search)
|
||||
if "]" not in acc_file_search:
|
||||
if search_element in no_square_bracket:
|
||||
pass
|
||||
elif search_element not in no_square_bracket:
|
||||
acc_first_square_bracket_line = acc_search_file_element(file_name, search_element)
|
||||
acc_second_square_bracket_line = acc_search_file_element(file_name, "]", acc_first_square_bracket_line)
|
||||
while True:
|
||||
bracket_lines = list(range(acc_first_square_bracket_line, acc_second_square_bracket_line + 1))
|
||||
elements = []
|
||||
for element_numbers in bracket_lines:
|
||||
element_list = fileprint[element_numbers]
|
||||
if search_element in element_list:
|
||||
if not "=" in search_element:
|
||||
search_element = search_element + "="
|
||||
element_list = element_list.replace(search_element, "")
|
||||
element_list = element_list.lstrip()
|
||||
elements.append(element_list)
|
||||
|
||||
acc_file_line = elements
|
||||
break
|
||||
|
||||
global acc_file
|
||||
acc_file_temporary = []
|
||||
for acc_file in acc_file_line:
|
||||
acc_file = acc_file
|
||||
if acc_file == "":
|
||||
if search_element in not_needed_informations:
|
||||
acc_file = ""
|
||||
return acc_file
|
||||
elif search_element not in not_needed_informations:
|
||||
acc_file = ""
|
||||
return acc_file
|
||||
else:
|
||||
acc_file = ""
|
||||
return acc_file
|
||||
if "[" in acc_file:
|
||||
acc_file = acc_file.replace("[", "")
|
||||
if "]" in acc_file:
|
||||
acc_file = acc_file.replace("]", "")
|
||||
if '"' in acc_file:
|
||||
acc_file = acc_file.replace('"', "")
|
||||
acc_file_temporary.append(acc_file)
|
||||
if len(acc_file_temporary) > 1:
|
||||
acc_file = (", ".join(acc_file_temporary))
|
||||
else:
|
||||
acc_file = ("".join(acc_file_temporary))
|
||||
if ",," in acc_file:
|
||||
acc_file = acc_file.replace(",,", ",")
|
||||
|
||||
return acc_file
|
||||
|
||||
def acc_search_file_element(file_name, search_element, from_line=0):
|
||||
if "]" in search_element:
|
||||
pass
|
||||
if "[" in search_element:
|
||||
pass
|
||||
while True:
|
||||
if search_element in open(file_name, "r").readlines()[from_line]:
|
||||
break
|
||||
else:
|
||||
from_line = from_line + 1
|
||||
return from_line
|
||||
|
||||
def start_command_creator():
|
||||
global root
|
||||
global menu
|
||||
global filemenu
|
||||
global helpmenu
|
||||
global ACC
|
||||
root.destroy()
|
||||
root = Tk()
|
||||
menu = Menu(root)
|
||||
root.config(menu=menu)
|
||||
filemenu = Menu(menu, tearoff=FALSE)
|
||||
helpmenu = Menu(menu, tearoff=FALSE)
|
||||
ACC = Menu(menu, tearoff=FALSE)
|
||||
command_window()
|
||||
|
||||
def create_acc_config():
|
||||
name = name_entry.get()
|
||||
author = author_entry.get()
|
||||
version = version_entry.get()
|
||||
command_type = command_type_entry.get()
|
||||
command_file = command_file_entry.get()
|
||||
raw_command = raw_command_scrolledtext.get(1.0, END)
|
||||
new_file = filedialog.asksaveasfile(mode="w", defaultextension=".cfg", filetypes=(("CFG Datei", "*.cfg"),))
|
||||
global new_file_name
|
||||
new_file_name = new_file.name
|
||||
new_file.write(
|
||||
'name=' + name + '\nauthor=' + author + '\nversion=' + version + '\ncommand_type=' + command_type + '\ncommand_file=["' + command_file + '"]\nraw_command=["' + raw_command + '"]')
|
||||
|
||||
def get_def():
|
||||
get_def_list = []
|
||||
numbers = []
|
||||
def_print = open(open_command_file_name, "r").read().splitlines()
|
||||
with open(open_command_file_name, "r") as get_def:
|
||||
for line in get_def:
|
||||
if "def " in line:
|
||||
def_line = line
|
||||
numbers.append(def_print[acc_search_file_element(open_command_file_name, def_line)])
|
||||
for space in numbers:
|
||||
non_space = space.lstrip()
|
||||
get_def_list.append(non_space)
|
||||
raw_command_scrolledtext.config(state=NORMAL)
|
||||
for insert in get_def_list:
|
||||
raw_command_scrolledtext.insert(1.0, insert + " = '',\n")
|
||||
|
||||
def new():
|
||||
get_function.config(state=DISABLED)
|
||||
name_entry.delete(0, END)
|
||||
author_entry.delete(0, END)
|
||||
version_entry.delete(0, END)
|
||||
command_type_entry.delete(0, END)
|
||||
command_file_entry.delete(0, END)
|
||||
raw_command_scrolledtext.delete(1.0, END)
|
||||
|
||||
def open_acc_config():
|
||||
open_file = filedialog.askopenfile(filetypes=(("CFG Datei", "*.cfg"), ("Alle Dateien", "*.*")))
|
||||
global open_file_name
|
||||
open_file_name = open_file.name
|
||||
if ".cfg" not in open_file_name:
|
||||
messagebox.showerror("Aion Command Creator", "Die Ausgewählte Datei ist keine config (*.cfg) Datei")
|
||||
else:
|
||||
open_file_read = open(open_file_name, "r").read()
|
||||
if "name=" and "version=" and "command_type=" and "command_file=" and "raw_command=" in open_file_read:
|
||||
raw_command_scrolledtext.config(state=NORMAL)
|
||||
name_entry_insert = acc_file_search(open_file_name, "name")
|
||||
author_entry_insert = acc_file_search(open_file_name, "author")
|
||||
version_entry_insert = acc_file_search(open_file_name, "version")
|
||||
command_type_entry_insert = acc_file_search(open_file_name, "command_type")
|
||||
command_file_entry_insert = acc_file_search(open_file_name, "command_file")
|
||||
raw_command_scrolledtext_insert = acc_file_search(open_file_name, "raw_command")
|
||||
raw_command_scrolledtext_insert = raw_command_scrolledtext_insert.replace(",", "\n")
|
||||
raw_command_scrolledtext_insert = raw_command_scrolledtext_insert.replace(" ", "")
|
||||
name_entry.delete(0, END)
|
||||
name_entry.insert(0, name_entry_insert)
|
||||
author_entry.delete(0, END)
|
||||
author_entry.insert(0, author_entry_insert)
|
||||
version_entry.delete(0, END)
|
||||
version_entry.insert(0, version_entry_insert)
|
||||
command_type_entry.delete(0, END)
|
||||
command_type_entry.insert(0, command_type_entry_insert)
|
||||
command_file_entry.delete(0, END)
|
||||
command_file_entry.insert(0, command_file_entry_insert)
|
||||
raw_command_scrolledtext.delete(1.0, END)
|
||||
raw_command_scrolledtext.insert(1.0, raw_command_scrolledtext_insert)
|
||||
else:
|
||||
print(open_file.name + " kann nicht gelesen werden")
|
||||
|
||||
def open_command_file():
|
||||
import ntpath
|
||||
open_file = filedialog.askopenfile(filetypes=(("PY Datei", "*.py"), ("Alle Dateien", "*.*")))
|
||||
global open_command_file_name
|
||||
open_command_file_name = open_file.name
|
||||
if ".py" not in open_command_file_name:
|
||||
messagebox.showerror("Aion Command Creator", "Die Ausgewählte Datei ist keine Python (*.py) Datei")
|
||||
else:
|
||||
command_file_entry.delete(0, END)
|
||||
command_file_entry.insert(0, ntpath.basename(open_file.name))
|
||||
raw_command_scrolledtext.config(state=NORMAL)
|
||||
get_function.config(fg="green", state=NORMAL)
|
||||
|
||||
def save():
|
||||
global file_name
|
||||
try:
|
||||
file_name = open_file_name
|
||||
except:
|
||||
try:
|
||||
file_name = new_file_name
|
||||
except:
|
||||
create_acc_config()
|
||||
return
|
||||
name = name_entry.get()
|
||||
author = author_entry.get()
|
||||
version = version_entry.get()
|
||||
command_type = command_type_entry.get()
|
||||
command_file = command_file_entry.get()
|
||||
raw_command = raw_command_scrolledtext.get("1.0", END)
|
||||
file = open(file_name, "w")
|
||||
file.write('name=' + name + '\nauthor=' + author + '\nversion=' + version + '\ncommand_type=' + command_type + '\ncommand_file=["' + command_file + '"]\nraw_command=["' + raw_command + '"]')
|
||||
|
||||
def show_help():
|
||||
help = Tk()
|
||||
|
||||
help.title("Hilfe anzeigen")
|
||||
help.resizable(width=0, height=0)
|
||||
|
||||
Label(help, text="Hilfe zum Aion Command Creator im Bereich 'config Creator'\n\n").pack()
|
||||
Label(help, text="'Befehlspaket' = Paket, worin sich alle Dateien befinden").pack()
|
||||
Label(help, text="'/' = oder").pack()
|
||||
Label(help, text="Name: ").pack()
|
||||
name = Text(help, height=2, width=100)
|
||||
name.insert(1.0, "Legt den Namen für das Befehlspaket fest\n"
|
||||
"Bsp: Tiergeräusche -> geräusche.py(Datei mit den Befehlsnamen) + geräusche.cfg(Konfigurations Datei)")
|
||||
name.config(state=DISABLED)
|
||||
name.pack()
|
||||
Label(help, text="Autor").pack()
|
||||
author = Text(help, height=2, width=100)
|
||||
author.insert(1.0, "Legt den Namen vom Autor des Befehlspaket fest\n"
|
||||
"Bsp: xXauthorXx / CaCtUsFiGhTeR")
|
||||
author.config(state=DISABLED)
|
||||
author.pack()
|
||||
Label(help, text="Version").pack()
|
||||
version = Text(help, height=2, width=100)
|
||||
version.insert(1.0, "Legt die Version vom Befehlspaket fest\n"
|
||||
"Bsp: v.1.1 / 1.3.7.4")
|
||||
version.config(state=DISABLED)
|
||||
version.pack()
|
||||
Label(help, text="Befehls Typ").pack()
|
||||
command_type = Text(help, height=2, width=100)
|
||||
command_type.insert(1.0, "Legt den Befehlstyp des Befehlspaket fest\n"
|
||||
"Bsp: Spiel / Antwort Erweiterung")
|
||||
command_type.config(state=DISABLED)
|
||||
command_type.pack()
|
||||
Label(help, text="Befehlsdatei").pack()
|
||||
command_file = Text(help, height=2, width=100)
|
||||
command_file.insert(1.0, "Legt die Datei mit den Befehlen fest\n"
|
||||
"Bsp: geräusche.py -> def kuh(): (enthält z.B. den Code zum abspielen von einem Kuh Geräusch)")
|
||||
command_file.config(state=DISABLED)
|
||||
command_file.pack()
|
||||
Label(help, text="Befehl(e)").pack()
|
||||
raw_command = Text(help, height=2, width=100)
|
||||
raw_command.insert(1.0, "Legt den Namen der Funktion fest und mit welchen Spracheingaben diese aufgerufen wird\n"
|
||||
"Bsp: def kuh(): = 'Mach Kuh Geräusche'")
|
||||
raw_command.config(state=DISABLED)
|
||||
raw_command.pack()
|
||||
|
||||
root.title("ACC | Aion Command Creator | config Creator")
|
||||
root.resizable(width=0, height=0)
|
||||
|
||||
menu.add_cascade(label="Datei", menu=filemenu)
|
||||
filemenu.add_command(label="Neu", command=new)
|
||||
filemenu.add_command(label="Öffnen...", command=open_acc_config)
|
||||
filemenu.add_command(label="Speichern", command=save)
|
||||
filemenu.add_command(label="Speichern unter...", command=create_acc_config)
|
||||
filemenu.add_separator()
|
||||
filemenu.add_command(label="Beenden", command=root.destroy)
|
||||
menu.add_cascade(label="Hilfe", menu=helpmenu)
|
||||
helpmenu.add_command(label="Hilfe anzeigen", command=show_help)
|
||||
helpmenu.add_separator()
|
||||
helpmenu.add_command(label="Info", command=info)
|
||||
menu.add_cascade(label="ACC", menu=ACC)
|
||||
ACC.add_command(label="Zum command Creator", command=start_command_creator)
|
||||
|
||||
Label(root, text="* = Wird nicht unbedingt benötigt").pack()
|
||||
|
||||
Label(root, text="Name:", font="Times").pack()
|
||||
name_entry = Entry(root, width=40)
|
||||
name_entry.pack()
|
||||
|
||||
Label(root, text="Autor*:", font="Times").pack()
|
||||
author_entry = Entry(root, width=40)
|
||||
author_entry.pack()
|
||||
|
||||
Label(root, text="Version*: ", font="Times").pack()
|
||||
version_entry = Entry(root, width=40)
|
||||
version_entry.pack()
|
||||
|
||||
Label(root, text="Befehls Typ*:", font="Times").pack()
|
||||
command_type_entry = Entry(root, width=40)
|
||||
command_type_entry.pack()
|
||||
|
||||
Label(root, text="Befehls Datei:", font="Times").pack()
|
||||
command_file_entry = Entry(root, width=55)
|
||||
command_file_entry.pack()
|
||||
|
||||
Button(root, text="Wähle Datei aus", command=open_command_file).pack()
|
||||
get_function = Button(root, text="Versuche alle Befehle aufzulisten", command=get_def)
|
||||
get_function.config(state=DISABLED)
|
||||
get_function.pack()
|
||||
|
||||
Label(root, text="Befehl(e):", font="Times").pack()
|
||||
raw_command_scrolledtext = scrolledtext.ScrolledText(root, height=15, width=50)
|
||||
raw_command_scrolledtext.config(state=DISABLED)
|
||||
raw_command_scrolledtext.pack()
|
||||
|
||||
root.mainloop()
|
||||
|
||||
|
||||
command_window()
|
91
aion-0.1.0_alpha/etc/ACC/acc_support.py
Normal file
91
aion-0.1.0_alpha/etc/ACC/acc_support.py
Normal file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
def acc_file_search(file_name, search_element):
|
||||
import re
|
||||
not_needed_informations = ["author=", "version=", "command_type="]
|
||||
no_square_bracket = ["name=", "author=", "version=", "command_type="]
|
||||
if "=" not in search_element:
|
||||
search_element = search_element + "="
|
||||
fileprint = open(file_name).read().splitlines()
|
||||
acc_search_line = acc_search_file_element(file_name, search_element)
|
||||
acc_file_search = fileprint[acc_search_line]
|
||||
acc_file_line = []
|
||||
if search_element in acc_file_search:
|
||||
acc_file_search = acc_file_search.replace(search_element, "")
|
||||
if "\n" in acc_file_search:
|
||||
acc_file_search = acc_file_search.replace("\n", "")
|
||||
acc_file_line.append(acc_file_search)
|
||||
if "]" not in acc_file_search:
|
||||
if search_element in no_square_bracket:
|
||||
pass
|
||||
elif search_element not in no_square_bracket:
|
||||
acc_first_square_bracket_line = acc_search_file_element(file_name, search_element)
|
||||
acc_second_square_bracket_line = acc_search_file_element(file_name, "]", acc_first_square_bracket_line)
|
||||
while True:
|
||||
bracket_lines = list(range(acc_first_square_bracket_line, acc_second_square_bracket_line + 1))
|
||||
elements = []
|
||||
for element_numbers in bracket_lines:
|
||||
element_list = fileprint[element_numbers]
|
||||
if search_element in element_list:
|
||||
if not "=" in search_element:
|
||||
search_element = search_element + "="
|
||||
element_list = element_list.replace(search_element, "")
|
||||
element_list = element_list.lstrip()
|
||||
elements.append(element_list)
|
||||
|
||||
acc_file_line = elements
|
||||
break
|
||||
|
||||
global acc_file
|
||||
acc_file_temporary = []
|
||||
for acc_file in acc_file_line:
|
||||
acc_file = acc_file
|
||||
if acc_file == "":
|
||||
if search_element in not_needed_informations:
|
||||
if "=" in search_element:
|
||||
search_element = search_element.replace("=", "")
|
||||
acc_file = ("There is no " + search_element)
|
||||
return acc_file
|
||||
elif search_element not in not_needed_informations:
|
||||
if "=" in search_element:
|
||||
search_element = search_element.replace("=", "")
|
||||
pass
|
||||
acc_file = ("There is no " + search_element + ", but it must be something indicated!")
|
||||
return acc_file
|
||||
else:
|
||||
acc_file = "An error appears!"
|
||||
return acc_file
|
||||
if "[" in acc_file:
|
||||
acc_file = acc_file.replace("[", "")
|
||||
if "]" in acc_file:
|
||||
acc_file = acc_file.replace("]", "")
|
||||
if '"' in acc_file:
|
||||
acc_file = acc_file.replace('"', "")
|
||||
acc_file_temporary.append(acc_file)
|
||||
if len(acc_file_temporary) > 1:
|
||||
acc_file = (", ".join(acc_file_temporary))
|
||||
else:
|
||||
acc_file = ("".join(acc_file_temporary))
|
||||
if ",," in acc_file:
|
||||
acc_file = acc_file.replace(",,", ",")
|
||||
if re.search("[a-zA-Z]", acc_file) == None:
|
||||
if search_element in no_square_bracket:
|
||||
if "=" in search_element:
|
||||
search_element = search_element.replace("=", "")
|
||||
print("There is no " + search_element + ", but it must be something indicated!")
|
||||
|
||||
return acc_file
|
||||
|
||||
def acc_search_file_element(file_name, search_element, from_line=0):
|
||||
if "]" in search_element:
|
||||
pass
|
||||
if "[" in search_element:
|
||||
pass
|
||||
while True:
|
||||
if search_element in open(file_name, "r").readlines()[from_line]:
|
||||
break
|
||||
else:
|
||||
from_line = from_line + 1
|
||||
return from_line
|
||||
|
||||
print(acc_file_search("example.cfg", "raw_command"))
|
22
aion-0.1.0_alpha/etc/ACC/acc_test.py
Normal file
22
aion-0.1.0_alpha/etc/ACC/acc_test.py
Normal file
@ -0,0 +1,22 @@
|
||||
from tkinter import *
|
||||
|
||||
root = Tk()
|
||||
frame = Frame(root)
|
||||
frame.pack()
|
||||
|
||||
bottomframe = Frame(root)
|
||||
bottomframe.pack( side = BOTTOM )
|
||||
|
||||
redbutton = Button(frame, text="Red", fg="red")
|
||||
redbutton.pack( side = LEFT)
|
||||
|
||||
greenbutton = Button(frame, text="green", fg="green")
|
||||
greenbutton.pack( side = LEFT )
|
||||
|
||||
bluebutton = Button(frame, text="Blue", fg="blue")
|
||||
bluebutton.pack( side = LEFT )
|
||||
|
||||
blackbutton = Button(bottomframe, text="Black", fg="black")
|
||||
blackbutton.pack( side = BOTTOM)
|
||||
|
||||
root.mainloop()
|
10
aion-0.1.0_alpha/etc/ACC/config_example.cfg
Normal file
10
aion-0.1.0_alpha/etc/ACC/config_example.cfg
Normal file
@ -0,0 +1,10 @@
|
||||
name=a
|
||||
author=
|
||||
version=
|
||||
command_type=
|
||||
command_file=["g"]
|
||||
raw_command=["defa():='a'
|
||||
'b'
|
||||
'c'
|
||||
|
||||
"]
|
BIN
aion-0.1.0_alpha/etc/Aion.pmdl
Normal file
BIN
aion-0.1.0_alpha/etc/Aion.pmdl
Normal file
Binary file not shown.
27
aion-0.1.0_alpha/etc/uninstall.sh
Normal file
27
aion-0.1.0_alpha/etc/uninstall.sh
Normal file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$#" -gt "1" ]; then
|
||||
echo "too many arguments were given"
|
||||
elif [ "$#" -eq "1" ]; then
|
||||
if [ "$1" == "--all" ]; then
|
||||
yes | pip3 uninstall aionlib colorama pafy pocketsphinx psutil pyaudio pyudev snowboy SpeechRecognition Wikipedia-API youtube_dl
|
||||
|
||||
apt-get -y purge bison build-essential espeak ffmpeg flac libasound2-dev libatlas-base-dev libpulse-dev python3-pyaudio sox subversion swig vlc wget
|
||||
apt-get -y autoremove
|
||||
|
||||
rm -r /usr/local/aion-*
|
||||
|
||||
rm -r /etc/aion_data
|
||||
|
||||
rm /usr/bin/aion
|
||||
else
|
||||
echo "unexpected argument were given"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
yes | pip3 uninstall aionlib colorama pafy pocketsphinx psutil pyaudio pyudev snowboy SpeechRecognition Wikipedia-API youtube_dl
|
||||
|
||||
apt-get -y remove bison build-essential espeak ffmpeg flac libasound2-dev libatlas-base-dev libpulse-dev python3-pyaudio sox subversion swig vlc wget
|
||||
|
||||
rm -r /usr/local/aion-*
|
||||
fi
|
11
aion_data/etc/install.sh
Normal file
11
aion_data/etc/install.sh
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d "/usr/local/aion-"]; then
|
||||
apt-get install git
|
||||
git --clone https://github.com/blueShard-dev/aion /tmp/aion_installation
|
||||
bash /tmp/aion_installation/install.sh
|
||||
|
||||
rm -r /tmp/aion_installation
|
||||
else
|
||||
echo "Aion is already installed"
|
||||
fi
|
10
aion_data/language/de_DE.acph
Normal file
10
aion_data/language/de_DE.acph
Normal file
@ -0,0 +1,10 @@
|
||||
<activate_phrases>
|
||||
<erzähle__and__über skill="skills" method="Wikipedia"/>
|
||||
<erzähl__and__über skill="skills" method="Wikipedia"/>
|
||||
<ip-adresse skill="skills" method="IpAddress"/>
|
||||
<prozessor_auslastung skill="skills" method="CpuUsage"/>
|
||||
<spiele skill="skills" method="Play"/>
|
||||
<spiel skill="skills" method="Play"/>
|
||||
<uhr skill="skills" method="CurrentTime"/>
|
||||
<zeit skill="skills" method="CurrenTime"/>
|
||||
</activate_phrases>
|
19
aion_data/language/de_DE.lng
Normal file
19
aion_data/language/de_DE.lng
Normal file
@ -0,0 +1,19 @@
|
||||
<de_DE>
|
||||
<skills.cpu_ram_usage>Der Prozessor wird zu {cpu_usage} und der RAM zu {ram_usage} prozent genutzt</skills.cpu_ram_usage>
|
||||
<skills.cpu_usage>Der Prozessor wird zu {cpu_usage} genutzt</skills.cpu_usage>
|
||||
<skills.current_time_full_am/>
|
||||
<skills.current_time_full_pm/>
|
||||
<skills.current_time_half_am/>
|
||||
<skills.current_time_half_pm/>
|
||||
<skills.current_time_past_am/>
|
||||
<skills.current_time_past_pm/>
|
||||
<skills.current_time_to_am/>
|
||||
<skills.current_time_to_pm/>
|
||||
<skills.current_time_full>Es ist {hour} Uhr</skills.current_time_full>
|
||||
<skills.current_time_half>Es ist {hour} Uhr {minute}</skills.current_time_half>
|
||||
<skills.current_time_etc>Es ist {hour} Uhr {minute}</skills.current_time_etc>
|
||||
<skills.ip_address>Meine IP ist {ip_address}</skills.ip_address>
|
||||
<skills.ram_usage>Der RAM wird zu {ram_usage} prozent genutzt</skills.ram_usage>
|
||||
<skills.wikipedia>{article_text}</skills.wikipedia>
|
||||
<skills.wikipedia_article_not_found>Der Artikel {article_text} existiert nicht</skills.wikipedia_article_not_found>
|
||||
</de_DE>
|
10
aion_data/language/en_US.acph
Normal file
10
aion_data/language/en_US.acph
Normal file
@ -0,0 +1,10 @@
|
||||
<activate_phrases>
|
||||
<cpu_usage skill="skills" method="CpuUsage"/>
|
||||
<ip_address skill="skills" method="IpAddress"/>
|
||||
<play skill="skills" method="Play"/>
|
||||
<processor_usage skill="skills" method="CpuUsage"/>
|
||||
<ram_usage skill="skills" method="RamUsage"/>
|
||||
<tell__and__about skill="skills" method="Wikipedia"/>
|
||||
<time skill="skills" method="CurrentTime"/>
|
||||
<virtual_memory_usage skill="skills", method="RamUsage"/>
|
||||
</activate_phrases>
|
19
aion_data/language/en_US.lng
Normal file
19
aion_data/language/en_US.lng
Normal file
@ -0,0 +1,19 @@
|
||||
<en_US>
|
||||
<skills.cpu_ram_usage>The processor uses {cpu_usage} and the ram {ram_usage} percent</skills.cpu_ram_usage>
|
||||
<skills.cpu_usage>The processor uses {cpu_usage} percent</skills.cpu_usage>
|
||||
<skills.current_time_full_am>It's {hour} a.m.</skills.current_time_full_am>
|
||||
<skills.current_time_full_pm>It's {hour} p.m.</skills.current_time_full_pm>
|
||||
<skills.current_time_half_am>It's half past {hour} a.m.</skills.current_time_half_am>
|
||||
<skills.current_time_half_pm>It's half past {hour} p.m.</skills.current_time_half_pm>
|
||||
<skills.current_time_past_am>It's {minute} past {hour} a.m.</skills.current_time_past_am>
|
||||
<skills.current_time_past_pm>It's {minute} past {hour} p.m.</skills.current_time_past_pm>
|
||||
<skills.current_time_to_am>It's {minute} to {hour} a.m.</skills.current_time_to_am>
|
||||
<skills.current_time_to_pm>It's {minute} to {hour} p.m.</skills.current_time_to_pm>
|
||||
<skills.current_time_full>It's {hour} o'clock</skills.current_time_full>
|
||||
<skills.current_time_half>It's half past {hour}</skills.current_time_half>
|
||||
<skills.current_time_etc>It's {hour} {minute}</skills.current_time_etc>
|
||||
<skills.ip_address>My IP is {ip_address}</skills.ip_address>
|
||||
<skills.ram_usage>The ram uses {ram_usage} percent</skills.ram_usage>
|
||||
<skills.wikipedia>{article_text}</skills.wikipedia>
|
||||
<skills.wikipedia_article_not_found>The article {article_name} doesnt exist</skills.wikipedia_article_not_found>
|
||||
</en_US>
|
2
aion_data/plugins/run_after/run_after.xml
Normal file
2
aion_data/plugins/run_after/run_after.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<run_after>
|
||||
</run_after>
|
2
aion_data/plugins/run_before/run_before.xml
Normal file
2
aion_data/plugins/run_before/run_before.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<run_before>
|
||||
</run_before>
|
235
aion_data/skills/skills.py
Normal file
235
aion_data/skills/skills.py
Normal file
@ -0,0 +1,235 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from glob import glob
|
||||
from sys import path
|
||||
|
||||
path.insert(0, glob("/usr/local/aion-*/aion_core")[0])
|
||||
|
||||
from aion_core import config as aconf
|
||||
from aion_core import language as alang
|
||||
|
||||
from aion_core.skill import Skill
|
||||
|
||||
|
||||
class CpuRamUsage(Skill):
|
||||
"""
|
||||
skill class to get the cpu and ram usage
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from psutil import cpu_percent, virtual_memory
|
||||
from statistics import mean
|
||||
from time import sleep
|
||||
|
||||
testing_time = 10
|
||||
print_process = False
|
||||
|
||||
cpu_list = []
|
||||
ram_list = []
|
||||
|
||||
while True:
|
||||
cpu = cpu_percent()
|
||||
cpu_list.append(cpu)
|
||||
ram = virtual_memory()[2]
|
||||
ram_list.append(ram)
|
||||
if print_process is True:
|
||||
print("CPU: " + str(cpu) + "%")
|
||||
print("RAM: " + str(ram) + "%")
|
||||
sleep(1)
|
||||
|
||||
if 0.0 in cpu_list:
|
||||
cpu_list.remove(0.0)
|
||||
if len(cpu_list) == testing_time and len(ram_list) == testing_time:
|
||||
cpu = mean(cpu_list)
|
||||
ram = mean(ram_list)
|
||||
break
|
||||
elif len(cpu_list) == testing_time - 1 and len(ram_list) == testing_time:
|
||||
cpu = cpu_percent()
|
||||
cpu_list.append(cpu)
|
||||
cpu = mean(cpu_list)
|
||||
ram = mean(ram_list)
|
||||
break
|
||||
|
||||
self.speech_output(alang.start("skills", "cpu_ram_usage", {"cpu_usage": round(cpu, 2), "ram_usage": round(ram, 2)}))
|
||||
|
||||
|
||||
class CpuUsage(Skill):
|
||||
"""
|
||||
skill class to get the cpu usage
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from statistics import mean
|
||||
from psutil import cpu_percent
|
||||
from time import sleep
|
||||
|
||||
testing_time = 10
|
||||
print_process = False
|
||||
|
||||
cpu_list = []
|
||||
|
||||
while True:
|
||||
cpu = cpu_percent()
|
||||
cpu_list.append(cpu)
|
||||
if print_process is True:
|
||||
print("CPU: " + str(cpu) + "%")
|
||||
sleep(1)
|
||||
|
||||
if 0.0 in cpu_list:
|
||||
cpu_list.remove(0.0)
|
||||
if len(cpu_list) == testing_time:
|
||||
cpu = (mean(cpu_list))
|
||||
break
|
||||
|
||||
self.speech_output(alang.start("skills", "cpu_usage", {"cpu_usage": round(cpu, 2)}))
|
||||
|
||||
|
||||
class CurrentTime(Skill):
|
||||
"""
|
||||
skill class to get the current time
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from datetime import datetime
|
||||
|
||||
current_time = datetime.now()
|
||||
time_dict = {"hour": current_time.hour, "minute": current_time.minute, "second": current_time.second, "microsecond": current_time.microsecond}
|
||||
if aconf.Aion().get_time_format() == "12":
|
||||
if time_dict["minute"] == 0:
|
||||
if time_dict["hour"] < 13:
|
||||
self.speech_output(alang.start("skills", "current_time_full_am", time_dict))
|
||||
else:
|
||||
time_dict["hour"] = time_dict["hour"] - 12
|
||||
self.speech_output(alang.start("skills", "current_time_full_pm", time_dict))
|
||||
elif time_dict["minute"] == 30:
|
||||
if time_dict["hour"] < 13:
|
||||
self.speech_output(alang.start("skills", "current_time_half_am", time_dict))
|
||||
else:
|
||||
time_dict["hour"] = time_dict["hour"] - 12
|
||||
self.speech_output(alang.start("skills", "current_time_half_pm", time_dict))
|
||||
elif 0 < time_dict["minute"] < 30:
|
||||
if time_dict["hour"] < 13:
|
||||
self.speech_output(alang.start("skills", "current_time_past_am", time_dict))
|
||||
else:
|
||||
time_dict["hour"] = time_dict["hour"] - 12
|
||||
self.speech_output(alang.start("skills", "current_time_past_pm", time_dict))
|
||||
elif time_dict["minute"] > 30:
|
||||
time_dict["minute"] = 60 - time_dict["minute"]
|
||||
if time_dict["hour"] < 13:
|
||||
self.speech_output(alang.start("skills", "current_time_to_am", time_dict))
|
||||
else:
|
||||
time_dict["hour"] = time_dict["hour"] - 12
|
||||
self.speech_output(alang.start("skills", "current_time_to_pm", time_dict))
|
||||
else:
|
||||
self.speech_output(alang.start("skills", "current_time_etc", time_dict))
|
||||
else:
|
||||
if time_dict["minute"] == 0:
|
||||
self.speech_output(alang.start("skills", "current_time_full", time_dict))
|
||||
elif time_dict["minute"] == 30:
|
||||
self.speech_output(alang.start("skills", "current_time_half", time_dict))
|
||||
else:
|
||||
self.speech_output(alang.start("skills", "current_time_etc", time_dict))
|
||||
|
||||
|
||||
class IpAddress(Skill):
|
||||
"""
|
||||
skill class to get the ip address
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from socket import gethostname, gethostbyname
|
||||
|
||||
self.speech_output(alang.start("skills", "ip_address", {"ip_address": gethostbyname(gethostname() + ".local")}))
|
||||
|
||||
|
||||
class Play(Skill):
|
||||
"""
|
||||
skill class to play a audio from youtube
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from aion_core.utils import get_full_directory_data, vlc
|
||||
|
||||
file_or_search_element = self.speech_input.lower().replace(self.activate_phrase.lower(), "")
|
||||
for file in get_full_directory_data(file_or_search_element):
|
||||
if file_or_search_element in file:
|
||||
return vlc(file_or_search_element)
|
||||
import urllib.parse, urllib.request
|
||||
from pafy import new
|
||||
from re import findall
|
||||
search_query = urllib.parse.urlencode({"search_query": file_or_search_element})
|
||||
for i in range(10): # sometimes the video url's cannot be found
|
||||
try:
|
||||
html_content = urllib.request.urlopen("https://www.youtube.com/results?" + search_query)
|
||||
search_results = findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
|
||||
vlc(new(str("https://www.youtube.com/watch?v=" + search_results[0])).getbestaudio().url)
|
||||
break
|
||||
# i do it this way, because vlc sometimes don't extract the 'only audio url' from the youtube url
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
def run_after(self):
|
||||
for plugin in self.run_after_plugins:
|
||||
self.start_run_after_plugin(plugin["name"])
|
||||
|
||||
|
||||
class RamUsage(Skill):
|
||||
"""
|
||||
skill class to get ram usage
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from statistics import mean
|
||||
from psutil import virtual_memory
|
||||
from time import sleep
|
||||
|
||||
testing_time = 10
|
||||
print_process = False
|
||||
|
||||
ram_list = []
|
||||
|
||||
while True:
|
||||
ram = virtual_memory()[2]
|
||||
ram_list.append(ram)
|
||||
if print_process is True:
|
||||
print("RAM: " + str(ram) + "%")
|
||||
sleep(1)
|
||||
|
||||
if len(ram_list) == testing_time:
|
||||
ram = mean(ram_list)
|
||||
break
|
||||
|
||||
self.speech_output(alang.start("skills", "ram_usage", {"ram_usage": round(ram, 2)}))
|
||||
|
||||
|
||||
class Shutdown(Skill):
|
||||
"""
|
||||
skill class to shutdown the system
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from os import system
|
||||
|
||||
system("sudo shutdown -h 0")
|
||||
|
||||
|
||||
class Wikipedia(Skill):
|
||||
"""
|
||||
skill class to search an article on wikipedia
|
||||
"""
|
||||
|
||||
def main(self):
|
||||
from aion_core.utils import remove_brackets, remove_space, remove_string_sequence
|
||||
from wikipediaapi import Wikipedia
|
||||
|
||||
splitted_acph = self.activate_phrase.split("__and__")
|
||||
searched_article = remove_string_sequence(self.speech_input, splitted_acph[0], splitted_acph[-1])
|
||||
wiki = Wikipedia(aconf.Aion().get_language().split("_")[0])
|
||||
article = wiki.page(searched_article)
|
||||
|
||||
if article.exists():
|
||||
article_text = remove_brackets(article.summary)
|
||||
article_text = remove_space(article_text)
|
||||
self.speech_output(alang.start("skills", "wikipedia", {"article_text": article_text}))
|
||||
else:
|
||||
self.speech_output(alang.start("skills", "wikipedia_article_not_found", {"article_name": searched_article}))
|
10
aion_data/skills/skills.xml
Normal file
10
aion_data/skills/skills.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<skills>
|
||||
<skills author="blueShard">
|
||||
<additional_directories>None</additional_directories>
|
||||
<description>The official skill library</description>
|
||||
<license>MIT</license>
|
||||
<main_file>skills.py</main_file>
|
||||
<required_python3_packages>['psutil', 'statistics', 'Wikipedia-API']</required_python3_packages>
|
||||
<version>1.0.0</version>
|
||||
</skills>
|
||||
</skills>
|
Loading…
x
Reference in New Issue
Block a user