Neda/Back/domains/realtime/speaker_service.py

80 lines
2.1 KiB
Python

import uuid
from livekit import api
from sqlalchemy.ext.asyncio import AsyncSession
from integrations.livekit.client import get_livekit_api
from db.redis import (
acquire_speaker,
release_speaker,
get_active_speaker
)
from domains.groups.repo import get_group_by_id
async def request_speak(
group_id: str | uuid.UUID,
user_id: str | uuid.UUID,
group_type: str
) -> bool:
group_id_str = str(group_id)
user_id_str = str(user_id)
if group_type == "private":
await grant_publish_permission(group_id_str, user_id_str, True)
return True
# group chat → push-to-talk
granted = await acquire_speaker(group_id_str, user_id_str)
if not granted:
return False
await grant_publish_permission(group_id_str, user_id_str, True)
return True
async def stop_speaking(
group_id: str | uuid.UUID,
user_id: str | uuid.UUID,
group_type: str
):
group_id_str = str(group_id)
user_id_str = str(user_id)
if group_type == "private":
await grant_publish_permission(group_id_str, user_id_str, False)
return True
released = await release_speaker(group_id_str, user_id_str)
if released:
await grant_publish_permission(group_id_str, user_id_str, False)
return released
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)
async def grant_publish_permission(room_name: str, identity: str, can_publish: bool):
lk_api = get_livekit_api() # همان متدی که در client.py نوشتی
await lk_api.room.update_participant(
api.UpdateParticipantRequest(
room=room_name,
identity=identity,
permission=api.ParticipantPermission(
can_publish=can_publish,
can_subscribe=True # همیشه بتواند بشنود
)
)
)