test voice rooms

This commit is contained in:
2026-01-02 15:32:59 +05:00
parent 16b477045c
commit baa4341129
3 changed files with 71 additions and 3 deletions

39
app/api/voice_ws.py Normal file
View File

@ -0,0 +1,39 @@
from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Query
from app.realtime.voice_hub import voice_hub
router = APIRouter()
@router.websocket("/ws/voice")
async def voice_ws(
ws: WebSocket,
room_id: str = Query(...),
username: str = Query(...)
):
await voice_hub.connect(room_id, username, ws)
# уведомим остальных
await voice_hub.broadcast(
room_id,
{"type": "join", "user": username}
)
try:
while True:
msg = await ws.receive_json()
if msg["type"] == "signal":
await voice_hub.send_to(
room_id,
msg["to"],
{
"type": "signal",
"from": username,
"data": msg["data"]
}
)
except WebSocketDisconnect:
voice_hub.disconnect(room_id, username)
await voice_hub.broadcast(
room_id,
{"type": "leave", "user": username}
)

30
app/realtime/voice_hub.py Normal file
View File

@ -0,0 +1,30 @@
from typing import Dict
from fastapi import WebSocket
class VoiceHub:
def __init__(self):
# room_id -> username -> websocket
self.rooms: Dict[str, Dict[str, WebSocket]] = {}
async def connect(self, room_id: str, username: str, ws: WebSocket):
await ws.accept()
self.rooms.setdefault(room_id, {})[username] = ws
def disconnect(self, room_id: str, username: str):
room = self.rooms.get(room_id)
if not room:
return
room.pop(username, None)
if not room:
self.rooms.pop(room_id, None)
async def send_to(self, room_id: str, to_user: str, payload: dict):
ws = self.rooms.get(room_id, {}).get(to_user)
if ws:
await ws.send_json(payload)
async def broadcast(self, room_id: str, payload: dict):
for ws in self.rooms.get(room_id, {}).values():
await ws.send_json(payload)
voice_hub = VoiceHub()

View File

@ -3,14 +3,12 @@ import os
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
import httpx import httpx
from app.api import admin_daily_quests, inventory, news, users, skins, capes, meta, server, store, pranks, marketplace, bonuses, case, promo from app.api import admin_daily_quests, inventory, news, users, skins, capes, meta, server, store, pranks, marketplace, marketplace_ws, bonuses, case, promo, voice_ws
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from app.core.config import CAPES_DIR, CAPES_STORE_DIR, SKINS_DIR from app.core.config import CAPES_DIR, CAPES_STORE_DIR, SKINS_DIR
from app.services.promo import PromoService from app.services.promo import PromoService
from app.webhooks import telegram from app.webhooks import telegram
from app.db.database import users_collection
from app.api import marketplace_ws
from app.db.database import users_collection, sessions_collection from app.db.database import users_collection, sessions_collection
@ -75,6 +73,7 @@ app.include_router(news.router)
app.include_router(telegram.router) app.include_router(telegram.router)
app.include_router(admin_daily_quests.router) app.include_router(admin_daily_quests.router)
app.include_router(promo.router) app.include_router(promo.router)
app.include_router(voice_ws.router)
# Монтируем статику # Монтируем статику
app.mount("/skins", StaticFiles(directory=str(SKINS_DIR)), name="skins") app.mount("/skins", StaticFiles(directory=str(SKINS_DIR)), name="skins")