[project] name = "goon" version = "0.1.0" description = "Self-hosted aggregator of adult scene metadata with multi-source dedup" requires-python = ">=3.12" dependencies = [ "fastapi>=0.115", "uvicorn[standard]>=0.32", "sqlalchemy>=2.0.36", "alembic>=1.14", "psycopg[binary]>=3.2", "pydantic>=2.10", "pydantic-settings>=2.7", "httpx>=0.28", # 0.15 breaks yt-dlp 2026.03.17 — yt-dlp's `_AVAILABLE_IMPERSONATE_TARGETS` # check fails AssertionError gdy podajemy string "chrome" zamiast # ImpersonateTarget object (bug-report 2026-05-16: xvideos/xnxx/youporn). # Pinned to <0.15 dopóki yt-dlp nie wystawi compat release. "curl_cffi>=0.7,<0.15", "gql[httpx]>=3.5", "apscheduler>=3.10", "rapidfuzz>=3.10", "recordlinkage>=0.16", "jinja2>=3.1", "python-multipart>=0.0.20", "python-slugify>=8.0", "tenacity>=9.0", "structlog>=24.4", "sentry-sdk[fastapi]>=2.20", "yt-dlp>=2025.1.15", # Perceptual hash thumbnaili w browse-mode scraperach (shyfap, freshporno, ...) # — pozwala matchować sceny do canonical (TPDB/StashDB) NIEZALEŻNIE od tube # branding/rebrand tytułów. Resolver Path 3 (fp_phash, waga 0.40) używa Hamming ≤5. "imagehash>=4.3", "Pillow>=11.0", # AES-CBC decrypt dla seekplayer-engine hosterów (embedseek/seekplayer/rpmplay/ # upns/player4me/easyvidplayer) — wszystkie używają hostname-independent # key=kiemtienmua911ca iv=1234567890oiuytr. "cryptography>=44.0", ] [project.optional-dependencies] dev = [ "pytest>=8.3", "pytest-asyncio>=0.24", "pytest-cov>=6.0", "ruff>=0.8", "mypy>=1.13", "respx>=0.21", ] [build-system] requires = ["setuptools>=68", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] include = ["app*"] [tool.ruff] line-length = 100 target-version = "py312" [tool.ruff.lint] select = ["E", "F", "I", "B", "UP", "N", "SIM"] ignore = ["E501"] [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto"