Kazdy tube zapisuje tytul po swojemu ("[Milfy] Koda Monroe (...)", "Milfy 26 09 16 ...",
"... 4K"), a miniatury sa z innych klatek, wiec ani phash, ani title_duration_dedup
(identyczny tytul) ich nie lapaly. Jedna scena Milfy wisiala w katalogu 8 razy.
Nowy job porownuje rdzen tytulu w obrebie studia: bez nazwy studia, dat, znacznikow
jakosci i nazwisk obsady. Numery czesci zostaja ("Part 1" to nie "Part 2"). Straznicy:
dlugosc, data premiery, wspolna obsada, dluzszy rdzen gdy brak dlugosci. Kopie bez studia
dolaczaja tylko przy zgodnej co do 3 s dlugosci. Kategorie wpisane przez tube jako obsada
nie skracaja rdzenia. Cyklicznie co 12 h z oknem 30 dni.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Latka z 0.4.1 kopiowala mape sesji przed zwolnieniem playerow, ale sama kopia
tez iteruje mape, a wpisy znikaja z innego watku. Na LinkedHashMap wywalalo sie
wiec dalej, juz w toList() (Sentry GOON-6W, Redmi Note 8 Pro, Android 11).
Mapa jest teraz ConcurrentHashMap, iteracja przezyje rownolegle usuniecie.
versionCode 16 zeby posiadacze 0.4.0/0.4.1 dostali monit: runtime zostaje 1.4,
wiec sam numer kanalu ich nie rozrozni.
Sprawdzone na emulatorze: dwie sesje mediow zywe, zamkniecie z listy ostatnich
zwalnia obie, pusty bufor crashy.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Agregat po 4,1 mln zywych zrodel trwa 0,6-2 s, a cache wygasal co 5 minut, wiec co
wygasniecie ktos placil pelnym czasem (Sentry Slow DB Query list_sources, 186 zdarzen,
ostatnie dzisiaj). Teraz po wygasnieciu oddajemy stary wynik i przeliczamy w watku w tle,
a TTL idzie z 5 do 15 minut. Liczby zmieniaja sie o promile na godzine.
Pomiar na prodzie: pierwsze wejscie po restarcie 2,1 s (nieuniknione), potem 11-15 ms,
a wejscie tuz po wygasnieciu 38 ms zamiast pelnego przeliczenia.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Prosba z apki 2026-09-16 („make a tv app of this"). Tania wersja: to samo APK,
zeby dalo sie je zainstalowac, znalezc w launcherze telewizora i obslugiwac pilotem
w istniejacym interfejsie. Pelnego interfejsu 10-stopowego (podswietlenie fokusu,
wieksze napisy, obejscie WebView przy hosterach) to NIE daje.
- uses-feature leanback i touchscreen jako NIEwymagane, plus jawne
screen.portrait=false: blokada pionu sama z siebie dokladala WYMAGANIE ekranu
pionowego i telewizor uznawal apke za niezgodna
- osobne wejscie TvMainActivity z LEANBACK_LAUNCHER, bez blokady pionu
(na telefonie nic sie nie zmienia, launcher TV pyta tylko o leanback)
- banner 320x180 w res/drawable (res/drawable-*/ jest w .gitignore)
Dwie slepe uliczki, stad osobna klasa: `setRequestedOrientation` w onCreate to zmiana
konfiguracji, wiec system relaunchowal aktywnosc i na TV zostawal bialy ekran (widok
Reacta nie wracal); orientacja z values-television nie przechodzi, bo manifest czyta
zasoby bez konfiguracji (lint ManifestResource).
Sprawdzone na emulatorze android-34 android-tv (1920x1080): apka jest na liscie
leanback launchera, startuje na caly ekran poziomo, a pilotem da sie przejsc bramke
wieku (fokus chodzi po elementach, CENTER zaznacza), pominac samouczek i przewijac
siatke scen. Odtwarzania na TV nie testowalem, emulator ma software'owe kodeki.
Wersji APK nie ruszam, zmiana pojedzie z najblizszym wydaniem.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zgloszenia z apki:
- „random filter on and searching titles shows few results": przy sort=random braliśmy
okno 2000 kolejnych id (0,05% katalogu) i dopiero na nim nakladalismy filtry, wiec
szukanie w losowej kolejnosci trafialo na garstke scen. Teraz przy aktywnym filtrze
(szukanie, tag, obsada, studio, strona, jakosc, data, dlugosc) losujemy WYNIKI:
md5(id + seed) nad pula do 5000 wynikow filtra. Okno po PK zostaje tylko dla listy
bez filtra, gdzie chronilo przed skanem 2,3 mln wierszy.
- „clicking install does nothing": pobieranie 87 MB szlo bez zadnego sladu w UI. Teraz
nakladka z kreceleem na czas pobierania, „Download" obok „Install" w monicie i link
do pliku w komunikacie bledu (na repo git APK nie ma, user szukal go tam).
Sprawdzone: szukanie „massage" z sort=random daje pelne strony (50 + kolejna), ten sam
seed powtarza kolejnosc, strony sie nie nakladaja, inny seed inna kolejnosc; czasy 120-800
ms (tag anal 1,1 s), lista bez filtra bez zmian. Na emulatorze pelna sciezka aktualizacji
z 0.4.0: monit z trzema przyciskami, Install, pobieranie, systemowy dialog, versionCode 15.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zgloszenie Jana (fold): rozlozony ekran jest prawie kwadratowy, a klip byl skalowany do
wypelnienia i zostawal z niego srodek. Teraz liczymy, ile by sie ucielo: do 30 % zostaje
wypelnienie (pionowy klip na zwyklym telefonie traci ok. 20 % szerokosci i to jest OK),
powyzej cale wideo i czarne pasy. Podpis i kolumna przyciskow stoja przy krawedziach
ekranu, wiec przy pasach same wchodza na pasy zamiast na wideo. Poster pod wideo dostaje
to samo kadrowanie, zeby nie mrugalo przy starcie.
Zysk takze na zwyklym telefonie: ok. 19 % klipow RedGifs jest poziomych i do tej pory byly
rozdmuchane na caly ekran.
Zmierzone na emulatorze przez rozmiar powierzchni wideo (dumpsys activity top):
- telefon 1080x2400: pionowy klip 1242x2209 (wypelnienie, jak dotad), poziomy 1080x607
i klip 3:4 1080x1440 (pasy zamiast kadrowania)
- rozlozony fold 1768x2208: pionowy klip 1140x1947 z pasami po 314 px, poziomy 1768x1298
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zgloszenia Jana 2026-09-16:
1+3. Tapniecie serduszka przelaczalo dzwiek i przewijalo klip na poczatek. Gesty lapala
cala komorka razem z przyciskami, wiec tap w serduszko byl tez tapem w ekran, a zmiana
dzwieku restartowala odtwarzanie (efekt aktywacji strony mial soundOn w zaleznosciach).
Teraz gesty lapie tylko warstwa wideo, a wyciszenie ma osobny efekt.
2. Dwa przyciski dzwieku. Zostaje ten w kolumnie przy kciuku, w gornym pasku wchodzi stroik.
4. Za malo tagow na starcie: bylo 24 z 40, „anal" (27. co do liczby klipow) wypadal.
Teraz 60 tagow + nisze + szukanie po calym slowniku (1,7 tys. tagow, nowy param q),
wskazanie wazy 8 zamiast 5, a stroik mozna otworzyc w kazdej chwili i zmiana dziala
od nastepnego rozdania.
5. Losowe miganie przy przewijaniu: dociagniecie kolejnej strony feedu podmienialo tablice
klipow i restartowalo biezacy klip. Efekt zalezy teraz od numeru strony i adresow wideo.
Sprawdzone na emulatorze: tap w serduszko zostawia wyciszenie bez zmian i zapisuje like,
przycisk dzwieku odcisza, gorny pasek otwiera stroik, szukanie „anal" daje 8 wariantow,
a po Apply w clip_affinity siedzi anal=8.0. Edge dalej odklada zdarzenia w clip_feed_events.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Regula sklejki sasiednich czlonow (JoannaAngel, Bonnieb) nie byla pilnowana na
granicy obsady: przy martwym separatorze "Dickft" i "Paigefeat" wychodzily jako
trafienia. Trzy przypadki, ktore na starym regexie daly True, a teraz daja False.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tapniecie nazwy tworcy otwiera jego strone: siatka wszystkich klipow, a tapniecie
kafelka gra je na pelnym ekranie z tym samym przewijaniem w pionie co Edge.
Zgloszenie z apki 2026-09-15: "cannot tap username as it's hidden behind icon tray".
- ClipPager: pionowy pager z dwoma playerami wyjety ze SwipeScreen, wspolny dla Edge
i strony tworcy; feed, telemetria i autoSwipe zostaly w ekranach
- /clips?creator= oddaje `total` (liczba klipow tworcy) do naglowka
- ze strony tworcy leca tylko like/unlike i "nie interesuje": ogladanie stad nie moze
zabetonowac feedu na jednym tworcy
Sprawdzone na emulatorze: link z Edge otwiera strone (@lilylovesyou2, 2 clips, verified),
kafelki trzymaja trzecia szerokosci takze w niepelnym rzedzie, pelny ekran gra i zamyka
sie przyciskiem pod paskiem stanu, a Edge dalej odklada zdarzenia w clip_feed_events.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0.4.0 i 0.4.1 maja ten sam runtime 1.4, a monit porownywal tylko runtime, wiec nikt
z 0.4.0 nie dostal propozycji aktualizacji i crash expo-video przy zamykaniu z ostatnich
wracal do Sentry dzien po poprawce (147164135).
- /version oddaje apk_build (versionCode 15)
- aplikacja czyta versionCode ZAINSTALOWANEGO APK przez natywny modul Sentry
(expo-constants w SDK 52 nie oddaje go wcale, expo-application wymagalby nowego APK)
- numer builda trafia tez do kontekstu zgloszen z apki: app_version jedzie z paczka OTA,
wiec nie mowil, ktore wydanie natywne ma zglaszajacy
Sprawdzone na emulatorze: 0.4.1 nie dostaje monitu i raportuje build=15, po instalacji
0.4.0 monit "Update available" pokazuje sie przy starcie.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Trzy zmiany wokol listy scen z filtrem originu, gdzie kandydatow sa dziesiatki tysiecy.
1. Kolejnosc czlonow OR w stub_exclusion_clause. Postgres liczy OR po kolei i przerywa na
pierwszym trafieniu, a sam czlonow nie przestawia. "Ma kanon" (jedyny czlon z JOIN-em do
sources) stal przed tanszym "ma performera", wiec placilismy za niego takze za sceny,
ktore performera mialy. Po zamianie ten czlon liczy sie 5146 razy zamiast 16 191.
2. Indeks scene_external_refs (scene_id, source_id), migracja 0041. Podzapytanie "ma
kanon" dociagalo source_id z heapu, bo stary indeks zna tylko scene_id. Teraz idzie
Index Only Scanem: Heap Fetches 16 191 -> 1241.
Razem: sort=title + origin=hqporner, strona 5 czyta 251 tys. blokow zamiast 294 tys.,
a na rozgrzanym cache trwa 305 ms zamiast 371 ms (mediana z 3 rund z rotowana
kolejnoscia). Zysk jest skromny. Pierwsze wykonanie na zimnym cache trwa 3-5 s i tak
zostaje, bo trzeba dotknac ~2 GB; sprawdzilem tez wariant z materializacja scen originu
i CTE, czyta wiecej blokow (302 tys.), wiec obecny plan zostaje.
3. has_playback=false RAZEM z filtrem originu to warunek sprzeczny, bo origin wymaga
zrodla z dead_at IS NULL. Wynik jest pusty z definicji, ale Postgres przemielal caly
katalog, zeby to stwierdzic: 148 s. Teraz zwarte na false(), 4,8 ms, dalej zero wynikow.
Przy has_playback=true z originem pomijamy z kolei nadmiarowe EXISTS o zywym playbacku,
bo origin sam go wymaga, a kosztowalo sonde na kazdym kandydacie.
Wyniki bez zmian: strony 1-5 dla origin=hqporner i dla glownego feedu porownane pozycja
po pozycji ze stara wersja daja zero roznic, a sam predykat stub zgadza sie na probce
200 tys. scen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ix_scenes_title_created_id_desc zaczyna sie od tej samej kolumny, wiec obsluguje wszystko,
co obslugiwal stary indeks: lookupy `title_normalized = X` z resolvera i skan zakresu przy
sortowaniu po tytule. Trzymanie obu to 367 MB na dysku i jeden indeks wiecej do utrzymania
przy kazdym zapisie do scenes, a ingest pisze tam caly czas.
Sprawdzone na produkcji przez BEGIN; DROP INDEX; EXPLAIN ANALYZE; ROLLBACK, zeby zobaczyc
wybor planera bez starego indeksu, a potem jeszcze raz po samym dropie:
exact title lookup 1,76 ms -> 0,07 ms, Index Scan po nowym indeksie
OR studio + exact title ten sam ksztalt planu (BitmapOr), 3,7 ms
OR data + exact title Seq Scan przy szerokim oknie dat, ale to decyzja o release_date:
z enable_seqscan=off BitmapOr siega po nowy indeks
trgm ILIKE bez zmian, swoj indeks GIN
W wariancie z OR planer i tak siegal juz po nowy indeks, jeszcze zanim stary znikl.
Indeksy scenes: 3544 MB -> 3177 MB. Listy scen po dropie bez zmian (tytul 22-54 ms,
studio 38-73 ms na stronach 1-5).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Obie listy chodzily na produkcji w dziesiatkach sekund, bo klucz sortu nie mial nic
wspolnego z filtrami widocznosci (zywy playback, odsiew wertykalow, odsiew stubow).
sort=studio: nazwa studia siedzi w dolaczonej tabeli, wiec zaden indeks scen jej nie
zna i planer materializowal caly przefiltrowany katalog (ponad 2 mln wierszy), po czym
sortowal go w calosci. Odwracamy zapytanie: idziemy po studiach w kolejnosci nazwy i dla
kazdego dobieramy jego sceny przez LATERAL po ix_scenes_studio_effective_date_desc.
Zewnetrzny skan jest posortowany, wiec LIMIT urywa go po kilkunastu studiach. Sceny bez
studia dobiera osobny ogon, tak jak wczesniej robilo NULLS LAST. Przy filtrze po studiach
zawezamy tez sam skan studiow, inaczej szedlby przez wszystkie 33 tys.
sort=title: nowy indeks na cale ORDER BY (title_normalized, created_at DESC, id DESC).
Sam title_normalized zostawial Incremental Sort, a ten przed oddaniem pierwszego wiersza
musi zebrac caly kubelek scen o tym samym tytule.
Pomiary na produkcji (2026-09-16, ten sam zestaw filtrow, po rozgrzewce):
studio strona 1 483 s -> 41 ms
studio strona 5 ponad 5 min -> 38 ms
studio + tag blowjob 71 s -> 226 ms
studio + min_duration 48 s -> 42 ms
studio + studio_slugs 255 ms -> 44 ms
tytul strona 1 709 ms -> 12 ms (81 wpisow indeksu zamiast 3064)
tytul + tag blowjob ponad 90 s -> 1,5 s
Wynik jest identyczny co do wiersza: pierwsze 251 pozycji pelnego katalogu porownane
pozycja po pozycji ze starym zapytaniem daje zero roznic, tak samo dwa okna alfabetyczne
studiow (w tym Brazzers, zeby sprawdzic wewnetrzny LIMIT).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
W _PERSON_SEPARATOR_RE zamiast \b staly doslowne znaki 0x08 (heredoc przy
commicie b7a8911), wiec tytul nigdy nie byl ciety na feat/ft. Regex uzywa
teraz prawdziwych granic slowa, lapie tez "featuring", a myslniki podaje
jako escape zamiast doslownych znakow.
Skutek w danych sprawdzony na prodzie: 255 701 przypisan na scenach z
sxyprn, 6530 tytulow z feat/ft, stara i nowa regula roznia sie w 0
przypadkach, bo sam czlon feat/ft i tak przerywal sasiedztwo nazwiska.
Poprawka zamyka przypadki brzegowe (smieciowy performer "Feat").
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Opisy scen szly do bazy z `"`, `<br>` i surowymi `<br />`, a apka i strona
SEO pokazuja opis jako tekst, wiec bylo to widac doslownie. clean_description
dekoduje encje, `<br>` i koniec akapitu zamienia na nowa linie, a znane znaczniki
wycina (`<3` zostaje tekstem). Wpiete w normalize_scene i normalize_movie.
bulk_rescrape_hqporner.py i repair_truncated_titles.py liczyly title_normalized
jako lower(title), przez co 6005 scen mialo interpunkcje w kluczu dopasowania.
Oba licza teraz normalize() i dekoduja encje w tytule.
Skrypty: fix_html_entity_titles.py przemianowany na fix_html_entities.py z
przebiegiem po opisach; nowy fix_title_normalized.py przelicza klucz tam, gdzie
rozjechal sie z normalize(title).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
xvideos (JSON-LD) i kilka innych tubow oddaje tytuly z encjami HTML5
(`we're`, `(AI)`), czasem podwojnie zakodowane. normalize
robil z nich slowa `apos`, `lpar`, wiec tytul nie trafial w wyszukiwarke
ani w kanon.
unescape_html w app/normalize/text.py dekoduje encje zakonczone srednikiem
po slowniku HTML5, do skutku (max 3 przebiegi). Wpiete w normalize_scene i
normalize_movie oraz w parsery xvideos_browse i pornxp. Skrypt
fix_html_entity_titles.py poprawia istniejace wiersze (title,
title_normalized, slug gdy byl wyliczony z tytulu).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- SegmentTabs w ui.tsx: zakladki w wierszu narzedzi obok ikon
- Ulubione, performerka, studio, Performers i Tags: jeden wiersz pod naglowkiem
zamiast trzech-czterech (etykieta z licznikiem, zakladki, podpowiedz, sortowanie)
- gwiazdka na ekranie performerki i studia bierze /favorites?counts=false
- Edge: kolejny klip chowa pasek, cofniecie pokazuje; podpis, przyciski i postep
jada razem z paskiem; FAB zgloszen ukryty, lezal na "Not interested"
- changelog 2026-09-15c/d
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- /favorites i /favorites/studios: liczniki w cache procesu (swiezy 5 min, potem
odswiezanie w tle), mark_seen zeruje od razu; parametr counts=false dla ekranow,
ktore chca tylko stan gwiazdki
- licznik studiow idzie indeksem ix_scenes_studio_effective_date_desc (migracja 0038)
i konczy po 200 scenach na studio: 10-25 s -> kilkanascie ms
- okno licznika sortuje tak jak lista (data premiery albo dzien dodania), wczesniej
rozjechane od 0033
- similar_scenes: pula z 4 najrzadszych tagow zamiast grupowania po wszystkich
(do 5 s -> ponizej 0,4 s)
- enrich-tags: tagi jednym zapytaniem po slugach i jeden INSERT
- /scene-favorites: serializer wsadowy
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- expo-file-system jako jawna zaleznosc: zagniezdzony pod expo nie byl autolinkowany,
ExpoAsset.downloadAsync padal na AppDirectories not found (Sentry 143555436)
- app/build.gradle: create*UpdatesResources zawsze generowane; zadanie mialo same napisy
jako wejscia i od 2026-05-31 osadzalo stary app.manifest (23 assety, bez fontu ikon)
- patch-package + patches/expo-video+2.0.6.patch: cleanup() iteruje po kopii mediaSessions
(ConcurrentModificationException w onTaskRemoved, Sentry 147164135)
- versionCode 15 / 0.4.1, runtime bez zmian (1.4), /version 0.4.1, linki na stronie
Test: czysta instalacja offline na emulatorze, 0.4.0 = 0 glifow ikon + blad w Sentry,
0.4.1 = 11 glifow i brak bledu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- /watch/recent: _build_scenes_out_batch(light) zamiast 5-7 zapytan na scene (N+1 w Sentry)
- /scenes?origin=tube❌ rownosc zamiast ILIKE '%...%', 4,6 s -> 1,1 s na hdporngg z q
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nazwa od edgingu: feed krotkich klipow bez konca (wybor Jana). W kodzie zostaje
Swipe (SwipeScreen, swipeTelemetry), etykieta i teksty user-facing to Edge.
Backend /version podaje 0.4.0 / 1.4, wiec starsze APK dostaja monit o nowej
wersji; plik app-release.apk podmieniany razem z publikacja.
Nowa zakladka w dolnym pasku: react-native-pager-view (pion, natywny snap), dwie
instancje createVideoPlayer (aktywna + nastepna w buforze), komorka z posterem,
podpisem tworcy i tagami, kolumna przyciskow, pasek postepu. Gesty bez reanimated:
tap = dzwiek, double-tap = ulubione z wybuchem serca i haptyka, przytrzymanie = 2x,
przesuniecie w lewo = arkusz "show less of this" (tworca / tagi / nisze / seen it,
plus blokada tworcy). Onboarding 3 tapow z top tagow, AutoSwipe (off/5/10 s),
licznik obejrzanych, nowe rozdanie.
Telemetria: SwipeTelemetry zbiera zdarzenia i wysyla paczki co 5 s / 10 zdarzen /
w tle; przy opuszczeniu strony impression z dwell, skip (<2 s) albo complete (petla
lub >=80%). Serwer z tego uczy wagi i uklada 80% nastepnych stron.
Pager to modul natywny, wiec import jest miekki (require w try/catch) i zakladka
pokazuje sie tylko od runtime 1.4; ten sam bundle leci OTA na 1.2/1.3 z wpisem
"pobierz 0.4.0" (onlyBelowRuntime), a wpis o Swipe ma nowe pole minRuntime.
Bump: app.json 0.4.0 / runtime 1.4, versionCode 14, AndroidManifest 1.4,
publish_update RUNTIME_DEFAULT 1.4, strona goon-foss.org pod 0.4.0.
Sprawdzone na emulatorze (APK 0.4.0): zakladka widoczna, onboarding zapisany na
serwerze, feed spersonalizowany 8/2, ExoPlayer dekoduje wideo i audio, swipe daje
zdarzenia complete/impression, double-tap daje like + ulubione + wagi.
Strona feedu spadla z 310-470 ms do 50-130 ms (srednio 85 ms na 30 stronach,
0 powtorek). Postgres nie ma max(uuid): koniec okna liczony po rzutowaniu na
tekst (ten sam porzadek dla malych hex w stalym formacie).
Pierwszy backfill po niszach przy ~3 zapytaniach/s po ~65 zapytaniach wpadl
w trwale 429 (cialo: delay 1167 s, subject per IP i endpoint) i przemielil
40 kolejnych nisz w bledach. Teraz: 1/s, odstep z Retry-After albo
error.delay, powyzej 5 min RateLimited i koniec przebiegu (wznowienie --skip).
Nowy wertykal krotkich pionowych klipow tworcow, osobno od scen: inne kolumny
(tworca, audio, lajki, nisze), inny cykl zycia, inna taksonomia, brak filtra
60 s. Tabele `clips` (unikalne source+source_id) i `clip_tags` z indeksem
(tag, clip_id) pod skan po tagu od losowego uuid w przyszlym feedzie.
Zrodlo nr 1: RedGifs, oficjalne API v2 z tokenem tymczasowym (zwiazany z IP
i UA, na 401 odnowienie). Globalne `order=latest` bez search_text daje ~100
na strone, kazde zapytanie widzi maks. 10 000 wynikow, wiec katalog chodzi
sie po niszach (skrypt backfillu). Pliki media.redgifs.com sa publiczne i bez
podpisu (206 z VPS-a i z telefonu), do bazy wchodzi gotowy adres.
Scheduler: job clips-latest co godzine (5 stron), zatrzymuje sie na stronie
bez nowych. Reaper (HEAD, 403/404/410 -> dead_at) jako skrypt, upsert
odzywia klip, ktory zrodlo znow podaje. API: GET /clips i /clips/stats do
pilota; wlasciwy feed, pamiec widzianych i telemetria to etap 3.
Sprawdzone tego dnia i odlozone: nsfwswipe (lustro v.redd.it, bez audio,
stoi od 19.08), Pornhub Shorties (zrodlo nr 2, HLS z tokenem 2 h, Referer
na segmentach, 0/110 performerow z kanonu).
- DOOD_OVERLAY_JS (injectedJavaScript po zaladowaniu): fixed + z-index > 100000 bez
Cloudflare -> pointer-events none, iframe sandbox/srcdoc usuwany; co 700 ms
- diagnoza devtools: pelnoekranowy div opacity 0.01 z z 2147463647, iframe reklamowy i
pusty kwadrat 80x80 dokladnie na przycisku play; popunder u nas zablokowany, wiec
warstwa nigdy nie znikala (zgloszenia e9fc12e8, 1278eb49)
- changelog 2026-09-14c, OTA 69b27e52 na 1.3
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- random: md5(seed) -> uuid startu, okno 2000 id (8000 dla wertykalow) po pk_scenes,
filtry na oknie; bez okna planer robil Merge Anti Join po 2,3 mln wierszy (7,6 s)
- duration_desc/asc: bez NULL, do 10 h, indeks ix_scenes_duration (migracja 0035)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- ScenesFilterModal: Reset all filters stosuje domyslne i zamyka arkusz (f5193fba)
- ScenesScreen: has_playback domyslnie wlaczone nie liczy sie jako filtr, za to sort,
min. dlugosc, min. jakosc i stuby tak
- MovieFiltersSheet: rok poza 1900..2100 ignorowany zamiast 422 (2b6dbc75)
- changelog 2026-09-14a, OTA 6cca22ce na 1.3
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- _search_base: hak _thumbnail_map (mapa url -> miniatura z calej strony) przed
szukaniem <img> w oknie tekstu; xhamster mial 54% zrodel bez miniatury
- mypornerleak search: karty maja teraz src zamiast data-src; browse (REST) bez
featured media -> og:image ze strony posta
- scripts/backfill_thumbs.py: uzupelnia miniatury ze strony sceny, od najnowszych
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- screenOptions: tlo ekranu, bez cienia, tytul 17 display, tint accentText
- HeaderIconButton (star/star-outline, eye-off-outline) na 5 ekranach zamiast ★/🚫
- BottomTabsBar: 76 dp, pierscien statyczny w iconBox w spoczynku, kapsula tylko w
trakcie przejscia, srodki zaokraglone do piksela
- changelog 2026-09-08b/c, OTA 1cbb9181 i 18ba425a na 1.3
- WebView: przed pierwszym onLoadEnd kazda nawigacja top-frame to lancuch redirectow
serwera, nie popunder; po zaladowaniu przeskoki w obrebie rodziny DoodStream tez OK
- SiteScenes: wyszukiwarka w obrebie strony + ikona tagow z licznikiem + X
- PerformerScenes: licznik scen + ikony szukaj-wiecej/filtr w jednym wierszu, chipsy
top-tagow wyciete (tagi sa w filtrze), zbedne zapytanie performer-tags usuniete
- changelog 2026-09-07h, OTA 49cda698 na 1.3
- scripts/site_icons.py: apple-touch-icon / icon / favicon.ico, PIL do 64x64 PNG,
proxy Bright Data w odwodzie, mapa domen dla sitetagow bez TLD
- /sources: icon_url gdy plik istnieje (BACKEND_PUBLIC_URL albo wzgledne)
- SitesScreen: SiteLogo z literowym fallbackiem, SortSheet (most scenes, recently
updated, best rated, name) zapamietany w SecureStore, koniec wiersza Top/Recent
- changelog 2026-09-07g, OTA 1e90f427 na 1.3
- useAutoHideOnScroll: licznik drogi w jednym kierunku (48 px w dol chowa, 24 w gore
pokazuje), strefy zawsze-widoczny przy gorze i dole listy, overscroll ignorowany
- HomeScreen useFocusEffect pokazuje pasek po powrocie z ekranu szczegolow
- changelog 2026-09-07e/f, OTA 40931479 i 8604dadb na 1.3
- lib/bottomBar.ts: stale paska, szyna scroll-top, wartosc Animated do chowania
(hysteresis po przebytej drodze, strefy gora/dol), inset dla list
- BottomTabsBar: absolute nad trescia, translateY z native drivera, null przy klawiaturze
- Scenes: Performers/Tags/Favorites jako IconButton obok lejka i zebatki, chipsy
zapisanych wyszukiwan tylko przy fokusie albo wpisanym tekscie, Save jako chip
- changelog 2026-09-07d, OTA 3f7e21c5 na 1.3
- pasek dolny nizszy (62) i przyciety na krawedzi ekranu, zaokraglone tylko gorne rogi
- IconButton (filter-variant z licznikiem) zamiast pigulki Filter, SettingsButton w
wierszu narzedzi Scenes/Movies/Sites
- ustawienia: sekcje Support the project i Backend (host + wylogowanie), tytul Settings
- changelog 2026-09-07c, OTA 5c8895d6 na 1.3
- BottomTabsBar: pigulka nad krawedzia, aktywna ikona w pierscieniu; przy zmianie
przednia krawedz wystrzela, tylna dogania (kapsula od starej do nowej), jeden
kolor accentText z miekka poswiata zamiast neonu z reela
- naglowek: nazwa sekcji obok logo zamiast gornego paska
- BugReportFAB wisi nad paskiem na ekranie-gospodarzu
- changelog 2026-09-07b, OTA a2328005 na 1.3
Nowe strony wchodza po stronie backendu, wiec bez publish OTA uzytkownik nie
dostaje popupu What's new (changelog jedzie w bundlu). Sam wpis, bez zmian w
kodzie apki.
tubepornclassic.com to SPA sieci TXXX (ten sam silnik co vjav): HTML ma pusty
<title> i zero linkow do scen, wszystko idzie z JSON API. Listing
/api/json/videos2/<cache>/str/latest-updates/60/..<page>.all...json oddaje
60 rekordow z pelnymi metadanymi (tytul, slug, dlugosc, post_date, obsada,
kategorie+tagi, miniatura), wiec nie ma fetchu per scena. ~168 tys. wideo,
wgrania codziennie. Koniec katalogu = 200 z code=videos_not_found.
Stream: videofile.php -> dekod video_url -> get_file -> f=video.m3u8 -> HLS
na ahcdn (klucz time-bound, nie IP-bound: adres wybity z VPS gra z lacza
domowego). Ten tor zyl dotad w tubes/vjav.py; wyniesiony do
_txxx.extract_hls, vjav i tubepornclassic wolaja to samo. HLS zamiast mp4,
bo mp4 z tego samego get_file ma w URL CDN speed=... (~1,2 MB/s), a segmenty
HLS leca ~3,6 MB/s. Wyzwanie 429 (ciasteczko w ciele) obsluzone w
ekstraktorze, scraperze i juz wczesniej w /proxy/hls.
Bramka: 38% tytulow to generator SEO ("Fabulous Sex Movie Vintage Try To
Watch For Ever Seen"). Z doczepionym nazwiskiem scena jest odnajdywalna
i zostaje; bez obsady (22%) nie wchodzi, bo nie ma po czym jej znalezc
ani z czym zdeduplikowac. Obsada u 46% scen, studiow brak.
Pilot: 2 strony, 120 scen, 111 nowych, 9 juz w bazie, wszystkie z dlugoscia.
Odtworzenie na emulatorze: playback_events success (ttff 3,3 s), AudioTrack
started. vjav po refaktorze: ten sam wynik ekstraktora co przed.
Z szesciu stron z listy piec juz jest lub bylo w bazie: fullmovies.xxx,
hdporn.gg, neporn.com sa zywe (ingest z dzisiaj, odtwarzanie 84-99%),
a hqfap.com i 4k69.com nadal oddaja Cloudflare JS-challenge na podstronach
(403 "Just a moment" takze z lacza domowego, wiec to nie blokada po IP).
Jedyna nowa to porndupe.
Porndupe wyglada jak KVS, ale to atrapa: kazdy get_stream/<id>-<q>.mp4?md5=
odpowiada doslownie "error" (sprawdzone z sesja, Refererem strony i embedu,
z permutacja md5 kodem licencyjnym). Prawdziwy tor widac w DevTools:
generate_mp4('<b64 JSON>', '<haslo>', '<okid>', '<id>')
-> {ciphertext, iv, salt, iterations: 999}
-> PBKDF2-SHA512 + AES-256-CBC -> klucz sesji OK.ru (staly; haslo i
ladunek zmieniaja sie co wczytanie, to zaciemnienie)
-> api.ok.ru/fb.do method=video.get -> url_low/medium/high/fullhd,
duration (ms), created_ms, thumbnail_url
Wariant PBKDF2 ustalony empirycznie: SHA-1/SHA-256 daja bad decrypt,
SHA-512 oddaje dokladnie klucz z trace'u.
okcdn: srcIp wbite w URL, NIE egzekwowane (URL z lacza domowego pobrany
z VPS -> 206, 514 MB, ftypisom) -> mobile_direct_ok. Cap 720p, bo OK.ru
dlawi polaczenie do ~2,1 Mbps (decyzja z 4k69/8kporner).
Browse po id (vjav pattern): kazdy listing to catch-all z tymi samymi 24
linkami, sitemapy pokrywaja 3500 z 12 887 id. /video/<id>/ -> 301 slug
(istnieje) albo 302 / (brak). Dlugosc z api.ok.ru przy ingescie (HTML nie
ma duration ani uploadDate). Daty CELOWO nie: created_ms to dwie fale
hurtowego wgrania (07.2024, 04.2025), nie premiery.
Katalog ZAMROZONY od kwietnia 2025, wiec to jednorazowy import, nie zrodlo
swiezosci. Wchodzi, bo 87% scen (52/60) nie mamy, a to tresc studyjna
(Nubile Films, NF Busty, Family Strokes) trafiajaca w kanon, w odroznieniu
od hentaicloud (17%). Pilot crawl_page(1): 22/22 z dlugoscia, 21/22 z
performerem, studia i tagi per-video.
Blad diagnostyczny po drodze: strona blankuje sie do about:blank po wykryciu
CDP (disable-devtool z jsdelivr); trace przezyl, DOM nie.
Zgloszenia "Playmogo nie dziala tutaj" (1278eb49, 2026-09-04) i seria
"Myvidplay nie dziala" (3b75cb54, d3af0813, 11d7b17b). myvidplay to 301
na playmogo, a playmogo to klon DoodStream z KLIKANYM Turnstile: widzet
pojawia sie po tapie w play i przeladowaniu, wiec pass_md5 nie ma w HTML
i telefon nie rozwiaze tego sam. Telemetria: ZERO zdarzen odtwarzania
w 30 dniach (droga WebView nic nie raportuje), gdy mixdrop/voe/luluvid/
vidara graja w ~99%.
Przyczyna kolejnosci: _movie_origin_priority dawal tym originom neutralne
500, wiec sortowaly sie z dzialajacymi po created_at DESC, a doply/playmogo
bywaja dopisane jako OSTATNIE -> ladowaly na GORZE "Watch on". Zgloszony
film 12e9d0c1 mial obok zywy mixdrop.
Pomiar 2026-09-05: rodzina siedzi w 54 446 filmach, 54 320 (99,8%) ma
dzialajaca alternatywe, tylko 126 zalezy od niej wylacznie. Nowy tier 800
(za neutralnymi 500, przed martwa rodzina seekplayer 900): dla tych 126
zostaje jako ostatnia deska ratunku, wiec nikomu nie zabiera dostepu.
Weryfikacja po deployu: film 12e9d0c1 -> [mangoporn:mixdrop, mangoporn:playmogo].
- person_named_in: jednowyrazowe nazwisko tylko co do znaku (albo zlepek sasiednich
czlonow tytulu), przedrostek co najwyzej o 2 znaki; "Thebdck" lapal kazde "the"
- sxyprn: autor z sciezki miniatury, _BLOCKED_AUTHORS (Shizuka, Ajx, Denzel),
karty z >20 hashtagami wchodza bez tagow
- scripts/sxyprn_purge_uploaders.py: dry-run/apply, sceny tych autorow + smieciowi performerzy