Neda/Back/domains/realtime/speaker_service.py
2026-03-10 18:58:10 +03:30

93 lines
2.0 KiB
Python

import uuid
from sqlalchemy.ext.asyncio import AsyncSession
from db.redis import (
acquire_speaker,
release_speaker,
get_active_speaker
)
from domains.groups.repo import get_group_by_id
from integrations.livekit.token_service import generate_join_token
async def request_speak(
db: AsyncSession,
group_id: str | uuid.UUID,
user_id: str | uuid.UUID
):
group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
group_id_str = str(group_id_uuid)
user_id_str = str(user_id)
group = await get_group_by_id(db, group_id_uuid)
if not group:
return None
# private chat → no speaker lock
if str(group.type) == "private":
token = generate_join_token(
user_id=user_id_str,
group_id=group_id_str,
can_publish=True
)
return token
# group chat → push-to-talk
granted = await acquire_speaker(group_id_str, user_id_str)
if not granted:
return None
token = generate_join_token(
user_id=user_id_str,
group_id=group_id_str,
can_publish=True
)
return token
async def stop_speaking(
db: AsyncSession,
group_id: str | uuid.UUID,
user_id: str | uuid.UUID
):
group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
group_id_str = str(group_id_uuid)
user_id_str = str(user_id)
group = await get_group_by_id(db, group_id_uuid)
if not group:
return False
# private chat → nothing to release
if str(group.type) == "private":
return True
return await release_speaker(group_id_str, user_id_str)
async def current_speaker(
db: AsyncSession,
group_id: str | uuid.UUID
):
group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
group_id_str = str(group_id_uuid)
group = await get_group_by_id(db, group_id_uuid)
if not group:
return None
if str(group.type) == "private":
return None
return await get_active_speaker(group_id_str)