feat(dm): ручки и события звонков в беседах (Фаза 7)
Звонки 1:1 и в групповых беседах до 10 участников поверх той же голосовой
инфраструктуры LiveKit: те же токены, что у серверных комнат, но без
серверных ролей — позвонить может участник беседы.
Ручки: POST /channels/{id}/call (создание, в ответе токен и адрес
сигналинга), accept, decline, end, PATCH /call/@me для флагов микрофона,
камеры и шаринга, GET /call (текущий звонок) и GET /calls (история: кто
звонил, когда, сколько длился, кто пропустил). Постороннему — 404,
существование чужой беседы не подтверждаем; в беседе больше десяти
участников звонить нельзя (dm.call_limit); выключенный голос отвечает
voice.disabled.
События: DM_CALL_RING приходит приглашённым, DM_CALL_UPDATE — участникам
при смене состояния, DM_CALL_END — с итогом и причиной. Звонок добавлен в
READY и в карточку беседы (active_call), поэтому «идёт звонок» переживает
перезагрузку. Вебхук LiveKit разбирает комнаты dm_call_* и синхронизирует
состояние, сторож голосовых состояний закрывает гудки без ответа и
опустевшие комнаты.
Тесты: жизненный цикл 1:1, отклонение и пропущенный, отказ постороннему
на всех ручках, предел десяти участников, поведение при выключенном
голосе, события Gateway и active_call в READY.
This commit is contained in:
@@ -58,6 +58,9 @@ type Server struct {
|
||||
editLimiter *httpx.RateLimiter
|
||||
// soundboardLimiter — не чаще 3 звуков в 10 секунд на пользователя.
|
||||
soundboardLimiter *httpx.RateLimiter
|
||||
// dmCallLimiter — 10 новых звонков в минуту на пользователя (Фаза 7):
|
||||
// гудки в беседе не должны превращаться в спам.
|
||||
dmCallLimiter *httpx.RateLimiter
|
||||
// inviteLimiter — 10 приглашений в сутки на пользователя (AGENT.md 8.6).
|
||||
inviteLimiter *httpx.RateLimiter
|
||||
// webhookLimiter — 30 сообщений в минуту на вебхук (AGENT.md 7.11, 8.6).
|
||||
@@ -136,6 +139,7 @@ func New(cfg config.Config, db *database.DB, logger *slog.Logger, deps Deps) *Se
|
||||
searchLimiter: httpx.NewRateLimiter(10, 10),
|
||||
editLimiter: httpx.NewRateLimiter(10, 10),
|
||||
soundboardLimiter: httpx.NewRateLimiterWindow(3, 10*time.Second, 3),
|
||||
dmCallLimiter: httpx.NewRateLimiterWindow(dmCallLimitCount, dmCallLimitWindow, dmCallLimitCount),
|
||||
inviteLimiter: httpx.NewRateLimiterWindow(10, 24*time.Hour, 10),
|
||||
webhookLimiter: httpx.NewRateLimiterWindow(webhookRateLimit, time.Minute, webhookRateLimit),
|
||||
// Второй аргумент NewRateLimiter — запас (burst), а не окно.
|
||||
@@ -216,6 +220,7 @@ func New(cfg config.Config, db *database.DB, logger *slog.Logger, deps Deps) *Se
|
||||
s.registerDMIconRoutes(apiRouter)
|
||||
s.registerEmojiRoutes(s.api, apiRouter)
|
||||
s.registerVoiceRoutes(s.api)
|
||||
s.registerDMCallRoutes(s.api)
|
||||
s.registerSoundsRoutes(s.api, apiRouter)
|
||||
s.registerWebhookRoutes(s.api, apiRouter)
|
||||
s.registerCosmeticRoutes(s.api, apiRouter)
|
||||
|
||||
Reference in New Issue
Block a user