Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException | |
| from fastapi.responses import HTMLResponse, FileResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| import uvicorn | |
| import json | |
| import secrets | |
| from typing import Dict, Set | |
| from datetime import datetime | |
| app = FastAPI(title="ParthMeet") | |
| # CORS middleware | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # In-memory storage | |
| meetings: Dict[str, dict] = {} | |
| connections: Dict[str, Dict[str, WebSocket]] = {} | |
| class MeetingCreate(BaseModel): | |
| host_name: str | |
| class MeetingJoin(BaseModel): | |
| meeting_id: str | |
| participant_name: str | |
| def generate_meeting_id() -> str: | |
| """Generate a unique 10-character meeting ID""" | |
| return secrets.token_urlsafe(8)[:10].replace('-', 'x').replace('_', 'y') | |
| async def read_root(): | |
| """Serve the main HTML page""" | |
| return HTMLResponse(content=open("index.html").read()) | |
| async def create_meeting(data: MeetingCreate): | |
| """Create a new meeting""" | |
| meeting_id = generate_meeting_id() | |
| meetings[meeting_id] = { | |
| "id": meeting_id, | |
| "host": data.host_name, | |
| "participants": [], | |
| "created_at": datetime.now().isoformat(), | |
| "active": True | |
| } | |
| connections[meeting_id] = {} | |
| return { | |
| "success": True, | |
| "meeting_id": meeting_id, | |
| "meeting": meetings[meeting_id] | |
| } | |
| async def get_meeting(meeting_id: str): | |
| """Get meeting details""" | |
| if meeting_id not in meetings: | |
| raise HTTPException(status_code=404, detail="Meeting not found") | |
| return { | |
| "success": True, | |
| "meeting": meetings[meeting_id] | |
| } | |
| async def end_meeting(meeting_id: str): | |
| """End a meeting""" | |
| if meeting_id not in meetings: | |
| raise HTTPException(status_code=404, detail="Meeting not found") | |
| meetings[meeting_id]["active"] = False | |
| # Notify all participants | |
| if meeting_id in connections: | |
| for ws in connections[meeting_id].values(): | |
| try: | |
| await ws.send_json({ | |
| "type": "meeting_ended", | |
| "data": {"message": "The meeting has been ended by the host"} | |
| }) | |
| except: | |
| pass | |
| connections[meeting_id].clear() | |
| return {"success": True, "message": "Meeting ended"} | |
| async def websocket_endpoint(websocket: WebSocket, meeting_id: str, participant_id: str): | |
| """WebSocket endpoint for real-time communication""" | |
| await websocket.accept() | |
| if meeting_id not in meetings: | |
| await websocket.send_json({ | |
| "type": "error", | |
| "data": {"message": "Meeting not found"} | |
| }) | |
| await websocket.close() | |
| return | |
| if not meetings[meeting_id]["active"]: | |
| await websocket.send_json({ | |
| "type": "error", | |
| "data": {"message": "Meeting has ended"} | |
| }) | |
| await websocket.close() | |
| return | |
| # Add connection | |
| if meeting_id not in connections: | |
| connections[meeting_id] = {} | |
| connections[meeting_id][participant_id] = websocket | |
| # Notify others about new participant | |
| for pid, ws in connections[meeting_id].items(): | |
| if pid != participant_id: | |
| try: | |
| await ws.send_json({ | |
| "type": "participant_joined", | |
| "data": {"participant_id": participant_id} | |
| }) | |
| except: | |
| pass | |
| try: | |
| while True: | |
| data = await websocket.receive_text() | |
| message = json.loads(data) | |
| # Broadcast to specific participant or all | |
| if message.get("target"): | |
| target_id = message["target"] | |
| if target_id in connections[meeting_id]: | |
| try: | |
| await connections[meeting_id][target_id].send_json(message) | |
| except: | |
| pass | |
| else: | |
| # Broadcast to all except sender | |
| for pid, ws in connections[meeting_id].items(): | |
| if pid != participant_id: | |
| try: | |
| await ws.send_json(message) | |
| except: | |
| pass | |
| except WebSocketDisconnect: | |
| # Remove connection | |
| if meeting_id in connections and participant_id in connections[meeting_id]: | |
| del connections[meeting_id][participant_id] | |
| # Notify others about participant leaving | |
| if meeting_id in connections: | |
| for ws in connections[meeting_id].values(): | |
| try: | |
| await ws.send_json({ | |
| "type": "participant_left", | |
| "data": {"participant_id": participant_id} | |
| }) | |
| except: | |
| pass | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |