feat(social): add friends, private chats, inbox and music sharing
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
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
This commit is contained in:
1 parent
f1528de948
commit
0a05bfe2cd
43 files changed
+2828
-389
No files matched your search
@@ -17,6 +17,7 @@ Pipu Music — self-hosted музыкальный сервис (веб + Android
|
||||
| [playback.md](playback.md) | Стриминг, транскодинг, состояние плеера, офлайн |
|
||||
| [genius.md](genius.md) | Genius: токен, поиск метаданных, парсинг текстов и проверочная команда |
|
||||
| [playlists.md](playlists.md) | Личные плейлисты: API, веб и Android |
|
||||
| [social.md](social.md) | Друзья, заявки, личные сообщения, уведомления и отправка музыки |
|
||||
| [recommendations.md](recommendations.md) | Рекомендательная система и «Моя волна» |
|
||||
| [web.md](web.md) | Веб-клиент |
|
||||
| [desktop.md](desktop.md) | Десктоп Windows / Linux / macOS (Tauri) |
|
||||
|
||||
@@ -96,6 +96,7 @@ pipu-music/
|
||||
│ │ ├── internal/
|
||||
│ │ │ ├── auth/ library/ search/ genius/
|
||||
│ │ │ ├── playback/ wave/ uploads/ appupdate/ system/
|
||||
│ │ │ ├── social/ # друзья, личные сообщения, центр уведомлений
|
||||
│ │ │ └── platform/ # db, redis, config, logging, http, jobs
|
||||
│ │ └── migrations/ # goose SQL-миграции; SQL-запросы — в адаптерах internal/
|
||||
│ └── recommender/ # Python (uv)
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# Друзья, сообщения и уведомления
|
||||
|
||||
Социальные функции работают между пользователями одного сервера. В 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`.
|
||||
Reference in new issue
Block a user