Files
pipu-music/docs/social.md
T
mrleo1nid 0a05bfe2cd
ci / module boundaries / boundaries (push) Successful in 7s
ci / api / api (push) Successful in 1m9s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m8s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m23s
ci / db / db (push) Successful in 2m29s
ci / ts / ts (packages + web) (push) Successful in 2m55s
feat(social): add friends, private chats, inbox and music sharing
2026-10-23 03:19:29 +03:00

5.8 KiB

Друзья, сообщения и уведомления

Социальные функции работают между пользователями одного сервера. В web и desktop открывается раздел «Друзья и общение», на Android — вкладка «Друзья».

Поведение

  • Поиск по логину и отображаемому имени начинается с двух символов, возвращает до 30 человек. Пароли, роли, настройки и другие приватные поля в результат не попадают.
  • Заявка требует явного принятия получателем. Встречная заявка не принимает дружбу автоматически. Можно отменить свою заявку, отклонить входящую или удалить друга.
  • Личные сообщения и отправка музыки доступны только текущим друзьям. Блокировка прекращает дружбу и закрывает общение в обоих направлениях. Разблокировка дружбу не восстанавливает.
  • История сохраняется после удаления друга, но доступна снова только после новой взаимной дружбы. В первой странице чата — последние 50 сообщений; ранние подгружаются отдельно.
  • В сообщении до 4000 символов. Музыкальное вложение — ID трека либо действующая ссылка общего доступа к плейлисту. Отзыв ссылки делает вложенный плейлист недоступным.
  • «Поделиться» открывает выбор: скопировать ссылку, вызвать системную отправку (когда она поддерживается клиентом) или отправить конкретному другу одним нажатием. Отправка другу создаёт сообщение с музыкальным вложением. Повтор после сетевого сбоя использует тот же UUID.

Спокойные уведомления

Четыре типа: входящая заявка, принятие заявки, личное сообщение, музыка. Центр событий и счётчики сохраняются на сервере, отметки прочтения общие для устройств. Нет звуков, автоматических всплывающих окон и запроса разрешений ОС.

Список уведомлений возвращает до 100 событий, сначала непрочитанные. По мере подтверждения новых становятся доступны более старые непрочитанные события. Открытый видимый чат подтверждает сообщения только до последнего полученного номера; более поздние сообщения не теряются. В скрытой вкладке и в фоне Android автоматического подтверждения нет.

Сейчас это уведомления внутри работающего приложения, с обновлением центра каждые 15 секунд и открытого чата каждые 8 секунд. Web использует стандартную приостановку фонового polling React Query; Android останавливает polling при уходе приложения в фон. Уведомления ОС при закрытом клиенте (Web Push/FCM/нативный desktop) в эту реализацию не входят.

Реализация и проверки

Контракт: api/openapi.yaml, операции getSocial, searchPeople, socialAction, getDirectMessages, sendDirectMessage. Модуль API: internal/social. Миграция 00019_social.sql создаёт дружбу, блокировки, сообщения и уведомления. Миграции применяются штатным запуском API.

Мутации пары сериализованы транзакционной advisory-блокировкой PostgreSQL. Отправка сообщения и создание уведомления атомарны. UUID сообщения глобально уникален; повтор с другим содержимым возвращает конфликт. Чужое уведомление нельзя отметить прочитанным. Поиск скрывает заблокированные аккаунты и личные блокировки, включая обратное направление.

Ограничения: до 50 исходящих ожидающих заявок, до 10 новых заявок за минуту, до 30 сообщений одному человеку за минуту; тело социального POST ограничено 32 KiB. Тексты выводятся обычным текстом, вложения формируют только внутренние маршруты каталога.

Проверки: go test ./internal/social, TEST_DATABASE_URL=… go test -tags integration ./internal/social, pnpm --filter @pipu/web test src/App.test.tsx -t 'social|playlist sharing', pnpm --filter @pipu/web test:e2e e2e/social.spec.ts e2e/playlists.spec.ts. Интеграционный сценарий включён в ci-db.