Первоначальная версия VidConf

This commit is contained in:
2026-07-23 01:04:01 +03:00
commit 896455381a
335 changed files with 61527 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
"""Приёмник webhook-событий LiveKit (без JWT — верификация подписью LiveKit)."""
import logging
from typing import Annotated, Any, cast
from fastapi import APIRouter, Depends, Header, HTTPException, Request, status
from livekit import api
from sqlalchemy import CursorResult
from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.ext.asyncio import AsyncSession
from core.config import get_settings
from core.db import get_session
from models.webhook_event import LivekitWebhookEvent
from services.webhook_handlers import WebhookDispatcher
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/v1/livekit", tags=["livekit"])
@router.post("/webhook")
async def receive_webhook(
request: Request,
session: Annotated[AsyncSession, Depends(get_session)],
authorization: Annotated[str | None, Header()] = None,
) -> dict[str, str]:
"""Принять, верифицировать и обработать webhook-событие LiveKit.
Дедупликация по `event.id`: `INSERT ... ON CONFLICT DO NOTHING` в
`livekit_webhook_events` в одной транзакции с эффектами обработчика —
при конфликте (дубль) эффекты пропускаются, но ответ всё равно 200.
"""
settings = get_settings()
raw_body = await request.body()
receiver = api.WebhookReceiver(
api.TokenVerifier(settings.livekit_api_key, settings.livekit_api_secret)
)
try:
event = receiver.receive(raw_body.decode(), authorization or "")
except Exception as exc: # noqa: BLE001 — SDK кидает generic Exception на невалидную подпись
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid_signature"
) from exc
insert_result = cast(
CursorResult[Any],
await session.execute(
pg_insert(LivekitWebhookEvent)
.values(event_id=event.id, event_type=event.event)
.on_conflict_do_nothing(index_elements=["event_id"])
),
)
if insert_result.rowcount == 0:
# Дубль уже обработанного события — пропускаем эффекты, но отвечаем 200.
await session.commit()
return {"status": "duplicate"}
dispatcher = WebhookDispatcher(session)
await dispatcher.dispatch(event)
await session.commit()
return {"status": "ok"}