Sebastiankay/eft_group_map_websocket
0
1from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect2from fastapi.middleware.cors import CORSMiddleware3from fastapi.responses import HTMLResponse4from fastapi.staticfiles import StaticFiles5from fastapi.templating import Jinja2Templates6import json7import uvicorn8 9app = FastAPI()10 11# Configure CORS12app.add_middleware(13 CORSMiddleware,14 allow_origins=["*"],15 allow_credentials=True,16 allow_methods=["*"],17 allow_headers=["*"],18)19 20# Serve static files21app.mount("/static", StaticFiles(directory="static"), name="static")22 23# Set up Jinja2 templates24templates = Jinja2Templates(directory="templates")25 26with open("data.json", "r", encoding="utf8") as file:27 maps_data = json.load(file)28 29 30with open("static/map.html", "r", encoding="utf-8") as f:31 map_html_template = f.read()32 33 34@app.get("/api/map/{normalized_name}")35async def get_map_data(normalized_name: str):36 map_entry = maps_data.get(normalized_name)37 if map_entry:38 return map_entry39 return {"error": "Map not found"}40 41 42@app.get("/", response_class=HTMLResponse)43async def read_index(request: Request):44 return templates.TemplateResponse("index.html", {"request": request, "maps": maps_data})45 46 47@app.get("/map/{normalized_name}", response_class=HTMLResponse)48async def get_map_page(normalized_name: str):49 # Optional: Prüfen, ob die Map existiert50 if normalized_name not in maps_data:51 return HTMLResponse(content="<h1>Map not found</h1>", status_code=404)52 53 # Gib einfach die statische HTML-Seite zurück54 return HTMLResponse(content=map_html_template)55 56 57# @app.get("/map/{normalized_name}", response_class=HTMLResponse)58# async def get_map_by_normalized_name(request: Request, normalized_name: str):59# map_entry = maps_data.get(normalized_name)60# if map_entry:61# filtered_maps = [map_entry]62# else:63# filtered_maps = []64# return templates.TemplateResponse("map.html", {"request": request, "maps": filtered_maps})65 66 67class ConnectionManager:68 def __init__(self):69 self.groups: dict[str, set[WebSocket]] = {}70 self.connections: dict[WebSocket, str] = {}71 72 async def connect(self, websocket: WebSocket):73 await websocket.accept()74 75 def disconnect(self, websocket: WebSocket):76 if websocket in self.connections:77 group_name = self.connections[websocket]78 self.remove_from_group(websocket, group_name)79 80 async def join_group(self, websocket: WebSocket, group_name: str):81 # Remove from previous group if exists82 if websocket in self.connections:83 old_group = self.connections[websocket]84 self.remove_from_group(websocket, old_group)85 86 # Add to new group87 if group_name not in self.groups:88 self.groups[group_name] = set()89 self.groups[group_name].add(websocket)90 self.connections[websocket] = group_name91 print(f"Client joined group '{group_name}'")92 93 def remove_from_group(self, websocket: WebSocket, group_name: str):94 if group_name in self.groups and websocket in self.groups[group_name]:95 self.groups[group_name].remove(websocket)96 if len(self.groups[group_name]) == 0:97 del self.groups[group_name]98 print(f"Group '{group_name}' deleted (no members)")99 if websocket in self.connections:100 del self.connections[websocket]101 print(f"Client removed from group '{group_name}'")102 103 async def broadcast_to_group(self, message: str, group_name: str):104 if group_name in self.groups:105 for connection in self.groups[group_name]:106 await connection.send_text(message)107 108 109manager = ConnectionManager()110 111 112@app.websocket("/ws")113async def websocket_endpoint(websocket: WebSocket):114 await manager.connect(websocket)115 try:116 while True:117 data = await websocket.receive_text()118 try:119 message = json.loads(data)120 # Handle join messages121 if message.get('type') == 'join':122 group_name = message.get('group')123 if group_name:124 await manager.join_group(websocket, group_name)125 else:126 error = json.dumps({127 "type": "error",128 "message": "Missing group name in join request"129 })130 await websocket.send_text(error)131 132 # Broadcast all other messages to the group133 else:134 if websocket in manager.connections:135 group_name = manager.connections[websocket]136 await manager.broadcast_to_group(data, group_name)137 else:138 error = json.dumps({139 "type": "error",140 "message": "Join a group before sending messages"141 })142 await websocket.send_text(error)143 144 except json.JSONDecodeError:145 # Handle non-JSON messages by broadcasting directly146 if websocket in manager.connections:147 group_name = manager.connections[websocket]148 await manager.broadcast_to_group(data, group_name)149 150 except WebSocketDisconnect:151 manager.disconnect(websocket)152 153 154if __name__ == "__main__":155 uvicorn.run(app, host="0.0.0.0", port=8000)