Zgloszenie 7f2234eb: "samo wideo dziala, a aplikacja zglasza problem
z hostem". Ekstraktor NIE jest zepsuty:
- try_extract oddaje dzialajacy manifest w 0,4 s
- z Refererem ekstraktora (galaxy.4meplayer.pro) link daje 200; bez
niego 403, wiec naglowek jest ustawiany poprawnie
- pobranie przez nasze /proxy oddaje 200 i playliste z wariantem 1080p
- telemetria 14 dni: 1140 udanych, 25 bledow (2,1%)
Padal POJEDYNCZY nod CDN. Kolejne wywolania resolve tej samej sceny
wracaja z ROZNYMI adresami (185.237.107.133, potem 203.188.166.163), a
token ma ~2,8 h TTL i nie jest IP-bound. Czyli ponowny resolve po prostu
laduje na zywym wezle — dokladnie wzorzec, ktory dziala juz dla watchporn.
Stad `tube:galaxyporncom` w BACKEND_RERESOLVE_ORIGINS.
Po drodze skorygowany FALSZYWY komentarz w seekplayer_engine.py: twierdzil,
ze stream_proxy.py ma galaz `verify=False` dla hostow pod golym IP. Nie ma
jej — slowo `verify` nie wystepuje w tym pliku ani razu. `proxy_no_verify`
i `cf_fallback` sa ustawiane przez trzy ekstraktory i przez NIC nieczytane.
cf_fallback jest o tyle bolesny, ze to gotowy zapasowy URL, ktory uratowalby
wlasnie ten przypadek. Osobne zadanie.
Blad diagnostyczny po drodze, dla potomnosci: pierwszy test dal 404, bo
przetestowalem URL uciety wlasnym printem [:70], bez /master.m3u8.
Wzorowane na reelu _code_and_chill_ ("the bar melts around it"), ale
technika wzieta z jego drugiego zdania: "every socket is solved for
tangency, so the liquid never creases". Czyli sciezka LICZONA, nie
rozmywana.
Filtr "goo" (rozmycie + prog alfy) byl pierwszym pomyslem i zostal
ODRZUCONY po zajrzeniu w zrodlo react-native-svg. Filtry na Androidzie
dzialaja (GroupView extends RenderableView, ktory obsluguje mFilter), ale
RenderableView.java:376 przy KAZDYM rysowaniu robi Bitmap.createBitmap(
canvas.getWidth(), canvas.getHeight(), ARGB_8888), rysuje do niej element,
naklada programowy filtr i wrzuca wynik z powrotem. Przy animowanej kropli
to pelnoekranowa alokacja na klatke, w nagłowku KAZDEGO ekranu.
liquidTabPath: gniazdo to dwa luki styczne jednoczesnie do krawedzi paska
(srodek na y=top+k) i do kropli (odleglosc srodkow = r+k), stad
dx = sqrt((r+k)^2 - (top+k-cy)^2). Jedna <Path>, zero alokacji.
Weryfikacja liczbowa (nie wizualna): trzy niezmienniki stycznosci trzymaja
sie do 1e-9, piec przypadkow brzegowych OK. Test wylapal brakujacy warunek
`cy - r < top`: bez niego wzor ma rozwiazanie takze gdy kropla siedzi CALA
w pasku (top=26, cy=45, r=17, k=12 -> dx≈28,1) i powstawaloby gniazdo, w
ktore nie ma sie co wtopic.
Animacja: Animated.Value + listener przepisujacy cx do stanu, bo sciezka
to string i nie da sie jej podac Animated wprost (brak Reanimated w
projekcie). ~12 re-renderow SVG na 200 ms przejscia, poza tym komponent stoi.
useNativeDriver=false swiadomie: animujemy geometrie, nie transform.
Etykieta aktywnej zakladki siedzi na wypelnieniu akcentu — jasny tekst daje
tam 5,03:1, jedyny wariant tego koloru przechodzacy AA (patrz theme.ts).
Pomiar na 200 tys. grywalnych scen >=60 s (2026-08-13): przy JEDNEJ linii
pelny tytul widzialo **14,3%** scen. Mediana tytulu to 46 znakow, a w
kolumnie dwukolumnowej siatki miesci sie ~24 na linie, wiec 85,7% tytulow
bylo przycietych. Przy dwoch liniach pelny tytul widzi 54,4%.
To SWIADOMIE odwraca czesc wczesniejszej decyzji ("Jan feedback: wieksze
miniaturki, mniej tekstu" w docstringu tego pliku) — uzgodnione, bo tamta
uwaga dotyczyla nadmiaru metadanych, nie przycinania samego tytulu.
Miniaturka zostaje w tym samym rozmiarze, rosnie tylko blok tekstu (~18 px).
Do tego `titleWithoutStudio`: gdy druga linia pokazuje studio, zdejmujemy
jego nazwe z PRZODU tytulu ("MYLF - Aria's MILF Temptation" nad meta
"MYLF"). Dotyczy 8,2% scen. Zdejmujemy tylko przedrostek, wiec studio na
koncu tytulu ("… - ATKGirlfriends") zostaje nietkniete. Gdy po zdjeciu
zostaje <12 znakow, oddajemy tytul nietkniety, bo "Scene 1" jest gorsze
niz powtorzenie. 9 przypadkow testowych na realnych tytulach.
Korekta wlasnej diagnozy z przegladu: napisalem tam, ze tytul i studio
maja niemal rowna wage. Nieprawda — 14 px display/fg vs 10 px mono/muted
wersalikami. Hierarchia byla w porzadku, problemem bylo obciecie.
Pomiar WCAG na realnych parach z apki (2026-08-13):
accent #B23A48 jako tekst: 3,21 na bg | 2,96 na bgElevated | 2,75 na card
border #3A3128 jako granica: 1,48 na bg | 1,27 na card
Czyli kolor MARKI byl ponizej nawet progu 3:1 dla elementow interfejsu,
a nie tylko ponizej 4,5 dla tekstu. Dotyczylo to aktywnych zakladek,
gwiazdek ulubionych, linkow i chipow. Ramki przy 1,27 nie byly granica,
tylko cieniem.
NIE zmieniam koloru marki. Podniesienie samego `accent` do progu tekstu
wymagaloby zejscia w roz (#CE6975), co likwiduje tozsamosc, ktorej broni
naglowek theme.ts. Zamiast tego rozdzielam ROLE tego samego koloru:
accent zostaje do WYPELNIEN — jasny tekst na nim ma 5,03, przechodzi
accentText #C75260 dla tekstu i obwodek — 4,30 / 3,96 / 3,68
62 podmiany w 24 plikach (34 color, 26 borderColor, 2 thumbColor).
38 wypelnien nietknietych. Sprawdzone skryptem, ze zaden zmieniony tekst
nie stoi na tle akcentu.
borderStrong #7B7065 dla granic NIOSACYCH ZNACZENIE (pola tekstowe, 12
miejsc); dekoracyjne wloski zostaja na `border`. Wartosc dobrana pod obie
powierzchnie, bo pola leza i na bg, i na card: #6B6157 dawal na karcie
2,66, a #73695E dokladnie 2,999, czyli wciaz ponizej progu.
Studio bywa WYLACZNIE filmowe: Jonathan Jordan XXX 0 scen / 654 filmy,
Kink Clips 0/616, EAGLE 0/523. Lista ulubionych pokazywala wtedy samo
"0 scenes", czyli wygladala na pusta, mimo ze badge "+N" liczyl filmy
juz od 2026-07-28 (_merged_new_counts).
Backend: `FavoriteStudioOut.movie_count`, liczony NA ZYWO. Ulubionych
studiow jest kilkaset na urzadzenie, a filmow o rzedy wielkosci mniej niz
scen, wiec agregat jest tani i nie trzeba kolejnej zdenormalizowanej
kolumny do utrzymania.
Apka pokazuje oba liczniki, a gdy jednego nie ma, pomija go, zeby nie
robic z tego "0 scenes · 654 movies".
Domyka to temat zaczety zakladka Movies na ekranie studia: dodanie do
ulubionych od strony filmu juz dzialalo (gwiazdka w StudioMoviesScreen).
Zgloszenie 7f2234eb: "Cos nie tak z ekstraktorem? Bo samo wideo dziala a
aplikacja zglasza problem z hostem" (scena galaxyporn).
Ekstraktor jest SPRAWNY. Sprawdzone end-to-end: resolve 200, master m3u8,
wariant, 525 segmentow, 60/60 pobranych. Telemetria 30 dni dla tego
zrodla: 1310 sukcesow, 25 bledow (1,9%).
Ale przy okazji wyszlo cos wiekszego. Wszystkie te bledy to "502", a
mapowanie w `_upstream_error_response` sklejalo w ten kod DWIE rozne
awarie: upstream 5xx (CDN padl) ORAZ kazde inne 4xx, w tym 403. Test
syntetyczny: upstream oddaje 403, nasze proxy oddawalo 502.
To bolalo podwojnie. `playback_events.error_detail` bierze sie z komunikatu
ExoPlayera, wiec w telemetrii nie dalo sie odroznic "CDN padl" od "wygasl
podpisany token" — a to zupelnie inne naprawy (pierwsze: czekac, drugie:
odswiezyc resolve). Do tego 403 szedl przez raise jako "moze nasz bug" i
zasmiecal Sentry, choc wygasanie tokenow na tych CDN-ach jest NORMALNE.
Zmiany:
1. 401/403 przepuszczane z prawdziwym kodem (+ log INFO, bez wyjatku).
Cache i tak byl juz invalidowany na 401/403/404/410, wiec kolejny
resolve dostaje swiezy URL.
2. Przejsciowe 502/503/504 ponawiane RAZ (tylko GET/HEAD, idempotentne).
Te CDN-y stoja na wielu wezlach (galaxyporn: 3 rozne IP w jednej
sesji), wiec druga proba zwykle trafia w zdrowy. 4xx nie ponawiamy.
Zweryfikowane: 403 wychodzi teraz jako 403 (bylo 502), normalne
odtwarzanie bez zmian (60/60 segmentow 200).
Uwaga: sciezka ponowienia nie zostala odpalona end-to-end, bo 502 nie da
sie wywolac na zadanie. Widac ja w logu ("proxy: upstream N, ponawiam").
Zgloszenie "Jakis problem z miniaturkami z fullporner" (36c33200).
fullporner NIE jest winowajca: pomiar 2026-08-13 dal 40/40 poprawnych
JPEG-ow i 0 z 68 414 zrodel bez URL-a. Winna byla KOLEJNOSC WYBORU.
Miniaturke wygrywal pierwszy origin alfabetycznie, a `tube:fullmoviesxxx`
sortuje sie PRZED `tube:fullporner`, wiec chwiejny host przykrywal zdrowy.
Pomiar (20-25 losowych URL-i na host):
img.fullmovies.xxx 12/20 ok (5x ReadTimeout, 3x 502) 54 019 zrodel
img.hdporn.gg 16/20 ok (3x 502, 1x ReadTimeout) 54 267 zrodel
imgs.xiaoshenke.net 20/20 ok (fullporner) 68 406 zrodel
freshporno.org 20/20 ok
Nowy predykat `_is_flaky_thumb`: degraduje do tieru fallback w LISCIE, ale
w odroznieniu od `_is_rotting_thumb` NIE zeruje w SceneDetail. Zerowanie
powtorzyloby wpadke z sierpnia, gdzie sceny majace tylko fullporner
tracily obrazek calkowicie.
Dwie iteracje, obie z pomiaru, nie z zalozenia:
1. Degradacja samego fullmovies przesunela wybor na hdporn (44 z 60),
czyli PRZENIOSLA problem. Stad hdporn dopisany.
2. Po zdegradowaniu obu fullmovies WROCIL (38 z 60): sceny majace tylko
te dwa hosty laduja w fallbacku, a `setdefault` bral pierwszy
alfabetycznie, czyli gorszy z dwoch. Stad `_FLAKY_RANK` — w obrebie
fallbacku wybieramy mniejsze zlo.
Po zmianie w dwoch niezaleznych losowaniach fullmovies nie wygrywa nigdzie,
a sceny majace WYLACZNIE chwiejne hosty dostaja hdporn (40/40, zero bez
miniatury), wiec nic nie traci obrazka.
`_pairs_exact_phash` laczylo scene_fingerprints po wartosci BEZ zadnego
ograniczenia. Do tej pory uchodzilo, bo zdegenerowanych wartosci bylo
malo i blacklista je kasowala. Zmienia to backfill: dokladamy ~240 tys.
odciskow z xvideos/xnxx/epornera, a te serwuja zaslepki przy usunietych
filmach.
Dwa problemy naraz:
1. Blacklista odswieza sie RAZ NA DOBE, wiec swiezo powstala zaslepka ma
pelna dobe okna na wpuszczenie do potoku tysiecy niepowiazanych scen.
2. Samozlaczenie jest KWADRATOWE po liczbie scen dzielacych wartosc:
zaslepka przy 5 tys. scen to 12,5 mln par i job pada na pamieci,
zanim cokolwiek zdazy ja zablacklistowac.
Teraz zapytanie samo odsiewa wartosci dzielone przez >=10 scen (ten sam
prog co phash_blacklist) ORAZ te juz zablacklistowane, wiec dziala
natychmiast, nie po dobie.
NIE jest to atrapa: 4% w backfill jedna taka wartosc juz istnieje
(12 scen) i blacklista jej jeszcze nie widziala. Po zmianie samozlaczenie
daje 23 555 par w 8,3 s.
Kasowane wiersze ida najpierw do `scene_performers_pruned`, w TEJ SAMEJ
transakcji co DELETE: albo wiersz jest zapisany i skasowany, albo nie
dzieje sie nic. Cofniecie to `INSERT ... SELECT`, nie backup calej bazy.
Archiwum trzyma tez nazwe performera i tytul sceny, wiec da sie je
przejrzec bez odtwarzania joinow. Tabela swiadomie poza alembikiem: to
slad po jednorazowym sprzataniu, nie czesc schematu.
Kryterium doprecyzowane po dwoch losowych probkach:
1. „brak nazwy w tytule" samo w sobie kasowalo MESKICH performerow (tuby
nie wypisuja ich w tytulach, przypisanie szlo z listy obsady) -> stad
warunek „inny performer sceny ma dowod I dzieli czlon".
2. Dowodem dla nazwy o >=2 czlonach jest kazdy czlon jako OSOBNE SLOWO,
nie spojna fraza: „Silvia and Eveline Dellai" to scena Silvii Dellai,
ale ciagu „silviadellai" tam nie ma (1 blad na 22 w probce). Nazwy o
jednym uzytecznym czlonie („Eliza E") zostaja przy ostrym kryterium,
bo inaczej lapia kazda inna Elize.
3. Granica slowa przez `strpos` na znormalizowanym tekscie, NIE regex:
nazwy z nawiasami wywalaly caly przebieg („parentheses not balanced"),
a metaznaki po cichu psulyby dopasowania.
Dry-run: 321 833 przypisania (vs 370 587 przed poprawka 2). Szkoda
rozproszona, nie skoncentrowana: rekordzistka traci 20 z 909.
Zgloszenie 2026-08-13: strona Tiffani Time pelna scen o Tiffany Tatum,
Tiffani Madison i Victorii Tiffani.
Przyczyna: `_search_base.search` dokleja szukanego performera do KAZDEJ
sceny bezwarunkowo (`all_performers = [RawPerformer(name=query), ...]`),
wiec cala poprawnosc obsady wisi na filtrze tokenow. A filtr testowal
PODCIAG na luznych tokenach, wiec:
"tiffany" ⊂ "lp-s-tiffany-love-first-time-gonzo" (inna osoba)
"time" ⊂ "adult-time", "first-time", "multiple-times" (pospolite slowo)
Historia tej linijki to trzy poziomy: any() -> all() -> (teraz) fraza.
`all()` naprawil "Ava Koxxx na scenach Avy Devine", ale zostawil oba
powyzsze. Teraz slug musi zawierac CALA nazwe jako ciag, z granica slowa
po bokach, z dowolnym separatorem miedzy czlonami.
Dozwolone koncowe "s": slug gubi apostrof, wiec "TiffaniTime's" zapisuje
jako "tiffanitimes". Nie luzuje bramki, bo przed tym "s" stoi cala fraza.
hqporner mial WLASNA kopie tego filtru (i wlasny zestaw dziur) - podpiety
pod ta sama funkcje, zeby sie nie rozjezdzalo.
12 przypadkow testowych z realnych danych, w tym te ktore MUSZA przejsc
(tiffani-time-*, tiffanitimes-*, mia-li-* z czlonem <3 znaki).
Do tego skrypt czyszczacy juz istniejace pomylki. Kryterium zawezone po
obejrzeniu probki: samo "brak nazwy w tytule" kasowalo MESKICH performerow
(tuby nie wypisuja ich w tytule, a przypisanie szlo z listy obsady, nie
z searcha). Dolozony warunek "inny performer sceny ma dowod I dzieli
czlon" - probka 14/14 to realne pomylki.
Root cause zgloszenia 9d272101 ("5 duplikatow, czemu nie zmergowane?"):
phash mialo tylko 37,8% grywalnych scen. Licza go WYLACZNIE niektore
konektory w momencie ingestu, wiec najwieksze zrodla maja miniaturke dla
~100% scen, a odcisk dla 1-2% (xvideos 1,8%, xnxx 1,4%, eporner 1,0%).
Material jest zapisany, brakowalo tylko obliczenia.
W zglaszanym przypadku 7 wierszy o identycznej dlugosci 2324 s, a dwa
kafelki z IDENTYCZNA okladka nie mialy phasha wcale, wiec jedyny sygnal,
ktory by je sklail, nigdy nie powstal.
Zakres CELOWANY, nie caly katalog: sceny w klastrze (performer, dokladna
dlugosc) o licznosci >1, bez phasha, ale z zapisana miniaturka = 238 704
pozycje (wobec ~1,4 mln scen bez phasha). Reszta nie ma sie z czym skleic.
Kolejka jako TABELA, nie zapytanie w locie: wyznaczenie kandydatow to
ciezki agregat po calym katalogu, ktorego nie chcemy powtarzac przy kazdej
paczce, a kolejka przezywa restart workera i widac z niej postep.
Weryfikacja end-to-end na zglaszanej scenie: ce81a110 dostal phash
85c1bac2f8c60ecf, czyli DOKLADNIE ten sam, ktory mial juz 8373bbb5 (dwa
z kafelkow uzytkownika) -> istniejacy phash_exact je teraz sklei.
Nie zapisujemy wartosci z phash_blacklist (zaslepki dzielone przez setki
scen). Throttling swiadomy: 800 co 15 min, ~3 dni na nadrobienie.
Dwie pulapki SQL zapisane w kodzie: `referer` ma 255 znakow wiec origin
wycinamy w SQL (pelny page_url wywalal planowanie), a rzutowanie musi isc
przez CAST() bo text() SQLAlchemy nie podstawia parametru za ktorym stoi
`::`.
1. WERTYKALY. Hentai i 3D szly do glownego feedu wymieszane z zachodnim
katalogiem, mimo ze argument za odgrodzeniem byl ten sam co przy JAV.
Zamiast drugiej kopii mechanizmu JAV wprowadzam wspolne pojecie wertykalu
(app/verticals.py): mapa nazwa -> originy, jeden predykat, `?vertical=`.
Brama po originie jest DOKLADNA, zmierzone: 9507 scen animowanych, ZERO
z originem spoza listy (nie maja sie z czym zdeduplikowac). Dlatego osobna
baza nie jest potrzebna, rozdzielam logicznie.
Tagi to samodzielny powod: z 3116 tagow przy scenach animowanych tylko 452
wystepuja tez poza animacja, czyli 85% to slownictwo wylacznie animacyjne.
`/tags?vertical=` liczy je NA ZYWO (male zbiory, zero migracji), a
zdenormalizowany Tag.scene_count opisuje juz WYLACZNIE glowny feed.
Przy okazji naprawione zasmiecenie JAV-em istniejace od lipca:
taxonomy_counts wliczal wertykaly do licznikow, ktore opisuja feed ich
nie pokazujacy. Refresh: 1476 tagow, 1402 performerow, 154 studia.
Stary `?jav=true` DZIALA dalej (instalacje sprzed sierpnia go wysylaja).
2. FILMY NA EKRANIE STUDIA. Zgloszenie: polubione studio od filmow nie
pokazuje nowych filmow i nie ma "+1". Backend liczyl je poprawnie
(_merged_new_counts scala sceny i filmy od 2026-07-28). Blad byl w apce:
tap na ulubione studio ZEROWAL licznik (markStudioSeen) i wchodzil na
ekran wylacznie ze scenami, wiec "+N" z nowych filmow znikalo, a filmy
nie mialy sie gdzie pokazac. StudioMoviesScreen istnial, ale wchodzilo
sie do niego tylko z detalu filmu. StudioScenes dostaje zakladki
Scenes/Movies, jak PerformerScenes.
Pasek zakladek w headerze przewija sie w poziomie, bo piata pozycja
(Anime) nie miescila sie na waskich telefonach.
Strona istniala WYLACZNIE na serwerze (wolumen infisical-caddy), a cala
historia to byly kopie index.html.bak-* obok pliku. Wjezdza do repo.
Tresc zaktualizowana o to, czego strona nie mowila:
- filmy (45k) w ogole nie byly wspomniane, mimo osobnej zakladki
- "30+ public tubes" -> 46 realnych zrodel
- pasek liczb w hero (3.8M scen, 108k performerow, 45k filmow, 46 zrodel)
- zakladki: scenes/movies/sites/JAV zamiast samego grida scen
- sekcja "What's new": animacja i 3D, filmy, JAV we wlasnej zakladce
Makiety w sekcji "In the app" zastapione prawdziwymi zrzutami (byl tam
komentarz zeby to zrobic po wgraniu realnych screenow). Miniaturki scen
sa na nich rozmyte. Przy okazji -100 linii martwego CSS-u makiet.
Machinima i animacje SFM/Blender. Kanon nie istnieje tak samo jak przy
hentai i rule34video, wiec kazda pozycja jest orphanem i to poprawne.
Najzdrowsza jednostka tresci calego wertykalu 3D: mediana 289 s, ZERO
pozycji ponizej minuty, 18/25 powyzej progu potoku. Dla porownania
rule34video ma mediane 68 s i traci ~70% katalogu.
Playback najprostszy z serii: jawne <source> w trzech jakosciach, bez
tokenu, bez AJAX-a, bez CF. Zweryfikowane z VPS: 206, ftypisom, 140 MB,
dziala bez Referera, wiec mobile_direct_ok i zero pracy po stronie apki
(inaczej niz rule34video, gdzie token byl IP-bound).
Szosty niezalezny host wertykalu (videos.naughtymachinima.com), zadna
z szesciu stron nie re-hostuje pozostalych.
Odsiewamy pusty <source src=""> (placeholder playera) i preroll
/images/preroll/NMintro.mp4, ktory pasuje do naiwnego \.mp4.
Bramka dlugosci zestrojona z min_ingest_duration_sec, jak przy
rule34video. Pilot 3 strony: seen 48, new 48, skipped 0, errors 0.
Animacje SFM/Blender. Kanon nie istnieje tak samo jak przy hentai, wiec
kazda pozycja jest orphanem i to poprawne.
Playback: KVS z jawnymi flashvars (4 jakosci, bez license_code), ale
`v-acctoken` jest ZWIAZANY Z IP tego, kto pobral strone. Test krzyzowy:
URL wygenerowany przez proxy i pobrany z VPS = 403, ten sam URL z IP
generujacego = 206 ftypisom 70 MB. Po zdekodowaniu tokenu adresu nie
widac wprost (inaczej niz fpoxxx), wiec samo ogladanie nie wystarcza.
Dlatego bez mobile_direct_ok: telefon resolwuje sam, UPFRONT, istniejaca
sciezka isGetFileUrl()/resolveGetFilePage z SceneDetailScreen. Rozszerzam
getfileResolver o flashvars, bo dotad umial tylko <source> (hdporn.gg,
fullmovies.xxx). Zweryfikowane end-to-end z residential IP: strona ->
flashvars 720p -> 302 na boomio-cdn -> 206 ftypisom 39,8 MB.
Bramka dlugosci zestrojona z `min_ingest_duration_sec` (prod 180 s)
zamiast wlasnej liczby: pierwsza wersja miala 60 s i liczniki klamaly
(seen 57, new 31, skipped 26). Po zestrojeniu seen 20, new 20, skipped 0.
Krotka tresc wycina ~70% katalogu (mediana 68 s).
Tagi TYLKO z class=tag_item. `class=button` wyglada na wlasciwe, a jest
chmura "Top Tags": przy filmie o Lux siedzialy tam "cell (dbz)" i
"queen of pain (dota)". Autor animacji zapisany jako studio.
CZWARTY niezalezny host: pliki na hentaiplanet.info, podczas gdy hentaimama ma
gdvid.info, xanimeporn download.xanimeporn.com, a hentaigasm hgasm<N>.com. Cztery
strony, cztery osobne pule plikow - zadna nie re-hostuje pozostalych, mimo ze katalogi
odcinkow mocno sie pokrywaja.
Metadane z RSS-a, tak jak przy hentaigasm i z tego samego powodu: /genre/ w HTML strony
to 2084 linki, najwieksza chmura z sidebara w calym wertykale (hentaigasm mial 38,
hentaimama 118). Feed daje date, tytul i realne kategorie. Odsiewamy przy tym pozycje
czysto techniczne (Hentai Anime, New Hentai, English Subbed) oraz rocznik, bo to nie sa
tagi tresci. /page/2/ nie zwraca odcinkow, /feed/?paged=N stronicuje chronologicznie.
Playback: mp4 wprost w HTML (video.js), bez AJAX-a i bez Cloudflare. Pulapka: serwis
nazywa miniaturki od pliku wideo (…-RAW.mp4_snapshot_07.59.jpg), wiec naiwne szukanie
.mp4 lapie zarowno wideo, jak i obrazek. Wymagamy URL-a KONCZACEGO sie na .mp4 i
odrzucamy wp-content/uploads.
Druga pulapka, zlapana dopiero testem: og:image na tej stronie NIE ISTNIEJE, miniaturka
jest tylko w JSON-LD i z escapowanymi ukosnikami. Pierwsza wersja dawala 12/12 odcinkow
bez miniaturki.
Zweryfikowane z VPS: 206 na Range, ftypmp42, 78 MB, dziala BEZ Referera i bez tokenu.
Serwer oddaje content-type application/octet-stream, ale sciezka konczy sie .mp4, wiec
ExoPlayer wybierze Mp4Extractor po rozszerzeniu.
Pilot: seen 48, new 48, errors 0. Komplet dat i miniaturek.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TRZECI niezalezny host w wertykale. Te same odcinki co hentaimama i xanimeporn, ale
znowu inne pliki: tutaj hgasm<N>.com/<Tytul Ze Spacjami>.mp4, tam gdvid.info/N/... i
download.xanimeporn.com/videos/1080p/[1080p]<id>.mp4. Zadna z trzech stron nie
re-hostuje pozostalych.
Metadane w CALOSCI z RSS-a i to nie skrot tylko koniecznosc:
- strona odcinka NIE MA daty publikacji w zadnym standardowym miejscu (ani JSON-LD,
ani article:published_time, ani <time>), a feed ma pubDate
- /genre/ w HTML to 38 linkow, czyli kolejna chmura z sidebara; feed daje 5 realnych
kategorii, gdzie pierwsza to nazwa serii
- /page/2/ nie zwraca odcinkow w ogole, a /feed/?paged=N stronicuje chronologicznie
Playback najprostszy z calej trojki: konfiguracja JWPlayera z gotowym file: wprost w
HTML, bez AJAX-a i bez Cloudflare. Sciezka zawiera SPACJE, wiec kodujemy sama sciezke,
zostawiajac schemat i host. Host ROTUJE miedzy odcinkami (hgasm1/hgasm3), wiec czytamy
go ze strony zamiast wpisywac na sztywno.
Zweryfikowane z VPS: 206 na Range, ftypisom, 198 MB, dziala BEZ Referera i bez tokenu,
wiec URL nie wygasa. mobile_direct_ok.
Pilot: seen 107, new 107, errors 0. Metadane: 100 procent z data, miniaturka i tagami.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NIE jest re-hostem hentaimamy i to bylo pierwsze, co sprawdzilem. Wspolny odcinek
(Shoujo Ramune 7) lezy na obu stronach, ale to zupelnie inne pliki: hentaimama serwuje
gdvid.info/S/shoujo-ramune-7.mp4 w jednej jakosci bez etykiety, a tutaj jest
download.xanimeporn.com z jawnym wyborem 1080p (222 MB) i 720p (84 MB).
Listing idzie z RSS-a i to jedyna droga, ktora dziala. Sprawdzone trzy inne:
- /page/2/ i /page/3/ oddaja ten sam zestaw co strona 1 (28 z 32 wspolnych),
czyli paginacja zepsuta jak przy 8kporner
- /uncensored/ i /censored/ stronicuja poprawnie, ale NIE sa chronologiczne: pierwsze
pozycje z 2024, zakres 2015-2026. Browse-latest nigdy nie zobaczylby nowego odcinka,
czyli pulapka z freshporno. Pierwsza wersja konektora wlasnie tak dzialala i dopiero
test na danych to pokazal
- /hentai-list/ ma caly katalog (1048) na jednej stronie, ale nie jest chronologiczny
Drugi filtr tez wymuszony przez dane: slugi gatunkow (/futanari/, /big-tits/) sa takimi
samymi slugami najwyzszego poziomu jak odcinki i wchodzily jako pozycje bez daty i
miniaturki. _parse_detail wymaga teraz postid w klasie body, ktory maja tylko
pojedyncze wpisy. Ten sam identyfikator jest potrzebny extractorowi.
Playback: Fluid Player z PUSTYM <source src=''>, wideo wstrzykiwane w runtime, wiec w
HTML nie ma zadnego linku. Wyjsciem jest zakladka Downloads:
videos.xanimeporn.com/download.php?id=<postId>&quality=. Oddajemy download.php, NIE
docelowy plik, zeby token generowal sie przy odtwarzaniu i nie wietrzal (lekcja z
watchporn). Bez Cloudflare i bez proxy, w odroznieniu od hentaimamy.
Pilot: seen 50, new 50, errors 0. Metadane: 100 procent z data, miniaturka, kategoria
i seria jako tagi.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Jednostka tresci to ODCINEK (/episodes/<seria>-episode-N/), mapowany na scene tak samo
jak w wertykale JAV, bez zmian w schemacie. Seria ladue jako tag, wiec odcinki daja sie
grupowac.
KRYTERIUM JEST TU INNE I TO CELOWE. Dla animacji nie istnieje kanon - TPDB i StashDB
nie maja rysowanych postaci - wiec kazda scena stad jest technicznie orphanem i to
jest POPRAWNE. Nie stosujemy ani bramki na obsade (nie ma obsady), ani miary canonical
match, ktora sluzyla nam do oceny tubow z zywymi aktorami. Jakosc mierzymy kompletem
seria + odcinek + gatunki.
Motyw jest z rodziny Dooplay, ale DooplayConnector NIE pasuje: brak data-fl-source i
data-post, na ktorych stoi tamten parser. Player idzie w trzech krokach: id posta ze
strony odcinka, POST /wp-admin/admin-ajax.php z action=get_player_contents, potem
strona wlasnego playera, ktora oddaje bezposredni mp4. Sam POST jest za Cloudflare
(GET-y przechodza), wiec wymaga Bright Data, dokladnie jak POST /api/video-info w sexu.
Playback najlepszy z mozliwych: preferujemy gdvid.info, bo oddaje plik BEZ tokenu,
wiec URL nie wygasa. Zweryfikowane z VPS: 206 na Range, ftypisom (faststart), dziala
BEZ Referera, stad mobile_direct_ok.
Pulapka obeszla: /genre/ w calym HTML to 118 linkow (chmura w sidebarze, ten sam wzorzec
co przy sexu i yourdailypornmovies). Gatunki bierzemy tylko z div.sgeneros, co daje 5-10
realnych pozycji na odcinek.
Pilot: seen 90, new 90, errors 0. W bazie 90 odcinkow, 100 procent z data i tagami,
zakres 2025-12-29 do 2026-07-31.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1745 wystapien w 291 plikach (backend, scripts, mobile). Dominowal jeden ksztalt,
' — ' laczace zdania, wiec poszedl przecinek; myslnik otwierajacy mysl zdjety;
zakresy 0–5 i A–Z na dywiz.
Podzial komentarz/kod robil skaner stanow, nie regex, zeby nie ruszyc myslnika
stojacego w stringu albo w wyrazeniu regularnym. Potwierdzone maszynowo: po wycieciu
komentarzy z wersji HEAD i z dysku obie sa identyczne we wszystkich 291 plikach,
czyli poza komentarzami nie zmienilo sie nic. 233 pliki .py parsuja sie bez bledu,
tsc ma te same 11 bledow w tych samych 3 plikach co przed zmiana.
Dwie rzeczy wymagaly poprawki po automacie: wyrownane listy definicji, gdzie myslnik
byl separatorem kolumny (37 miejsc, kolumna przywrocona), i trzy przeniesienia mysli
do nowej linii, gdzie zostawal wiszacy przecinek na poczatku (poprawione recznie).
Bundla nie republikuje: Hermes i tak nie niesie komentarzy, wiec dla uzytkownika
to zero zmiany.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
32 miejsca w 14 plikach: changelog, onboarding, ekrany Sites/Blacklist/Login/Player,
komunikaty bledow, placeholdery. Zamiast myslnika przecinek, dwukropek, kropka albo
nawias, zaleznie od tego co dane zdanie robi.
Zostawione swiadomie: pojedynczy glif U+2014 jako znacznik BRAKU WARTOSCI
(release_year ?? '—', nieocenione osie w SitesScreen, separator zakresu w filtrze
filmow). To element interfejsu, nie proza, a zwykly dywiz wyglada tam gorzej.
Zostawione tez komentarze w kodzie, w tym te wewnatrz INJECTED_JS.
Przy okazji: MigrationBanner dostal twardy warunek na runtime (needsManualMigration).
Wczesniej przed pokazaniem go nowej wersji chronilo TYLKO to, ze kanal OTA 1.2 byl
pusty. Pierwsza publikacja na 1.2 wyslalaby ten sam bundle i baner kazalby migrowac
z wersji, na ktora user wlasnie przeszedl.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
RUNTIME_DEFAULT 1.1 -> 1.2 (APK 0.2.2 z expo-keep-awake). Kanal 1.1 zostaje zywy
dla instalacji sprzed 0.2.2, ktore nie zaktualizuja sie in-place (stary klucz
podpisujacy przepadl) i dostaly baner migracji; poprawki dla nich publikuj jawnie
przez --runtime 1.1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wgrane razem z APK. Bez tego stary dialog Update available wyskakuje z mylacym
Server 0.2.1 / App 0.2.2 (bundle OTA niesie app.json, wiec APP_VERSION raportuje
juz 0.2.2 nawet na starym APK).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Katalog android/ jest w repo (bare workflow), wiec zmiana runtimeVersion w app.json
sama nie przepisuje manifestu, robi to dopiero prebuild. Bez tego APK 0.2.2 siedzialoby
na kanale OTA 1.1 i dostaloby baner migracji, czyli kazaloby migrowac jeszcze raz,
w kolko. Zlapane przed wydaniem.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Weryfikacja na emulatorze (build debugowy, Metro): pasek i modal renderuja sie
poprawnie, kod synchronizacji sie pokazuje, przycisk otwiera goon-foss.org.
Tresc byla za dluga, urywala sie na naglowku kroku 4 i wygladala jak zepsuta;
po skroceniu miesci sie bez scrollowania.
Przy okazji potwierdzone na dexach: ExpoKeepAwake/KeepAwakeModule wchodzi teraz
do APK, wiec keep-awake zadziala po wydaniu 0.2.2.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Klucz podpisujacy stare buildy przepadl, wiec update in-place jest niemozliwy:
Android nadpisze aplikacje tylko buildem z tym samym podpisem. Odinstalowanie
czysci SecureStore, a w nim goon.device_id, czyli kod synchronizacji, bez ktorego
ulubione/postep zostaja na serwerze bez sposobu wskazania ich. Baner pokazuje kod
na wierzchu i prowadzi przez kroki (kopiuj kod, pobierz, odinstaluj, wklej kod).
expo-keep-awake: sprawdzenie stringow w dexach APK 0.2.1 potwierdzilo, ze modulu
ExpoKeepAwake tam nie ma (jest tylko interfejs z expo-modules-core), wiec ekranu
gasnacego w trakcie ogladania NIE dalo sie naprawic przez OTA. Teraz jawna
zaleznosc, autolinking ja widzi, wchodzi do APK 0.2.2 (runtime 1.2).
UWAGA przy publikacji banera na runtime 1.1: manifest bierze runtimeVersion z
argumentu --runtime, wiec 1.1 jest serwowane poprawnie mimo app.json=1.2, ale
extras nadal niosa app.json (APP_VERSION zaczyna raportowac 0.2.2). Dlatego
serwerowe /version trzeba bumpnac do 0.2.2 razem z wgraniem APK, inaczej stary
dialog Update available wyskoczy z mylacym Server 0.2.1 / App 0.2.2.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pomiar na 300 losowych URL-ach z bazy: 298 prawdziwych JPEG-ow (5-25 kB),
tak samo z VPS jak i z lacza domowego. Wpis w _is_rotting_thumb zerowal
miniature w SceneDetail, wiec sceny majace tylko fullporner traciły ja
calkowicie (53 tys. zrodel).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zgloszenie b52470be ('Doply resolver chyba padl', err 'Source error None of the').
Diagnoza: protokol dziala (doply -> playmogo, pass_md5 obecny, CDN oddaje 206
video/mp4), ale strona jawnie mowi '<h1>Not Found</h1> video you are looking for is
not found' - wideo jest USUNIETE. Detekcja szukala doslownej frazy 'video not found',
ktora w tym wariancie NIE pada, wiec resolver uznawal usuniete wideo za sukces.
Playmogo mimo usuniecia dalej wystawia token pass_md5 i serwuje plik-zaslepke, stad
u usera 'Source error' zamiast czytelnego komunikatu.
Rozszerzone markery: 'is not found', 'no_video_' (obrazek-zaslepka
i.doodcdn.io/img/no_video_3.svg - najpewniejszy), 'video has been deleted',
'file was deleted'. Blad 'video_deleted' jest NIEretryowalny, wiec apka od razu
pokaze komunikat i pozwoli oznaczyc zrodlo jako martwe.
1) Changelog obiecywal 'screen no longer turns off', ale to NIE dziala. Audyt APK
v0.2.1: nazwa 'ExpoKeepAwake' NIE wystepuje w zadnym classes*.dex - jest tylko
KeepAwakeManager z expo-modules-core (wewnetrzny interfejs). Czyli expo-keep-awake
nie zostal wkompilowany, requireNativeModule rzuca, a moj try/catch cicho polyka
blad. Blad w moim wczesniejszym rozumowaniu: obecnosc w node_modules/expo/
node_modules NIE oznacza, ze autolinking wciagnal modul do konkretnego builda.
Keep-awake WYMAGA nowego APK (OTA dowozi tylko JS), wiec wpis usuniety zamiast
obiecywac cos, czego nie ma. Zgloszenie 9d5618dd.
2) fastpic.org (galaxyporn) zrywa polaczenie zamiast oddac obraz -> dopisany do
_is_rotting_thumb. Bonus: scena bez miniatury odpala w apce auto-enrich, ktory
sciaga swieza ze strony tube'a. Zgloszenie c2f1dd41, 240 z 20213 zrodel.
Po naprawie dostepu vjav ruszyl, ale zaczal sypac smieciem: pomiar na 295 scenach z
doby po fixie dal 78,6 proc. tytulow slug-concat i ZERO przypisanej obsady. Takie
sceny sa w apce nieodnajdywalne - nie maja ani tytulu, ani performera.
Bramka odrzuca cztery wzorce: prefiks id_JAV, hash x1x..., kod typu
QCT062-KPUDYLMLBL913295279 oraz ciagi bez samoglosek/spacji (walniecie w klawiature).
Zmierzone na probce 6000 tytulow: odrzuca 80 proc. swiezych i 27 proc. starych, przy
39 przepuszczonych na 200 obejrzanych - zrodlo nie jest wyzerowane.
WAZNE, znalezione przy pomiarze pierwszej wersji: str.isalpha() jest prawdziwe dla
kana i kanji, a japonski nie stawia spacji, wiec reguly "za malo samoglosek" i "brak
spacji" odrzucalyby PRAWDZIWE tytuly na serwisie JAV - 708 z 708 tytulow CJK z probki.
Stad jawny wyjatek _has_cjk. Kontrola jednostkowa: 8/8 przypadkow, w tym dwa CJK.
Drugi blad, wprowadzony przez sama bramke i zlapany dopiero pilotem: strona 1 jest w
100 proc. smieciowa, wiec po odsianiu zwracala [], a bazowe latest_scenes traktuje
pusta strone jako koniec katalogu i konczylo caly run. Zrodlo dawalo seen: 0 mimo 39
dobrych scen na stronach 2-5. Wlasna iteracja rozstrzyga wyczerpanie po dlugosci listy
id, nie po liczbie scen po filtrze. To ta sama pulapka co w _load_ids.
Pilot po obu poprawkach: seen 39 (wszystkie skipped - weszly przed bramka).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Na zyczenie uzytkownika. Alerty zostaja wylacznie w Sentry - z eskalacja poziomu i
kubelkami wieku w fingerprincie z poprzedniego commita, wiec sama poprawa
powiadamiania zostaje nienaruszona.
Usuniete: app/notify/ (caly pakiet), job watchdog-digest, parametr to_slack w
run_ingest_freshness_watchdog oraz klucze konfiguracji sched_watchdog_digest_hours,
slack_bot_token i slack_channel. Zadna wartosc SLACK nigdy nie trafila do .env ani do
compose, wiec nic nie bylo wysylane.
Po usunieciu watchdog dalej sprawdza 41 zrodel (sceny + filmy), scheduler rejestruje
juz tylko ingest-watchdog.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Watchdog dzialal poprawnie - vjav i superporn wypisywal co 6h przez caly czas ich
ciszy. Zawiodlo POWIADOMIENIE, w trzech miejscach naraz.
1. Filmy nie byly pokryte w ogole. Watchdog skanowal tylko origins tube:<sitetag> ze
scen, wiec streamporn.vip stal 23 dni i zaden automat nie mial jak tego zauwazyc.
Doszlo 6 konektorow filmowych (35 -> 41 sprawdzanych zrodel), prog 72h. Zweryfikowane
przez celowe obnizenie progu do 1h: wszystkie 6 matchuje realne liczby pozycji, a nie
zwraca cicho zera - bo to dokladnie ta klasa bledu, ktora naprawiamy.
2. Stabilny fingerprint per origin tworzyl JEDNO issue przy pierwszym wystapieniu i
potem tylko licznik. Sentry powiadamia o nowych i regresjach, nie o kolejnych
wystapieniach otwartego issue. Teraz fingerprint zawiera kubelek wieku (2d+/7d+/30d+),
wiec przekroczenie kazdego progu zaklada nowe issue, ale w obrebie kubelka nadal nie
ma spamu co 6h.
3. Poziom byl zawsze warning, a reguly alertow celuja w error. Od 7 dni ciszy idzie
error. Sprawdzone: vjav i superporn eskaluja teraz do error, pornbusy/youperv/porndish
zostaja na warning.
Plus kanal, ktory czlowiek realnie czyta: dobowy digest na Slacka (osobny job, zeby
nie wysylac tej samej listy 4x dziennie). Domyslnie NO-OP - bez GOON_SLACK_BOT_TOKEN
i GOON_SLACK_CHANNEL nic nie probuje wysylac, kanalu nie zgadujemy.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Audyt po fixie streamporn.vip. vjav (77 tys. zrodel) nie dodal nic od 2026-07-22 i
NIE zglaszal bledu - crawl_page oddawal 0 scen, licznik pokazywal errors: 0.
Przyczyna: vjav odcial IP VPS-a. Sprawdzone 2026-08-03 - sitemap, strona glowna i
/latest-updates/ daja 429 przy trzech probach z rzedu, a przez Bright Data 200 od
pierwszej. Kod tego nie widzial, bo browser_get NIE rzuca na 4xx, wiec 343-bajtowa
tresc bledu byla parsowana jako XML: zero sitemap, zero id.
Drugi blad, ktory to ukryl: przy niepowodzeniu _load_ids ustawialo _sorted_ids = [],
a crawl_page tlumaczy [] na "koniec katalogu" (poprawny stan), nie na awarie. Teraz
przy bledzie zostaje None, ktore crawl_page zwraca jako transient-fail.
Fix: proxy Bright Data na sitemap i API metadanych (ten sam host, ten sam 429), jawne
sprawdzanie statusu, [] tylko dla realnie pustego katalogu.
Po fixie crawl_page oddaje 120 scen zamiast 0. Nowej podazy to jeszcze nie dalo
(wszystkie 120 to pozycje sprzed blokady, skipped na niezmienionym hashu) - sitemap
vjav nie przesunal sie od czasu odciecia. Do obserwacji. Uwaga na jakosc: w tej
partii 58 proc. tytulow to slug-concat typu 0008363_JAV_..., przy 2,9 proc. w calym
katalogu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zrodlo nie dodalo nic nowego od 2026-07-11. Strona jednak ZYLA, a konektor parsowal
poprawnie - problem byl w tym, ze `/movies/` na tym motywie NIE jest sortowane po
dacie i oddaje stary katalog. Zmierzone na tych samych 8 pozycjach: `/movies/` dalo
roczniki 2012-2015, strona glowna wylacznie 2026, po 10-11 zrodel playbacku kazda.
`?orderby=date` motyw ignoruje (odpowiedz identyczna z domyslna).
To ta sama klasa bledu co przy freshporno: wlasciwa strona, zly endpoint listingu.
Diagnoza po licznikach per zrodlo (ostatni nowy film + nowe w 30d/7d), nie po tym,
czy konektor rzuca wyjatkiem - bo nie rzucal.
Fix: `_listing_path` na `/` + `/page/N/`. Strony 1 i 2 wspoldziela ~44 linki
(sidebar/widgety), ale dedup po URL w fetch_movies je odsiewa.
Pilot po zmianie: seen 40, new 18, updated 10, skipped 12, errors 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sprawdzony NA DUPLIKAT przed budowa, bo poprzedni kandydat (speedporn.net) okazal sie
kolejna nakladka na pandanetwork.club - 49/49 miniaturek z tego samego hosta co nasze
pandamovies, 0 nowych filmow. Tutaj z 40 pozycji ze strony glownej 13 mielismy po
tytule, 9 po id produktu Adult Empire, a 18 bylo nowych. Inna pula tresci: okladki DVD
z imgs1cdn.adultempire.com, nie re-hosty.
Pilot na 40: seen 40, new 22, updated 18, errors 0. W bazie 36 filmow, z tego 34 z
obsada, 36 ze studiem, 14 dopielo sie do pozycji, ktore juz mielismy.
WordPress z wlasnym motywem, wiec nie da sie podpiac pod DooplayConnector.
Pulapka, ktora trzeba bylo obejsc: /tag/ w calym HTML to 2177 linkow, czyli chmura
tagow w sidebarze (ten sam wzorzec co przy sexu). Obsada, tagi i studio czytane
WYLACZNIE z blokow div.xmll - efekt to 5-14 tagow na film zamiast 2177.
Druga rzecz: /director/ trzyma w praktyce STUDIO (New Sensations, VIXEN, Zero
Tolerance Films), nie rezysera. Bierzemy to jako studio, bo tak jest uzyte.
Playback: voe i mixdrop maja gotowe moduly hosterow i zweryfikowalem, ze resolwuja
(voe m3u8, mixdrop mp4). vidara.to nieznana, leci jako zwykly embed do WebView.
Katalog min. 8000 pozycji, siega 2003. Brak dlugosci filmu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1) Duplikaty tagow wrocily, ale INNYM wzorcem niz w lipcu: alnum-klucz z natury nie
lapie liczby mnogiej ('blowjob' != 'blowjobs'). Audyt: 1944 pary, m.in.
Blowjob/Blowjobs (390728 vs 791), Teen/Teens (53096 vs 41294), Cumshot/Cumshots.
Scalone oba kierunki (kanoniczny = wiekszy scene_count): 1938 + 2063 tagow,
przeniesione 251251 + 26142 przypisan scen i 118522 + 392 filmow. Zostaje 581 par
(lancuchy i remisy) - celowo pominiete, wymagaja recznej decyzji.
2) Prewencja w _resolve_by_altkey: gdy alnum-klucz nie trafi, probujemy obu form
(+s / -s). Tylko proste 's' - form nieregularnych (panty/panties) NIE ruszamy, bo
zbyt latwo o falszywy zlew (glass/glasses, bra/bras). Zweryfikowane na prodzie:
Blowjobs->Blowjob, Teens->Teen, Cumshots->Cumshot, Lesbians->Lesbian.
3) UI: formatCount() skraca duze liczniki (181764 -> 181k, 1200 -> 1,2k) w tagach,
performerach, ulubionych i filtrach filmow - user-request, chipy przestaja puchnac.
Druga i ostateczna deaktywacja (pierwsza 2026-06-25, wtedy stub-pliki). Strona
wdrozyla Cloudflare z JS-challenge na /watch/. Sprawdzone TRZY drogi, wszystkie 403:
VPS (Hetzner), residential IP z pelnym kompletem naglowkow przegladarki, oraz
Bright Data ISP proxy. Czyli blokada NIE jest po IP - wymaga wykonania JS.
Przelaczenie na WebView (commit 140764b) tez nie wystarczylo: challenge pokazuje sie
userowi zamiast przechodzic samoczynnie (zgloszenia 92e9133e / 60576a84 / 244131ba).
Telemetria: ZERO prob odtworzenia od 27.07, czyli realnie martwe od tygodnia.
Utrzymanie wymagaloby headless-przegladarki na VPS - nieproporcjonalne do zysku,
decyzja uzytkownika: usunac. Wyrejestrowany scraper (browse) i extractor;
61238 playback_sources oznaczone dead_at. Uwaga: hqporner to INNE zrodlo o mylnie
podobnej nazwie - nietkniete, dziala.
Zgloszenia a01dc891 / 2fbba822 / b437d5f7 ('3 zrodla live, a miniaturki nie ma',
'jakby przy merge scen cos ginelo'). Diagnoza: WSZYSTKIE zrodla mialy
thumbnail_url w bazie, wiec problem byl w wyborze. Apka bierze PIERWSZE zrodlo z
ustawionym URL-em, a po scaleniu na czolo listy wchodzilo zrodlo ktore formalnie
'ma miniature', ale realnie oddaje smiec - dzialajaca lezala nizej i nigdy nie
byla uzyta. Przy jednym zrodle bralo sie to dobre, stad objaw dopiero po merge.
Dwa hosty dopisane do _is_rotting_thumb (istniejacy mechanizm zerowania martwych):
- imgs.xiaoshenke.net (fullporner): HTTP 200 z ~153-bajtowa ATRAPA zamiast obrazu,
- tn.sextu.com (fullvideosporn): 429 dla IP datacenter, wiec nasze image-proxy tej
miniatury NIGDY nie pobierze (znany problem tego zrodla).
Zweryfikowane na wszystkich trzech zgloszonych scenach: bylo 153B/404/429,
teraz 200 i realne obrazy (22287 / 21633 / 32820 B).
Bug-reports 40ec88cc / 92e9133e ('zacina sie na pierwszych sekundach i robi loop').
Trace CDP wykazal: iframe pervl4.xtremestream.xyz/player/index.php?data=<md5> ma w
HTML WYLACZNIE preroll/midroll (opencdn.b-cdn.net) - to one lecialy w petli. Wideo
player dociaga dopiero w runtime:
GET /player/xs1.php?data=<md5>&q=<480|720> -> GOTOWY manifest HLS (#EXTM3U, VOD,
segmenty ~4,17s z PELNYMI URL-ami do pervl4.xspcdn{01..10}.sa.com/cdn/down/...).
Segmenty maja rozszerzenie .html (kamuflaz), ale to zwykly HLS - nic nie trzeba
deszyfrowac ani skladac.
Nowy extractor zwraca oba warianty jako type='m3u8' z referer=index.php?data=<md5>
(taki Referer wysyla przegladarka; bez niego ryzyko 403). Zweryfikowane na prodzie:
2 zrodla, oba HTTP 200 i #EXTM3U (44245 / 41142 B).
Uwaga: sciezka manifestu nie konczy sie na .m3u8, wiec musi isc przez /proxy/hls
passthrough (casus pornhat) - segmenty i tak leca direct z CDN.
User-request 89845707 ('quality customisation button in player'). Do tej pory
jakosc dalo sie wybrac TYLKO przed startem (PlaybackQualityModal w SceneDetail);
zeby ja zmienic, trzeba bylo wyjsc z playera i puscic scene od nowa.
SceneDetail przekazuje teraz cala liste jakosci w params.qualityLinks (label+url+
headers), player pokazuje ikone kolka gdy jest >1 wariant. Przelaczenie robi
replace() i przywraca pozycje sprzed podmiany (replace resetuje czas, wiec
zapisujemy currentTime i ustawiamy go po zaladowaniu), czyli user nie traci
miejsca w filmie. Lista jako overlay, nie Alert - Androidowy AlertDialog renderuje
max 3 przyciski, a jakosci bywa wiecej.
Bug-reports 40ec88cc / 92e9133e: perverzija zacina sie na pierwszych sekundach
i robi loop. Player xtremestream (pervl4.xtremestream.xyz) serwuje w HTML WYLACZNIE
preroll.mp4 + midroll1/2.mp4 z opencdn.b-cdn.net i odtwarza je zanim poda wlasciwy
stream (ten doladowuje sie dopiero w runtime, w kodzie strony go nie ma).
isLikelyAd odsiewal te URL-e przy auto-ekstrakcji, ale strona i tak je ladowala,
wiec user ogladal reklame w kolko. Dodane do AD_HOSTS.
To lagodzi objaw; pelny resolve streamu xtremestream wymaga przesledzenia XHR
w DevTools (osobne zadanie). Zasieg maly: 2 proby odtworzenia w 8 dni.
Bug-report 986d3018 ('O co chodzi z tym Lady Vi? To wcale nie jest aktorka z tych
filmow'). Search-scrapery filtruja wyniki po tokenach nazwy >=3 znaki, wiec czlon
2-znakowy wypada: 'Lady Vi' -> {lady}, i degeneruje sie do 'slug zawiera
lady' = KAZDA scena z tym slowem. Dla nazw gdzie WSZYSTKIE czlony sa krotkie
('Jj Jj', 'Mi Su') zbior tokenow jest PUSTY, a
przepuszcza wtedy absolutnie wszystko.
Audyt: Lady Vi miala 116 przypisan z tube, z czego 115 pasowalo tylko przez 'lady'
a realnie o niej byla 1. Wyczyszczone (zostaly kanoniczne stashdb + 1 trafione).
Fix: gdy nazwa ma czlon <3 znaki, wymagamy dodatkowo CALEJ nazwy sklejonej bez
separatorow ('lady-vi-...' -> 'ladyvi'). Zweryfikowane: lady-vi-hot-scene przyjmie,
lady-sonia-milf i busty-lady-next-door odrzuci.
hqfap wdrozyl Cloudflare na strony /watch/ (2026-07-28): 403 z VPS ORAZ z
residential IP, takze przy pelnym komplecie naglowkow przegladarki (strona glowna
dalej 200, wiec blokada celuje w strony wideo). Phone-side resolveHqfapPage to
zwykly fetch, wiec nie ma jak wykonac JS-challenge -> resolve padal i user
ladowal na stronie hostera (bug-report 92e9133e 'Hqfap przekierowuje na strone').
Telemetria tego NIE pokazala: hqfap ma 99-100% do 26.07 i ZERO eventow od 27.07,
bo blad wystepuje PRZED playerem, wiec event nie powstaje. Ten sam wzorzec co przy
freshporno - przy takich zgloszeniach nie ufac samemu success-rate.
Fix: hqfapcom -> _vps_blocked_fallback (WebView, Chrome engine + JS + cookie
przechodzi challenge; INJECTED_JS i tak wylusknie mp4 i wroci na native player).
Zdjety z PHONE_RESOLVE_ORIGINS i z lancucha phone-resolve w SceneDetail/Player.
1) Auto-rotate (bug-report 55da1c3f: 'I can't turn off auto rotate. Which is a
problem when I put the phone on a flat surface'). Player robil bezwarunkowy
unlockAsync, wiec telefon lezacy plasko skakal miedzy orientacjami. Nowa
preferencja goon.player_auto_rotate (default true = dotychczasowe zachowanie),
przelacznik w Settings. Off = player zostaje w pionie, ale przycisk pelnego
ekranu dalej wchodzi w poziom recznie, wiec nic nie ginie.
2) '+N nowych' na ulubionym performerze/studiu liczylo TYLKO sceny (user-request
2026-07-28). Dochodzi _new_movie_counts: filmy z zywym playbackiem, created_at >
last_seen_at, po MoviePerformer / Movie.studio_id. Filmow jest o rzedy wielkosci
mniej niz scen (brak tube-spamu), wiec bez okna top-N i odsiewu stub/backfill -
te pojecia dotycza scen. Zweryfikowane: performer 1633 scen + 436 filmow = 2069,
studio 648 + 95 = 743, /favorites 200 OK.
Ranking z poprzedniego commita ujawnil klase, ktorej zaden wczesniejszy sygnal nie
widzial: wpisy bedace SAMYM NAZWISKIEM albo samym imieniem, powstale z rozbicia peleno
nazwy przez tube-search. "Devine" obok "Shalina Devine", "Kitana" obok "Kitana A",
"Rayne" obok "Tiffany Rayne". Taki wpis lapie potem kazda scene z tym slowem,
nalezaca do zupelnie innej osoby.
Regula jest DOWODLIWIE BEZSTRATNA: kasujemy przypisanie jednotokenowe tylko wtedy, gdy
ta sama scena ma juz przypisana osobe pelnoimienna zawierajaca to slowo. Informacja o
obsadzie zostaje, znika tylko niejednoznaczny duplikat. Kontrola potwierdzila, ze zadna
scena nie zostala przez to bez obsady (0).
Prowenancja z migracji 0026 dala zabezpieczenie: z 62 783 zbednych przypisan 62 120 to
scraper (skasowane), 73 kanon (chronione), 590 nieznane (zostawione). Bez niej nie dalo
by sie tego rozdzielic.
Wynik: 62 120 przypisan zdjetych, 2156 wpisow odchudzonych (Devine 170 na 60), 1740
pustych rekordow usunietych. Regula dopieta do joba junk_performers, drugi przebieg
daje zera.
Zostaje residuum: sceny, na ktorych osoba pelnoimienna NIE byla przypisana, wiec
regula nie miala sie o co oprzec (James, Blue, Moon, Crystal, Cruz, Starr, Knight po
60-160 przypisan). Tam trzeba by DOPISAC wlasciwa osobe, a nie kasowac - to osobne,
bardziej ryzykowne zadanie.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Kazde szukanie slowa w tytulach bylo sekwencyjnym skanem 3,46 mln wierszy. Blokowalo
to ranking over-attribution: metryka "ile scen ma te nazwe w tytule, ale NIE jest do
niej przypisanych" wymaga jednego skanu NA KANDYDATA, a kandydatow jest ~800. Proba
zostala ubita po 10 minutach.
GIN + gin_trgm_ops obsluguje LIKE, ILIKE i regexy, a pg_trgm sam normalizuje wielkosc
liter, wiec indeks na surowym title wystarcza. Efekt: 26 ms zamiast sekund na
zapytanie, ranking 800 kandydatow w 48 sekund zamiast godzin. Indeks 315 MB.
Zbudowany CONCURRENTLY w autocommit_block: zwykle CREATE INDEX trzymaloby lock
blokujacy zapisy na scenes przez cala budowe i zatrzymalo ingest.
Ranking od razu pokazuje dwie rozne rzeczy. Czyste smieci ("Pornhub" 105.9, "Monster"
92, "Pretty" 63, "Nice" 42) oraz SAME NAZWISKA (Devine, Starr, Dior, Cruz, West,
Knight, Johnson, James) - wpisy powstale z rozbicia imienia i nazwiska, ktore potem
lapia kazda scene z tym nazwiskiem, nalezaca do zupelnie innej osoby.
Usuniete przy okazji: "Pornhub" (108 scen, 0 z kanonu, wszystkie to "full video on
pornhub") i "Precious" (119 scen, 0 z kanonu, sam przymiotnik).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ostatnia klasa smieci: REALNA osoba o nazwie bedacej pospolitym slowem, do ktorej
tube-search dokleja wszystko, co ma to slowo w tytule. Rapture miala 30 z 72
przypisan falszywych (film "The Rapture" z Mimi Rogers, literowka "hymen raptured",
tytuly scen).
NIE MA na to sygnalu automatycznego. Przetestowalem piec i zaden nie rozstrzyga:
- sama provenance ze scrapera: realni tworcy spoza TPDB (Amouranth, MollyRedWolf)
tez maja 100 procent przypisan ze scrapera
- obsada z kanonu na scenie: backfill 0026 wypelnil tylko sceny jednozrodlowe, wiec
sceny mieszane maja NULL - 1 trafienie na 560 tys.
- udzial nazwy w tytule: u niszowych prawdziwych tez ~100 procent (Amouranth 100,
Clanddi 100)
- obce sceny ze slowem: myli generyczne uzycie z pominieta atrybucja
- stosunek tag/performer >=1: wyklucza 79 pozycji, ale samej Rapture BY NIE ZLAPAL
Zostaje czytanie tytulow. Skrypt robi z tego kilka minut zamiast pol godziny: listuje
komplet z provenance i kontekstem, liczy wskaznik pospolitosci nazwy, przyjmuje liste
prefiksow do odpiecia i DOMYSLNIE nie rusza przypisan potwierdzonych przez kanon.
Bez trybu rankingu wszystkich kandydatow: bez indeksu trigramowego na scenes.title to
skan 3,4 mln tytulow RAZY ~800 kandydatow. Sprobowalem, ubilem po 10 minutach.
Przy okazji przeglad zdemaskowal "Precious" (119 scen, 0 z kanonu) - wszystkie
przypisania to przymiotnik ("precious stepdaughter", "her ass is precious"). Usuniete.
Skala reszty: 1335 kandydatow z >=20 scenami, 539 z >=100. Nie ma sensu przerabiac
wszystkich - narzedzie jest na zglaszane przypadki.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"A", "L", "Ro", "Be", "Js" mialy po 250-290 scen kazdy. To artefakty parsowania
tytulow przez tube-search, ale NIE wszystkie: "Cj", "PD" i "JD" to realne krotkie
pseudonimy z obsada potwierdzona w TPDB i StashDB, z prawdziwymi partnerami
scenicznymi (Cj z Lucy Belle i Denisem Martim, PD z Victoria Love).
Dlatego nie kasujemy tu performera, tylko przypisania, o ktorych WIEMY ze dokleil je
scraper. Reszta rozstrzyga sie sama: komu nic nie zostanie, ten znika. To pierwsze
uzycie provenance z migracji 0026 - bez niej nie dalo sie odroznic "Cj" z obsady
TPDB od "Cj" wylusknietego z tytulu.
Rozklad byl jednoznaczny: z 9404 przypisan 9232 (98,2 proc.) ze scrapera, 141 z
kanonu, 31 nieznanych. Wiersze z NULL-em zostawiamy, nie zgadujemy.
Wynik: 9232 przypisan zdjetych, 20 performerow zniknelo calkiem, 31 zostalo z sama
prawdziwa obsada (Cj 41, PD 38, JD 20, reszta <=10). Dopiete do joba junk_performers,
zeby nie odroslo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
scene_performers nie zapisywalo, KTO przypisal performera do sceny. Przez to nie dalo
sie odroznic obsady z kanonu od performera doklejonego przez tube-search, ktory
dopasowuje wynik po JEDNYM tokenie zapytania. Stad przypadek "Rapture": 30 z 72 jej
przypisan bylo falszywych (film "The Rapture" z Mimi Rogers, literowka "hymen
raptured", tytuly scen) i trzeba bylo je przegladac recznie, bo nie bylo sygnalu.
Kolumna trzyma NAJBARDZIEJ wiarygodne zrodlo, jakie przypisalo. Regula idzie tylko w
gore: NULL wypelnia cokolwiek, kanon nadpisuje scraper, scraper NIGDY nie zamazuje
kanonu. Inaczej dowolny pozniejszy tube-search zatarlby informacje, ze obsade
potwierdzilo TPDB. To samo przy merge_scenes: przy kolizji przenosimy lepsza
provenance na keepera, zeby scalanie nie degradowalo potwierdzonej obsady.
Backfill wypelnil 4 147 128 wierszy (96,3 procent) wnioskowaniem, ktore jest pewne:
scena z refami z DOKLADNIE jednego zrodla ma cala obsade stamtad. Sceny wielozrodlowe
(67 tys.) zostaja z NULL-em, bo tam zgadywanie zepsuloby sens kolumny. Wsadowo, z
commitem na paczke: pojedynczy UPDATE na 4 mln wierszy trzymalby locki na
scene_performers i zablokowal ingest.
Rozklad: tube-scraper 3 219 677, tpdb 747 540, stashdb 180 355.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Klasa "prawdziwy performer o pospolitej nazwie" okazala sie zawierac 211 rekordow,
ktore w ogole nie sa osobami, tylko kategoriami z refem kanonicznym: "Big Tits"
(931 scen), "Big Ass" (640), "Hardcore" (222), "Blonde" (238), "Masturbation".
TPDB i StashDB SAME zawieraja takie wpisy, wiec ref kanoniczny ich nie oczyszcza.
Kryterium promiskuitycznosci z poprzedniego commita tu NIE dziala i sprawdzenie tego
bylo kluczowe: w tej populacji obcy mierzy popularnosc, nie smieciowosc. Przy
wartosciach 50-59 stoja Adriana Chechik (4201 scen), Lauren Phillips, Jane Wilde i
Jordi El Nino Polla. Moja wczesniejsza walidacja progu 50 byla obciazona, bo grupa
bez refa to sami malo znani.
Rozstrzyga stosunek scen-z-tagiem do scen-performera, i to z uzasadnienia, nie z
probki: nazwisko uzyte jako wlasny tag daje stosunek ~1 Z DEFINICJI, bo tag siedzi
dokladnie na jej scenach. Potwierdzone na markach osobistych: Hotwifevictoria 1,02,
Rossmexicana 0,99, Sexwithmilfstella 0,87. Wielkie gwiazdy jeszcze nizej, maksimum
0,35 wsrod 921 pewnych osob. Kategorie: Hardcore 1720, Masturbation 1570, Blonde 770.
Prog 2 + wymog >=50 scen (ponizej stosunek jest szumem).
Skasowane 211 rekordow / ~32 tys. przypisan w dwoch przebiegach. Job idempotentny.
Ogon klasy jest zdrowy: z 8116 pozostalych 92% miesci sie ponizej 0,35.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>