From bd9d683767aadbc4fca9b72850e97761dbd6abf4 Mon Sep 17 00:00:00 2001 From: "info@pi-farm.de" Date: Fri, 6 Mar 2026 22:39:01 +0000 Subject: [PATCH] main.py aktualisiert --- main.py | 61 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/main.py b/main.py index 7a2cfd3..7fe3a27 100644 --- a/main.py +++ b/main.py @@ -7,6 +7,8 @@ import asyncio import openai import re import httpx +import struct +import termios from google import genai from google.genai import types import json @@ -337,30 +339,63 @@ async def log_websocket(websocket: WebSocket): @app.websocket("/ws/terminal/{ip}") async def terminal_websocket(websocket: WebSocket, ip: str): await websocket.accept() - conn = get_db(); node = conn.execute('SELECT * FROM nodes WHERE ip = ?', (ip,)).fetchone(); conn.close() - if not node: await websocket.close(); return + conn = get_db() + node = conn.execute('SELECT * FROM nodes WHERE ip = ?', (ip,)).fetchone() + conn.close() + + if not node: + await websocket.close() + return + master_fd, slave_fd = pty.openpty() - proc = await asyncio.create_subprocess_exec("ssh", "-o", "StrictHostKeyChecking=no", "-t", f"{node['user']}@{ip}", stdin=slave_fd, stdout=slave_fd, stderr=slave_fd) + # Wir starten SSH im interaktiven Modus + proc = await asyncio.create_subprocess_exec( + "ssh", "-o", "StrictHostKeyChecking=no", "-t", + f"{node['user']}@{ip}", + stdin=slave_fd, stdout=slave_fd, stderr=slave_fd + ) + async def pty_to_ws(): - fl = fcntl.fcntl(master_fd, fcntl.F_GETFL); fcntl.fcntl(master_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + fl = fcntl.fcntl(master_fd, fcntl.F_GETFL) + fcntl.fcntl(master_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) try: while True: await asyncio.sleep(0.01) try: data = os.read(master_fd, 1024).decode(errors='ignore') - if data: await websocket.send_text(data) - except BlockingIOError: continue - except: pass + if data: + await websocket.send_text(data) + except BlockingIOError: + continue + except: + pass + async def ws_to_pty(): try: while True: - data = await websocket.receive_text(); os.write(master_fd, data.encode()) - except: pass - try: await asyncio.gather(pty_to_ws(), ws_to_pty()) - finally: - if proc.returncode is None: proc.terminate() - os.close(master_fd); os.close(slave_fd) + data = await websocket.receive_text() + # Prüfen, ob es ein Resize-Kommando (JSON) ist + if data.startswith('{"type":"resize"'): + resize_data = json.loads(data) + cols = resize_data['cols'] + rows = resize_data['rows'] + # Das hier setzt die Größe des PTY im Betriebssystem + s = struct.pack("HHHH", rows, cols, 0, 0) + fcntl.ioctl(master_fd, termios.TIOCSWINSZ, s) + else: + # Normale Terminal-Eingabe + os.write(master_fd, data.encode()) + except: + pass + try: + await asyncio.gather(pty_to_ws(), ws_to_pty()) + finally: + if proc.returncode is None: + proc.terminate() + os.close(master_fd) + os.close(slave_fd) + @app.websocket("/ws/chat") async def chat_endpoint(websocket: WebSocket): await websocket.accept()