- Python 99.3%
- Dockerfile 0.7%
| heuristic | ||
| tests | ||
| .gitignore | ||
| config.example.yaml | ||
| config.py | ||
| docker-compose.example.yml | ||
| Dockerfile | ||
| README.md | ||
| requirements.txt | ||
| server.py | ||
| sonarrcli.py | ||
sonarr-anime-proxy
Torznab-прокси между Sonarr и Jackett для RuTracker. Переписывает кривые русские заголовки раздач в формат, который парсит Sonarr — без LLM, чистая эвристика.
Зачем
RuTracker-заголовки выглядят так:
Эксперименты Лэйн / Serial Experiments Lain [TV] [13 из 13]
[RUS(int), JAP+Sub] [1998, киберпанк, драма, BDRip] [1080p]
Sonarr такое не матчит. Эвристика превращает это в:
Serial Experiments Lain - S01 1080p BDRip [JAP+RUS+Sub]
и Sonarr забирает раздачу как season pack.
Архитектура
Sonarr ─HTTP──► proxy (FastAPI, :9119) ─HTTP──► Jackett (:9118)
│
├─ split query: "Series 01" → "Series", ep=1
├─ forward q к Jackett (без season/ep — иначе 0 результатов)
├─ парсер: XML → переписать <title> эвристикой
└─ кеш ответов по cleaned-query (TTL 5 мин)
Эвристика: raw → tokenize → extract (quality/source/season/ep/langs/HDR) → pick English title → format Sonarr-style. Ни одна модель не используется.
Запуск
cp config.example.yaml config.yaml
# отредактируй config.yaml — вставь свой Jackett URL и apikey
pip install -r requirements.txt
py server.py
Проверка:
curl http://127.0.0.1:9119/health
curl "http://127.0.0.1:9119/normalize?title=Chainsaw+Man+%5BTV%5D+%5BE12+of+12%5D+%5B2022%2C+BDRip%5D+%5B1080p%5D"
Интеграция с Sonarr
Settings → Indexers → Add → Torznab / Custom:
| Поле | Значение |
|---|---|
| URL | http://<host>:9119/api |
| API Key | любое непустое (игнорируется, прокси подставляет свой) |
| Categories | по желанию |
Для аниме-серий в Sonarr ставь Series Type: Anime / Absolute — прокси работает в обоих режимах.
CLI
sonarrcli.py — эмулятор Sonarr для ручной отладки.
py sonarrcli.py "Chainsaw Man" 12 # искать 12 эпизод
py sonarrcli.py "One Piece" 1105 --raw # показать оригинальные заголовки
py sonarrcli.py "Overlord" 5 --season 4 # season 4 ep 5
py sonarrcli.py "Attack on Titan" --proxy # гнать через локальный прокси
Клиент-сайд фильтр по S<season>E<ep> оставляет только релевантные раздачи.
Тесты
py tests/test_parser.py
Golden-набор — 38 кейсов из реальных данных, покрывают все найденные форматы RuTracker (TV-сериалы, Movies, OVA, Movie packs, Chinese donghua, Korean animation, batch/partial/single episode, HDR/Dolby Vision, многоязычные строки).
Структура
heuristic/
tokenize.py — разбор raw title на name + brackets + trailing
extract.py — regex-extractор полей: quality/source/season/ep/lang/hdr
titlepick.py — выбор английского названия из RU/pinyin/romaji/EN
format.py — сборка Sonarr-формата
parser.py — orchestrator
tests/
golden.py — корпус (raw, expected) пар
test_parser.py — runner с diff-таблицей
server.py — FastAPI-прокси
sonarrcli.py — CLI
config.py — pydantic-конфиг
Лицензия
MIT