Commit graph

110 commits

Author SHA1 Message Date
goon-foss
a872fc3a88 fix(perverzija): manifest HLS z AES-128 skladany w /proxy/hls, proxy bez gzip, porndoe poza alarmem, skrypt dlugosci porntrex
Some checks are pending
Backend tests / test (push) Waiting to run
- xtremestream od 12.10 szyfruje segmenty (AES-128-CBC, IV = numer segmentu, klucz spod
  tokenu zwiazanego z IP i UA): producent manifestu bierze xs1.php, przepisuje sciezki
  na _enc i dokleja EXT-X-KEY; klucz oddaje /proxy/hls/<token>/key.bin na wlasny token
- proxy: Accept-Encoding identity (skompresowany manifest bez naglowka konczyl na
  "Input does not start with the #EXTM3U header"), play.m3u8 z nazwy pliku jako manifest
- ingest_watchdog: porndoe jako zrodlo zamrozone (nowe sceny przekierowuja z kazdego IP)
- scripts/porntrex_duration_walk.py: dlugosci z listingu /latest-updates/N/, z dry-run
2026-10-14 14:57:29 +02:00
goon-foss
88f8729840 feat(survey): jednorazowa ankieta in-app (6 pytan), endpointy i podsumowanie
- backend: tabela survey_responses (0055), GET /survey/current z bramka po obejrzanych
  scenach, POST /survey/{id} (upsert per urzadzenie), GET /survey/{id}/summary
- apka: SurveyModal po tutorialu i po "What's new" (popupBus), raz na urzadzenie,
  pomijalna, flaga w SecureStore; wpis w changelogu
2026-10-12 17:34:19 +02:00
goon-foss
cd34b296e2 fix(performers): szukanie po aliasach i w odwrotnej kolejnosci slow
Zgloszenie 436121fb: "Takase Rina" (japonska kolejnosc) nie znajdowalo
"Rina Takase" (15 scen) i wygladalo, jakby jej nie bylo. Wyszukiwanie
patrzy teraz na podciag nazwy albo aliasu, dla dwoch slow tez w odwrotnej
kolejnosci; trafienia w nazwie ida przed trafieniami tylko w aliasie.
Obie kolumny maja indeksy trigramowe, 0,2 do 1,1 s w sandboksie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:56:59 +02:00
goon-foss
6540d4a009 feat(blacklist): ukrywanie stron per urzadzenie
Zgloszenie 3910b19b: brak przycisku ukrywania stron. Tabela hidden_sites
(0054), POST/DELETE /blacklist/sites/{origin}, pole sites w GET /blacklist.
Scena znika z list tylko gdy wszystkie jej zywe zrodla sa z ukrytych stron
(ta sama scena z innego serwisu zostaje); w szczegolach sceny przyciski
ukrytych stron znikaja, o ile zostaje inne zrodlo.

Cache pustosci blacklist trzyma teraz, ktore listy sa niepuste, wiec ukryte
strony nie doklejaja trzech pustych NOT EXISTS, i jest czyszczony przy kazdej
zmianie (wczesniej pierwszy wpis dzialal po 5 minutach). Kod synchronizacji
kopiuje hidden_sites oraz favorite_sites, ktorych tam brakowalo.

Sandbox na produkcyjnej bazie: strona porndoe 42 z 60 scen tylko z porndoe
przed ukryciem, 0 po; feed 0,34 s, duze tagi 0,3 do 0,8 s z dwiema ukrytymi.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:34:52 +02:00
goon-foss
2feef620a1 feat(telemetry): playback_events.via, skad przyszedl adres w odtwarzaczu
Po przejsciu porndoe na resolver po stronie telefonu 35 urzadzen dalej
dostawalo wylacznie 403 i nie dalo sie odroznic, czy pada nowa droga, zapas
przez WebView, czy stara paczka. Apka wysyla teraz via: phone, backend,
hoster, webview, proxy, movie; '-re' po ponownym rozwiazaniu w tym samym
ekranie, '<droga>>wv' gdy adres wyciagnal WebView jako zapas. NULL = paczka
sprzed tej zmiany. Migracja 0053 (kolumna nullable, sama zmiana metadanych).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:25:56 +02:00
goon-foss
7e48cdee06 fix(clips): wyscig przy pierwszym zapisie afinicznosci urzadzenia
Onboarding Edge i zdarzenia z pierwszych klipow przychodza naraz, oba
widzialy brak wiersza clip_affinity i oba robily INSERT, drugi konczyl sie
UniqueViolation i bledem 500 (GOON-7X). Pusty wiersz przez ON CONFLICT DO
NOTHING, potem odczyt z blokada i dodanie naszych przyrostow do tego, co
zapisalo rownolegle zadanie. Test z dwoma watkami: bez bledow, obie wagi.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:52:54 +02:00
goon-foss
edf9e8a39f fix(proxy): okcdn odrzuca obcy Origin, ponowienie bez niego
_build_headers dokleja Origin zawsze, gdy znamy Referer. okcdn (OK.ru,
porndupe) na ten sam adres z Refererem daje 206, a z Refererem i Originem
400, wiec kazdy zapasowy proxy porndupe konczyl sie 502 (120 bledow 502
w tydzien). Przy 400 jedno ponowienie bez Origin; zwykly <video> w
przegladarce i tak go nie wysyla.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 15:04:14 +02:00
goon-foss
ba53f872d2 fix(proxy): hdporn.gg i fullmovies, swiezy adres zamiast 410 w zapasowym proxy
get_file jest przypiety do IP i sesji ladujacej strone i bywa jednorazowy.
Gdy resolver na telefonie zawiodl, proxy dostawalo ten sam zuzyty adres i
oddawalo 410/503: 14 urzadzen w tydzien mialo na tych serwisach same porazki
(inne serwisy graly im bez problemu). Teraz po 403/404/410 albo trwalym 503
proxy pobiera strone na nowo (try_extract) i bierze adres w tej samej jakosci.
Test: adres pobrany z innego IP przez proxy 410 -> z odswiezaniem 206 video/mp4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:16:14 +02:00
goon-foss
0f128d2e17 feat(playback): zgloszenie 404/410 z telefonu sprawdzane z serwera
Zrodlo znikalo tylko po dlugim przytrzymaniu przez uzytkownika. Teraz
zgloszenie "Response code: 404/410" uruchamia w tle ponowny resolve z serwera;
martwe dopiero, gdy ekstraktor mowi "usuniete" albo plik z serwera tez daje
404/410 (dwie kontrole). Na sucho na 84 parach z 14 dni: 0 martwych, 83 zywe,
czyli 410 z telefonu prawie zawsze znaczy zly adres, nie skasowany plik.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:16:14 +02:00
goon-foss
4666fcb04a feat(edge): nowa punktacja feedu z historii klipu u nas, 25% w grupie kontrolnej
Odtworzenie uczenia na 189 tys. zdarzen (wagi zdarzenie po zdarzeniu, bez
zagladania w przyszlosc, test na 30% najnowszych): stara punktacja porzadkowala
klipy w obrebie urzadzenia z AUC 0,576 (lajk albo >= 10 s vs ucieczka < 2 s).
Tagi RedGifs sa liczne i ogolne, wiec ich suma dominowala, a mowila malo; nisze
prawie nic, popularnosc z RedGifs slabo, tworca i przyjecie klipu u nas najwiecej.

Nowa: log(waga tagu x rzadkosc tagu) + 0,25 log(nisze) + 2,5 log(tworca)
+ 0,8 ln(1+lajki RedGifs) + 120 (odsetek lajkow u nas - 3%) - 15 (odsetek
ucieczek - 50%) + 0,3 za swiezosc. Na tescie 0,652, regresja na tych samych
cechach 0,654. Liczniki clips.feed_views/skips/likes (migracja 0052, wypelnione
z historii), bumpowane w POST /clips/events. 25% urzadzen (hash id) zostaje na
starej punktacji do porownania na zywym ruchu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:47:02 +02:00
goon-foss
8753243e15 fix(edge): skasowany klip nie zostawia czarnego ekranu
Klip skasowany u zrodla daje 403 i na wideo, i na plakacie, a apka nic z tym
nie robila. Teraz odtwarzacz zglasza zdarzenie 'error' (i 'stall' po 12 s bez
obrazu), przy 403/404/410 przewija dalej (max 3 z rzedu, bledy sieci i TLS nie
przewijaja), a serwer od razu sprawdza plik i oznacza klip martwy. Reaper co
godzine po 1000 klipow zamiast 2000 na dobe: ~4% zywych klipow w feedzie
zwracalo juz 403. Zejscie z zepsutego klipu nie psuje wag jako "skip".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:30:50 +02:00
goon-foss
92f83b93fe feat(favorites): ulubione z nowosciami na gorze, osobno nowe sceny i filmy
Zgloszenie 5a724cc8: aktorki i studia z "+N" grupowane u gory listy, a znaczek
rozbity na sceny i filmy (new_scene_count, new_movie_count). new_count zostaje
jako suma dla starszych wersji apki, ktore dostaja tez nowa kolejnosc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:30:50 +02:00
goon-foss
77679b26bb perf(scenes): lista serwisu od najnowszych prosto z indeksu
Some checks failed
Backend tests / test (push) Has been cancelled
Ekran serwisu (/scenes?origin=tube:X&sort=release_date) dla serwisow,
ktorych scen nie ma wsrod najnowszych w katalogu (perverzija, hdporn.gg,
tubepornclassic, yesporn), sortowal wszystkie ich sceny: 9-19 s na
zimnym cache, 1-4 s na cieplym, 39 wejsc w 3 h.

Wzorem scene_tags.sort_date (GOON-64): data sortu powielona w
playback_sources i pilnowana wyzwalaczami (0048), wypelniona skryptem,
indeks (origin, sort_date DESC, scene_id DESC) WHERE dead_at IS NULL
(0049). API dolacza DISTINCT ON zgodny z indeksem, bo 190 tys. scen ma
dwa zywe zrodla z tego samego serwisu. Po zmianie 0,03-0,24 s, takze
dalsze strony.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 20:18:59 +02:00
goon-foss
c97af57979 perf(tags): liczniki tagow JAV i animacji liczone w tle
/tags?vertical=jav liczyl agregat po zrodlach i scene_tags na kazde
wejscie, dwa razy: 1 s na rozgrzanym cache, 17-24 s na zimnym. Teraz
czyta tabele tag_vertical_counts (migracja 0047), ktora odswieza
refresh_taxonomy_counts co 3 h. Zakladka JAV: 0,35 s. Gdy tabela jest
pusta dla wertykalu, zostaje stary agregat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 19:37:23 +02:00
goon-foss
2a2c0d7e9d fix(api): bez planow ogolnych i szybkie listy serwisow, ktore stoja
Some checks failed
Backend tests / test (push) Has been cancelled
- db: prepare_threshold=None. psycopg przygotowywal zapytanie po 5 wykonaniach na
  polaczeniu, a Postgres przechodzil potem na plan ogolny. Lista duzego tagu na takim
  planie: "pov" 44 s zamiast 0,46 s, "masturbation" 46 s zamiast 0,18 s. Stad listy
  ladowaly sie raz szybko, raz minute, zaleznie od polaczenia z puli (tez GOON-73/75).
- Lista jednego serwisu bez frazy: przejscie od najnowszych z limitem 1 s, a po nim
  start od scen serwisu (do 150 tys.). Serwis, ktory stoi, mial sceny gleboko:
  superporn 72-92 s -> 1,7 s, yespornvip 15 s -> 1,5 s, hentaiplay 9 s -> 0,06 s.

Porownanie ze starym kodem na 88 listach serwisow: wyniki identyczne przy
zapytaniach puszczonych po sobie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 09:45:05 +02:00
goon-foss
3349700f72 fix(api): szukanie w serwisie i sortowanie po studiu z rzadka fraza
Some checks are pending
Backend tests / test (push) Waiting to run
- Szukanie w jednym serwisie do 60 tys. scen zaczyna od jego scen (scenes.id = ANY),
  gdy fraza jest popularna albo bez trigramu: "sel" w hqporner 3,4 s -> 0,1 s, "brat"
  w fullmoviesxxx 2,9 s -> 0,15 s. Rzadkie frazy dalej trigramami (GOON-75).
- Poprawka regresji z c08abf6: fraza bez trigramu przy zawezeniu po 3 s oddawala
  pusta liste ("ai" w fullmoviesxxx: 0 wynikow). Teraz od serwisu albo limit 10 s.
- sort=studio z rzadka fraza: JOIN ze studiami i sort samych trafien zamiast
  przejscia po 33 tys. studiow ("sunny leone" 928 s -> 0,26 s, "savanna" 20 s -> 0,17 s).

Porownanie ze starym kodem na 100 wyszukiwaniach w serwisach i 12 z sortem po studiu:
wyniki identyczne poza naprawionymi pustymi listami.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 17:13:39 +02:00
goon-foss
0da36d5c1e perf(tags): warianty pisowni tagow jednym zapytaniem
Some checks are pending
Backend tests / test (push) Waiting to run
enrich-tags wolal resolve_tag dla kazdej nazwy spoza slugow, a ten szukal po
alnum-kluczu i liczbie mnogiej osobnymi zapytaniami (N+1, GOON-5F). Nowe
resolve_tags_by_altkey robi to jednym IN po indeksie ix_tags_name_altkey;
_resolve_by_altkey dla jednej nazwy korzysta z niego (1 zapytanie zamiast 2).
Na 603 nazwach z produkcji wyniki identyczne, 0,77 s -> 0,03 s.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 13:24:18 +02:00
goon-foss
cb9e4ab035 fix(siska): przeniesienie na siska.tv po wygasnieciu siska.video
siska.video od 2026-09-22 nie istnieje (NXDOMAIN), ten sam serwis dziala pod
siska.tv z tymi samymi videoID i sciezkami miniatur. Scraper bierze kafelki z obu
domen i z www, zapisuje jeden kanoniczny adres. Lista najnowszych jest pod
best_xvideos.php?page=N, bo /page/N/ na siska.tv zawsze oddaje strone 1.

Na produkcji adresy stron, miniatur i external_id przepisane na siska.tv
(16 007 zrodel, 16 265 powiazan scen); 103 duplikaty www.siska.video oznaczone
jako martwe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 13:18:22 +02:00
goon-foss
45ee7a81e1 fix(api): szybkie szukanie po tytule dla popularnych i krotkich fraz
Some checks are pending
Backend tests / test (push) Waiting to run
Planer szacowal kazda fraze na 427 trafien (histogram 100 probek, dolny limit), wiec
zawsze szedl indeksem trigramow i sortowal wszystkie trafienia: "vo" 44 s (dwie
litery nie maja trigramu, indeks oddaje 4,3 mln wierszy), "mis" 6,5 s, "free" 1,9 s
(GOON-73/75).

- 0046: histogram title_normalized 1000 probek, szacunki bliskie prawdy.
- list_scenes: przy q i sorcie po dacie najpierw przejscie po indeksie sortu z
  limitem 300 ms (bez bitmap, w SAVEPOINT wycofywanym zawsze), gdy probka tytulow
  z pg_stats mowi, ze wystarczy przejsc do 30 tys. scen; inaczej zwykly plan.
  Frazy bez trigramu zawsze przejsciem (limit 3 s, potem pusto).

115 prawdziwych wyszukiwan z logow: wyniki identyczne, najgorszy 44 s -> 0,8 s,
srednie frazy dotykaja 3-7x mniej stron ("bad" 122 tys. -> 16 tys.).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00
goon-foss
7accd4692f fix(seo): bez prywatnych blacklist i z cache indeksu sitemapy
Blacklisty sa per urzadzenie od 2026-06-10, a SEO dalej wycinalo sume blacklist
wszystkich urzadzen: 465 osob, 4477 tagow, z publicznych stron znikalo ~86% scen.
To samo zapytanie przy liczeniu do /sitemap.xml pisalo 3,7 GB plikow tymczasowych
i przy kilku wejsciach robota naraz zapychalo dysk (GOON-22). Teraz strony SEO
pokazuja to, co katalog nowemu urzadzeniu, a indeks sitemapy liczy sie raz na 6 h
(blokada na rownolegle zadania). Liczenie 135 MB plikow tymczasowych, indeks 13 s,
potem 0,2 s. Wykonawcy 20 tys. -> 81 tys., sceny 3,5 mln.

Na VPS dodatkowo temp_file_limit=2GB dla API w override.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00
goon-foss
41ad7f1818 feat: automatyczne sprzatanie martwych zrodel sxyprn i eporner
Oba serwisy kasuja filmy po cichu: strona odpowiada 200 z "Post Not Found" albo "Video has
been deleted". Probka 2026-09-19: 57% zywych w bazie zrodel sxyprn w wieku 10-40 dni i 22%
eporner bylo juz usunietych; w apce to puste kafelki i "the tube removed" po kliknieciu.

- eporner: ekstraktor rozpoznaje usunieta strone i rzuca HosterDead, wiec resolve oznacza
  zrodlo zamiast oddawac "blad chwilowy" (82 takie wejscia w 48 h, nic nie oznaczal).
- proxy miniatur: "Post Not Found" na sxyprn oznacza zrodlo od razu, 404 na miniaturze
  eporner uruchamia w tle sprawdzenie strony (28/30 takich miniatur to usuniete filmy).
  Indeks hash po thumbnail_url tylko dla eporner (0044), zeby znalezc zrodlo po obrazku.
- job dead-reap co 6 h: po 1500 zywych zrodel na serwis, polowa z ostatnich 30 dni.
  Oznacza tylko przy pewnym sygnale; siec i timeouty zostawia.

Sprawdzone na produkcji: 10/10 miniatur eporner i 23/23 postow sxyprn oznaczone, 17 zywych
postow nietknietych.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00
goon-foss
0edc85c05f feat(api): glowny feed bez archiwum i z limitem jednego zrodla na strone
"Newest ingest" bez filtrow pomija sceny z dociagania archiwum (backfill): deep-crawl
tubepornclassic dokladal 7,9 tys. scen z lat 2016-2018 dziennie, a xhamster/xnxx/xvideos/
sxyprn kolejne 3,3 tys., wszystkie na szczycie listy. Po odcieciu eporner (2 tys. anonimowych
uploadow dziennie) mial 121 ze 150 pozycji, wiec na pierwszych 8 stronach jedno zrodlo zajmuje
najwyzej 1/3 strony, dopoki sa inne; nadmiar zjezdza nizej, nic nie ginie. Pierwsze 3 strony:
eporner 51, xvideos 24, xnxx 20, youporn 20, pornxpph 15, fullporner 12.

Z filtrami i w sekcjach JAV/Anime bez zmian.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00
goon-foss
73853eb9ed perf(api): kilka tagow od najnowszych idzie po indeksie najrzadszego z nich
Z dwoma tagami (rough-sex + anal) lista szla stara droga po calym katalogu, 7,4 s na zimnym
cache. Teraz dolaczamy najrzadszy tag po ix_scene_tags_tag_sort, a reszta zostaje jako
EXISTS: 0,2 s. Dolaczona tabela ma alias, inaczej EXISTS po scene_tags korelowal sie z nia.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00
goon-foss
7f2fdfaed0 perf(api): lista scen jednego tagu od najnowszych po indeksie na scene_tags (GOON-64)
Ekran tagu (jeden tag, sort=release_date, 200 scen) sortowal po dacie z `scenes`, a filtrowal
po `scene_tags`. Postgres szedl od najnowszej sceny calego katalogu i kazda sprawdzal; przy
tagach rzedu 40-60 tys. scen (`rough-sex`) to 46 tys. scen na strone, 7-15 s na zimnym cache.
Dwie przebudowy samego zapytania nie pomogly (2x albo 30 s na duzych tagach), cache tez nie,
bo wejscia rozkladaja sie na setki tagow.

`scene_tags.sort_date` (0042) trzyma ta sama date co `_effective_date_desc()`, pilnowana przez
wyzwalacze w bazie, indeks (tag_id, sort_date DESC, scene_id DESC) w 0043. Wypelnianie 23 mln
wierszy: scripts/backfill_scene_tags_sort_date.py, partiami z pauza.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00
goon-foss
3c1d2c5907 perf(api): lista stron odswiezana w tle, nikt nie czeka na przeliczenie
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>
2026-09-22 12:00:10 +02:00
goon-foss
c8035c68fa fix: losowanie w obrebie wynikow filtra, widoczne pobieranie aktualizacji
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>
2026-09-22 12:00:10 +02:00
goon-foss
7bfd194485 fix(mobile): Edge - serduszko nie rusza dzwieku ani nie przewija klipu, jeden przycisk dzwieku, stroik feedu
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>
2026-09-22 12:00:10 +02:00
goon-foss
bfa3444de2 feat(mobile): strona tworcy w Edge
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>
2026-09-22 12:00:09 +02:00
goon-foss
2cdc3d69da perf(api): tanszy odsiew stub-scen i zwarcie sprzecznego filtra playbacku
Some checks failed
Backend tests / test (push) Has been cancelled
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>
2026-09-16 11:11:17 +02:00
goon-foss
b6a075b28a perf(db): kasuje ix_scenes_title_normalized, zbedny prefiks indeksu z 0039
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>
2026-09-16 10:47:24 +02:00
goon-foss
470beb4aa6 perf(api): sortowanie scen po studiu i tytule bez sortowania calego katalogu
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>
2026-09-16 10:37:26 +02:00
goon-foss
37e6b7f03c perf(api): liczniki +N ulubionych z cache i indeksem, podobne sceny z najrzadszych tagow
- /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>
2026-09-15 15:05:43 +02:00
goon-foss
747d0cec3b perf(api): historia ogladania wsadowo, wyszukiwanie w obrebie strony po rownosci originu
- /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>
2026-09-15 14:06:01 +02:00
goon-foss
538a72107e perf(clips): explore po podzapytaniu okna, kandydaci bez ORM i bez tagow, max(uuid) przez tekst
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).
2026-09-14 20:34:19 +02:00
goon-foss
0df2236b37 feat(clips): feed Swipe z afinicznoscia, pamiecia widzianych i telemetria (etap 3)
Tabele per urzadzenie (migracja 0037): clip_seen (wykluczenie, wiersz przy
podaniu klipu), clip_feed_events (append-only: impression z dwell, skip,
complete, like, unlike, not_interested, autoswipe), clip_affinity (wagi
tag/nisza/tworca w JSONB), clip_favorites, clip_blacklist. GIN na clips.niches.

GET /clips/feed: kursor base64 {seed, pk, page} zamiast offsetu; 80% z puli
afinicznosci (skany po tagu/niszy/tworcy od losowego uuid, punktacja
sum wag + 0,3 ln(1+lajki) + swiezosc, max 2 klipy tworcy na strone) + 20%
explore (okno 2000 id po PK, losowanie wazone lajkami, zawijanie na koncu).
Bez wag 100% explore. POST /clips/events: zapis, podniesienie outcome,
ulubione, delty wag (like +5, complete +3, dwell>=10 s +1, skip<2 s -1,
not_interested -4 i -8 na wskazany cel). Onboarding 3 tapow, opcje,
blacklista tag/nisza/tworca, reset feedu, ulubione. Import miedzy
urzadzeniami kopiuje clip_seen, clip_favorites i clip_blacklist.

Job clips-maintenance co 24 h: decay wag x0,97, retencja zdarzen 90 dni,
reaper (HEAD na 2000 najdawniej sprawdzanych). Logika bez bazy w
app/clips_feed.py z testami (kursor, delty, cap/decay, punktacja, sklad).
2026-09-14 20:29:49 +02:00
goon-foss
4f5de92bfc feat(clips): tabele klipow do feedu Swipe + ingest RedGifs (etap 2)
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).
2026-09-14 16:32:57 +02:00
goon-foss
be6c18b3b4 feat(scenes): sortowanie losowe (seed, okno po PK) i po dlugosci (indeks partial), zgloszenie ae6a045b
- 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>
2026-09-14 15:13:13 +02:00
goon-foss
385aeb3ddb perf(api): lista filmow serializowana wsadowo (7 zapytan/film -> 8 na strone), /sources z agregatem w pamieci na 5 min
- GET /movies 371 -> 82 ms, z has_playback 477 -> 209 ms; GET /sources 604 -> 8 ms
- VACUUM ANALYZE tabel filmow po tygodniu przemialu (11k martwych wierszy w movies)
2026-09-08 10:04:01 +02:00
goon-foss
e13463cba4 feat(sites): loga stron (favicon -> PNG w static, job co 24h) + sortowanie w arkuszu pod ikona
- 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
2026-09-07 12:13:58 +02:00
goon-foss
25416a2858 fix(movies): rodzina DoodStream (playmogo/doply/myvidplay) na koniec listy zrodel
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].
2026-09-05 22:21:13 +02:00
goon-foss
f1b8b8d466 feat(favorites): przypinane strony (favorite_sites) z endpointami list/add/remove
Prosba z apki 2026-09-02: ulubione strony maja siedziec na gorze zakladki Sites. Po
stronie serwera jak reszta ulubionych, bo kod synchronizacji to device_id i tabele
kluczowane po nim przechodza na nowe urzadzenie razem. Origin bez klucza obcego
(zrodla nie maja tabeli po origin), za to przy dodawaniu sprawdzany w playback_sources,
a sam napis ograniczony wzorcem, zeby nie dalo sie wpisac smieci.

Migracja 0034 (create table, bez blokad). Sprawdzone TestClientem w kontenerze api:
dodanie, powtorne dodanie (created=false), lista w kolejnosci dodania, nieznany origin
404, zly wzorzec 422, usuniecie 204.
2026-09-02 22:44:35 +02:00
goon-foss
ef43b61a12 fix(playback): odrzucaj nie-manifest z 200 i odswiezaj zrodlo dla 8kporner i perverzija
Sprawdzenie dwoch tubow, ktore w statystyce bledow odtwarzania wygladaly zle. Oba maja
inna przyczyne niz vjav i ZADEN nie jest awaria calego tuba.

**perverzija.** Naglowkowe "44% bledow" jest mylace: 132 ze 176 bledow pochodzi z awarii
13-18 sierpnia, ktora sama minela (te dni maja zero udanych odtworzen). Ostatnie 8 dni to
~16%. Wszystkie trzy sceny, ktore realnie padly u userow, resolwuja sie dzis poprawnie i
przechodza przez /proxy/hls jako prawidlowy manifest, wiec biezacej awarii nie ma.

Zostaje jednak realna dziura: hoster potrafi oddac 200 z trescia, ktora manifestem nie
jest (strona bledu albo reklama). Przepuszczalismy to dalej jako
`application/vnd.apple.mpegurl` ze statusem 200, a odtwarzacz konczyl komunikatem "Input
does not start with the #EXTM3U header" (203 zdarzenia w 14 dni). Gorsze od samego bledu
bylo to, ze przy statusie 200 apka uznawala odpowiedz za dobra i nie probowala odswiezyc
zrodla. Teraz w takiej sytuacji leci 502.

**8kporner.** Bledy to 502 i 400 z okcdn, rozlozone rownomiernie, przy stale dzialajacym
tubie. To zwietrzaly zapisany adres, ten sam wzorzec co watchporn. Potwierdzone na
czterech scenach, ktore padly u userow: swiezy resolve kazdej z nich oddal 206 z trescia.
Jeden przypadek w tej probce byl bledem DNS po stronie klienta, nie naszym.

Stad oba origins dopisane do `BACKEND_RERESOLVE_ORIGINS`, czyli mechanizmu juz dzialajacego
dla watchporn i galaxyporn.

Sprawdzone na prodzie po wdrozeniu: prawdziwy manifest dalej przechodzi (200, 58 kB),
a odpowiedz nie bedaca manifestem dostaje 502 zamiast 200 ze smieciami.
2026-08-27 20:36:24 +02:00
goon-foss
b84ff5bdbc fix(vjav): powtorz pobranie manifestu z ciasteczkiem wyzwania (100% bledow -> gra)
vjav mial 587 bledow odtwarzania i ZERO udanych, przez caly czas, odkad zbieramy dla
niego zdarzenia. Kazdy blad to ten sam komunikat odtwarzacza: "Source error Response
code: 429". Dotyczylo to 58 779 zrodel, czyli tub nigdy ani razu nie zagral.

Siec TXXX dlawi ruch z serwerowni: zamiast tresci oddaje 429 i mikroskopijna strone,
ktora w JS ustawia jedno ciasteczko i przeladowuje sie. Wartosc stoi wprost w tej
odpowiedzi, wiec wystarczy ja odczytac i powtorzyc zapytanie, bez wykonywania JS.

Ekstraktor vjav robil dokladnie to od 2026-08-21, ale TYLKO przy `videofile.php`. Adres
manifestu oddawany odtwarzaczowi tej sztuczki nie dostawal, a `/proxy/hls` pobiera go z
VPS przy KAZDYM odtworzeniu. Stad komplet bledow.

To dlatego bug byl niewidoczny z zewnatrz: `try_extract` konczyl sie sukcesem, wiec w
kazdym pomiarze zrodla vjav wychodzily jako zywe (149 na 150), podczas gdy u userow nie
dzialalo nic. "Zywe" znaczy "ekstraktor zwrocil adres", a nie "to gra".

Sprawdzone na prodzie: przed poprawka /proxy/hls oddawal 429, po poprawce 200 i poprawny
#EXTM3U z segmentami na vjav0.ahcdn.com. Ponowienie odpala sie wylacznie przy 429 z
odpowiedzia ponizej 4 KB, wiec nie dotyka pozostalych hosterow.

Osobno potwierdzone, ze blokada jest po adresie IP: ta sama strona z VPS oddaje 429, a
przez proxy z innym IP 200 i 72 KB tresci.
2026-08-27 19:23:55 +02:00
goon-foss
ccba96376c fix(performers): "Search more scenes" odpowiada od razu, wyszukiwanie mieli w tle
Zgloszenie 23c64a28: "Search more scenes button not working". Przycisk DZIALAL, tylko
wygladal na zepsuty: endpoint byl synchroniczny i przy performerce z 871 scenami search
po ~25 tubach trwal dluzej, niz telefon utrzymuje polaczenie. W logu zostaly 4 starty
performer_driven bez ANI JEDNEJ domknietej odpowiedzi HTTP: kazdy tap konczyl sie
"Refresh failed", uzytkownik klikal znowu i szukania mielily sie rownolegle, a wyniki
i tak dopisywaly sie w tle, tylko bez zadnego sygnalu dla czlowieka.

Endpoint startuje teraz watek i odpowiada od razu (`status="started"`). Rate-guard 60s
bez zmian, `last_searched_at` idzie w gore PRZED startem watku, wiec chroni tez przed
zdublowaniem samego startu. Watek ma wlasna obsluge bledow, bo nie ma juz requestu,
ktoremu moglby oddac wyjatek.

Mobile: przy `status="started"` komunikat "Searching... new finds appear within a
minute or two" i odswiezenie listy po 60 s. Stare pola odpowiedzi zostaly, wiec klient
sprzed OTA pokaze "0 new scenes", co jest znosne przez kilkuminutowe okno do publikacji.

Zweryfikowane na produkcji: odpowiedz w 0,03 s, drugi strzal 429, watek tla skonczyl
po 30 s i zalogowal wynik.
2026-08-26 14:12:25 +02:00
goon-foss
360af9fabc fix(movies): rozwiazuj przekierowanie hostera na serwerze, zanim embed trafi do WebView
Zgloszenia 3b75cb54/11d7b17b/d3af0813: "Myvidplay nie dziala", czarny ekran.

Mechanizm to powtorka z galaxyporn (vikingfile -> vik1ngfile), tylko w drugiej galezi,
ktorej wtedy nie sprawdzilem: myvidplay.com i doply.net odpowiadaja 30x na playmogo.com,
a WebView w apce blokuje top-frame skok na inna domene (ochrona przed popunderami).
Telefon dostawal surowy adres myvidplay, przekierowanie bylo blokowane i zostawala czern.
Lekcja "sprawdz te sama pulapke w pozostalych galeziach" byla zapisana w pamieci po
galaxyporn; ta galaz wlasnie ja potwierdzila.

`resolve_movie_playback` rozwiazuje teraz przekierowanie po stronie serwera i UTRWALA
koncowy adres w `embed_url`, wiec kazdy adres kosztuje jeden fetch raz w zyciu, a po
utrwaleniu regex przestaje pasowac i krok jest darmowy. Fetch odpala sie WYLACZNIE dla
rodziny DoodStream (znanej ze zmiany szyldu co pare miesiecy); zwykle embedy ida bez
dotykania sieci. Blad hostera (5xx) nie jest utrwalany, zeby nie zabetonowac chwilowej
awarii jako nowego adresu.

Easyvidplayer z tych samych zgloszen NIE wymagal zmian: zrodla juz sa oznaczone
martwymi przez niedzielny mechanizm HosterDead, czyli samoleczenie dziala.

Zweryfikowane na wszystkich trzech zgloszonych filmach: resolve oddaje
https://playmogo.com/e/..., baza utrwalona, telefon rozpoznaje playmogo natywnie
(DOOD_HOSTS), a strona playmogo z tymi sciezkami byla sprawdzona 2026-08-24 (200,
markery Turnstile). Deploy backendu, bez OTA.
2026-08-26 14:00:56 +02:00
goon-foss
bdac60f022 feat(mobile): Chromecast (0.3.0, runtime 1.3)
Zgloszenie de93ba42 ("Can't stream to Chrome cast"). Cast to natywny SDK, wiec NIE da
sie go wyslac przez OTA: to nowe APK, ktore ludzie musza pobrac sami. Klucz podpisujacy
ten sam, wiec ALLOWED_APP_SIG_HASH bez zmian i aktualizacja wchodzi na wierzch starej.

Argument, ktory przewazyl: od czerwca release ma wlaczone FLAG_SECURE, wiec zwykle
mirrorowanie ekranu na telewizor jest zablokowane. Cast jest jedyna droga na duzy ekran.

Zasieg: 77% udanych odtworzen konczy sie bezposrednim adresem, plus czesc hosterow
filmowych oddajacych gotowy plik. Okolo 13% (porndoe, mypornerleak, superporn) idzie
przez WebView i castowac sie NIE DA, tam przycisku nie ma.

Wpiete recznie, bez `expo prebuild`, bo katalog android/ jest w repo i ma reczne zmiany,
ktore prebuild by przepisal. Cztery edycje, dokladnie to co robi config plugin:
manifest (OPTIONS_PROVIDER + expanded controller), MainActivity, castFrameworkVersion
w rootProject.ext oraz JAWNA zaleznosc play-services-cast-framework w app/build.gradle.
Ta ostatnia jest konieczna, bo biblioteka deklaruje ja jako `implementation`, co nie
jest przechodnie na sciezke kompilacji, i bez niej build pada na compileReleaseKotlin.

Identyfikator odbiornika CELOWO zaden: bez wpisu biblioteka bierze domyslny odbiornik
Google. Rejestracja wlasnego wiazalaby konto Google z Goonem, a przy tresci dla
doroslych latwo o cofniecie.

Urzadzenia bez Google Play Services zabezpieczone w DWOCH miejscach, bo mamy uzytkownika
na LineageOS (GOON-3B) i sideload na zegarku (GOON-51): `getSharedInstance` w try/catch
po stronie natywnej, a po stronie JS cala obsluga w osobnym `CastControl`, montowanym
dopiero gdy `useCastAvailable` potwierdzi Play Services. To nie jest ostroznosc na
wyrost: hooki biblioteki synchronicznie subskrybuja natywne zdarzenia i bez GMS wywracaja
ekran, a hooka nie da sie wywolac warunkowo.

Chromecast pobiera plik SAM i nie wysyla naszych naglowkow, wiec zrodla wymagajace
Referera ida przez /proxy (dokłada go po stronie serwera), a reszta bezposrednio, zeby
nie obciazac VPS. Do tego proxy przestaje przekazywac CORS hostera: mixdrop oddawal
`Access-Control-Allow-Origin: https://mixdrop.my`, co odbiornik odrzucal przy HLS.

Przy okazji GOON-3B: doszedl brakujacy wpis `com.google.android.gms.version`, ktory
wywracal apke na LineageOS, gdy Chromium probowal podpiac skaner kodow.

Zweryfikowane na emulatorze na podpisanym APK: certyfikat identyczny ze starym
(3294aba5...), instalacja NA WIERZCH 0.2.2 udana, wersja 13/0.3.0, runtime 1.3 w
manifescie, aplikacja wstaje bez crasha, ExoPlayer gra (MediaCodec dla video), a SDK
Casta startuje poprawnie: dynamite sie laduje i `MediaRouterProxy` czyta NASZ CastOptions.
Logika wyboru adresu przetestowana osobno na osmiu przypadkach.

CZEGO NIE ZWERYFIKOWALEM: realnego rzutu na telewizor. W sieci emulatora nie ma zadnego
Chromecasta, wiec `loadMedia` i odtwarzanie po stronie odbiornika sa niesprawdzone.

Build wymaga SENTRY_DISABLE_AUTO_UPLOAD=true, bo sentry.properties czeka na
SENTRY_ORG/SENTRY_PROJECT/SENTRY_AUTH_TOKEN ze srodowiska (Infisical, workspace
goon-app). Skutek: slady JS z 0.3.0 beda w Sentry nieczytelne do czasu przebudowy z tymi
zmiennymi.
2026-08-24 14:27:41 +02:00
goon-foss
5a48175a85 fix(movies): przestan podsuwac hostery z rodziny seekplayer, ktore nie maja plikow
Zgloszenia z 2026-08-24: "Easyvidplayer nie chce odpalic" (ccbc75da), "Embedseek tez
nie rusza" (d59fc396) i sasiednie. To NIE byl nasz blad parsowania.

Co ustalone: `/api/v1/video` odpowiada 200 i poprawnie sie odszyfrowuje, tylko nie ma
w odpowiedzi pola `source`. W ich wlasnym bundlu warunek jest doslownie taki sam i
konczy sie komunikatem "Video is not ready yet". Potwierdzone w przegladarce z lacza
domowego (plakat obok oddal 502), z VPS i przez brytyjskie proxy, wiec to nie blokada
po IP ani po kraju. Protokol sie nie zmienil, hoster po prostu nie ma juz plikow.

Skala na 250 losowych zrodlach: 3 zywe, 88 razy HTTP 404, 79 razy brak `source`.
Czyli okolo 2% jeszcze gra.

Dwie zmiany:
* `seekplayer_engine.extract` rzuca `HosterDead` zamiast zwracac None. Dopiero wtedy
  `resolve_movie_playback` oznacza zrodlo martwe. Zwracanie None dawalo WebView z tym
  samym komunikatem, w kolko, i wlasnie to zglaszali uzytkownicy. Katalog czysci sie
  teraz sam, w miare jak ludzie po nim chodza.
* De-ranking calej rodziny w `_movie_origin_priority`, zeby na wierzch wychodzily
  hostery, ktore graja. Nie usuwamy ich z listy, bo te 2% bywa jedynym zrodlem.

Bezpieczne: filmow zaleznych WYLACZNIE od tej rodziny jest w bazie jeden, pozostale
26 223 maja alternatywe.

Dolozony `scripts/seekplayer_reap.py` do sprzatania calosci na zadanie. NIE odpalam go
w tle: przy limitach hostera (32% odpowiedzi to 429) pelny przemial to kilkadziesiat
godzin ciaglego pukania, co grozi zablokowaniem naszego IP dla prawdziwych resolve.

Zweryfikowane na filmie ze zgloszenia: piec zrodel seekplayer oznaczonych martwymi,
zostaly mixdrop (206 video/mp4) i voe (200 m3u8), oba sprawdzone spoza serwerowni.
2026-08-24 13:39:40 +02:00
goon-foss
e26c78df24 fix(ingest,proxy): pusta strona to nie koniec katalogu + miniaturki blokowane po IP
naughtymachinima (zgloszenie 83eb300d, "tylko 148 scen"): deep-crawl uznal katalog
za wyczerpany na stronie 8, bo trafil na pusta strone. Listing ma 1770 stron po 30
filmow, a ponowne wejscie na strone 9 oddalo 13 scen i ZERO bledow pobrania, czyli
tamto zero bylo chwilowym dlawieniem. Pusta strona bywa tez calkiem legalna, bo
bramka odrzuca klipy < 180 s, a to 2/3 tego katalogu. Konczymy wiec dopiero po trzech
pustych stronach pod rzad. Kursor odblokowany, kontrolny run przeszedl strony 9-14:
49 scen, 7 nowych, bez oznaczenia exhausted.

fullvideosporn (zgloszenie f4995691, "brak miniaturek"): adresy w bazie sa poprawne,
ale tn.sextu.com odrzuca nasz adres serwerowni: 429 przy kazdej probie, takze po
przerwie, a przez residential proxy 200 i 26 kB. Proxy obrazkow po odmowie
(401/403/429) ponawia teraz raz przez to proxy. Obrazek ma kilkadziesiat kB i klient
cachuje go dobe, wiec to nie jest proxowanie wideo. Sprawdzone: 6/6 miniaturek
laduje sie (15-116 kB), wczesniej 0/6.

Uwaga na przyszlosc: helper wladowal sie przy pierwszym podejsciu MIEDZY dekorator
trasy a proxy_image, wiec @router.get udekorowal jego, a /proxy/img/ oddawalo URL
proxy z loginem i haslem jako JSON. Naprawione, w docstringu ostrzezenie.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 16:43:29 +02:00
goon-foss
fa7fb668b6 fix(sites): sortuj po dacie premiery z fallbackiem na date dodania + napraw miniaturki
Zgloszenie 1df50de3 ("hqporner: brak nowych scen ze strony, brak miniaturek").
Oba objawy mialy inne przyczyny i oba sie potwierdzily.

1. Kolejnosc. Sceny byly i ingest dzialal (91 nowych w 7 dni, ostatnia tego dnia),
ale tuby daty premiery zwykle NIE podaja: xhamster 99,2% scen bez daty, xnxx 97,7%,
porntrex 95,8%, hqporner 93,5%, sxyprn 85,7%. Przy release_date DESC NULLS LAST
wszystkie bezdatowe ladowaly ZA datowanymi, wiec 82 z tych 91 scen siedzialy za
3,4 tys. starszych pozycji. Teraz sortujemy po dacie premiery, a gdy jej brak, po
dniu trafienia do katalogu; sceny z prawdziwa data (kanon) bez zmian. Wyrazenie jest
immutable (jawne AT TIME ZONE 'UTC'), wiec wchodzi do indeksu, migracja 0033.

2. Miniaturki. Kafelki bez obrazka byly podpisane FULLPORNER, nie HQPORNER. Picker
bral pierwsze zrodlo alfabetycznie, a tube:fullporner < tube:hqpornercom. Dwie wady
naraz: czesc miniaturek fullporner to 153-bajtowa atrapa oddawana z kodem 200, a
czesc wskazuje CDN hqporner, ktory odrzuca Referer fullporner.com (ten sam plik:
Referer fullporner.com 403, wlasny host obrazka 200, 30 kB). Wiec: przegladany
serwis wygrywa wybor miniaturki, a proxy obrazkow po 403 ponawia raz z wlasnym
originem obrazka.

Pomiar na 40 kafelkach hqporner: przed 38 ladowalo i 1 nie, po 39 ladowalo i 0 nie,
wszystkie podpisane wlasciwym serwisem. Glowny feed bez zmian.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 16:25:53 +02:00
goon-foss
34276afb71 fix(scenes): min_duration_sec=0 znaczy bez progu, nie duration_sec >= 0
Zgloszenie 2ec95be5 ("Hentaimama dalej 0 scen") bylo trafne, mimo ze drill-downy
juz wysylaly min_duration_sec=0. Backend tlumaczyl to na duration_sec >= 0, a w SQL
NULL nie przechodzi ZADNEGO porownania, wiec scena o nieznanej dlugosci wypadala
dokladnie tak samo jak dziesieciosekundowy smiec. Serwisy, ktore dlugosci nie podaja
w ogole (hentaimama, javflix, supjav, hentaigasm, hentaiplay, xanimeporn to 100%
NULL), oddawaly PUSTA liste.

Teraz 0 znaczy brak progu i filtr w ogole sie nie naklada, a prog > 0 dalej odcina
NULL-e swiadomie, bo tam chodzi o smieci w glownym feedzie. To samo rozroznienie w
scieszce "pure default", zeby jawne 0 nie gubilo taniego liczenia.

Zweryfikowane na produkcji: hentaimama, javflix, supjav, hentaigasm i xanimeporn
oddaja sceny, glowny feed z progiem 60 bez zmian.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 16:03:51 +02:00