From ded80d3bc72471402501835178e1a3afdfb2062f Mon Sep 17 00:00:00 2001 From: goon-foss Date: Fri, 4 Sep 2026 11:27:21 +0200 Subject: [PATCH] feat(sxyprn purge): tryb --strip, sceny zostaja bez tagow i performerow spoza tytulu --- scripts/sxyprn_purge_uploaders.py | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/scripts/sxyprn_purge_uploaders.py b/scripts/sxyprn_purge_uploaders.py index 6a3dec1..4f369c4 100644 --- a/scripts/sxyprn_purge_uploaders.py +++ b/scripts/sxyprn_purge_uploaders.py @@ -23,6 +23,10 @@ Co robi: Uzycie (na VPS, z pliku, nie przez stdin): docker compose run --rm worker python3 -u /srv/scripts/sxyprn_purge_uploaders.py docker compose run --rm worker python3 -u /srv/scripts/sxyprn_purge_uploaders.py --apply + docker compose run --rm worker python3 -u /srv/scripts/sxyprn_purge_uploaders.py --apply --strip + +Wariant --strip (wybrany 2026-09-04): sceny zostaja z playbackiem, ulubionymi i historia, +wylatuja tylko tagi i performerzy spoza tytulu. """ from __future__ import annotations @@ -100,6 +104,12 @@ def main() -> int: ap.add_argument("--apply", action="store_true", help="bez tego tylko raport") ap.add_argument("--skip-junk", action="store_true", help="pomin krok 3 (smieciowi performerzy)") ap.add_argument("--only-junk", action="store_true", help="tylko krok 3, scen i zrodel nie ruszaj") + ap.add_argument( + "--strip", + action="store_true", + help="zamiast kasowac sceny: zdejmij im wszystkie tagi i performerow spoza tytulu " + "(decyzja 2026-09-04, zeby nie tracic ulubionych i historii userow)", + ) ap.add_argument("--authors", default=",".join(AUTORZY), help="id autorow po przecinku") args = ap.parse_args() autorzy = [a.strip().lower() for a in args.authors.split(",") if a.strip()] @@ -158,6 +168,43 @@ def main() -> int: do_odciecia, do_usuniecia = [], [] print("tylko krok 3, sceny i zrodla zostaja") + if args.strip: + # Sceny wylacznie tych autorow: zostaja razem ze zrodlem, ale bez tagow + # (wszystkie sa z hashtagow spamera) i bez performerow, ktorych nie ma w tytule. + n_tag = n_perf = 0 + for chunk in _chunks(do_usuniecia, _CHUNK): + n_tag += s.execute( + text("DELETE FROM scene_tags WHERE scene_id = ANY(:sceny)"), {"sceny": chunk} + ).rowcount + n_perf += s.execute( + text( + "DELETE FROM scene_performers sp USING scenes sc, performers p " + "WHERE sc.id = sp.scene_id AND p.id = sp.performer_id AND sp.scene_id = ANY(:sceny) " + "AND position(lower(p.canonical_name) IN lower(sc.title)) = 0 " + "AND position(regexp_replace(lower(p.canonical_name), '[^a-z0-9]', '', 'g') " + "IN regexp_replace(lower(sc.title), '[^a-z0-9]', '', 'g')) = 0" + ), + {"sceny": chunk}, + ).rowcount + s.commit() + # Sceny scalone z innymi tubami: tagow nie da sie przypisac do autora, wiec + # tylko podpis Shizuki. + n_siz = 0 + for chunk in _chunks(do_odciecia, _CHUNK): + n_siz += s.execute( + text( + "DELETE FROM scene_tags st USING tags t " + "WHERE t.id = st.tag_id AND t.slug = 'sizuka' AND st.scene_id = ANY(:sceny)" + ), + {"sceny": chunk}, + ).rowcount + s.commit() + print( + f"strip: scen {len(do_usuniecia)}, zdjete tagi {n_tag}, zdjeci performerzy {n_perf}; " + f"scalone {len(do_odciecia)}, zdjety tag sizuka {n_siz}" + ) + do_odciecia, do_usuniecia = [], [] + # 2. sceny scalone: zostaja, wylatuje tylko zrodlo autora + tag Sizuka n_ps = 0 for chunk in _chunks(do_odciecia, _CHUNK):