From 8b212187d17f5c1e337232de5816c215d06b9cd7 Mon Sep 17 00:00:00 2001 From: retoor Date: Sun, 29 Dec 2024 16:51:03 +0100 Subject: [PATCH] Ready to run. --- Makefile | 4 +- src/boeh/__init__.py | 10 ++- src/rwebgui/__main__.py | 9 ++- src/rwebgui/app.py | 87 ++++++++++---------- src/rwebgui/component.py | 167 ++++++++++++++++++++------------------- 5 files changed, 144 insertions(+), 133 deletions(-) diff --git a/Makefile b/Makefile index 6f44c5b..2fb608a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ BIN = ./.venv/bin/ PYTHON = ./.venv/bin/python PIP = ./.venv/bin/pip -APP_NAME=boeh +APP_NAME=rwebgui all: install build @@ -24,5 +24,5 @@ build: $(PYTHON) -m build run: - $(BIN)$(APP_NAME) --port=3028 + $(BIN)$(APP_NAME).serve --port=3080 diff --git a/src/boeh/__init__.py b/src/boeh/__init__.py index bc4711d..7ec8583 100644 --- a/src/boeh/__init__.py +++ b/src/boeh/__init__.py @@ -1,8 +1,10 @@ -from nio import AsyncClient, RoomMessageText import random +from nio import AsyncClient, RoomMessageText + + class BooeehBot: - + def generate_boeh(self): boeh = "b" for _ in range(random.randint(1, 10)): @@ -10,9 +12,9 @@ class BooeehBot: for _ in range(random.randint(1, 5)): boeh += "e" for _ in range(random.randint(1, 3)): - boeh += "e" + boeh += "e" return boeh - + def __init__(self, url, username, password): self.url = url self.username = username diff --git a/src/rwebgui/__main__.py b/src/rwebgui/__main__.py index 6553314..ab439cf 100644 --- a/src/rwebgui/__main__.py +++ b/src/rwebgui/__main__.py @@ -1,16 +1,17 @@ -from rwebgui.app import Application -from aiohttp import web import asyncio - from concurrent.futures import ThreadPoolExecutor as Executor +from aiohttp import web + +from rwebgui.app import Application + def main(): app = Application() executor = Executor(max_workers=20) loop = asyncio.get_event_loop() loop.set_default_executor(executor) - web.run_app(app, loop=loop,port=3080) + web.run_app(app, loop=loop, port=3080) if __name__ == "__main__": diff --git a/src/rwebgui/app.py b/src/rwebgui/app.py index a1fbc32..7c1e5a2 100644 --- a/src/rwebgui/app.py +++ b/src/rwebgui/app.py @@ -1,59 +1,63 @@ +import asyncio +import json import pathlib -from aiohttp import web +import time import uuid -from app.app import Application as BaseApplication + +from aiohttp import web +from app.app import Application as BaseApplication + from rwebgui.component import Component -import traceback -import time -import asyncio -import json + class EvalBox(Component): async def on_change(self, value): - + try: if value and value.strip().endswith("="): value = value.strip()[:-1] try: result = eval(value) value = value + "= " + str(result) - await self.set_attr("value",value) + await self.set_attr("value", value) except: pass - except AttributeError as ex: + except AttributeError: print(value) return value - class Button(Component): async def on_click(self, event): component = self.app.search - await component.set_attr("value","Woeiii") + await component.set_attr("value", "Woeiii") + class Button1(Component): - async def on_click(self,event): + async def on_click(self, event): field = self.app.search await field.toggle() - value = await field.get_style("display","block") + value = await field.get_style("display", "block") await self.set_attr("innerText", value) + class RandomString(Component): - async def task_random(self): - import random + import random + rand_bytes = [random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(15)] random_data = "".join(rand_bytes) while True: remember = random_data[0] - random_data = random_data[1:] + remember - await self.set_attr("innerHTML",random_data) + random_data = random_data[1:] + remember + await self.set_attr("innerHTML", random_data) await asyncio.sleep(0.01) + class Counter(Component): async def task_test(self): @@ -61,8 +65,6 @@ class Counter(Component): await asyncio.sleep(10) print("Slow task") - - async def task_increment(self): if not self.value: self.value = 0 @@ -72,41 +74,46 @@ class Counter(Component): except: self.value = 0 self.value += 1 - await self.set_attr("value",self.value) + await self.set_attr("value", self.value) await asyncio.sleep(1) + class GPT(Component): class Children: - prompt = Component + prompt = Component answer = Component + class submit(Component): async def trigger(self, id_, event, data): - print("GOGOG",event,data) + print("GOGOG", event, data) return await super().trigger(id_, event, data) - async def on_click(self,data): - from xmlrpc.client import ServerProxy + + async def on_click(self, data): + from xmlrpc.client import ServerProxy + client = ServerProxy("https://api.molodetz.nl/rpc") prompt = await self.app.prompt.get_attr("value") print(prompt) exit(0) - - await self.answer.set_attr("value",client.gpt4o(prompt)) - return {"event_id":data['event_id'],"success":True} + + await self.answer.set_attr("value", client.gpt4o(prompt)) + return {"event_id": data["event_id"], "success": True} + class SpeedMeter(Component): - def __init__(self, app, id_, description=None, ws = None): + def __init__(self, app, id_, description=None, ws=None): self.time_start = time.time() self.bytes_received = 0 super().__init__(app, id_, description, ws) async def task_update(self): while True: - bytes_received = self.bytes_received + bytes_received = self.bytes_received self.bytes_received = 0 - - await self.set_attr("value","{} kb/s".format(bytes_received / 1000)) + + await self.set_attr("value", f"{bytes_received / 1000} kb/s") await asyncio.sleep(1) async def trigger(self, id_, event, data): @@ -116,7 +123,7 @@ class SpeedMeter(Component): class App(Component): - + class Children: eval_box = EvalBox search = Component @@ -142,31 +149,29 @@ class Application(BaseApplication): self.location_static = self.location.joinpath("static") self.template_path = self.location.joinpath("templates") super().__init__(template_path=self.template_path) - self.router.add_static('/static', self.location_static) + self.router.add_static("/static", self.location_static) self.router.add_get("/", self.index_handler) self.router.add_get("/ws/{uuid}", self.websocket_handler) async def websocket_handler(self, request): # Extract the UUID from the route - uuid_value = request.match_info['uuid'] - + uuid_value = request.match_info["uuid"] + # Validate if it's a valid UUID try: uuid_obj = uuid.UUID(uuid_value) except ValueError: return web.Response(text="Invalid UUID", status=400) - + # Upgrade the connection to WebSocket ws = web.WebSocketResponse() await ws.prepare(request) - + print(f"WebSocket connection established with UUID: {uuid_obj}") component = App(self, "app", ws=ws) await component.service() - + return ws - - async def index_handler(self, request): - return await self.render_template("index.html",request,{}) + return await self.render_template("index.html", request, {}) diff --git a/src/rwebgui/component.py b/src/rwebgui/component.py index 4ca54de..b1428a5 100644 --- a/src/rwebgui/component.py +++ b/src/rwebgui/component.py @@ -1,54 +1,55 @@ -import uuid -import json +import asyncio import time -import aiohttp -import asyncio +import uuid + from aiohttp import web + class Component: - @classmethod + @classmethod def define(cls): return cls - def __init__(self,app, id_, description=None,ws: web.WebSocketResponse=None): + def __init__(self, app, id_, description=None, ws: web.WebSocketResponse = None): self.id = id_ - self.ws = ws + self.ws = ws self.app = app self.description = description self.children = [] self._callbacks = {} self.value = None self._running = False - if not hasattr(self,"Children"): - return + if not hasattr(self, "Children"): + return for name in dir(self.Children): if name.startswith("__"): continue obj = getattr(self.Children, name) - - instance = obj(app=self.app,id_=name,ws=ws ) + + instance = obj(app=self.app, id_=name, ws=ws) self.add_child(instance) instance.app = self instance.ws = self.ws setattr(self, name, instance) + @classmethod def from_json(cls, json): obj = cls(None, None) obj.__dict__ = json return obj - + @classmethod def to_json(cls): - obj = cls.__dict__ .copy() + obj = cls.__dict__.copy() return obj - - @classmethod + + @classmethod def clone(cls): return cls.from_json(cls.to_json()) - + @property def running(self): if not hasattr(self.app, "_running"): @@ -57,21 +58,25 @@ class Component: @property def tasks(self): - tasks_ = [getattr(self, name) for name in dir(self) if name.startswith("task_") and hasattr(self, name)] + tasks_ = [ + getattr(self, name) + for name in dir(self) + if name.startswith("task_") and hasattr(self, name) + ] for child in self.children: - tasks_ += child.tasks#.extend(await child.get_tasks()) + tasks_ += child.tasks # .extend(await child.get_tasks()) return tasks_ async def communicate(self, event_id=None): - + async for msg in self.ws: if msg.type == web.WSMsgType.TEXT: # Echo the message back to the client - #print(f"Received message: {msg.data}") + # print(f"Received message: {msg.data}") data = msg.json() if not event_id: pass - #return data + # return data else: if data.get("event_id") == event_id: return data @@ -80,55 +85,55 @@ class Component: def callbacks(self): return hasattr(self.app, "callbacks") and self.app.callbacks or self._callbacks - - async def trigger(self,id_, event,data): + async def trigger(self, id_, event, data): if self.id == id_: - method_name = "on_"+event + method_name = "on_" + event if hasattr(self, method_name): method = getattr(self, method_name) await method(data) print("JAAJ") for child in self.children: - await child.trigger(id_,event,data) - + await child.trigger(id_, event, data) + async def register_callback(self, event_id, callback): self.callbacks[event_id] = callback - async def call(self, method, args=None,id_=None, callback=True): + async def call(self, method, args=None, id_=None, callback=True): while not self.running: await asyncio.sleep(0.1) if not args: - args= [] + args = [] event_id = str(uuid.uuid4()) loop = asyncio.get_running_loop() future = loop.create_future() self.callbacks[event_id] = lambda data: future.set_result(data) - await self.ws.send_json({ - "event_id": event_id, - "event": "call", - "id": id_ and id_ or self.id, - "method": method, - "args": args, - "callback": callback - }) + await self.ws.send_json( + { + "event_id": event_id, + "event": "call", + "id": id_ and id_ or self.id, + "method": method, + "args": args, + "callback": callback, + } + ) if callback: - response = await self.communicate(event_id=event_id) - return response['result'] - #print("GLUKT") - #return response['result'] - - return True - #return await future + response = await self.communicate(event_id=event_id) + return response["result"] + # print("GLUKT") + # return response['result'] + return True + # return await future async def get_attr(self, key, default=None): - result = await self.call("getAttr", [self.id, key],True) + result = await self.call("getAttr", [self.id, key], True) return result or default async def set_attr(self, key, value): - result = await self.call("setAttr", [self.id,key,value],callback=False) - return result + result = await self.call("setAttr", [self.id, key, value], callback=False) + return result async def get(self, id_): if self.id == id_: @@ -139,16 +144,16 @@ class Component: return child async def set_data(self, key, value): - result = await self.call("setData", [self.id, key,value], callback=False) - return result + result = await self.call("setData", [self.id, key, value], callback=False) + return result async def get_data(self, key, default=None): - result = await self.call("getData", [self.id,key], default,True) + result = await self.call("getData", [self.id, key], default, True) return result or default async def set_style(self, key, value): - result = await self.call("setStyle", [self.id, key,value], callback=False) - return result + result = await self.call("setStyle", [self.id, key, value], callback=False) + return result async def toggle(self): value = await self.get_style("display", "block") @@ -160,13 +165,10 @@ class Component: await self.set_style("display", value) async def get_style(self, key, default=None): - result = await self.call("getStyle", [self.id,key], default) + result = await self.call("getStyle", [self.id, key], default) return result or default - - - - async def on_keyup(self,event): + async def on_keyup(self, event): value = await self.get_attr("value") if self.value != value: if hasattr(self, "on_change"): @@ -174,11 +176,10 @@ class Component: self.value = value return self.value - async def get_tasks(self): tasks = self.tasks for child in self.children: - tasks += child.tasks#.extend(await child.get_tasks()) + tasks += child.tasks # .extend(await child.get_tasks()) return tasks async def set_running(self): @@ -197,42 +198,44 @@ class Component: async for msg in self.ws: if msg.type == web.WSMsgType.TEXT: # Echo the message back to the client - #print(f"Received message: {msg.data}") + # print(f"Received message: {msg.data}") data = msg.json() - response = {"event_id":data['event_id'],"success":True} - response['time_start'] = time.time() - if self.callbacks.get(data['event_id']): - self.callbacks[data['event_id']](data['result']) - elif data.get('data') and not data['data'].get('id'): - response['handled'] = False - elif data.get('data'): - response['handled'] = True - response['data'] = await self.trigger(data['data']['id'], data['event'],data['data']) - response['cancel'] = True + response = {"event_id": data["event_id"], "success": True} + response["time_start"] = time.time() + if self.callbacks.get(data["event_id"]): + self.callbacks[data["event_id"]](data["result"]) + elif data.get("data") and not data["data"].get("id"): + response["handled"] = False + elif data.get("data"): + response["handled"] = True + response["data"] = await self.trigger( + data["data"]["id"], data["event"], data["data"] + ) + response["cancel"] = True - response['time_end'] = time.time() - response['time_duration'] = response['time_end'] - response['time_start'] - await self.ws.send_json(response) - - #await ws.send_str(f"Echo: {msg.data}") + response["time_end"] = time.time() + response["time_duration"] = ( + response["time_end"] - response["time_start"] + ) + await self.ws.send_json(response) + + # await ws.send_str(f"Echo: {msg.data}") elif msg.type == web.WSMsgType.ERROR: print(f"WebSocket error: {self.ws.exception()}") except Exception as ex: print(ex) pass - - #async def the_task(): - # while True: - # time.sleep(1) - #while True: + # async def the_task(): + # while True: + # time.sleep(1) + # while True: tasks.append(events) await asyncio.gather(*[task() for task in tasks]) - #await asyncio.create_task(asyncio.gather(*[task() for task in tasks])) - #await tasks() + # await asyncio.create_task(asyncio.gather(*[task() for task in tasks])) + # await tasks() print("AFTERR") - def add_child(self, child): child.app = self.app child.ws = self.ws