from typing import Union from ujson import JSONDecodeError as JSONDecodeError from ujson import loads, dumps from sys import exit from os import kill, sep from os import name as osname from traceback import print_exc from modules.logging import logWrite def jsonLoad(filename): """Loads arg1 as json and returns its contents""" with open(filename, "r", encoding='utf8') as file: try: output = loads(file.read()) except JSONDecodeError: logWrite(f"Could not load json file {filename}: file seems to be incorrect!\n{print_exc()}") raise except FileNotFoundError: logWrite(f"Could not load json file {filename}: file does not seem to exist!\n{print_exc()}") raise return output def jsonSave(contents, filename): """Dumps dict/list arg1 to file arg2""" try: with open(filename, "w", encoding='utf8') as file: file.write(dumps(contents, ensure_ascii=False, indent=4)) except Exception as exp: logWrite(f"Could not save json file {filename}: {exp}\n{print_exc()}") return def configSet(key: str, value, *args: str, file: str = "config"): """Set key to a value Args: * key (str): The last key of the keys path. * value (str/int/float/list/dict/None): Some needed value. * *args (str): Path to key like: dict[args][key]. * file (str): User ID to save. Saved to config if not provided. Defaults to "config". """ if file == "config": filepath = "" this_dict = jsonLoad(f"{filepath}{file}.json") if this_dict["debug"] is True: try: this_dict = jsonLoad("config_debug.json") file = "config_debug" except FileNotFoundError: print("Debug mode is set but config_debug.json is not there! Falling back to config.json", flush=True) else: filepath = f"data{sep}users{sep}" this_dict = jsonLoad(f"{filepath}{file}.json") string = "this_dict" for arg in args: string += f'["{arg}"]' if type(value) in [str]: value.replace("'", "\'").replace('"', '\"') if len(value) < 30: string += f'["{key}"] = "{value}"' else: string += f'["{key}"] = """{value}"""' else: string += f'["{key}"] = {value}' exec(string) jsonSave(this_dict, f"{filepath}{file}.json") return def configGet(key: str, *args: str, file: str = "config"): """Get value of the config key Args: * key (str): The last key of the keys path. * *args (str): Path to key like: dict[args][key]. * file (str): User ID to load. Loads config if not provided. Defaults to "config". Returns: * any: Value of provided key """ if file == "config": try: this_dict = jsonLoad("config.json") except FileNotFoundError: print("Config file not found! Copy config_example.json to config.json, configure it and rerun the bot!", flush=True) exit() if this_dict["debug"] is True: try: this_dict = jsonLoad("config_debug.json") except FileNotFoundError: print("Debug mode is set but config_debug.json is not there! Falling back to config.json", flush=True) else: this_dict = jsonLoad(f"data{sep}users{sep}{file}.json") this_key = this_dict for dict_key in args: this_key = this_key[dict_key] return this_key[key] def locale(key: str, *args: str, locale=configGet("locale")) -> Union[str, list, dict]: """Get value of locale string Args: * key (str): The last key of the locale's keys path. * *args (list): Path to key like: dict[args][key]. * locale (str): Locale to looked up in. Defaults to config's locale value. Returns: * any: Value of provided locale key """ if (locale == None): locale = configGet("locale") try: this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{locale}.json') except FileNotFoundError: try: this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{configGet("locale")}.json') except FileNotFoundError: return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"' this_key = this_dict for dict_key in args: this_key = this_key[dict_key] try: return this_key[key] except KeyError: return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"' try: from psutil import Process except ModuleNotFoundError: # print(locale("deps_missing", "console", locale=configGet("locale")), flush=True) print("Missing dependencies! Please install all needed dependencies and run the bot again!") exit() def killProc(pid): if osname == "posix": from signal import SIGKILL # type: ignore kill(pid, SIGKILL) else: p = Process(pid) p.kill()