feat: finish the upload, playback, and test gaps from the docs
ci / api / api (push) Successful in 40s
ci / db / db (push) Successful in 1m3s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Failing after 1m48s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 46s
ci / ts / ts (packages + web) (push) Failing after 4m57s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 5m7s

Quality upgrades, batch covers, staging preview, and resume after reload are in the queue. Loudness and crossfade work on web and Android, and the documented checks now have suites.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
mrleo1nidandCursor committed 2026-10-21 09:37:53 +03:00
1 parent 2b76060ea3
commit 066ba24834
61 files changed
+2818 -463

No files matched your search

+190 -1
View File
@@ -404,6 +404,40 @@ export interface paths {
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;
@@ -484,6 +518,48 @@ export interface paths {
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;
@@ -1307,6 +1383,7 @@ export interface components {
artist?: string;
title?: string;
duration_ms?: number;
album?: string;
}[];
};
UploadPrecheckResult: {
@@ -1399,6 +1476,8 @@ export interface components {
/** @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) */
@@ -1412,6 +1491,8 @@ export interface components {
updated_at: string;
/** @description Только автору и пока файл в статусе uploading */
tus_url: string | null;
/** @description Подписанная ссылка прослушивания из staging; null, если файла уже нет */
stream_url: string | null;
};
UploadFilePage: {
items: components["schemas"]["UploadFile"][];
@@ -1422,6 +1503,14 @@ export interface components {
/** 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} */
@@ -1446,6 +1535,8 @@ export interface components {
max_file_bytes: number;
/** Format: uuid */
default_source_id: string | null;
/** @description Тот же трек в лучшем качестве идёт на рассмотрение, а не в дубли */
allow_quality_upgrade: boolean;
};
/** @description Лимит на пользователя и хранилище по умолчанию передаются всегда (null — выключить / не задано). */
UploadSettingsPatch: {
@@ -1463,6 +1554,7 @@ export interface components {
* @description null — без хранилища по умолчанию
*/
default_source_id: string | null;
allow_quality_upgrade?: boolean;
};
HealthStatus: {
/** @enum {string} */
@@ -1538,7 +1630,7 @@ export interface components {
* @enum {string}
*/
search_position?: "center" | "left" | "right";
/** @description Сворачивать поиск в кнопку с лупой без фокуса (по умолчанию true) */
/** @description Сворачивать поиск в кнопку с лупой без фокуса (по умолчанию false) */
search_collapse?: boolean;
/** @description Показывать на главной веба выбор занятия (по умолчанию true) */
home_activities?: boolean;
@@ -2702,6 +2794,48 @@ export interface operations {
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;
@@ -2803,6 +2937,61 @@ export interface operations {
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;