kylsprt commited on
Commit
ad09c4d
·
verified ·
1 Parent(s): a7e3093

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +77 -21
main.py CHANGED
@@ -2,9 +2,10 @@ from fastapi import FastAPI, WebSocket, WebSocketDisconnect
2
  from fastapi.responses import HTMLResponse
3
  from pathlib import Path
4
  import uvicorn
 
5
 
6
  app = FastAPI()
7
- rooms: dict[str, set[WebSocket]] = {}
8
 
9
  @app.get("/")
10
  async def index():
@@ -12,32 +13,87 @@ async def index():
12
 
13
  @app.get("/ping")
14
  async def ping():
15
- return {"status": "alive", "rooms": {k: len(v) for k, v in rooms.items()}}
16
 
17
  @app.websocket("/ws/{room}")
18
- async def ws_relay(websocket: WebSocket, room: str):
19
  await websocket.accept()
20
- rooms.setdefault(room, set()).add(websocket)
21
- print(f"[+] Join room '{room}' | total: {len(rooms[room])}")
 
 
 
22
  try:
23
  while True:
24
- data = await websocket.receive_bytes()
25
- if len(data) < 100:
26
- continue # skip keep-alive ping
27
- dead = []
28
- for peer in rooms.get(room, set()):
29
- if peer != websocket:
30
- try:
31
- await peer.send_bytes(data)
32
- except Exception:
33
- dead.append(peer)
34
- for d in dead:
35
- rooms[room].discard(d)
36
  except (WebSocketDisconnect, Exception):
37
- rooms.get(room, set()).discard(websocket)
38
- if room in rooms and not rooms[room]:
39
- del rooms[room]
40
- print(f"[-] Left room '{room}'")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  if __name__ == "__main__":
43
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
2
  from fastapi.responses import HTMLResponse
3
  from pathlib import Path
4
  import uvicorn
5
+ import json
6
 
7
  app = FastAPI()
8
+ rooms = {}
9
 
10
  @app.get("/")
11
  async def index():
 
13
 
14
  @app.get("/ping")
15
  async def ping():
16
+ return {"status": "alive"}
17
 
18
  @app.websocket("/ws/{room}")
19
+ async def ws_endpoint(websocket: WebSocket, room: str):
20
  await websocket.accept()
21
+ if room not in rooms:
22
+ rooms[room] = {"peers": set(), "server": None}
23
+ r = rooms[room]
24
+ r["peers"].add(websocket)
25
+ await broadcast_state(r)
26
  try:
27
  while True:
28
+ msg = await websocket.receive()
29
+ if "text" in msg:
30
+ await handle_signal(r, websocket, json.loads(msg["text"]))
31
+ elif "bytes" in msg:
32
+ raw = msg["bytes"]
33
+ if len(raw) < 2:
34
+ continue
35
+ tag = raw[0]
36
+ if tag == 1:
37
+ await relay(r, websocket, raw)
38
+ elif tag == 2 and websocket == r["server"]:
39
+ await relay(r, websocket, raw)
40
  except (WebSocketDisconnect, Exception):
41
+ r["peers"].discard(websocket)
42
+ if websocket == r["server"]:
43
+ r["server"] = None
44
+ if not r["peers"]:
45
+ rooms.pop(room, None)
46
+ else:
47
+ await broadcast_state(r)
48
+
49
+ async def relay(r, sender, data):
50
+ dead = []
51
+ for peer in list(r["peers"]):
52
+ if peer != sender:
53
+ try:
54
+ await peer.send_bytes(data)
55
+ except:
56
+ dead.append(peer)
57
+ for d in dead:
58
+ r["peers"].discard(d)
59
+
60
+ async def handle_signal(r, ws, data):
61
+ t = data.get("type")
62
+ if t == "set_server":
63
+ old = r["server"]
64
+ r["server"] = ws
65
+ if old and old != ws and old in r["peers"]:
66
+ try:
67
+ await old.send_text(json.dumps({"type": "force_client"}))
68
+ except:
69
+ pass
70
+ await broadcast_state(r)
71
+ elif t == "set_client":
72
+ if ws == r["server"]:
73
+ r["server"] = None
74
+ await broadcast_state(r)
75
+ elif t == "remote_speaker":
76
+ srv = r["server"]
77
+ if srv and srv in r["peers"]:
78
+ try:
79
+ await srv.send_text(json.dumps({
80
+ "type": "remote_speaker",
81
+ "enabled": data.get("enabled", True)
82
+ }))
83
+ except:
84
+ pass
85
+
86
+ async def broadcast_state(r):
87
+ for peer in list(r["peers"]):
88
+ try:
89
+ await peer.send_text(json.dumps({
90
+ "type": "state",
91
+ "peers": len(r["peers"]),
92
+ "has_server": r["server"] is not None,
93
+ "is_server": peer == r["server"]
94
+ }))
95
+ except:
96
+ r["peers"].discard(peer)
97
 
98
  if __name__ == "__main__":
99
  uvicorn.run(app, host="0.0.0.0", port=7860)