Справочник API: точные строки классов, схемы полей с null, коды и тело ошибок
docker / build (push) Successful in 35s

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
DenozordecandClaude Sonnet 5.5 committed 2026-10-29 13:56:12 +07:00
1 parent e2acebadc6
commit 4e83474652
1 file changed
+83 -1
+83 -1
View File
@@ -54,7 +54,7 @@
| `series` | object \| null | сезон, выпущенные серии, «какая студия какие серии» (для Sonarr); `null` — сведений нет | | `series` | object \| null | сезон, выпущенные серии, «какая студия какие серии» (для Sonarr); `null` — сведений нет |
| `title` | string \| null | заголовок раздачи, если найден | | `title` | string \| null | заголовок раздачи, если найден |
| `segmenter` | `"model"` \| `"rules"` | чем страница разбита на строки дорожек: обученным сегментатором или запасными правилами | | `segmenter` | `"model"` \| `"rules"` | чем страница разбита на строки дорожек: обученным сегментатором или запасными правилами |
| `tracker` | string | только для `url`: `rutracker`, `nnmclub` или `kinozal` | | `tracker` | string | только для `url`: `rutracker`, `nnm` или `kinozal` |
`series`: `season` — номер сезона строкой или `null`; `episodes` — выпущенные серии («1-9»); `series`: `season` — номер сезона строкой или `null`; `episodes` — выпущенные серии («1-9»);
`total` — всего серий; `by_studio` — `{студия: серии}`; `full_release` — студии без указанных серий `total` — всего серий; `by_studio` — `{студия: серии}`; `full_release` — студии без указанных серий
@@ -86,6 +86,22 @@
### translation_type: 14 классов ### translation_type: 14 классов
Точные строки (регистр, пробелы и точки после префикса — как есть; сортировка — по алфавиту, так их
возвращает `GET /health` → `classes`):
```json
["авт. двухголосый", "авт. многоголосый", "авт. одноголосый", "двухголосый", "люб. двухголосый",
"люб. многоголосый", "люб. одноголосый", "многоголосый", "неизвестно", "одноголосый",
"проф. двухголосый", "проф. дубляж", "проф. многоголосый", "проф. одноголосый"]
```
Для клиентов, которые сводят класс к своим типам (Dub / MVO / DVO / AVO), надёжно сопоставление по
**подстроке** нижнего регистра: `дубляж` → дубляж; `многоголос` → многоголосый; `двухголос` →
двухголосый; `одноголос` → одноголосый; ровно `неизвестно` → тип не определён (такие дорожки обычно
пропускают). Подстрока `дублирован` в классах **не встречается** (дублированные страницы сводятся к
`проф. дубляж`). Префикс (`проф.`/`люб.`/`авт.`/нет) — отдельный признак. Если набор классов в будущей
модели изменится, ориентируйтесь на `/health` → `classes`, а неизвестное значение не считайте ошибкой.
Класс — составная метка «кто делал × сколько голосов». Других значений сервис не возвращает. Класс — составная метка «кто делал × сколько голосов». Других значений сервис не возвращает.
| Значение | Кто озвучивал | Вид | | Значение | Кто озвучивал | Вид |
@@ -113,6 +129,72 @@
доверять осторожно. Состав и названия классов задаёт обучение; актуальный список для конкретной доверять осторожно. Состав и названия классов задаёт обучение; актуальный список для конкретной
модели — `GET /health` → `classes`. модели — `GET /health` → `classes`.
## Схема полей и допустимые null
Дорожка (`tracks[]`), нотация TypeScript. Все ключи **присутствуют всегда** (значение может быть
`null`, но ключ не пропускается), кроме помеченных «только в ответе релиза».
```ts
type Track = {
segment: string; // никогда null
translation_type: string; // один из 14 классов, никогда null
type_confidence: number; // 0..1
studio_span: string | null; // null — автора в тексте нет
studio: string | null; // null вместе со studio_span
studio_confidence: number | null; // null вместе со studio_span
is_18plus: boolean;
age_confidence: number; // 0..1
lang: string | null; // 3-буквенный код или null
lang_confidence: number | null; // не null только при lang_source == "model"
lang_source: "model" | "audio" | "text" | null; // null вместе с lang
role: "перевод" | "оригинал" | "комментарии"; // никогда null
official: boolean;
audio: { codec: string | null; channels: number | null; bitrate_kbps: number | null } | null;
// только в ответе релиза (html / url):
source: "page" | "title";
episodes: string | null; // "1-4", "1,3-5"; null — серии не указаны
episode_ranges: [number, number][]; // [[1,4]]; пустой массив, если серий нет
};
type Release = {
tracks: Track[]; // может быть пустым массивом
studios: { studio: string | null; translation_type: string; is_18plus: boolean; episodes: string | null }[];
translation_types: string[];
is_18plus: boolean;
series: {
season: string | null; // "2"
episodes: string | null; // выпущенные серии, "1-9"
total: number | null; // всего серий
by_studio: Record<string, string>; // { "LostFilm": "1-4" }, может быть {}
full_release: string[]; // студии без указанных серий
} | null; // null — ни сезона, ни серий в раздаче нет
title: string | null;
segmenter: "model" | "rules";
tracker?: "rutracker" | "nnm" | "kinozal"; // только для url
};
```
Ответ на `text` — `{"tracks": [Track]}` (без полей релиза и без `source`/`episodes`/`episode_ranges`).
Клиентам стоит читать ответ толерантно: неизвестные поля игнорировать, отсутствующие считать `null`.
## Ошибки
Тело любой ошибки — JSON `{"detail": "<сообщение>"}`; у `401` добавлен заголовок
`WWW-Authenticate: Bearer`.
| Код | Когда | Пример `detail` |
|---|---|---|
| 400 | передано не ровно одно из `text` / `html` / `url` | «нужно ровно одно поле: text (дорожка), html (страница) или url (ссылка на раздачу)» |
| 400 | пустой `text`; страница не разобрана; хост ссылки не из разрешённых (rutracker / nnmclub / kinozal); страница недоступна или слишком большая; трекер отдал заглушку Cloudflare или форму входа без FlareSolverr/`cookie`; ошибка FlareSolverr | текст причины на русском («неподдерживаемый хост: …», «страница недоступна: …», «FlareSolverr: …») |
| 401 | задан `DUB_API_TOKEN`, а токена нет или он неверный | «нужен токен: Authorization: Bearer <токен> или X-API-Key» |
| 422 | тело запроса не JSON-объект или поля не тех типов (валидация FastAPI; `detail` — массив) | `[{"loc": [...], "msg": "...", "type": "..."}]` |
| 502 | сетевая ошибка при скачивании страницы по `url` (соединение, DNS, таймаут) | «не удалось загрузить страницу: …» |
`GET /health` не требует токена и возвращает: `status`, `model`, `device`, `classes`, `segmenter`
(`"model"`/`"rules"`), `flaresolverr` (bool), `auth` (bool). Страница, на которой не найдено дорожек,
— не ошибка: ответ `200` с `"tracks": []`. Повторяйте запрос при `502` и при ответах `400` про
Cloudflare: FlareSolverr нестабилен.
## Принцип работы ## Принцип работы
1. **Получение страницы.** `url` скачивается самим сервисом: сначала напрямую, при 403/503 или 1. **Получение страницы.** `url` скачивается самим сервисом: сначала напрямую, при 403/503 или