Релиз целиком: вход по ссылке, агрегат студий/типов/18+, малая int8-модель

- src/fetch.py: загрузка по URL (allowlist трекеров, защита от SSRF, cp1251)
- src/release.py: агрегат релиза, студии из заголовка раздачи (ПМ (LostFilm))
- predict --url, POST /predict {"url"}; ответ расширен, tracks сохранён
- export_onnx --quantize: tiny2 int8 29 МБ, parity 99.2-100%
- тесты (52 ok), docs/plan.md, docs; target/ убран из git

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
DenozordecandClaude Sonnet 5.5 committed 2026-10-27 17:02:04 +07:00
1 parent 98e4031037
commit 8cbd800ec7
2473 files changed
+424 -6060

No files matched your search

+38
View File
@@ -163,5 +163,43 @@ try:
except Exception as e: # noqa: BLE001
print(f" пропущено (нет модели models/best): {e}")
# ---------------------------------------------------------------- релиз / ссылки
print("== release / fetch ==")
from src.fetch import decode_bytes, detect_tracker # noqa: E402
from src.release import aggregate, title_segments # noqa: E402
check("tracker rutracker", detect_tracker("https://rutracker.org/forum/viewtopic.php?t=1") == "rutracker")
check("tracker kinozal", detect_tracker("https://kinozal.tv/details.php?id=1") == "kinozal")
check("tracker nnm", detect_tracker("https://nnmclub.to/forum/viewtopic.php?t=1") == "nnm")
for bad in ("http://localhost:8000/", "http://127.0.0.1/", "http://169.254.169.254/",
"https://rutracker.org.evil.com/", "file:///etc/passwd", "ftp://rutracker.org/"):
try:
detect_tracker(bad)
check(f"SSRF отклонён: {bad}", False)
except ValueError:
check(f"SSRF отклонён: {bad}", True)
check("decode cp1251", decode_bytes("Перевод".encode("cp1251")) == "Перевод")
check("decode charset", decode_bytes("Перевод".encode("cp1251"), "text/html; charset=windows-1251") == "Перевод")
check("title: ПМ (студия)",
title_segments("Гангстерленд / 2025 / ПМ (LostFilm) / WEB-DLRip")
== ["Профессиональный (многоголосый закадровый) | LostFilm"])
check("title: ДБ + список ПМ без студий",
title_segments("Х / 2026 / ДБ (Red Head Sound), 5 x ПМ, ПД, ЛМ, СТ / 4K")
== ["Профессиональный (дублированный) | Red Head Sound"])
check("title: пусто", title_segments("Просто фильм / 2020 / WEB-DL") == [])
def _t(typ, st, age=False):
return {"segment": f"{typ}|{st}", "translation_type": typ, "studio": st, "is_18plus": age}
agg = aggregate([_t("проф. дубляж", "MovieDalen"), _t("проф. дубляж", "moviedalen", True),
_t("проф. многоголосый", "LostFilm")])
check("aggregate: дедуп", len(agg["tracks"]) == 2, str(agg))
check("aggregate: 18+ = OR", agg["is_18plus"] is True)
check("aggregate: студии", [x["studio"] for x in agg["studios"]] == ["MovieDalen", "LostFilm"])
check("aggregate: пусто", aggregate([])["is_18plus"] is False)
print(f"\nитог: {PASS} ok, {FAIL} failed")
sys.exit(1 if FAIL else 0)