From 58ebd3bc0f00c532e97e9a5571471ffab87934ba Mon Sep 17 00:00:00 2001 From: AL-LCL Date: Fri, 19 May 2023 10:39:49 +0200 Subject: GOD-VIEW --- server/request.py | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 server/request.py (limited to 'server/request.py') diff --git a/server/request.py b/server/request.py new file mode 100644 index 0000000..66529b7 --- /dev/null +++ b/server/request.py @@ -0,0 +1,210 @@ +''' + Handles the requests made to clients, including + interval, autotasks, terminal & GUI. These are + correctly interpreted to specific formats & + is the foundation of the program. + + Verified: 2021 February 8 + * Follows PEP8 + * Tested Platforms + * Windows 10 + * Third Party Modules + * eel +''' + +from server.state import ServerStatic, Dynamic +from server.controller import Controller +from server.helper import ServerHelper +from server.settings import Settings +from server.console import Console +from shared.helper import Helper +from shared.state import Static +from shared.data import Data + +import threading +import traceback +import queue +import os + +if not ServerStatic.TERMINAL: + import eel + + +class Request: + + __LOADING_AMID_LENGTH = len(ServerStatic.LOADING_AMID) + __AUTOTASK_FN = 'autotasks.txt' + __LOCK = threading.Lock() + + def __init__(self, message, loading=ServerStatic.LOADING, + ret=False, callback=None, args=(), custom=None): + self.__queue = queue.Queue() + + self.__message = message + self.__loading = loading + self.__callback = callback + self.__args = args + + if custom is None: + self.__clients = [(unique_id, Dynamic.CLIENTS[unique_id]) + for unique_id in Dynamic.SESSION] + self.__autotask = False + self.__interval = False + self.__ret = ret + + if not self.__ret: + self.__first_stdout = True + else: + self.__clients = [(unique_id, Dynamic.CLIENTS[unique_id]) + for unique_id in custom[0]] + self.__autotask = custom[1] + self.__interval = not self.__autotask + self.__ret = False + + if self.__ret: + self.__responses = [] + self.__html = False + + def send(self): + if any((self.__ret, self.__autotask, self.__interval)): + self.__employ_workers() + self.__create_jobs() + + if self.__ret: + if self.__html: + return dict(html=True, + message=Helper.join( + *self.__responses)) + else: + return Helper.join(*self.__responses) + else: + with Console.LOCK: + Console.printf(self.__loading, raw=True, + loading=True, lock=False) + + self.__employ_workers() + self.__create_jobs() + + Console.printf(raw=True, lock=False) + + def __employ_workers(self): + for _ in self.__clients: + Helper.thread(self.__worker) + + def __create_jobs(self): + for client in self.__clients: + self.__queue.put(client) + + self.__queue.join() + + def __worker(self): + try: + unique_id, client = self.__queue.get() + response = self.__execute_request(unique_id, client) + + if self.__ret: + self.__responses.append( + self.__main_response(unique_id, client, response)) + elif self.__autotask: + dirpath = os.path.join(ServerStatic.ARCHIVE_DIR, + client.connect_ip.safe) + + if not os.path.isdir(dirpath): + os.makedirs(dirpath, exist_ok=True) + + Helper.write_file( + os.path.join(dirpath, Request.__AUTOTASK_FN), + 'AUTOTASK ACTION: [ {} {} ]\n{}\n'.format( + self.__message['message'], ServerStatic.LOADING_AMID, + self.__main_response(unique_id, client, response))) + elif self.__interval: + if not ServerStatic.TERMINAL: + if eel._websockets != []: + if Settings.GUI_UPDATE: + response.update(dict(unique_id=unique_id)) + eel.activityUpdateEel(response) + else: + with Request.__LOCK: + if self.__first_stdout: + self.__first_stdout = False + Console.printf(ServerHelper.repeat( + len(self.__loading)), raw=True, + loading=True, lock=False) + else: + Console.printf(ServerHelper.repeat( + Request.__LOADING_AMID_LENGTH), + raw=True, loading=True, lock=False) + + self.__main_response(unique_id, client, response) + Console.printf(ServerStatic.LOADING_AMID, + raw=True, loading=True, + newline=True, lock=False) + + if self.__callback: + if 'custom' in response: + self.__callback(client.connect_ip, unique_id, + response['custom'], *self.__args) + except Exception: + Console.log(traceback.format_exc(), + log_type=ServerStatic.TRACEBACK) + finally: + self.__queue.task_done() + + def __main_response(self, unique_id, client, response): + prefix = 'Response: {} {} {}'.format(client.connect_ip.pure, + ServerStatic.SEPERATOR, + unique_id) + message = response['message'] + table = type(message) is list + + try: + if message: + if table: + table_response = Console.tabulate( + *message, self.__ret, self.__autotask, f'{prefix}\n') + + if self.__ret: + if not self.__html: + self.__html = True + + return table_response + else: + return Console.printf( + f'{prefix}\n{message}', **response['headers'], + ret=self.__ret or self.__autotask, lock=False) + else: + return Console.printf( + f'{prefix}\nEmpty Response\n', Static.INFO, False, + ret=self.__ret or self.__autotask, lock=False) + except Exception: + Console.log('Response Handling Error\n', + Static.DANGER, ServerStatic.ACTION) + Console.log(traceback.format_exc(), + log_type=ServerStatic.TRACEBACK) + + return Console.printf( + f'{prefix}\nResponse Handling Error', Static.DANGER, + False, ret=self.__ret or self.__autotask, lock=False) + + def __execute_request(self, unique_id, client): + try: + Data.send(client.socket, self.__message) + response = Data.recv(client.socket, True) + + return response + except Exception: + Console.log('Request Execution Errror\n', + Static.DANGER, ServerStatic.ACTION) + Console.log(traceback.format_exc(), + log_type=ServerStatic.TRACEBACK) + + try: + Controller.delete_client(unique_id) + except Exception: + Console.log(traceback.format_exc(), + log_type=ServerStatic.TRACEBACK) + finally: + return Data.parse(Helper.join( + 'Timeout / error emerged awaiting client response', + 'Client disconnected & removed from active session' + ), status=Static.DANGER) -- cgit v1.2.3