Webseite überarbeitet und Telegram Bot funktion hinzugefügt #1
61
main.py
61
main.py
@@ -7,6 +7,8 @@ import asyncio
|
|||||||
import openai
|
import openai
|
||||||
import re
|
import re
|
||||||
import httpx
|
import httpx
|
||||||
|
import struct
|
||||||
|
import termios
|
||||||
from google import genai
|
from google import genai
|
||||||
from google.genai import types
|
from google.genai import types
|
||||||
import json
|
import json
|
||||||
@@ -337,30 +339,63 @@ async def log_websocket(websocket: WebSocket):
|
|||||||
@app.websocket("/ws/terminal/{ip}")
|
@app.websocket("/ws/terminal/{ip}")
|
||||||
async def terminal_websocket(websocket: WebSocket, ip: str):
|
async def terminal_websocket(websocket: WebSocket, ip: str):
|
||||||
await websocket.accept()
|
await websocket.accept()
|
||||||
conn = get_db(); node = conn.execute('SELECT * FROM nodes WHERE ip = ?', (ip,)).fetchone(); conn.close()
|
conn = get_db()
|
||||||
if not node: await websocket.close(); return
|
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()
|
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():
|
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:
|
try:
|
||||||
while True:
|
while True:
|
||||||
await asyncio.sleep(0.01)
|
await asyncio.sleep(0.01)
|
||||||
try:
|
try:
|
||||||
data = os.read(master_fd, 1024).decode(errors='ignore')
|
data = os.read(master_fd, 1024).decode(errors='ignore')
|
||||||
if data: await websocket.send_text(data)
|
if data:
|
||||||
except BlockingIOError: continue
|
await websocket.send_text(data)
|
||||||
except: pass
|
except BlockingIOError:
|
||||||
|
continue
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
async def ws_to_pty():
|
async def ws_to_pty():
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
data = await websocket.receive_text(); os.write(master_fd, data.encode())
|
data = await websocket.receive_text()
|
||||||
except: pass
|
# Prüfen, ob es ein Resize-Kommando (JSON) ist
|
||||||
try: await asyncio.gather(pty_to_ws(), ws_to_pty())
|
if data.startswith('{"type":"resize"'):
|
||||||
finally:
|
resize_data = json.loads(data)
|
||||||
if proc.returncode is None: proc.terminate()
|
cols = resize_data['cols']
|
||||||
os.close(master_fd); os.close(slave_fd)
|
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")
|
@app.websocket("/ws/chat")
|
||||||
async def chat_endpoint(websocket: WebSocket):
|
async def chat_endpoint(websocket: WebSocket):
|
||||||
await websocket.accept()
|
await websocket.accept()
|
||||||
|
|||||||
Reference in New Issue
Block a user