summaryrefslogtreecommitdiff
path: root/server/request.py
diff options
context:
space:
mode:
Diffstat (limited to 'server/request.py')
-rw-r--r--server/request.py210
1 files changed, 210 insertions, 0 deletions
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)