47 lines
4.3 KiB
Markdown
47 lines
4.3 KiB
Markdown
# chat-service
|
||
|
||
Подсистема 2 платформы (RPC-чат, друзья, presence, телеметрия виджетов). Сейчас реализован только **GUI presence**;
|
||
чат и друзья позже (WebSocket). Сервис без БД: состояние в памяти, живёт секунды.
|
||
|
||
## GUI presence (идея из evo `GuiPresence`, наш вариант)
|
||
|
||
Зачем: LoVisual-игроки видят друг у друга над рукой мини-копию открытого меню клиента (какая категория, куда наведён курсор,
|
||
поиск), и знают, кто вообще пользуется LoVisual (значок у ника). Без видео и без чужих данных: только положение курсора и флаги.
|
||
|
||
### Протокол
|
||
`POST /presence/gui` (через gateway, нужен device-токен `lvd_...`, gateway кладёт `x-lovisual-account-id`):
|
||
|
||
```json
|
||
{ "server": "play.example.com", "mc": "<uuid игрока>", "gui": "<base64>|null", "want": ["<uuid>", "..."], "publish": true }
|
||
```
|
||
Ответ: `{ "players": [ { "mc": "<uuid>", "gui": "<base64>|null", "age": 120 } ] }`, `age` в мс с последнего обновления.
|
||
|
||
- Один запрос и публикует состояние вызывающего, и возвращает состояние тех, кого он видит (`want`, не больше 40).
|
||
- `publish = false` (по умолчанию true): только чтение, вызывающий сам не появляется у других.
|
||
- `gui = null` значит «меню закрыто, но LoVisual запущен» (значок у ника). Запись живёт 6 с без обновления.
|
||
- Игроки разных серверов не видят друг друга (ключ `server`, нормализуется в нижний регистр, ≤64 символов).
|
||
- Частота клиента: раз в ~350 мс при открытом меню (пачка до 8 сэмплов курсора по 100 мс), раз в 2 с при закрытом.
|
||
Лимит на gateway: 6 запросов в секунду на аккаунт.
|
||
|
||
### Формат `gui` (36 байт максимум, base64 ≤48 символов; сервис его не разбирает, только проверяет алфавит и длину)
|
||
| байт | значение |
|
||
|---|---|
|
||
| 0 | версия = 1 |
|
||
| 1 | биты 0-3 категория (0..15), бит 4 открыта страница настроек, бит 5 поиск, бит 7 меню закрыто |
|
||
| 2 | индекс модуля под курсором в списке категории (255 = нет) |
|
||
| 3 | число сэмплов n (0..8) |
|
||
| 4+4i | сэмпл: x (0..255 по ширине меню), y (0..255 по высоте), бит 0 = зажата ЛКМ, прокрутка списка (0..255) |
|
||
|
||
### Безопасность
|
||
- Идентичность только из заголовка gateway; прямой доступ закрыт общим секретом (как у остальных сервисов).
|
||
- Привязка `mc uuid` к аккаунту: чужой аккаунт не может публиковать за занятый uuid (409), привязка снимается через 10 мин
|
||
простоя; аккаунт владеет одним uuid, смена альта освобождает прежний. Это защита от подделки, не доказательство владения
|
||
аккаунтом Minecraft: серверной верификации uuid нет.
|
||
- Размер тела ≤8 КБ, payload только `[A-Za-z0-9+/=]`, `want` ≤40.
|
||
|
||
### Структура
|
||
`src/presence/{payload.rs (валидация), store.rs (состояние + TTL + привязка), handlers.rs (sync)}`; тесты: модульные в `store.rs`,
|
||
`payload.rs`, интеграционные `tests/presence.rs`. Порт `CHAT_PORT` (8083), `INTERNAL_KEY` общий. В gateway маршрут `/presence/*`.
|
||
|
||
### Не сделано
|
||
Просмотр видео (`.watch` у evo), чат и друзья (WebSocket), метрики, горизонтальное масштабирование (состояние в памяти одного процесса).
|