111 lines
3.1 KiB
Python
111 lines
3.1 KiB
Python
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
|
|
|
from core.websocket import get_ws_current_user
|
|
|
|
from domains.realtime.ws_manager import manager
|
|
from domains.realtime.presence_service import (
|
|
user_join_group,
|
|
user_leave_group,
|
|
list_online_users
|
|
)
|
|
|
|
from domains.realtime.speaker_service import (
|
|
request_speak,
|
|
stop_speaking,
|
|
current_speaker
|
|
)
|
|
|
|
from integrations.livekit.token_service import generate_join_token
|
|
from db.session import AsyncSessionLocal
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.websocket("/ws/groups/{group_id}")
|
|
async def group_ws(websocket: WebSocket, group_id: str):
|
|
|
|
user = await get_ws_current_user(websocket)
|
|
user_id = str(user.id)
|
|
|
|
# connect websocket
|
|
await manager.connect(group_id, websocket)
|
|
|
|
# add presence
|
|
await user_join_group(group_id, user_id)
|
|
|
|
# give listener token
|
|
listener_token = generate_join_token(
|
|
user_id=user_id,
|
|
group_id=group_id,
|
|
can_publish=False
|
|
)
|
|
|
|
await websocket.send_json({
|
|
"type": "livekit_token",
|
|
"token": listener_token
|
|
})
|
|
|
|
# broadcast updated presence
|
|
await manager.broadcast(
|
|
group_id,
|
|
{
|
|
"type": "presence",
|
|
"users": await list_online_users(group_id)
|
|
}
|
|
)
|
|
|
|
try:
|
|
|
|
while True:
|
|
data = await websocket.receive_json()
|
|
event = data.get("type")
|
|
# user wants to speak
|
|
if event == "request_speak":
|
|
async with AsyncSessionLocal() as db:
|
|
token = await request_speak(
|
|
db,
|
|
group_id,
|
|
user_id
|
|
)
|
|
if token:
|
|
await manager.broadcast(
|
|
group_id,
|
|
{
|
|
"type": "speaker",
|
|
"user_id": user_id
|
|
}
|
|
)
|
|
await websocket.send_json({
|
|
"type": "speaker_granted",
|
|
"token": token
|
|
})
|
|
else:
|
|
async with AsyncSessionLocal() as db:
|
|
speaker = await current_speaker(db, group_id)
|
|
|
|
await websocket.send_json({
|
|
"type": "speaker_busy",
|
|
"speaker": speaker
|
|
})
|
|
|
|
# user stops speaking
|
|
elif event == "stop_speak":
|
|
async with AsyncSessionLocal() as db:
|
|
await stop_speaking(db, group_id, user_id)
|
|
await manager.broadcast(
|
|
group_id,
|
|
{
|
|
"type": "speaker_released"
|
|
}
|
|
)
|
|
|
|
except WebSocketDisconnect:
|
|
manager.disconnect(group_id, websocket)
|
|
await user_leave_group(group_id, user_id)
|
|
await manager.broadcast(
|
|
group_id,
|
|
{
|
|
"type": "presence",
|
|
"users": await list_online_users(group_id)
|
|
}
|
|
) |