fix(playback): przytrzymanie nie zabija ostatniego zrodla sceny bez potwierdzenia
W 30 dni 490 scen zostalo przez "mark as broken" bez zadnego zrodla, glownie przez problemy sieci uzytkownika (porndoe 403, galaxyporn, perverzija). Ostatnie zrodlo znika tylko, gdy serwer widzi 404/410 albo HosterDead. Skrypt przywrocil 366 zrodel z pozytywnym potwierdzeniem, ze strona zyje. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6da817dc79
commit
e0744da8c7
2 changed files with 128 additions and 0 deletions
|
|
@ -374,12 +374,51 @@ def mark_playback_dead(
|
||||||
raise HTTPException(status_code=404, detail="playback source not found for scene")
|
raise HTTPException(status_code=404, detail="playback source not found for scene")
|
||||||
if pb.dead_at is None:
|
if pb.dead_at is None:
|
||||||
tag = _requester_tag(request)
|
tag = _requester_tag(request)
|
||||||
|
others_alive = session.scalar(
|
||||||
|
select(func.count())
|
||||||
|
.select_from(PlaybackSource)
|
||||||
|
.where(
|
||||||
|
PlaybackSource.scene_id == scene_id,
|
||||||
|
PlaybackSource.id != pb.id,
|
||||||
|
PlaybackSource.dead_at.is_(None),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not others_alive and not _scene_source_confirmed_dead(pb):
|
||||||
|
log.info(
|
||||||
|
"user mark-dead na ostatnim zrodle sceny %s odrzucone, serwer go nie potwierdzil (%s)",
|
||||||
|
pb.id, tag,
|
||||||
|
)
|
||||||
|
return
|
||||||
pb.dead_at = datetime.now(UTC)
|
pb.dead_at = datetime.now(UTC)
|
||||||
pb.dead_reason = f"user-marked dead (mobile long-press) {tag}"[:512]
|
pb.dead_reason = f"user-marked dead (mobile long-press) {tag}"[:512]
|
||||||
session.commit()
|
session.commit()
|
||||||
log.info("user marked playback %s dead (origin=%s %s)", pb.id, pb.origin, tag)
|
log.info("user marked playback %s dead (origin=%s %s)", pb.id, pb.origin, tag)
|
||||||
|
|
||||||
|
|
||||||
|
def _scene_source_confirmed_dead(pb: PlaybackSource) -> bool:
|
||||||
|
"""Czy serwer sam widzi, ze zrodlo sceny nie zyje. Uzywane, gdy przytrzymanie w apce
|
||||||
|
zabiloby OSTATNIE zywe zrodlo sceny (scena znika wtedy z list).
|
||||||
|
|
||||||
|
W 30 dni do 2026-10-15 z 617 zrodel oznaczonych w apce 490 zostawilo scene bez zadnego
|
||||||
|
zrodla, glownie porndoe (403 z sieci uzytkownika), galaxyporn, perverzija, javflix
|
||||||
|
(zgloszenie cbb87c8e: strona zyje, ekstraktor daje voe i doodstream). Martwe tylko,
|
||||||
|
gdy strona daje 404/410 albo ekstraktor mowi wprost, ze film usuniety; kazda
|
||||||
|
niepewnosc zostawia zrodlo.
|
||||||
|
"""
|
||||||
|
origin = pb.origin or ""
|
||||||
|
if not origin.startswith(("tube:", "pornapp:")):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
try_extract(origin.split(":", 1)[1], pb.page_url)
|
||||||
|
except HosterDead:
|
||||||
|
return True
|
||||||
|
except TubePageError as e:
|
||||||
|
return e.status_code in (404, 410)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _movie_source_confirmed_dead(pb: Any) -> bool:
|
def _movie_source_confirmed_dead(pb: Any) -> bool:
|
||||||
"""Czy serwer sam widzi, ze link filmu nie zyje. Uzywane, gdy przytrzymanie w apce
|
"""Czy serwer sam widzi, ze link filmu nie zyje. Uzywane, gdy przytrzymanie w apce
|
||||||
zabiloby OSTATNI link filmu.
|
zabiloby OSTATNI link filmu.
|
||||||
|
|
|
||||||
89
scripts/revive_user_marked_last_sources.py
Normal file
89
scripts/revive_user_marked_last_sources.py
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
"""Przywraca ostatnie zrodla scen zabite przytrzymaniem w apce, jesli strona zyje (2026-10-15).
|
||||||
|
|
||||||
|
Do 15.10 przytrzymanie "mark as broken" zabijalo zrodlo bez sprawdzenia. W 30 dni 490 scen
|
||||||
|
zostalo przez to bez zadnego zrodla i zniknelo z list (porndoe: 403 z sieci uzytkownika,
|
||||||
|
galaxyporn, perverzija, javflix...). Od 15.10 serwer sprawdza ostatnie zrodlo przed
|
||||||
|
oznaczeniem; ten skrypt cofa wczesniejsze przypadki, ale tylko z POZYTYWNYM dowodem:
|
||||||
|
- ekstraktor zwraca zrodla (strona i film istnieja),
|
||||||
|
- dla serwisow grajacych tylko w WebView (ekstraktor nic nie pobiera): strona odpowiada 200.
|
||||||
|
|
||||||
|
python scripts/revive_user_marked_last_sources.py # podglad
|
||||||
|
python scripts/revive_user_marked_last_sources.py --apply [--days 30]
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from app.db import session_scope
|
||||||
|
from app.extractors import is_vps_blocked_fallback, try_extract
|
||||||
|
from app.extractors._fetch import browser_get
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _alive(origin: str, page_url: str) -> bool:
|
||||||
|
if not origin.startswith(("tube:", "pornapp:")):
|
||||||
|
return False
|
||||||
|
sitetag = origin.split(":", 1)[1]
|
||||||
|
if is_vps_blocked_fallback(sitetag):
|
||||||
|
try:
|
||||||
|
return browser_get(page_url, timeout=20.0).status_code < 400
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
return bool(try_extract(sitetag, page_url))
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def run(apply: bool, days: int) -> dict:
|
||||||
|
with session_scope() as s:
|
||||||
|
rows = s.execute(
|
||||||
|
sa.text(
|
||||||
|
"""
|
||||||
|
SELECT p.id, p.origin, p.page_url
|
||||||
|
FROM playback_sources p
|
||||||
|
WHERE p.dead_reason LIKE 'user-marked dead%'
|
||||||
|
AND p.dead_at > now() - make_interval(days => :d)
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM playback_sources o
|
||||||
|
WHERE o.scene_id = p.scene_id AND o.dead_at IS NULL
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
),
|
||||||
|
{"d": days},
|
||||||
|
).all()
|
||||||
|
revive: list = []
|
||||||
|
by_origin: Counter = Counter()
|
||||||
|
for pb_id, origin, url in rows:
|
||||||
|
if _alive(origin, url):
|
||||||
|
revive.append(pb_id)
|
||||||
|
by_origin[origin] += 1
|
||||||
|
print({"candidates": len(rows), "alive": len(revive)}, by_origin.most_common(8))
|
||||||
|
if apply and revive:
|
||||||
|
with session_scope() as s:
|
||||||
|
s.execute(
|
||||||
|
sa.text("UPDATE playback_sources SET dead_at = NULL, dead_reason = NULL WHERE id = ANY(:ids)"),
|
||||||
|
{"ids": revive},
|
||||||
|
)
|
||||||
|
s.commit()
|
||||||
|
print("revived", len(revive))
|
||||||
|
return {"candidates": len(rows), "revived": len(revive) if apply else 0}
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
logging.basicConfig(level=logging.WARNING)
|
||||||
|
p = argparse.ArgumentParser()
|
||||||
|
p.add_argument("--apply", action="store_true")
|
||||||
|
p.add_argument("--days", type=int, default=30)
|
||||||
|
args = p.parse_args()
|
||||||
|
run(args.apply, args.days)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Loading…
Add table
Reference in a new issue