""" AUTHOR: Khushal P Soonderji DATE: Create: Tuesday, 30th Sept., 2025 OBJECTIVE: A namespace to REFERENCES: N/A DOWNLOADS: N/A """ # ***************************************************************************************************************** # ***** **** # *** IMPORT *** # ***** **** # ***************************************************************************************************************** # To make sibling directories accessible for imports: import sys sys.path.append(".") sys.path.append("..") # To work with SocketIO: import socketio # To maintain the app's state: from wsio_v2.app_state import AppState # For pre-modelled responses: from utils_v2.api.codes import HttpCodes, StatusCodes from utils_v2.api.response import ResponseModel # ***************************************************************************************************************** # ***** **** # *** MACROS / ONE-TIME INIT *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** VARIABLES *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** FUNCTIONS *** # ***** **** # ***************************************************************************************************************** class EchoNamespace(socketio.AsyncNamespace): def __init__( self, namespace: str, app_state: AppState, ): """ To set up the namespace that will handle tick data. :param namespace: The string that defines the path of the namespace. E.g.: "/test". :param app_state: The AppState that defines the state of the app and carries any custom variables that will be needed across various namespaces. It's a good way to pass instances of database connections and other shared variables. """ super().__init__(namespace) self.app_state = app_state self.app_state.printer("Registered!") async def on_connect(self, sid, environ, *args) -> bool | None: """ The handler that validates and accepts or rejects incoming connection requests. :param sid: The socketio session id. :param environ: The environment information. :param args: The arguments passed to the handler. :returns: True if the connection was accepted, else False. """ self.app_state.printer("Connection Attempt", sid) async def on_disconnect(self, sid, reason, *args): """ The handler that notes down that the user has been disconnected and frees up any relevant resources. :param sid: The socketio session id. :param reason: The reason for termination. :param args: The arguments passed to the handler. :returns: None. """ self.app_state.printer("On Disconnect", sid) async def on_echo(self, sid, data): """ A test event that can be used to see if the namespace is up and running, or not. :param sid: The socketio session id. :param data: The data sent by the client. :returns: None. """ self.app_state.printer("Event", sid, data, type(data).__name__) await self.emit("echo", data, to = sid) async def on_set_watchlist(self, sid, data) -> dict: """ To handle the request to set the watchlist for a particular user. :param sid: The socketio session id. :param data: The data sent by the client. :returns: None. """ self.app_state.printer("Setting Watchlist", sid) # Start by assuming success: response = ResponseModel( status_code = StatusCodes.OK, message = "Watchlist set successfully.", data = None ) # Prepare a list of tickers from the request: tickers_list = [] # Remove the user from all rooms (tickers): if response.success: try: rooms = self.rooms(sid) for room in rooms: if room != sid: # ... Don't remove them from their private room. await self.leave_room(sid, room) except Exception as e: self.app_state.printer("EXCEPTION!", e) response.status_code = StatusCodes.FAILED response.message = "Failed to reset previous watchlist." # Now add the user back to just those rooms (tickers) that he has requested: if response.success: try: for room in tickers_list: await self.enter_room(sid, room) except Exception as e: self.app_state.printer("EXCEPTION!", e) response.status_code = StatusCodes.FAILED response.message = "Failed to set new watchlist." # Done here: response_dict, response_http_code = response.for_quart() await self.emit("set_watchlist", response_dict, to = sid) # ***************************************************************************************************************** # ***** **** # *** MAIN PROGRAM *** # ***** **** # ***************************************************************************************************************** if __name__ == "__main__": pass