hentaimama: nowy zapis id posta i 5 playerow w admin-ajax, adresy w JSON-ie; bierzemy mp4 z gdvid (3 jakosci, bez tokenu), POST najpierw bez proxy. Ogon "Watch Online Free in HD" w tytulach ucinany. xanimeporn: przekierowanie download.php rozwiazywane na serwerze, apka dostawala .php, otwierala WebView i pobierala plik zamiast grac. Blad resolve (extractor pusty, HTTP strony) trafia do playback_events. Filmy: tytul z okruszkow (motyw dooplay losuje "Watch"/"Now Playing:"), linki nitroflare/rapidgator nie sa juz brane za wideo, sam landing idzie do WebView, a przytrzymanie w apce nie zabija ostatniego linku filmu, jesli serwer widzi, ze zyje. Skrypty naprawcze: tytuly dooplay, tytuly i miniatury hentaimama, repair_dooplay_movies dla streampornvip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
98 lines
3.6 KiB
Python
98 lines
3.6 KiB
Python
"""Czysci tytuly filmow z naglowka nowego motywu dooplay (10.2026) i scala duplikaty.
|
|
|
|
Motyw mangoporn/streamporn.li wstawia do h1 "Watch TYTUL 2026 by STUDIO Porn Movie Online
|
|
Free" albo "Now Playing: TYTUL". Parser od 2026-10-15 bierze tytul z okruszkow, ten skrypt
|
|
poprawia to, co weszlo wczesniej:
|
|
|
|
- "Now Playing: X" -> "X" (zawsze naglowek, nigdy prawdziwy tytul),
|
|
- "Watch X RRRR by S Porn Movie Online Free" -> "X" (tylko z tym ogonem; "Watch Me Eat My
|
|
Creampie 5" to prawdziwy tytul i zostaje),
|
|
- "Play X" zostaje, bo bywa tytulem ("Play Time!").
|
|
|
|
Jesli po poprawce istnieje juz inny film o tym samym title_normalized i zgodnym roku
|
|
(rowny albo jeden pusty), poprawiany film jest do niego dolaczany (merge_movies, starszy
|
|
zostaje). Wiecej niz jedno trafienie = tylko poprawka tytulu, bez scalania.
|
|
|
|
python scripts/fix_dooplay_junk_titles.py # podglad
|
|
python scripts/fix_dooplay_junk_titles.py --apply
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import logging
|
|
import re
|
|
|
|
import sqlalchemy as sa
|
|
|
|
from app.db import session_scope
|
|
from app.models.movie import Movie
|
|
from app.normalize.text import normalize
|
|
from app.resolve.movie_merge import merge_movies
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
_NOW_PLAYING_RE = re.compile(r"^Now\s+Playing:\s*(?P<title>.+?)\s*$", re.IGNORECASE | re.DOTALL)
|
|
_WATCH_TAIL_RE = re.compile(
|
|
r"^Watch\s+(?P<title>.+?)(?:\s+(?:19|20)\d{2}\s+by\s+.+?)?\s+Porn\s+Movie\s+Online\s+Free\s*$",
|
|
re.IGNORECASE | re.DOTALL,
|
|
)
|
|
|
|
|
|
def clean_title(title: str) -> str | None:
|
|
for rx in (_NOW_PLAYING_RE, _WATCH_TAIL_RE):
|
|
m = rx.match(title)
|
|
if m and m.group("title").strip():
|
|
return m.group("title").strip()
|
|
return None
|
|
|
|
|
|
def run(apply: bool) -> dict[str, int]:
|
|
counters = {"candidates": 0, "retitled": 0, "merged": 0, "ambiguous": 0}
|
|
with session_scope() as session:
|
|
rows = session.execute(
|
|
sa.select(Movie.id, Movie.title, Movie.release_year).where(
|
|
sa.or_(
|
|
Movie.title.op("~*")(r"^now playing:"),
|
|
Movie.title.op("~*")(r"^watch .+ porn movie online free\s*$"),
|
|
)
|
|
)
|
|
).all()
|
|
for movie_id, title, year in rows:
|
|
new_title = clean_title(title)
|
|
if not new_title:
|
|
continue
|
|
counters["candidates"] += 1
|
|
norm = normalize(new_title)
|
|
twins = session.execute(
|
|
sa.select(Movie.id, Movie.release_year, Movie.created_at)
|
|
.where(Movie.title_normalized == norm, Movie.id != movie_id)
|
|
.order_by(Movie.created_at)
|
|
).all()
|
|
twins = [t for t in twins if t.release_year is None or year is None or t.release_year == year]
|
|
print(f"{title[:70]!r} -> {new_title[:60]!r} twins={len(twins)}")
|
|
if not apply:
|
|
continue
|
|
movie = session.get(Movie, movie_id)
|
|
movie.title = new_title[:512]
|
|
movie.title_normalized = norm[:512]
|
|
counters["retitled"] += 1
|
|
if len(twins) == 1:
|
|
merge_movies(session, keep_id=twins[0].id, drop_id=movie_id, resolved_by="fix_dooplay_junk_titles")
|
|
counters["merged"] += 1
|
|
elif len(twins) > 1:
|
|
counters["ambiguous"] += 1
|
|
session.commit()
|
|
return counters
|
|
|
|
|
|
def main() -> int:
|
|
logging.basicConfig(level=logging.INFO)
|
|
p = argparse.ArgumentParser()
|
|
p.add_argument("--apply", action="store_true")
|
|
args = p.parse_args()
|
|
print(run(args.apply))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|