-- +goose Up -- Фаза 7: звонки в личных и групповых беседах (AGENT.md 7.8, 7.14). -- -- Звонок — отдельная сущность беседы: у него своя комната LiveKit, своё -- состояние участников и своя история (кто звонил, когда, сколько длился, -- кто пропустил). В voice_states звонок не помещается: там guild_id -- обязателен, а у личной беседы сервера нет. -- -- Статусы звонка (dm_calls.status): ringing — идут гудки, active — хотя бы -- двое в комнате, ended — завершён. Состояния участника -- (dm_call_participants.state): invited — приглашён и ещё не ответил, -- joined — в звонке, declined — отклонил, left — вышел, missed — не ответил. CREATE TABLE dm_calls ( id INTEGER PRIMARY KEY, channel_id INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE, initiator_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, status TEXT NOT NULL, -- media: audio | video — чем открыли звонок, клиент показывает это в истории. media TEXT NOT NULL DEFAULT 'audio', created_at TEXT NOT NULL, -- started_at — момент, когда звонок стал active: от него считается -- длительность разговора, а не от гудков. started_at TEXT, ended_at TEXT, ended_by INTEGER REFERENCES users (id) ON DELETE SET NULL, -- end_reason: completed | canceled | declined | missed | failed. end_reason TEXT ); CREATE INDEX dm_calls_channel_idx ON dm_calls (channel_id, id DESC); -- В беседе одновременно идёт не больше одного звонка: гонку двух «позвонить» -- закрывает сама база, а не проверка в приложении. CREATE UNIQUE INDEX dm_calls_live_channel_idx ON dm_calls (channel_id) WHERE status <> 'ended'; CREATE TABLE dm_call_participants ( call_id INTEGER NOT NULL REFERENCES dm_calls (id) ON DELETE CASCADE, user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, state TEXT NOT NULL, invited_at TEXT NOT NULL, joined_at TEXT, left_at TEXT, self_mute INTEGER NOT NULL DEFAULT 0, self_deaf INTEGER NOT NULL DEFAULT 0, camera INTEGER NOT NULL DEFAULT 0, screen INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (call_id, user_id) ); CREATE INDEX dm_call_participants_user_idx ON dm_call_participants (user_id, call_id DESC); -- +goose Down DROP TABLE dm_call_participants; DROP TABLE dm_calls;