goon/app/extractors/_models.py
goon-foss ad0284585b Initial commit
Goon — self-hosted aggregator for adult-content scene metadata.

Indexes scenes from TPDB, StashDB, and 30+ public adult tube sites.
Cross-source deduplication via perceptual hash + Levenshtein distance.
FastAPI backend + APScheduler worker + React Native (Expo) mobile client.

FOSS, ad-free, donation-funded. See README for details.
2026-05-20 10:10:22 +02:00

48 lines
1.5 KiB
Python

"""Stream source DTO + wspólne wyjątki extractorów."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
@dataclass
class StreamSource:
"""Pojedynczy resolved stream URL.
Mapuje na `StreamLink` w playback API (api/playback.py) — `link` → `stream_url`,
`quality` → `quality`, `type` → `type`.
`referer` — opcjonalny override Referera używanego przez stream_proxy. Niektóre
CDN-y (KVS-style watchporn.to, fpo.xxx itp.) zwracają 410/403 gdy Referer nie
pasuje do *embed page'a* (np. proxy używa `Referer: 0dayxx.com` ale CDN expectuje
`Referer: watchporn.to`). Gdy None → caller (playback.py) używa `page_url`.
"""
link: str
quality: str | None = None
type: str | None = None # 'mp4' | 'm3u8' | 'mpd' | 'hoster'
raw: dict[str, Any] | None = None
referer: str | None = None
class HosterDead(Exception):
"""Hoster embed page mówi że video jest skasowane / nie istnieje.
Caller w playback.py łapie i oznacza `playback_source.dead_at`.
"""
class TubePageError(Exception):
"""Tube page fetch zwrócił HTTP error (404/410/5xx).
Caller (playback.py) może oznaczyć dead_at jeśli 404/410. Trzymamy `status_code`
+ `url` w atrybutach żeby caller nie musiał parsować message stringa.
"""
def __init__(self, status_code: int, url: str):
super().__init__(f"HTTP {status_code} for {url}")
self.status_code = status_code
self.url = url
__all__ = ["StreamSource", "HosterDead", "TubePageError"]