import json # Used by long_strings(), get_params() and make_files() import logging # Used for logging import os # Used by make_files() to check if files exist import sys # Used to specify printing for logging # All of this is logging configuration FORMAT = " %(asctime)s | %(name)-16s | %(levelname)-8s | %(message)s" PRINTFORMAT = "%(asctime)s - %(message)s" DATEFORMAT = "%Y-%m-%d %H:%M:%S" logging.addLevelName(25, "PRINT") loggingConfigParams = { "format": FORMAT, "datefmt": DATEFORMAT, "level": logging.INFO, "filename": "gwendolyn.log" } logging.basicConfig(**loggingConfigParams) logger = logging.getLogger("Gwendolyn") printer = logging.getLogger("printer") handler = logging.StreamHandler(sys.stdout) handler.setFormatter(logging.Formatter(fmt=PRINTFORMAT, datefmt=DATEFORMAT)) printer.addHandler(handler) printer.propagate = False def sanitize(data: str, lower_case_value: bool = False): """ Sanitize and create a dictionary from a string. Each element is created from a line with a : in it. The key is left of the :, the value is right of it. *Parameters* ------------ data: str The string to create a dict from. lower_case_value: bool = False Whether the value of each element should be lowercase. *Returns* --------- dct: dict The sanitized dictionary of elements. """ data = data.splitlines() dct = {} for line in data: if line[0] != "#" and ":" in line: line_values = line.split(":") line_values[0] = line_values[0].lower() line_values[1] = line_values[1].replace(" ", "") if lower_case_value: line_values[1] = line_values[1].lower() if line_values[0] in ["testing guild ids", "admins"]: line_values[1] = line_values[1].split(",") if all(i.isnumeric() for i in line_values[1]): line_values[1] = [int(i) for i in line_values[1]] if any(i == line_values[1] for i in ["true", "false"]): line_values[1] = (line_values[1] == "true") dct[line_values[0]] = line_values[1] return dct def get_options(): """ Get the bot options as dict. *Returns* --------- options: dict The options of the bot. """ with open("options.txt", "r", encoding="utf-8") as file_pointer: data = sanitize(file_pointer.read(), True) options = {} options["testing"] = data["testing"] options["guild_ids"] = data["testing guild ids"] options["admins"] = data["admins"] return options def get_credentials(): """ Returns the credentials used by the bot as a dict. *Returns* --------- credentials: dict The credentials used by the bot. """ with open("credentials.txt", "r", encoding="utf-8") as file_pointer: data = sanitize(file_pointer.read()) credentials = {} credentials["token"] = data["bot token"] credentials["wordnik_key"] = data["wordnik api key"] credentials["mongo_db_user"] = data["mongodb user"] credentials["mongo_db_password"] = data["mongodb password"] credentials["wolfram_alpha_key"] = data["wolframalpha appid"] credentials["radarr_key"] = data["radarr api key"] credentials["sonarr_key"] = data["sonarr api key"] credentials["qbittorrent_username"] = data["qbittorrent username"] credentials["qbittorrent_password"] = data["qbittorrent password"] return credentials def long_strings(): """ Get the data from gwendolyn/resources/long_strings.json. *Returns* --------- data: dict The long strings and their keys. """ long_strings_path = "gwendolyn/resources/long_strings.json" with open(long_strings_path, "r", encoding="utf-8") as file_pointer: data = json.load(file_pointer) return data def log(messages, channel: str = "", level: int = 20): """ Log something in Gwendolyn's logs. *Parameters* ------------ messages: Union[str, list] A string or list of strings to be logged. If there are multiple strings and the level is PRINT (25) or higher, only the first string will be printed. channel: str = "" The channel the event to be logged occurred in. Will be logged along with the message(s). level: int = 20 The level to log the message(s) at. If PRINT (25) or higher, the first message will be printed to the console. """ channel = channel.replace("Direct Message with ", "") if isinstance(messages, str): messages = [messages] print_message = messages[0] for i, message in enumerate(messages): if channel != "": messages[i] = f"{message} - ({channel})" # Adds channel ID # to log messages if len(messages) > 1: # Tells user to check the log if there are # more messages there print_message += " (details in log)" if level >= 25: printer.log(level, print_message) for log_message in messages: logger.log(level, log_message) def make_files(): """Create all the files and directories needed by Gwendolyn.""" def make_json_file(path, content): """Create json file if it doesn't exist.""" if not os.path.isfile(path): log(path.split("/")[-1]+" didn't exist. Making it now.") with open(path, "w", encoding="utf-8") as file_pointer: json.dump(content, file_pointer, indent=4) def make_txt_file(path, content): """Create txt file if it doesn't exist.""" if not os.path.isfile(path): log(path.split("/")[-1]+" didn't exist. Making it now.") with open(path, "w", encoding="utf-8") as file_pointer: file_pointer.write(content) def directory(path): """Create directory if it doesn't exist.""" if not os.path.isdir(path): os.makedirs(path) log("The "+path.split("/")[-1]+" directory didn't exist") file_path = "gwendolyn/resources/starting_files.json" with open(file_path, "r", encoding="utf-8") as file_pointer: data = json.load(file_pointer) for path in data["folder"]: directory(path) for path, content in data["json"].items(): make_json_file(path, content) for path, content in data["txt"].items(): make_txt_file(path, content)