diff --git a/app/api/scenes.py b/app/api/scenes.py index 6c025fb..67670f5 100644 --- a/app/api/scenes.py +++ b/app/api/scenes.py @@ -709,6 +709,27 @@ def _build_scene_out(session: Session, scene: Scene) -> SceneOut: .scalars() .all() ) + # Collapse źródła dzielące ten sam origin (hoster). Zmergowana scena często agreguje + # kilka uploadów z JEDNEGO tube'a (re-enkody / wersje 4K: bug-report aa79a995 "2 linki, + # oba do porntrex" = ta sama scena std+4K) — w UI to nierozróżnialne linki do tego + # samego hostera (resolvują tym samym extractorem). Zostawiamy jeden najlepszy per + # origin: preferuj długość zgodną ze sceną (realny match) → jakąkolwiek długość → + # pierwszy (stabilnie, query jest origin-asc). Martwe już odfiltrowane (dead_at). + def _origin_pick_key(p: PlaybackSource) -> tuple[int, int]: + dur_match = ( + 0 if (scene.duration_sec and p.duration_sec + and abs(p.duration_sec - scene.duration_sec) <= 5) else 1 + ) + return (dur_match, 0 if p.duration_sec else 1) + + _best_by_origin: dict[str, PlaybackSource] = {} + for p in playback_rows: + key = p.origin or "" + cur = _best_by_origin.get(key) + if cur is None or _origin_pick_key(p) < _origin_pick_key(cur): + _best_by_origin[key] = p + playback_rows = list(_best_by_origin.values()) + playback_out: list[PlaybackSourceOut] = [] for p in playback_rows: out = PlaybackSourceOut.model_validate(p)