Files
pipu-music/packages/api-client/src/generated/schema.ts
T
mrleo1nid cd84ceecb2
ci / api / api (push) Successful in 1m11s
ci / db / db (push) Failing after 23s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m29s
ci / ts / ts (packages + web) (push) Successful in 3m15s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m27s
feat(social): show friend presence and require online listening
2026-10-23 12:52:00 +03:00

6062 lines
191 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/
export interface paths {
"/api/v1/me/social/recommendations": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put: operations["setFriendsRecommendations"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/listening": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["getListeningState"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/listening/preferences": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put: operations["setListeningPreferences"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/listening/actions": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** @description Join requests target the host; invites target a guest and use the sender's own stream. Accept/decline/cancel target a request UUID. Leave/end target the room UUID. Automatic acceptance always respects the receiving user's admission policy. No control transfer. */
post: operations["listeningAction"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/listening/state": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
/** @description Only the room owner's source device may publish. Monotonic sequence prevents stale updates; room expires after 30 seconds without host heartbeat. */
put: operations["publishListeningState"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/activity": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
/** @description Ephemeral playback lease, expires after 90 seconds. Ignored when visibility is nobody. Sequence is monotonic per device; paused updates clear only that device. No offline replay. */
put: operations["publishListeningActivity"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/activity/visibility": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
/** @description Applies to all devices. Nobody clears all current activity immediately. */
put: operations["setActivityVisibility"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/social/activity/{userId}/playlist": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** @description Read-only current playlist subject to live visibility, friendship, blocking and expiry. Does not create or reveal a permanent share token. */
get: operations["getActivityPlaylist"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** @description Friends, incoming/outgoing requests, own blocks and up to 100 notifications, unread first. No private account fields. */
get: operations["getSocial"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/people": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["searchPeople"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/actions": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** @description Request is idempotent; accept is recipient-only. Remove cancels, declines or unfriends. Block removes friendship. Unblock never restores it. Read chat acknowledges only messages through up_to_seq. Read notification uses notification ID as target_id. */
post: operations["socialAction"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/chats/{peerId}": {
parameters: {
query?: never;
header?: never;
path: {
peerId: string;
};
cookie?: never;
};
/** @description Last 50 messages in ascending sequence order. Before loads older history. Requires current friendship, never marks messages read. */
get: operations["getDirectMessages"];
put?: never;
/** @description Friends only. Client-generated UUID makes retries idempotent; changed payload for the same ID returns 409. Playlist attachment is its active share UUID; track attachment is a catalog UUID. No arbitrary URLs. */
post: operations["sendDirectMessage"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/chats/{peerId}/meta": {
parameters: {
query?: never;
header?: never;
path: {
peerId: string;
};
cookie?: never;
};
get: operations["getChatMeta"];
put: operations["setChatTyping"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/social/chats/{peerId}/messages/{messageId}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
/** @description Friends only. Edit/delete are sender-only. Delete removes content for both participants; react toggles one allowed emoji. Reply targets must belong to the same conversation. */
patch: operations["updateChatMessage"];
trace?: never;
};
"/api/v1/admin/server/updates": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["getServerUpdates"];
put?: never;
post: operations["startServerUpdate"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/server/update-sources": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put: operations["saveServerUpdateSources"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/server/config": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["getServerConfig"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch: operations["saveServerConfig"];
trace?: never;
};
"/api/v1/admin/server/config/apply": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
post: operations["applyServerConfig"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/genius": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["getGeniusStats"];
put?: never;
post: operations["controlGenius"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/tracks/{id}/genius": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get: operations["getTrackGenius"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/healthz": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Живость процесса */
get: operations["getHealthz"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/readyz": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Готовность обслуживать запросы (зависимости доступны) */
get: operations["getReadyz"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/server-info": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Сведения о сервере для клиентов
* @description Вызывается без аутентификации: веб и Android проверяют версию сервера,
* совместимость клиента и поддерживаемые языки (экран подключения).
*/
get: operations["getServerInfo"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/auth/login": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Вход по логину и паролю
* @description Веб (`client_type: web`) получает refresh-токен в cookie `pipu_rt`
* (`HttpOnly; Secure; SameSite=Strict; Path=/api/v1/auth`), Android — в поле `refresh_token`.
* Неверный логин или пароль, а также временно заблокированный перебором вход — всегда
* `401 auth.invalid_credentials`. Превышен лимит попыток с адреса — `429 auth.too_many_attempts`.
*/
post: operations["login"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/auth/refresh": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Ротация refresh-токена
* @description Refresh-токен берётся из cookie `pipu_rt` (веб) или из тела (Android). Старый токен
* становится использованным; его повторное предъявление отзывает всю семью токенов.
*/
post: operations["refreshTokens"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/auth/logout": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Выход — отзыв текущей сессии */
post: operations["logout"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/auth/logout-all": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Выход на всех устройствах */
post: operations["logoutAll"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Текущий пользователь */
get: operations["getMe"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
/**
* Изменить имя, язык, настройки интерфейса
* @description Поля `ui_prefs` сливаются с сохранёнными; не переданные поля не меняются.
*/
patch: operations["updateMe"];
trace?: never;
};
"/api/v1/me/password": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Сменить пароль
* @description `current_password` обязателен, кроме случая `must_change_password` (вход по временному паролю).
* Все сессии отзываются; текущему устройству выдаётся новая пара токенов.
*/
post: operations["changePassword"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/bootstrap-credentials": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Первый запуск — новые логин и пароль администратора
* @description Только при `must_change_credentials`. Пароль должен отличаться от текущего.
* Все прочие сессии отзываются, выдаётся новая пара токенов.
*/
post: operations["setBootstrapCredentials"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/sessions": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Активные сессии (устройства) */
get: operations["listMySessions"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/sessions/{id}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/** Завершить сессию на устройстве */
delete: operations["revokeMySession"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/users": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Пользователи (admin, moderator)
* @description Сортировка по логину. `q` ищет по логину и имени без учёта регистра.
*/
get: operations["listUsers"];
put?: never;
/**
* Создать пользователя
* @description Пароль генерирует сервер и возвращает **один раз**; при первом входе его нужно сменить.
* Модератор создаёт только `user`, админ — любые роли.
*/
post: operations["createUser"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources/{id}/cover-stats": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Покрытие аудиофайлов локальными обложками (admin) */
get: operations["getSourceCoverStats"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/users/export": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Экспорт учётных записей с ролями и хэшами паролей (admin)
* @description Только учётные записи и права доступа, без рекомендаций, истории, лайков и сессий. Ответ не кэшируется.
*/
get: operations["exportUsers"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/users/import": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Импорт учётных записей с сохранением паролей (admin)
* @description Атомарное добавление пользователей из экспорта, до 10000 записей и 16 MiB.
* Существующие логины пропускаются без изменений. Новые записи получают новые ID.
* Рекомендации, история, лайки и сессии не импортируются.
*/
post: operations["importUsers"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/users/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["UserId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/** Удалить пользователя (admin) */
delete: operations["deleteUser"];
options?: never;
head?: never;
/**
* Изменить имя, роль, блокировку
* @description Роль меняет только админ. Смена роли и блокировка мгновенно отзывают токены пользователя.
* Последнего активного админа нельзя понизить или заблокировать — `409 users.last_admin`.
*/
patch: operations["updateUser"];
trace?: never;
};
"/api/v1/admin/users/{id}/reset-password": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["UserId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* Сбросить пароль
* @description Новый временный пароль возвращается один раз; все сессии пользователя завершаются.
*/
post: operations["resetUserPassword"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/users/{id}/reset-recommendations": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["UserId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* Сбросить рекомендации
* @description Рекомендации начинаются с нуля: стираются профиль вкуса (онбординг, CF-вектор, бандит),
* статистика прослушиваний и показы волны; онбординг покажется снова.
* Лайки, дизлайки и история остаются.
*/
post: operations["resetUserRecommendations"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/uploads/quota": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Квота очереди на добавление (moderator, admin) */
get: operations["getUploadQuota"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/uploads/precheck": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Предпроверка дублей до загрузки (moderator, admin)
* @description Ничего не резервирует. SHA-256 и теги клиент считает сам (docs/uploads.md#4).
*/
post: operations["precheckUploads"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/uploads": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Создать пачку и зарезервировать место (moderator, admin)
* @description Для принятых файлов — `tus_url` (tus 1.0.0, только HEAD / PATCH, куски до 64 МБ). Не поместившиеся —
* `uploads.queue_full` / `uploads.user_quota_full`, дубли — `uploads.duplicate`, без места в квоте.
*/
post: operations["createUploadBatch"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/uploads/mine": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Мои предложения (moderator, admin) */
get: operations["listMyUploads"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/uploads/unseen": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Сколько решений по своим предложениям с прошлого визита (moderator, admin) */
get: operations["unseenUploadDecisions"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/uploads/seen": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Отметить свои предложения просмотренными */
post: operations["markUploadsSeen"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/uploads/files/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/**
* Отозвать своё предложение до решения
* @description HEAD / PATCH по этому же адресу — приём файла по tus (вне контракта OpenAPI).
*/
delete: operations["withdrawUpload"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/uploads": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Очередь на добавление (admin) */
get: operations["listUploads"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/uploads/files/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
/**
* Править метаданные и хранилище (admin)
* @description Путь в хранилище пересчитывается; правленые теги записываются в файл при импорте.
*/
patch: operations["updateUpload"];
trace?: never;
};
"/api/v1/admin/uploads/files/{id}/retry": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get?: never;
put?: never;
/** Повторить импорт после import_failed (admin) */
post: operations["retryUploadImport"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/uploads/files/{id}/stream": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Прослушать файл из staging (подпись, как у стрима трека)
* @description Ссылку даёт `stream_url` файла очереди. Range поддерживается.
*/
get: operations["streamUpload"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/uploads/batches/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
/**
* Правка метаданных и обложки на всю пачку (admin)
* @description Исполнитель, альбом и год применяются к файлам в pending_review и import_failed. Обложка встраивается при импорте.
*/
patch: operations["updateUploadBatch"];
trace?: never;
};
"/api/v1/admin/uploads/review": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Одобрить / отклонить файлы (admin) */
post: operations["reviewUploads"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/settings/uploads": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Настройки очереди (admin) */
get: operations["getUploadSettings"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
/**
* Изменить настройки очереди (admin)
* @description Уменьшение лимита ниже занятого ничего не удаляет — новые загрузки ждут, пока очередь освободится.
*/
patch: operations["updateUploadSettings"];
trace?: never;
};
"/api/v1/admin/audit": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Журнал действий (admin), новые сверху */
get: operations["listAudit"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Хранилища (admin) */
get: operations["listSources"];
put?: never;
/**
* Подключить хранилище (admin)
* @description `local` — подпапка в каталоге LIBRARY_HOST сервера; `nfs` — монтирует storage-agent.
* Хранилище сохраняется, даже если подключиться не удалось: статус и сообщение — в ответе.
*/
post: operations["createSource"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
/** Хранилище (admin) */
get: operations["getSource"];
put?: never;
post?: never;
/**
* Отключить и удалить хранилище (admin)
* @description Треки, файлы которых были только в этом хранилище, удаляются из каталога.
*/
delete: operations["deleteSource"];
options?: never;
head?: never;
/**
* Изменить хранилище (admin)
* @description Изменение адреса NFS или папки переподключает хранилище.
*/
patch: operations["updateSource"];
trace?: never;
};
"/api/v1/admin/sources/{id}/test": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
get?: never;
put?: never;
/** Проверить подключение (admin) */
post: operations["testSource"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources/{id}/patterns": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
/** Шаблоны путей (admin) */
get: operations["getSourcePatterns"];
/**
* Заменить шаблоны путей (admin)
* @description Ошибка компиляции — `422 validation.pattern_invalid` с `params.index` и `params.reason`.
*/
put: operations["putSourcePatterns"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources/{id}/patterns/preview": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
get?: never;
put?: never;
/** Предпросмотр разбора путей без сохранения (admin) */
post: operations["previewSourcePatterns"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources/{id}/write-template/suggest": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* Подобрать шаблон пути по существующей структуре (admin)
* @description Выражение хранилища, совпавшее с наибольшим числом путей выборки, превращается в шаблон.
* Не удалось (нет файлов или выражения не переводятся) — `422 library.template_unavailable`.
*/
post: operations["suggestWriteTemplate"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources/{id}/write-template/check": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* Проверить шаблон на обратимость (admin)
* @description Шаблон применяется к 50 трекам хранилища, пути разбираются его выражениями обратно.
*/
post: operations["checkWriteTemplate"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/sources/{id}/scan": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* Запустить скан (admin)
* @description Скан идёт в фоне; прогресс — в `GET /admin/library/status`. Уже идёт — `409 library.scan_running`.
*/
post: operations["scanSource"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/library/status": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Состояние библиотеки (admin, moderator) */
get: operations["getLibraryStatus"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/library/errors": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Файлы, которые не удалось прочитать (admin) */
get: operations["listLibraryErrors"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/library/analysis/errors": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Неудавшиеся задачи аудиоанализа с путями файлов (admin) */
get: operations["listAnalysisErrors"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/library/host-dirs": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Подпапки каталога LIBRARY_HOST — выбор папки для local-хранилища (admin) */
get: operations["listHostDirs"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/artists/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
/** Исполнитель */
get: operations["getArtist"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/artists/{id}/albums": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
/** Альбомы исполнителя (свои и сборники с его треками) */
get: operations["listArtistAlbums"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/artists/{id}/top-tracks": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
/** Популярные треки исполнителя (по прослушиваниям всех пользователей) */
get: operations["listArtistTopTracks"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/albums/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
/** Альбом с треками */
get: operations["getAlbum"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/tracks/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
/** Трек */
get: operations["getTrack"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/search/suggest": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Выпадающий список поиска — до 3 исполнителей, 3 альбомов, 5 треков
* @description Если по запросу ничего не найдено, сервер повторяет его в другой раскладке клавиатуры
* («ghbdtn» → «привет») и возвращает исправленный запрос в `corrected_query`.
*/
get: operations["searchSuggest"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/search": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Страница поиска
* @description `type=all` — по несколько результатов каждого вида без пагинации;
* конкретный тип — страницы с `next_cursor`.
*/
get: operations["search"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/library/analysis/retry": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Вернуть в очередь треки, которые не удалось проанализировать (admin) */
post: operations["retryAnalysis"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/admin/search/reindex": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Пересобрать поисковые индексы (admin) */
post: operations["reindexSearch"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/covers/{id}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Обложка альбома (WebP)
* @description Ссылку целиком даёт `cover_url` альбома (подписана, без срока: обложка с данным `v` неизменна);
* клиент добавляет `size`. Файл отдаёт nginx через X-Accel-Redirect.
*/
get: operations["getCover"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/stream/{id}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Аудио трека (поддерживает Range)
* @description Ссылку целиком даёт `stream_url` трека (подпись пользователя и срок 12 ч); клиент может добавить `q`.
* Файл отдаёт nginx через X-Accel-Redirect: оригинал из хранилища или транскод в Opus из кэша.
*/
get: operations["streamTrack"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/tracks/batch": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Треки по списку id (восстановление очереди) */
post: operations["getTracksBatch"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/events": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Пачка событий прослушивания (до 500)
* @description Повторно присланные события (тот же id) не учитываются дважды.
*/
post: operations["postEvents"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/playback-state": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Последнее состояние плеера (трек, позиция, очередь) */
get: operations["getPlaybackState"];
/** Сохранить состояние плеера (last-write-wins) */
put: operations["putPlaybackState"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/history": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** История прослушиваний, новые сверху */
get: operations["getHistory"];
put?: never;
post?: never;
/** Очистить историю (события остаются для статистики) */
delete: operations["clearHistory"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/likes": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Лайки, новые сверху */
get: operations["getLikes"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/dislikes": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Дизлайки, новые сверху */
get: operations["getDislikes"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/reactions/tracks/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get?: never;
/** Лайк или дизлайк трека */
put: operations["setTrackReaction"];
post?: never;
/** Снять реакцию */
delete: operations["clearTrackReaction"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/onboarding": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Анкета рекомендаций — варианты, сохранённые ответы и необходимость заполнения
* @description `required` — пользователь не проходил и не пропускал анкету либо администратор сбросил рекомендации.
* `choice` содержит ответы с текущей приблизительной возрастной группой; исходная группа и год хранятся на сервере.
*/
get: operations["getOnboarding"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/onboarding": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
/** Сохранить выбор онбординга (или пропуск — пустые списки) */
put: operations["saveOnboarding"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/wave/options": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Занятия и настроения (ключи для i18n и иконки) */
get: operations["getWaveOptions"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/wave/sessions": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Начать «Мою волну» */
post: operations["startWave"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/wave/sessions/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/** Завершить сессию волны */
delete: operations["endWave"];
options?: never;
head?: never;
/** Сменить занятие / настроение на лету — пачка пересобирается */
patch: operations["updateWave"];
trace?: never;
};
"/api/v1/wave/sessions/{id}/next": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
get?: never;
put?: never;
/** Следующая пачка с учётом реакций на выданные треки */
post: operations["nextWave"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/app/clients": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Клиенты последних релизов (Android и десктоп)
* @description Тот же релиз Gitea, что и для Android: APK, установщик Windows, .deb, DMG.
* У каждой платформы `older` — предыдущие сборки (до 8 релизов, сколько есть с файлами).
* Нет настроек Gitea или файлов клиентов — `404 app.update_unavailable`.
*/
get: operations["getAppClients"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/app/download/{client}/{version}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Файл клиента (кэшируется на сервере, поддерживает Range) */
get: operations["downloadAppClient"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/app/android/latest": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Последняя версия Android-приложения (из релизов Gitea через сервер)
* @description Сервер сам опрашивает Gitea своим токеном и кэширует ответ на 10 минут, поэтому приложению
* не нужен доступ к Gitea. Нет настроек Gitea или релиза с APK — `404 app.update_unavailable`.
*/
get: operations["getAndroidLatest"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/app/android/download/{version}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** APK версии (кэшируется на сервере, поддерживает Range для докачки) */
get: operations["downloadAndroidApk"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/playlists": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["listPlaylists"];
put?: never;
post: operations["createPlaylist"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/playlists/{id}": {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
get: operations["getPlaylist"];
put: operations["updatePlaylist"];
post?: never;
delete: operations["deletePlaylist"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/me/playlists/{id}/share": {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
get?: never;
put?: never;
/** Создать или вернуть ссылку только для чтения (только владелец) */
post: operations["sharePlaylist"];
/** Отозвать ссылку (только владелец); повторная публикация создаёт новую ссылку */
delete: operations["revokePlaylistShare"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/shared/playlists/{shareId}": {
parameters: {
query?: never;
header?: never;
path: {
shareId: string;
};
cookie?: never;
};
/** Прочитать плейлист по действующей ссылке (требуется вход) */
get: operations["getSharedPlaylist"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
}
export type webhooks = Record<string, never>;
export interface components {
schemas: {
ListeningPreferences: {
requests: components["schemas"]["ActivityVisibility"];
auto_accept: components["schemas"]["ActivityVisibility"];
/** @default true */
autoplay: boolean;
};
ListeningAction: {
/** Format: uuid */
id: string;
/** @enum {string} */
action: "join" | "invite" | "accept" | "decline" | "cancel" | "leave" | "end";
/** Format: uuid */
target_id: string;
/** Format: uuid */
device_id?: string;
/** Format: uuid */
track_id?: string;
position_ms?: number;
playing?: boolean;
};
ListeningRoomInput: {
/** Format: uuid */
room_id: string;
/** Format: uuid */
device_id: string;
/** Format: int64 */
sequence: number;
/** Format: uuid */
track_id?: string;
playing: boolean;
position_ms: number;
};
ListeningRoom: {
/** Format: uuid */
id: string;
/** Format: uuid */
owner_id: string;
owner_name: string;
/** Format: uuid */
device_id: string;
/** Format: uuid */
track_id: string | null;
position_ms: number;
playing: boolean;
/** Format: date-time */
updated_at: string;
participants: {
/** Format: uuid */
id: string;
name: string;
}[];
};
ListeningRequest: {
/** Format: uuid */
id: string;
/** Format: uuid */
sender_id: string;
sender_name: string;
/** Format: uuid */
recipient_id: string;
/** Format: uuid */
owner_id: string;
/** @enum {string} */
kind: "join" | "invite";
/** Format: date-time */
expires_at: string;
};
ListeningState: {
preferences: components["schemas"]["ListeningPreferences"];
room: components["schemas"]["ListeningRoom"] | null;
requests: components["schemas"]["ListeningRequest"][];
/** Format: date-time */
server_time: string;
};
/**
* @default nobody
* @enum {string}
*/
ActivityVisibility: "nobody" | "friends" | "everyone";
ListeningActivityInput: {
/** Format: uuid */
device_id: string;
/** Format: int64 */
sequence: number;
playing: boolean;
/** @default 0 */
position_ms: number;
/** Format: uuid */
track_id?: string;
/** @enum {string} */
context: "other" | "wave" | "playlist";
/** Format: uuid */
playlist_id?: string;
};
ListeningActivity: {
/** Format: uuid */
track_id: string;
track_title: string;
artist: string;
/** @enum {string} */
context: "other" | "wave" | "playlist";
/** Format: uuid */
playlist_id?: string;
playlist_name?: string;
};
SocialPerson: {
/** Format: uuid */
id: string;
username: string;
display_name: string;
/** @enum {string} */
relationship: "none" | "incoming" | "outgoing" | "friend" | "blocked";
/** @description A current friend has an active client heartbeat within 45 seconds. Independent of music visibility; false for non-friends and blocked people. */
online: boolean;
unread: number;
activity?: components["schemas"]["ListeningActivity"];
last_message?: components["schemas"]["SocialMessagePreview"];
};
/** @description Latest message in a current friendship, without marking it read. Deleted content is never returned. */
SocialMessagePreview: {
/** Format: uuid */
id: string;
/** Format: uuid */
sender_id: string;
text: string;
/** @enum {string} */
attachment_kind: "none" | "track" | "playlist";
/** Format: date-time */
created_at: string;
deleted: boolean;
};
SocialNotification: {
/** Format: uuid */
id: string;
/** Format: uuid */
actor_id: string;
actor_name: string;
/** @enum {string} */
kind: "friend_request" | "friend_accepted" | "message" | "music" | "listening_request" | "listening_invite" | "listening_accepted";
/** Format: date-time */
created_at: string;
read: boolean;
};
SocialInbox: {
/** @default true */
friends_recommendations: boolean;
activity_visibility: components["schemas"]["ActivityVisibility"];
people: components["schemas"]["SocialPerson"][];
notifications: components["schemas"]["SocialNotification"][];
unread: number;
};
SocialAction: {
/** @enum {string} */
action: "request" | "accept" | "remove" | "block" | "unblock" | "read_chat" | "read_notification";
/** Format: uuid */
target_id: string;
/** Format: int64 */
up_to_seq?: number;
};
SendDirectMessage: {
/** Format: uuid */
id: string;
text: string;
/** @enum {string} */
attachment_kind: "none" | "track" | "playlist";
/** Format: uuid */
attachment_id?: string;
/** Format: uuid */
reply_to?: string;
};
DirectMessage: {
/** Format: uuid */
id: string;
/** Format: int64 */
seq: number;
/** Format: uuid */
sender_id: string;
text: string;
/** @enum {string} */
attachment_kind: "none" | "track" | "playlist";
/** Format: uuid */
attachment_id?: string;
/** Format: date-time */
created_at: string;
read: boolean;
/** Format: uuid */
reply_to?: string;
reply_preview?: string;
/** Format: date-time */
edited_at?: string;
deleted?: boolean;
reactions?: components["schemas"]["MessageReaction"][];
};
MessageReaction: {
emoji: string;
count: number;
mine: boolean;
};
ServerSource: {
id: string;
name: string;
url: string;
};
ServerSources: {
sources: components["schemas"]["ServerSource"][];
};
ServerJob: {
id: string;
/** @enum {string} */
kind: "update" | "config";
/** @enum {string} */
state: "running" | "succeeded" | "failed";
started_at: string;
finished_at: string;
target: string;
log: string;
};
ServerUpdates: {
sources: components["schemas"]["ServerSource"][];
versions: string[];
current_version: string;
current_commit: string;
target_version: string;
target_commit: string;
/** @enum {string} */
update_state: "available" | "current" | "ahead" | "unknown" | "unavailable" | "select_version";
source_error: string;
job: components["schemas"]["ServerJob"] | null;
};
ServerUpdateRequest: {
source_id: string;
/** @enum {string} */
channel: "latest" | "version" | "main";
version?: string;
expected_commit?: string;
};
ServerConfigEntry: {
key: string;
group: string;
type: string;
secret: boolean;
readonly: boolean;
effective: string;
env: string | null;
local: string | null;
default_value: string;
/** @enum {string} */
source: "env" | "local" | "default";
};
ServerConfig: {
revision: string;
restart_required: boolean;
entries: components["schemas"]["ServerConfigEntry"][];
};
ServerConfigPatch: {
revision: string;
values: {
[key: string]: string | null;
};
};
PlaylistShare: {
/** Format: uuid */
share_id: string;
};
PlaylistInput: {
name: string;
description: string;
track_ids: string[];
};
PlaylistUpdate: components["schemas"]["PlaylistInput"] & {
revision: number;
};
PlaylistSummary: {
/** Format: uuid */
id: string;
name: string;
description: string;
revision: number;
track_count: number;
/** Format: int64 */
duration_ms: number;
/** Format: date-time */
created_at: string;
/** Format: date-time */
updated_at: string;
};
Playlist: components["schemas"]["PlaylistSummary"] & {
/**
* Format: uuid
* @description Действующая ссылка; возвращается только владельцу через /me/playlists
*/
readonly share_id?: string | null;
tracks: components["schemas"]["Track"][];
};
PlaylistList: {
items: components["schemas"]["PlaylistSummary"][];
};
Onboarding: {
required: boolean;
choice?: components["schemas"]["OnboardingChoice"];
artists: {
/** Format: uuid */
id: string;
name: string;
track_count: number;
/** @description Обложка самого большого альбома исполнителя */
cover_url: string | null;
cover_colors: string[];
}[];
genres: {
name: string;
track_count: number;
}[];
};
OnboardingChoice: {
/** @enum {string|null} */
gender?: "male" | "female" | "other" | null;
/**
* @description Текущая приблизительная возрастная группа. Сервер хранит год выбора и учитывает прошедшие годы.
* @enum {string|null}
*/
age_group?: "under_13" | "13_19" | "20_29" | "30_39" | "40_49" | "50_59" | "60_plus" | null;
/** @description Год последнего выбора возрастной группы. */
readonly age_group_year?: number;
artist_ids: string[];
genres: string[];
};
UserRef: {
/** Format: uuid */
id: string;
username: string;
};
/** @enum {string} */
UploadStatus: "uploading" | "processing" | "pending_review" | "approved" | "importing" | "imported" | "import_failed" | "duplicate" | "invalid" | "rejected" | "withdrawn" | "expired";
UploadQuota: {
/** Format: int64 */
limit_bytes: number;
/** Format: int64 */
used_bytes: number;
/** Format: int64 */
per_user_limit_bytes: number | null;
/** Format: int64 */
user_used_bytes: number;
/** Format: int64 */
max_file_bytes: number;
};
UploadPrecheckRequest: {
files: {
client_id: string;
/** Format: int64 */
size: number;
sha256: string;
artist?: string;
title?: string;
duration_ms?: number;
album?: string;
}[];
};
UploadPrecheckResult: {
files: {
client_id: string;
/** @enum {string} */
result: "accepted" | "duplicate" | "too_large";
/**
* Format: uuid
* @description С каким треком совпал (дубль или похожие метаданные)
*/
track_id: string | null;
/** @description Совпали только метаданные — файл примут, админ решит */
possible_duplicate: boolean;
}[];
};
UploadBatchRequest: {
comment?: string;
files: {
client_id: string;
name: string;
/** @description Относительный путь в перетащенной папке */
rel_path?: string;
/** Format: int64 */
size: number;
sha256: string;
}[];
};
UploadBatchCreated: {
/** Format: uuid */
batch_id: string;
files: {
client_id: string;
/** Format: uuid */
upload_file_id: string | null;
tus_url: string | null;
/** @description Код отказа — uploads.queue_full, uploads.user_quota_full, uploads.too_large, uploads.duplicate, uploads.unsupported_format */
rejected: string | null;
/** Format: uuid */
track_id: string | null;
}[];
};
UploadMeta: {
artist: string;
albumartist: string;
album: string;
title: string;
genre: string;
year: number | null;
track: number | null;
disc: number | null;
};
UploadFile: {
/** Format: uuid */
id: string;
/** Format: uuid */
batch_id: string;
batch_comment: string | null;
author: components["schemas"]["UserRef"];
status: components["schemas"]["UploadStatus"];
original_name: string;
client_rel_path: string | null;
/** Format: int64 */
size_bytes: number;
/** Format: int64 */
received_bytes: number;
format: string | null;
codec: string | null;
bitrate: number | null;
sample_rate: number | null;
bit_depth: number | null;
duration_ms: number | null;
tags: {
[key: string]: string;
};
metadata: components["schemas"]["UploadMeta"] | null;
metadata_edited: boolean;
/**
* Format: uuid
* @description Найден в каталоге — файл добавится к существующему исполнителю
*/
matched_artist_id: string | null;
/**
* Format: uuid
* @description Найден в каталоге — «будет добавлено к существующему альбому»
*/
matched_album_id: string | null;
/** Format: uuid */
duplicate_of_track_id: string | null;
/** @enum {string|null} */
duplicate_level: "sha256" | "metadata" | "fingerprint" | null;
possible_duplicate: boolean;
/** @description Тот же трек, но лучшего качества — ждёт решения, если включён allow_quality_upgrade */
quality_upgrade: boolean;
/** Format: uuid */
target_source_id: string | null;
/** @description Путь в хранилище по write_template (null — не построился, причина в status_reason) */
target_rel_path: string | null;
status_reason: string | null;
/** Format: date-time */
reviewed_at: string | null;
/** Format: date-time */
created_at: string;
/** Format: date-time */
updated_at: string;
/** @description Только автору и пока файл в статусе uploading */
tus_url: string | null;
/** @description Подписанная ссылка прослушивания из staging; null, если файла уже нет */
stream_url: string | null;
};
UploadFilePage: {
items: components["schemas"]["UploadFile"][];
next_cursor: string | null;
};
UploadPatch: {
metadata?: components["schemas"]["UploadMeta"];
/** Format: uuid */
target_source_id?: string;
};
/** @description Пустые поля не меняют файлы. cover_base64 null снимает обложку пачки. */
UploadBatchPatch: {
artist?: string;
album?: string;
year?: number | null;
/** @description JPEG, PNG или WebP, не больше 8 МБ после декодирования */
cover_base64?: string | null;
};
UploadReviewRequest: {
file_ids: string[];
/** @enum {string} */
decision: "approve" | "reject";
/** @description Причина отклонения — её видит автор */
reason?: string;
};
UploadReviewResult: {
items: {
/** Format: uuid */
id: string;
ok: boolean;
error: components["schemas"]["Problem"] | null;
}[];
};
UploadSettings: {
/** Format: int64 */
queue_limit_bytes: number;
/** Format: int64 */
per_user_limit_bytes: number | null;
/** Format: int64 */
max_file_bytes: number;
/** Format: uuid */
default_source_id: string | null;
/** @description Тот же трек в лучшем качестве идёт на рассмотрение, а не в дубли */
allow_quality_upgrade: boolean;
};
/** @description Лимит на пользователя и хранилище по умолчанию передаются всегда (null — выключить / не задано). */
UploadSettingsPatch: {
/** Format: int64 */
queue_limit_bytes?: number;
/**
* Format: int64
* @description null — выключить лимит на пользователя
*/
per_user_limit_bytes: number | null;
/** Format: int64 */
max_file_bytes?: number;
/**
* Format: uuid
* @description null — без хранилища по умолчанию
*/
default_source_id: string | null;
allow_quality_upgrade?: boolean;
};
HealthStatus: {
/** @enum {string} */
status: "ok";
};
ReadyStatus: {
/** @enum {string} */
status: "ok" | "degraded";
/** @description Результат проверки каждой зависимости */
checks: {
[key: string]: string;
};
};
ServerInfo: {
/** @example pipu-music */
name: string;
/**
* @description Версия сервера (SemVer)
* @example 0.1.0
*/
version: string;
/** @example v1 */
api_version: string;
/**
* @example [
* "ru",
* "en"
* ]
*/
supported_locales: string[];
/**
* @description Минимальный versionCode Android-приложения, которое поддерживает сервер
* @example 10099
*/
min_android_version_code: number;
/** @description Первый вход администратора ещё не завершён — клиент может показать подсказку */
bootstrap_required: boolean;
};
/** @enum {string} */
Role: "admin" | "moderator" | "user";
/** @enum {string} */
ClientType: "web" | "android" | "desktop";
LoginRequest: {
username: string;
password: string;
client_type: components["schemas"]["ClientType"];
/** @description Например «Chrome / Windows», «Pixel 8» */
device_name?: string;
};
RefreshRequest: {
/** @description Android и desktop; веб передаёт токен в cookie */
refresh_token?: string;
};
AuthTokens: {
access_token: string;
/** @enum {string} */
token_type: "Bearer";
/** @description Срок жизни access-токена, секунды */
expires_in: number;
/** @description Для `client_type: android` и `client_type: desktop` */
refresh_token?: string;
user: components["schemas"]["Me"];
};
UiPrefs: {
/** @enum {string} */
theme?: "dark" | "light" | "system";
/** @enum {string} */
wave_variant?: "orb" | "liquid";
/** @enum {string} */
web_player?: "bar" | "island";
/**
* @description Где в топбаре веба поиск (по умолчанию center)
* @enum {string}
*/
search_position?: "center" | "left" | "right";
/** @description Сворачивать поиск в кнопку с лупой без фокуса (по умолчанию false) */
search_collapse?: boolean;
/** @description Показывать на главной веба выбор занятия (по умолчанию true) */
home_activities?: boolean;
/** @description Показывать на главной веба выбор настроения (по умолчанию true) */
home_moods?: boolean;
/** @enum {string} */
mobile_player?: "cover" | "wave";
ambient?: boolean;
crossfade_s?: number;
normalize?: boolean;
};
Me: {
/** Format: uuid */
id: string;
username: string;
display_name: string | null;
role: components["schemas"]["Role"];
/** @description Управление обновлениями сервера. У admin всегда; другим выдаёт только admin */
manages_updates?: boolean;
/** @description Может рассматривать очередь на добавление. Не следует из роли и может быть у нескольких людей сразу */
reviews_uploads: boolean;
locale: string;
ui_prefs: components["schemas"]["UiPrefs"];
must_change_password: boolean;
must_change_credentials: boolean;
/** Format: date-time */
created_at: string;
};
UpdateMeRequest: {
/** @description Пустая строка — сбросить имя */
display_name?: string;
locale?: string;
ui_prefs?: components["schemas"]["UiPrefs"];
};
ChangePasswordRequest: {
current_password?: string;
new_password: string;
};
BootstrapCredentialsRequest: {
new_username: string;
new_password: string;
};
SourceCoverStats: {
/** Format: int64 */
files_total: number;
/**
* Format: int64
* @description Файлы, альбом которых имеет готовую локальную обложку (встроенную или из папки)
*/
files_with_cover: number;
/** Format: int64 */
albums_pending: number;
};
UserArchive: {
/** @enum {integer} */
version: 1;
users: components["schemas"]["UserArchiveEntry"][];
};
UserArchiveEntry: {
username: string;
display_name: string | null;
role: components["schemas"]["Role"];
/** @description Argon2id PHC. Секретные данные; файл нужно хранить в защищённом месте. */
password_hash: string;
is_blocked: boolean;
must_change_password: boolean;
must_change_credentials: boolean;
reviews_uploads: boolean;
manages_updates: boolean;
};
UserImportResult: {
created: number;
skipped: string[];
};
AdminUser: {
/** Format: uuid */
id: string;
username: string;
display_name: string | null;
role: components["schemas"]["Role"];
/** @description Управление обновлениями сервера. У admin всегда; другим выдаёт только admin */
manages_updates?: boolean;
/** @description Может рассматривать очередь на добавление. Не следует из роли и может быть у нескольких людей сразу */
reviews_uploads: boolean;
locale: string;
is_blocked: boolean;
must_change_password: boolean;
must_change_credentials: boolean;
/** Format: date-time */
created_at: string;
/** Format: date-time */
last_login_at: string | null;
};
AdminUserPage: {
items: components["schemas"]["AdminUser"][];
next_cursor: string | null;
};
CreateUserRequest: {
username: string;
display_name?: string;
role: components["schemas"]["Role"];
/** @description Управление обновлениями сервера. У admin всегда; другим выдаёт только admin */
manages_updates?: boolean;
/** @description Сразу выдать аудит загрузок. Может задать только админ */
reviews_uploads?: boolean;
};
CreatedUser: {
user: components["schemas"]["AdminUser"];
/** @description Показывается один раз */
temporary_password: string;
};
UpdateUserRequest: {
/** @description Новый логин. Может менять только администратор, в том числе у себя */
username?: string;
/** @description Пустая строка — сбросить имя */
display_name?: string;
role?: components["schemas"]["Role"];
is_blocked?: boolean;
/** @description Управление обновлениями сервера. У admin всегда; другим выдаёт только admin */
manages_updates?: boolean;
/** @description Выдать или забрать аудит загрузок. Может менять только админ, в том числе у себя */
reviews_uploads?: boolean;
};
TemporaryPassword: {
temporary_password: string;
};
AuditActor: {
/** Format: uuid */
id: string;
username: string;
};
AuditEntry: {
/** Format: uuid */
id: string;
/** @description null — система или удалённый пользователь */
actor: components["schemas"]["AuditActor"] | null;
/** @example user.create */
action: string;
target_type: string | null;
/** Format: uuid */
target_id: string | null;
payload: {
[key: string]: unknown;
} | null;
/** Format: date-time */
created_at: string;
};
AuditPage: {
items: components["schemas"]["AuditEntry"][];
next_cursor: string | null;
};
/** @enum {string} */
SourceType: "nfs" | "local";
/** @enum {string} */
SourceStatus: "pending" | "mounted" | "error" | "disabled";
/** @enum {string} */
TagPriority: "tags_first" | "path_first";
Source: {
excluded_dirs?: components["schemas"]["ExcludedDirs"];
/** Format: uuid */
id: string;
name: string;
type: components["schemas"]["SourceType"];
nfs_server: string | null;
nfs_export: string | null;
nfs_options: string;
/** @description Подпапка относительно LIBRARY_HOST, пусто — весь каталог */
local_path: string | null;
tag_priority: components["schemas"]["TagPriority"];
/** @description Автоматический скан, null — только вручную */
scan_interval_minutes: number | null;
/** @description Принимает импорт из очереди на добавление (NFS монтируется агентом ещё и на запись) */
accepts_uploads: boolean;
/** @description Шаблон пути новых файлов (docs/uploads.md#7), null — не задан */
write_template: string | null;
status: components["schemas"]["SourceStatus"];
status_message: string | null;
/** Format: date-time */
last_scan_at: string | null;
/** Format: date-time */
created_at: string;
scan: components["schemas"]["ScanProgress"] | null;
};
SourceList: {
items: components["schemas"]["Source"][];
};
SourceInput: {
excluded_dirs?: components["schemas"]["ExcludedDirs"];
name: string;
type: components["schemas"]["SourceType"];
nfs_server?: string;
nfs_export?: string;
nfs_options?: string;
local_path?: string;
tag_priority?: components["schemas"]["TagPriority"];
scan_interval_minutes?: number | null;
accepts_uploads?: boolean;
write_template?: string;
};
SourcePatch: {
excluded_dirs?: components["schemas"]["ExcludedDirs"];
name?: string;
nfs_server?: string;
nfs_export?: string;
nfs_options?: string;
local_path?: string;
tag_priority?: components["schemas"]["TagPriority"];
/** @description 0 — отключить автоматический скан */
scan_interval_minutes?: number;
/** @description false — отключить хранилище (треки становятся недоступны), true — подключить снова */
enabled?: boolean;
/** @description Смена переподключает NFS-хранилище (rw-точка агента) */
accepts_uploads?: boolean;
/**
* @description Шаблон пути новых файлов; пусто — убрать. Неверный синтаксис — `422 validation.template_invalid`
* с `params.reason`. Проверка обратимости не обязательна для сохранения — её показывает `write-template/check`.
*/
write_template?: string;
};
/** @description Literal folder paths relative to the storage root, including all descendants. Case sensitive; no glob matching. Empty list clears exclusions. Existing library records are retained, but their scan and analysis are skipped. Changes require no running scan. */
ExcludedDirs: string[];
SourceTestResult: {
ok: boolean;
message: string;
/** @description Сколько аудиофайлов найдено (проверка останавливается на 1000) */
audio_files: number;
/** @description Удалось создать и удалить `.pipu-write-test` (только для accepts_uploads; иначе null) */
write_ok?: boolean | null;
write_message?: string | null;
};
WriteTemplateSuggestion: {
template: string;
};
WriteTemplateCheckRequest: {
template: string;
};
WriteTemplateMismatch: {
/** @description Реальный путь файла */
rel_path: string;
/** @description Путь по шаблону, null — не построился */
rendered: string | null;
/** @description Поля, которые регэкспы хранилища распознали не так; `pattern` — не совпало ни одно выражение */
fields: string[];
error: string | null;
};
WriteTemplateCheck: {
/** @description Все пути разобраны обратно без изменений и ≥ 90% совпали с реальными */
ok: boolean;
total: number;
round_trip: number;
same_path: number;
mismatches: components["schemas"]["WriteTemplateMismatch"][];
};
PathPattern: {
regex: string;
is_enabled: boolean;
};
PatternList: {
patterns: components["schemas"]["PathPattern"][];
};
PatternPreviewRequest: {
patterns: components["schemas"]["PathPattern"][];
/** @default 50 */
sample: number;
};
TrackMeta: {
artist: string;
album_artist: string;
album: string;
title: string;
genres: string[];
year: number | null;
track: number | null;
disc: number | null;
};
PreviewItem: {
rel_path: string;
/** @description Номер совпавшего шаблона, null — ни один */
pattern_index: number | null;
skipped: boolean;
path_fields: {
[key: string]: string;
};
tags: {
[key: string]: string;
};
result: components["schemas"]["TrackMeta"];
error: string | null;
};
PatternPreview: {
items: components["schemas"]["PreviewItem"][];
unmatched: number;
};
ScanRequest: {
/** @description Перечитать все файлы, а не только новые и изменённые */
full?: boolean;
};
ScanProgress: {
/**
* @description Current scan stage; progress percentage is available only during processing.
* @enum {string}
*/
phase?: "walking" | "preparing" | "processing" | "finalizing";
/** @description Directories visited so far, including the source root. */
walked_dirs?: number;
/** @description Current directory relative to the source root, using forward slashes. */
current_dir?: string;
running: boolean;
full: boolean;
/** Format: date-time */
started_at: string;
/** Format: date-time */
finished_at: string | null;
found: number;
to_process: number;
processed: number;
added: number;
updated: number;
moved: number;
missing: number;
errors: number;
error: string | null;
};
LibraryStatus: {
analysis: components["schemas"]["AnalysisStatus"];
wave: components["schemas"]["WaveMetrics"];
artists: number;
albums: number;
tracks: number;
files: number;
missing_files: number;
file_errors: number;
sources: components["schemas"]["SourceStatusItem"][];
};
SourceStatusItem: {
/** Format: uuid */
id: string;
name: string;
status: components["schemas"]["SourceStatus"];
status_message: string | null;
/** Format: date-time */
last_scan_at: string | null;
scan: components["schemas"]["ScanProgress"] | null;
};
LibraryError: {
/** Format: uuid */
file_id: string;
/** Format: uuid */
source_id: string;
rel_path: string;
error: string;
};
LibraryErrorPage: {
items: components["schemas"]["LibraryError"][];
next_cursor: string | null;
};
AnalysisError: {
/** Format: uuid */
track_id: string;
title: string;
/** Format: uuid */
source_id: string | null;
source_name: string | null;
/** @description Path relative to the source root; primary file if available, otherwise a known file of this track. */
rel_path: string | null;
error: string;
};
AnalysisErrorPage: {
items: components["schemas"]["AnalysisError"][];
next_cursor: string | null;
};
HostDirList: {
path: string;
dirs: string[];
};
ArtistRef: {
/** Format: uuid */
id: string;
name: string;
};
AlbumRef: {
/** Format: uuid */
id: string;
title: string;
year: number | null;
cover_url: string | null;
cover_colors: string[];
};
Track: {
/** Format: uuid */
id: string;
title: string;
duration_ms: number;
artists: components["schemas"]["ArtistRef"][];
album: components["schemas"]["AlbumRef"];
genres: string[];
disc_no: number | null;
track_no: number | null;
/** @description Есть доступный файл (хранилище подключено, файл на месте) */
available: boolean;
/** @description Подписанная ссылка на аудио (12 ч); null — трек недоступен */
stream_url: string | null;
reaction: components["schemas"]["Reaction"] | null;
/** @description Аудиопризнаки (после анализа) — для анимации волны и выравнивания громкости */
features: components["schemas"]["TrackFeatures"] | null;
};
GeniusStats: {
configured: boolean;
paused: boolean;
running: boolean;
total: number;
pending: number;
matched: number;
lyrics: number;
annotations: number;
images: number;
unmatched: number;
errors: number;
last_error: string;
/** Format: date-time */
cooldown_until: string;
};
GeniusContent: {
status: string;
lyrics: string;
source_url: string;
song_image_url: string;
artist_image_url: string;
description: string;
annotations: components["schemas"]["GeniusAnnotation"][];
};
GeniusAnnotation: {
fragment: string;
text: string;
url: string;
verified: boolean;
authors: string;
};
Artist: {
image_url?: string;
/** Format: uuid */
id: string;
name: string;
album_count: number;
track_count: number;
};
AlbumSummary: {
/** Format: uuid */
id: string;
title: string;
year: number | null;
cover_url: string | null;
cover_colors: string[];
artist: components["schemas"]["ArtistRef"];
track_count: number;
};
AlbumSummaryList: {
items: components["schemas"]["AlbumSummary"][];
};
Album: {
/** Format: uuid */
id: string;
title: string;
year: number | null;
cover_url: string | null;
cover_colors: string[];
artist: components["schemas"]["ArtistRef"];
duration_ms: number;
tracks: components["schemas"]["Track"][];
};
SearchResults: {
artists: components["schemas"]["ArtistRef"][];
albums: components["schemas"]["AlbumSummary"][];
tracks: components["schemas"]["Track"][];
/** @description Оценка общего числа совпадений */
totals: {
artists: number;
albums: number;
tracks: number;
};
/** @description Запрос в другой раскладке, если по исходному ничего не нашлось */
corrected_query: string | null;
next_cursor: string | null;
};
TrackFeatures: {
bpm: number | null;
energy: number | null;
loudness_lufs: number | null;
};
/** @enum {string} */
StreamQuality: "auto" | "original" | "high" | "medium" | "low";
/** @enum {string} */
Reaction: "like" | "dislike";
TrackIds: {
ids: string[];
};
TrackList: {
items: components["schemas"]["Track"][];
};
PlayEvent: {
/**
* Format: uuid
* @description UUIDv7 от клиента — ключ идемпотентности
*/
id: string;
/** @enum {string} */
type: "play_start" | "play_end" | "skip" | "seek" | "pause" | "resume" | "like" | "unlike" | "dislike" | "undislike";
/** Format: uuid */
track_id: string;
/** Format: date-time */
occurred_at: string;
position_ms?: number;
played_ms?: number;
from_ms?: number;
/** @enum {string} */
context_type?: "wave" | "album" | "artist" | "search" | "collection" | "history" | "queue";
context_id?: string;
/** Format: uuid */
wave_session_id?: string;
offline?: boolean;
};
EventBatch: {
events: components["schemas"]["PlayEvent"][];
};
EventBatchResult: {
accepted: number;
duplicates: number;
/** @description Слишком старые (> 30 дней) или с неизвестным треком */
rejected: number;
};
PlaybackContext: {
type?: string;
id?: string;
label?: string;
/** Format: uuid */
wave_session_id?: string;
};
PlaybackStateInput: {
/** Format: uuid */
track_id: string | null;
position_ms: number;
queue: string[];
queue_index: number;
context?: components["schemas"]["PlaybackContext"];
shuffle?: boolean;
/** @enum {string} */
repeat_mode?: "off" | "one" | "all";
volume?: number;
device_id?: string;
};
PlaybackState: {
/** Format: uuid */
track_id: string | null;
position_ms: number;
queue: string[];
queue_index: number;
context: components["schemas"]["PlaybackContext"] | null;
shuffle: boolean;
/** @enum {string} */
repeat_mode: "off" | "one" | "all";
volume: number;
device_id: string | null;
/** Format: date-time */
updated_at: string | null;
};
HistoryItem: {
/** Format: uuid */
id: string;
/** Format: date-time */
played_at: string;
track: components["schemas"]["Track"];
};
HistoryPage: {
items: components["schemas"]["HistoryItem"][];
next_cursor: string | null;
};
ReactedTrack: {
/** Format: date-time */
created_at: string;
track: components["schemas"]["Track"];
};
ReactedTrackPage: {
items: components["schemas"]["ReactedTrack"][];
total: number;
next_cursor: string | null;
};
ReactionInput: {
reaction: components["schemas"]["Reaction"];
};
WaveOption: {
/** @example running */
key: string;
/** @description Имя иконки Material Symbols */
icon: string;
};
WaveOptions: {
activities: components["schemas"]["WaveOption"][];
moods: components["schemas"]["WaveOption"][];
};
WaveContext: {
activity?: string | null;
mood?: string | null;
};
WaveStart: {
activity?: string | null;
mood?: string | null;
seed?: {
/** @enum {string} */
type: "track" | "album" | "artist";
/** Format: uuid */
id: string;
};
};
WaveFeedback: {
/** Format: uuid */
track_id: string;
/** @enum {string} */
outcome: "complete" | "skip" | "skip_early" | "like" | "dislike";
};
WaveNext: {
feedback?: components["schemas"]["WaveFeedback"][];
};
WaveBatch: {
/** Format: uuid */
session_id: string;
activity: string | null;
mood: string | null;
tracks: components["schemas"]["Track"][];
/** @description Рекомендатель недоступен — пачка собрана упрощённо (лайки, любимые исполнители) */
fallback: boolean;
};
AnalysisStatus: {
queued: number;
running: number;
done: number;
failed: number;
analyzer_ver: string | null;
/** @description Самая частая ошибка среди неудавшихся — подсказка, что чинить */
top_error: string | null;
};
/** @description Метрики волны за 7 дней */
WaveMetrics: {
served: number;
listen_through_rate: number | null;
early_skip_rate: number | null;
/** @description Лайков на 100 треков */
like_rate: number | null;
sessions: number;
/** @description Те же метрики по версии модели показа (v1 / ALS / ранжировщик) — сравнение онлайн */
by_model: components["schemas"]["WaveModelMetrics"][];
};
WaveModelMetrics: {
model_ver: string;
served: number;
listen_through_rate: number | null;
early_skip_rate: number | null;
like_rate: number | null;
};
/** @enum {string} */
AppClient: "android" | "windows" | "linux" | "macos";
AppClientBuild: {
version: string;
filename: string;
/** Format: int64 */
size: number;
sha256?: string;
download_url: string;
};
AppClientFile: {
client: components["schemas"]["AppClient"];
version?: string;
filename: string;
/** Format: int64 */
size: number;
sha256?: string;
download_url: string;
older?: components["schemas"]["AppClientBuild"][];
};
AppClients: {
version: string;
version_code: number;
notes_md: string;
clients: components["schemas"]["AppClientFile"][];
};
AndroidRelease: {
/** @example 0.6.1 */
version: string;
version_code: number;
/** @description Что нового (Markdown из релиза) */
notes_md: string;
/** Format: int64 */
size: number;
sha256: string;
download_url: string;
/** @description Версии ниже обязаны обновиться */
min_supported: number;
};
Session: {
/** Format: uuid */
id: string;
device_name: string | null;
client_type: components["schemas"]["ClientType"];
/**
* Format: date-time
* @description Время входа
*/
created_at: string;
/** Format: date-time */
last_used_at: string;
/** @description Сессия, из которой сделан запрос */
current: boolean;
};
SessionList: {
items: components["schemas"]["Session"][];
};
FieldError: {
field: string;
code: string;
};
Problem: {
/** @default about:blank */
type: string;
status: number;
/** @description Машинный код ошибки для i18n, например `auth.invalid_credentials` */
code: string;
/** @description Пояснение для логов (не для показа пользователю) */
detail?: string;
params?: {
[key: string]: unknown;
};
/** @description Ошибки отдельных полей запроса */
errors?: components["schemas"]["FieldError"][];
};
};
responses: {
/** @description Ошибка (RFC 9457) */
Problem: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["Problem"];
};
};
};
parameters: {
SourceId: string;
EntityId: string;
Limit: number;
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
Cursor: string;
/** @description Статусы через запятую */
UploadStatusFilter: components["schemas"]["UploadStatus"][];
UserId: string;
};
requestBodies: never;
headers: never;
pathItems: never;
}
export type $defs = Record<string, never>;
export interface operations {
setFriendsRecommendations: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": {
enabled: boolean;
};
};
};
responses: {
/** @description Saved */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getListeningState: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Listening preferences, current room and pending requests */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ListeningState"];
};
};
default: components["responses"]["Problem"];
};
};
setListeningPreferences: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ListeningPreferences"];
};
};
responses: {
/** @description Saved */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
listeningAction: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ListeningAction"];
};
};
responses: {
/** @description Applied */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
publishListeningState: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ListeningRoomInput"];
};
};
responses: {
/** @description Applied */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
publishListeningActivity: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ListeningActivityInput"];
};
};
responses: {
/** @description Applied */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
setActivityVisibility: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": {
visibility: components["schemas"]["ActivityVisibility"];
};
};
};
responses: {
/** @description Saved */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getActivityPlaylist: {
parameters: {
query?: never;
header?: never;
path: {
userId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Read-only playlist */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Playlist"];
};
};
default: components["responses"]["Problem"];
};
};
getSocial: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Social inbox */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SocialInbox"];
};
};
default: components["responses"]["Problem"];
};
};
searchPeople: {
parameters: {
query: {
q: string;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Up to 30 people, excluding blocked accounts and either direction of personal blocking */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SocialPerson"][];
};
};
default: components["responses"]["Problem"];
};
};
socialAction: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["SocialAction"];
};
};
responses: {
/** @description Applied */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getDirectMessages: {
parameters: {
query?: {
before?: number;
q?: string;
/** @description Only non-deleted track and playlist attachments, with the same history pagination. */
music?: boolean;
};
header?: never;
path: {
peerId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Message page */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["DirectMessage"][];
};
};
default: components["responses"]["Problem"];
};
};
sendDirectMessage: {
parameters: {
query?: never;
header?: never;
path: {
peerId: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["SendDirectMessage"];
};
};
responses: {
/** @description Stored message */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["DirectMessage"];
};
};
default: components["responses"]["Problem"];
};
};
getChatMeta: {
parameters: {
query?: never;
header?: never;
path: {
peerId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Ephemeral typing indicator, friends only */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
typing: boolean;
};
};
};
default: components["responses"]["Problem"];
};
};
setChatTyping: {
parameters: {
query?: never;
header?: never;
path: {
peerId: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": {
typing: boolean;
};
};
};
responses: {
/** @description Applied */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
updateChatMessage: {
parameters: {
query?: never;
header?: never;
path: {
peerId: string;
messageId: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": {
/** @enum {string} */
action: "edit" | "delete" | "react";
text?: string;
/** @enum {string} */
emoji?: "❤️" | "👍" | "🔥" | "😂" | "🎵" | "👏";
};
};
};
responses: {
/** @description Applied */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getServerUpdates: {
parameters: {
query?: {
source_id?: string;
channel?: "latest" | "version" | "main";
version?: string;
fresh?: boolean;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Server management result */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ServerUpdates"];
};
};
default: components["responses"]["Problem"];
};
};
startServerUpdate: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ServerUpdateRequest"];
};
};
responses: {
/** @description Server management result */
202: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ServerJob"];
};
};
default: components["responses"]["Problem"];
};
};
saveServerUpdateSources: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ServerSources"];
};
};
responses: {
/** @description Server management result */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ServerSources"];
};
};
default: components["responses"]["Problem"];
};
};
getServerConfig: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Server management result */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ServerConfig"];
};
};
default: components["responses"]["Problem"];
};
};
saveServerConfig: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ServerConfigPatch"];
};
};
responses: {
/** @description Server management result */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ServerConfig"];
};
};
default: components["responses"]["Problem"];
};
};
applyServerConfig: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Server management result */
202: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ServerJob"];
};
};
default: components["responses"]["Problem"];
};
};
getGeniusStats: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Persistent enrichment statistics (admin only) */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["GeniusStats"];
};
};
};
};
controlGenius: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": {
/** @enum {string} */
action: "start" | "pause" | "retry";
};
};
};
responses: {
/** @description Updated statistics */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["GeniusStats"];
};
};
};
};
getTrackGenius: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Cached lyrics and annotations; never makes an upstream request */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["GeniusContent"];
};
};
};
};
getHealthz: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Процесс жив */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HealthStatus"];
};
};
};
};
getReadyz: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Все зависимости доступны */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ReadyStatus"];
};
};
/** @description Одна или несколько зависимостей недоступны */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ReadyStatus"];
};
};
};
};
getServerInfo: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Сведения о сервере */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ServerInfo"];
};
};
default: components["responses"]["Problem"];
};
};
login: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["LoginRequest"];
};
};
responses: {
/** @description Успешный вход */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AuthTokens"];
};
};
default: components["responses"]["Problem"];
};
};
refreshTokens: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: {
pipu_rt?: string;
};
};
requestBody?: {
content: {
"application/json": components["schemas"]["RefreshRequest"];
};
};
responses: {
/** @description Новая пара токенов */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AuthTokens"];
};
};
default: components["responses"]["Problem"];
};
};
logout: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Сессия завершена, cookie `pipu_rt` очищена */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
logoutAll: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Все сессии пользователя завершены */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getMe: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Профиль */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Me"];
};
};
default: components["responses"]["Problem"];
};
};
updateMe: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UpdateMeRequest"];
};
};
responses: {
/** @description Обновлённый профиль */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Me"];
};
};
default: components["responses"]["Problem"];
};
};
changePassword: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ChangePasswordRequest"];
};
};
responses: {
/** @description Пароль изменён, новая пара токенов */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AuthTokens"];
};
};
default: components["responses"]["Problem"];
};
};
setBootstrapCredentials: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["BootstrapCredentialsRequest"];
};
};
responses: {
/** @description Учётные данные заменены, новая пара токенов */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AuthTokens"];
};
};
default: components["responses"]["Problem"];
};
};
listMySessions: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Список сессий, новые сверху */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SessionList"];
};
};
default: components["responses"]["Problem"];
};
};
revokeMySession: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Сессия завершена */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
listUsers: {
parameters: {
query?: {
q?: string;
role?: components["schemas"]["Role"];
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница пользователей */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AdminUserPage"];
};
};
default: components["responses"]["Problem"];
};
};
createUser: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["CreateUserRequest"];
};
};
responses: {
/** @description Пользователь создан */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["CreatedUser"];
};
};
default: components["responses"]["Problem"];
};
};
getSourceCoverStats: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Доступные аудиофайлы без исключённых папок; внешние обложки не учитываются */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SourceCoverStats"];
};
};
default: components["responses"]["Problem"];
};
};
exportUsers: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Файл переноса пользователей */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UserArchive"];
};
};
default: components["responses"]["Problem"];
};
};
importUsers: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UserArchive"];
};
};
responses: {
/** @description Результат импорта */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UserImportResult"];
};
};
default: components["responses"]["Problem"];
};
};
deleteUser: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["UserId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Удалён */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
updateUser: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["UserId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UpdateUserRequest"];
};
};
responses: {
/** @description Обновлённый пользователь */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AdminUser"];
};
};
default: components["responses"]["Problem"];
};
};
resetUserPassword: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["UserId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Временный пароль */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["TemporaryPassword"];
};
};
default: components["responses"]["Problem"];
};
};
resetUserRecommendations: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["UserId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Сброшено */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getUploadQuota: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Лимиты и занятое место */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadQuota"];
};
};
default: components["responses"]["Problem"];
};
};
precheckUploads: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UploadPrecheckRequest"];
};
};
responses: {
/** @description Итог по каждому файлу */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadPrecheckResult"];
};
};
default: components["responses"]["Problem"];
};
};
createUploadBatch: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UploadBatchRequest"];
};
};
responses: {
/** @description Пачка создана */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadBatchCreated"];
};
};
default: components["responses"]["Problem"];
};
};
listMyUploads: {
parameters: {
query?: {
/** @description Статусы через запятую */
status?: components["parameters"]["UploadStatusFilter"];
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница предложений */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadFilePage"];
};
};
default: components["responses"]["Problem"];
};
};
unseenUploadDecisions: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Число */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
count: number;
};
};
};
default: components["responses"]["Problem"];
};
};
markUploadsSeen: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Отмечено */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
withdrawUpload: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Отозвано, место освобождено */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
listUploads: {
parameters: {
query?: {
/** @description Статусы через запятую */
status?: components["parameters"]["UploadStatusFilter"];
author?: string;
batch?: string;
possible_duplicate?: boolean;
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница очереди */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadFilePage"];
};
};
default: components["responses"]["Problem"];
};
};
updateUpload: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UploadPatch"];
};
};
responses: {
/** @description Файл */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadFile"];
};
};
default: components["responses"]["Problem"];
};
};
retryUploadImport: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Файл снова одобрен */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadFile"];
};
};
default: components["responses"]["Problem"];
};
};
streamUpload: {
parameters: {
query: {
exp: number;
sig: string;
};
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Аудио из staging */
200: {
headers: {
[name: string]: unknown;
};
content: {
"audio/*": string;
};
};
default: components["responses"]["Problem"];
};
};
updateUploadBatch: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UploadBatchPatch"];
};
};
responses: {
/** @description Обновлённые файлы пачки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
items: components["schemas"]["UploadFile"][];
};
};
};
default: components["responses"]["Problem"];
};
};
reviewUploads: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UploadReviewRequest"];
};
};
responses: {
/** @description Итог по каждому файлу */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadReviewResult"];
};
};
default: components["responses"]["Problem"];
};
};
getUploadSettings: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Настройки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadSettings"];
};
};
default: components["responses"]["Problem"];
};
};
updateUploadSettings: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UploadSettingsPatch"];
};
};
responses: {
/** @description Настройки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadSettings"];
};
};
default: components["responses"]["Problem"];
};
};
listAudit: {
parameters: {
query?: {
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница журнала */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AuditPage"];
};
};
default: components["responses"]["Problem"];
};
};
listSources: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Список хранилищ */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SourceList"];
};
};
default: components["responses"]["Problem"];
};
};
createSource: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["SourceInput"];
};
};
responses: {
/** @description Хранилище создано */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Source"];
};
};
default: components["responses"]["Problem"];
};
};
getSource: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Хранилище */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Source"];
};
};
default: components["responses"]["Problem"];
};
};
deleteSource: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Удалено */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
updateSource: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["SourcePatch"];
};
};
responses: {
/** @description Хранилище */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Source"];
};
};
default: components["responses"]["Problem"];
};
};
testSource: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Результат проверки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SourceTestResult"];
};
};
default: components["responses"]["Problem"];
};
};
getSourcePatterns: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Шаблоны по порядку */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PatternList"];
};
};
default: components["responses"]["Problem"];
};
};
putSourcePatterns: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["PatternList"];
};
};
responses: {
/** @description Сохранённые шаблоны */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PatternList"];
};
};
default: components["responses"]["Problem"];
};
};
previewSourcePatterns: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["PatternPreviewRequest"];
};
};
responses: {
/** @description Разбор выборки файлов */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PatternPreview"];
};
};
default: components["responses"]["Problem"];
};
};
suggestWriteTemplate: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Предложенный шаблон */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["WriteTemplateSuggestion"];
};
};
default: components["responses"]["Problem"];
};
};
checkWriteTemplate: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["WriteTemplateCheckRequest"];
};
};
responses: {
/** @description Итог проверки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["WriteTemplateCheck"];
};
};
default: components["responses"]["Problem"];
};
};
scanSource: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["SourceId"];
};
cookie?: never;
};
requestBody?: {
content: {
"application/json": components["schemas"]["ScanRequest"];
};
};
responses: {
/** @description Скан запущен */
202: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ScanProgress"];
};
};
default: components["responses"]["Problem"];
};
};
getLibraryStatus: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Счётчики и сканы */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["LibraryStatus"];
};
};
default: components["responses"]["Problem"];
};
};
listLibraryErrors: {
parameters: {
query?: {
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница ошибок */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["LibraryErrorPage"];
};
};
default: components["responses"]["Problem"];
};
};
listAnalysisErrors: {
parameters: {
query?: {
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница ошибок аудиоанализа, упорядоченная по ID трека */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AnalysisErrorPage"];
};
};
default: components["responses"]["Problem"];
};
};
listHostDirs: {
parameters: {
query?: {
/** @description Путь относительно корня, пусто — корень */
path?: string;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Подпапки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HostDirList"];
};
};
default: components["responses"]["Problem"];
};
};
getArtist: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Исполнитель */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Artist"];
};
};
default: components["responses"]["Problem"];
};
};
listArtistAlbums: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Альбомы исполнителя (свои и сборники с его треками) */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AlbumSummaryList"];
};
};
default: components["responses"]["Problem"];
};
};
listArtistTopTracks: {
parameters: {
query?: {
limit?: number;
};
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Треки, самые слушаемые первыми */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["TrackList"];
};
};
default: components["responses"]["Problem"];
};
};
getAlbum: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Альбом с треками */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Album"];
};
};
default: components["responses"]["Problem"];
};
};
getTrack: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Трек */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Track"];
};
};
default: components["responses"]["Problem"];
};
};
searchSuggest: {
parameters: {
query: {
q: string;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Подсказки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SearchResults"];
};
};
default: components["responses"]["Problem"];
};
};
search: {
parameters: {
query: {
q: string;
type?: "all" | "artists" | "albums" | "tracks";
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Результаты */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SearchResults"];
};
};
default: components["responses"]["Problem"];
};
};
retryAnalysis: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Сколько задач снова в очереди */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
requeued: number;
};
};
};
default: components["responses"]["Problem"];
};
};
reindexSearch: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Переиндексация запущена */
202: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getCover: {
parameters: {
query: {
v: string;
sig: string;
size?: 64 | 300 | 1200;
};
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Картинка */
200: {
headers: {
[name: string]: unknown;
};
content: {
"image/webp": string;
};
};
default: components["responses"]["Problem"];
};
};
streamTrack: {
parameters: {
query: {
u: string;
exp: number;
sig: string;
q?: components["schemas"]["StreamQuality"];
};
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Аудио */
200: {
headers: {
[name: string]: unknown;
};
content: {
"audio/*": string;
};
};
default: components["responses"]["Problem"];
};
};
getTracksBatch: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["TrackIds"];
};
};
responses: {
/** @description Треки в порядке запроса; удалённые пропущены */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["TrackList"];
};
};
default: components["responses"]["Problem"];
};
};
postEvents: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["EventBatch"];
};
};
responses: {
/** @description Принято */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["EventBatchResult"];
};
};
default: components["responses"]["Problem"];
};
};
getPlaybackState: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Состояние; пусто — плеер ещё не запускался */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PlaybackState"];
};
};
default: components["responses"]["Problem"];
};
};
putPlaybackState: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["PlaybackStateInput"];
};
};
responses: {
/** @description Сохранённое состояние */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PlaybackState"];
};
};
default: components["responses"]["Problem"];
};
};
getHistory: {
parameters: {
query?: {
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница истории */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HistoryPage"];
};
};
default: components["responses"]["Problem"];
};
};
clearHistory: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Очищено */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getLikes: {
parameters: {
query?: {
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ReactedTrackPage"];
};
};
default: components["responses"]["Problem"];
};
};
getDislikes: {
parameters: {
query?: {
limit?: components["parameters"]["Limit"];
/** @description Непрозрачный курсор из `next_cursor` предыдущей страницы */
cursor?: components["parameters"]["Cursor"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Страница */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ReactedTrackPage"];
};
};
default: components["responses"]["Problem"];
};
};
setTrackReaction: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ReactionInput"];
};
};
responses: {
/** @description Сохранено */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
clearTrackReaction: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Снято */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getOnboarding: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Варианты и состояние */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Onboarding"];
};
};
default: components["responses"]["Problem"];
};
};
saveOnboarding: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["OnboardingChoice"];
};
};
responses: {
/** @description Сохранено */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getWaveOptions: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Варианты */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["WaveOptions"];
};
};
default: components["responses"]["Problem"];
};
};
startWave: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: {
content: {
"application/json": components["schemas"]["WaveStart"];
};
};
responses: {
/** @description Сессия и первая пачка */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["WaveBatch"];
};
};
default: components["responses"]["Problem"];
};
};
endWave: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Завершена */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
updateWave: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["WaveContext"];
};
};
responses: {
/** @description Новая пачка */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["WaveBatch"];
};
};
default: components["responses"]["Problem"];
};
};
nextWave: {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: {
content: {
"application/json": components["schemas"]["WaveNext"];
};
};
responses: {
/** @description Пачка */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["WaveBatch"];
};
};
default: components["responses"]["Problem"];
};
};
getAppClients: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Доступные сборки */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AppClients"];
};
};
default: components["responses"]["Problem"];
};
};
downloadAppClient: {
parameters: {
query?: never;
header?: never;
path: {
client: components["schemas"]["AppClient"];
version: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Установщик или APK */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/octet-stream": string;
};
};
default: components["responses"]["Problem"];
};
};
getAndroidLatest: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Последний релиз */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AndroidRelease"];
};
};
default: components["responses"]["Problem"];
};
};
downloadAndroidApk: {
parameters: {
query?: never;
header?: never;
path: {
version: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description APK */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/vnd.android.package-archive": string;
};
};
default: components["responses"]["Problem"];
};
};
listPlaylists: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Success */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PlaylistList"];
};
};
default: components["responses"]["Problem"];
};
};
createPlaylist: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["PlaylistInput"];
};
};
responses: {
/** @description Success */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Playlist"];
};
};
default: components["responses"]["Problem"];
};
};
getPlaylist: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Success */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Playlist"];
};
};
default: components["responses"]["Problem"];
};
};
updatePlaylist: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["PlaylistUpdate"];
};
};
responses: {
/** @description Success */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Playlist"];
};
};
default: components["responses"]["Problem"];
};
};
deletePlaylist: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Deleted */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
sharePlaylist: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Идентификатор ссылки для /shared/playlist/{shareId}; для открытия требуется вход */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PlaylistShare"];
};
};
default: components["responses"]["Problem"];
};
};
revokePlaylistShare: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Доступ по прежней ссылке отключён */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
default: components["responses"]["Problem"];
};
};
getSharedPlaylist: {
parameters: {
query?: never;
header?: never;
path: {
shareId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Плейлист с реакциями и ссылками на стрим для текущего слушателя */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Playlist"];
};
};
default: components["responses"]["Problem"];
};
};
}