[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"
