Files
VideoHost/backend/main.py
2026-01-14 10:43:02 +06:00

162 lines
4.7 KiB
Python

from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from typing import Dict, List
import uuid
from datetime import datetime
from models import User, Stream, StreamCreate, AuthCallback, ChatMessage
from auth import oidc_client, get_current_user, create_access_token
from config import settings
app = FastAPI(title="Video Streaming Platform")
app.add_middleware(
CORSMiddleware,
allow_origins=[settings.frontend_url],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# In-memory storage
streams: Dict[str, Stream] = {}
users: Dict[str, User] = {}
active_connections: Dict[str, List[WebSocket]] = {}
@app.get("/")
async def root():
return {"message": "Video Streaming API"}
@app.get("/auth/login")
async def login():
discovery = await oidc_client.get_discovery_document()
auth_endpoint = discovery["authorization_endpoint"]
auth_url = (
f"{auth_endpoint}?"
f"client_id={settings.oidc_client_id}&"
f"redirect_uri={settings.oidc_redirect_uri}&"
f"response_type=code&"
f"scope=openid email profile"
)
return {"auth_url": auth_url}
@app.post("/auth/callback")
async def auth_callback(callback: AuthCallback):
try:
token_response = await oidc_client.exchange_code(callback.code)
access_token = token_response.get("access_token")
if not access_token:
raise HTTPException(status_code=400, detail="Failed to get access token")
user_info = await oidc_client.get_user_info(access_token)
user = User(
id=user_info.get("sub"),
email=user_info.get("email"),
name=user_info.get("name", user_info.get("email")),
picture=user_info.get("picture")
)
users[user.id] = user
jwt_token = create_access_token({
"sub": user.id,
"email": user.email,
"name": user.name
})
return {"access_token": jwt_token, "user": user}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.get("/streams")
async def get_streams():
return list(streams.values())
@app.get("/streams/{stream_id}")
async def get_stream(stream_id: str):
if stream_id not in streams:
raise HTTPException(status_code=404, detail="Stream not found")
return streams[stream_id]
@app.post("/streams")
async def create_stream(
stream_data: StreamCreate,
current_user: dict = Depends(get_current_user)
):
stream_id = str(uuid.uuid4())
stream = Stream(
id=stream_id,
user_id=current_user["sub"],
title=stream_data.title,
description=stream_data.description,
is_live=True,
created_at=datetime.now()
)
streams[stream_id] = stream
active_connections[stream_id] = []
return stream
@app.delete("/streams/{stream_id}")
async def end_stream(
stream_id: str,
current_user: dict = Depends(get_current_user)
):
if stream_id not in streams:
raise HTTPException(status_code=404, detail="Stream not found")
stream = streams[stream_id]
if stream.user_id != current_user["sub"]:
raise HTTPException(status_code=403, detail="Not authorized")
stream.is_live = False
for connection in active_connections.get(stream_id, []):
await connection.close()
active_connections[stream_id] = []
return {"message": "Stream ended"}
@app.websocket("/ws/stream/{stream_id}")
async def websocket_stream(websocket: WebSocket, stream_id: str):
await websocket.accept()
if stream_id not in streams:
await websocket.close(code=1008)
return
if stream_id not in active_connections:
active_connections[stream_id] = []
active_connections[stream_id].append(websocket)
streams[stream_id].viewer_count = len(active_connections[stream_id])
try:
while True:
data = await websocket.receive_json()
for connection in active_connections[stream_id]:
if connection != websocket:
await connection.send_json(data)
except WebSocketDisconnect:
active_connections[stream_id].remove(websocket)
streams[stream_id].viewer_count = len(active_connections[stream_id])
@app.get("/me")
async def get_me(current_user: dict = Depends(get_current_user)):
user_id = current_user["sub"]
if user_id in users:
return users[user_id]
return current_user
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)