Commit graph

69 commits

Author SHA1 Message Date
goon-foss
b19d041f09 perf(mobile): rule34video rozwiazywany od razu na telefonie
Some checks are pending
Backend tests / test (push) Waiting to run
Wczesniej resolve na serwerze, a potem telefon i tak pobieral cala strone
jeszcze raz (token zwiazany z IP) i robil przeskok przez get_file. Teraz
jedno pobranie strony na telefonie i wszystkie jakosci z flashvars,
przekierowanie get_file robi ExoPlayer. Limity czasu na pobrania.
Emulator: wybor jakosci -> odtwarzacz 3,1 s -> 0,1 s, -> dzwiek 7,2 s -> 2,9 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 12:51:14 +02:00
goon-foss
ca9ccf29f1 fix(mobile): reklamy sacdnssedge na liscie, changelog poprawek serwisow
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 12:23:54 +02:00
goon-foss
ffb4ecda18 fix(mobile): tablety w poziomie, porndoe w stronie po 403
Some checks are pending
Backend tests / test (push) Waiting to run
Tablety: obrot odblokowany przy starcie aplikacji, odtwarzacz go nie rusza.
Wczesniej aplikacja byla pionowym paskiem, a odblokowanie w odtwarzaczu
zmienialo najmniejszy wymiar okna, aktywnosc byla tworzona od nowa i
ExoPlayer zwalniany po 2 s. Manifest dostaje smallestScreenSize (nastepne APK).

porndoe: po bledzie w ExoPlayerze gramy w stronie zamiast wyciagac adres.
canPlayType dla HLS zwraca pusto, bo WebView mowi "maybe", a nie gra (strona
bierze wtedy wlasne hls.js). Sukces liczy sie od filmu dluzszego niz minuta,
nie od reklamy. Zapamietujemy tryb na 7 dni dopiero po udanym odtworzeniu.
Telemetria via=page, blad page_no_play po 25 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 10:59:19 +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
6c5d409fcc fix(porndoe): link do pliku pobierany na telefonie, nie przez WebView
Linki porndoe (mp4 z ip= i HLS z tokenem w sciezce) sa podpisane pod adres,
z ktorego przyszlo /service/index.json: token z IPv4 gra tylko przez IPv4,
z IPv6 tylko przez IPv6, z VPS 403. Token pobieral WebView (Chromium),
a plik ExoPlayer (OkHttp), wiec na sieciach dual-stack i za CGNAT wychodzily
innymi adresami: 164 bledy 403 na 278 udanych w tydzien.

Nowy resolver po stronie telefonu robi jedno zapytanie (film rozpoznawany po
Refererze) zwyklym fetch, ta sama droga co odtwarzacz; mp4 przed HLS, ponowne
rozwiazanie przy bledzie jak eporner/sxyprn. Pusto = dotychczasowy WebView.
Emulator: gra bez WebView.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:58:19 +02:00
goon-foss
3b127bff3d fix(player): vikingfile dostawal adres reklamy zamiast filmu
Wyjscie z wstrzykiwanego skryptu dla stron z Turnstile siedzialo w tym samym
try co oswajanie strony vikingfile. Skrypt startuje przed powstaniem <html>,
appendChild na null rzucal, a catch omijal return. Na vikingfile szedl caly
skrypt ekstrakcji i podsluch fetch bral zapytanie Adcash
(adexchangerapid.com/...&cbtitle=<plik>.mp4) za film: "None of the available
extractors" albo brak polaczenia z adexchangerapid przy blokadzie reklam,
polowa odtworzen galaxyporn.

Host liczony na poczatku, wyjscie poza try, styl dokladany po zaladowaniu
DOM, podsluch tylko na POST do wlasnej domeny, zapas z <video>.src.
Domeny Adcash na liscie reklam. Sprawdzone na emulatorze przez DevTools
WebView: stara paczka 3x blad, nowa gra (link z POST vikingfile).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:43:28 +02:00
goon-foss
617dda0bbe fix(player): myvidplay/playmogo/doply graja natywnie, bez WebView
Some checks are pending
Backend tests / test (push) Waiting to run
Szablon playera playmogo zawsze zawiera ukryty (d-none) blok "Not Found",
a resolver bral te slowa za usuniety film i poddawal sie od razu, wiec cala
rodzina DoodStream szla do WebView z klikanym Cloudflare. pass_md5 jest w
HTML, a adres gra bez weryfikacji. Teraz usuniety = tytul "not found" albo
widoczny blok. Sprawdzone na emulatorze: ExoPlayer, ttff 4,2 s, postep rosnie.
Bledy cichego resolvera ida do telemetrii (error_kind 'resolver'), poza ocena
zrodel. Wpis changelogu dla OTA d5906704.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:30:51 +02:00
goon-foss
5640ee094d fix(mobile): blad certyfikatu to nie usuniety film
"Trust anchor for certification path not found" lapal sie na "not found", wiec
odtworzenia eporner z bledem SSL szly jako "gone" (93 w tydzien): zly komunikat i zla
telemetria. Wejdzie z najblizsza paczka OTA.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00
goon-foss
f28acf8f0d fix(player): rodzina DoodStream, warstwy reklamowe nad playerem nie lapia juz stukniec
- 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>
2026-09-14 15:40:42 +02:00
goon-foss
b0350baff0 fix(player): przekierowanie z pierwszego adresu przechodzi (myvidplay -> playmogo), rodzina dooda jako jeden host; jeden wiersz ikon na ekranie strony i performera
- 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
2026-09-07 15:13:43 +02:00
goon-foss
e5eb27228e fix(player): dolny pasek sterowania nad systemowym paskiem nawigacji
Zgloszenie 386ef7ab (Galaxy S25, Android 16, nawigacja trzema przyciskami): pasek
przewijania niewidoczny w pionie. `controlsBottom` mial `bottom: 0` i stale
`paddingBottom: 18`, bez marginesow systemowych. Od Androida 15 apka rysuje pod paskiem
nawigacji, wiec przy trzech przyciskach (~48 dp) scrubber ladowal pod nimi.

Dolozony `useSafeAreaInsets()`: dol plus lewy i prawy, bo w poziomie pasek przyciskow
siedzi z boku. Z gestami margines to kilka dp, wiec wyglad prawie bez zmian.
`SafeAreaProvider` juz owija apke, ten sam hook jest w nawigacji.

tsc: 11 bledow przed i po, zadnego w okolicy zmiany. Wpis w changelogu 2026-09-02a.
2026-09-02 12:26:20 +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
38eee03902 fix(player): nie wstrzykuj naszego skryptu na stronach rodziny DoodStream
Zgloszenie Jana: myvidplay i easyvidplayer na filmach dalej nie dzialaly, mimo
wczorajszych poprawek backendu.

Backend byl OK, sprawdzone na zywo: myvidplay resolwuje sie teraz na playmogo.com, a
easyvidplayer oddaje 410 i znika z listy. Problem byl PO STRONIE APLIKACJI.

Playmogo (tam laduja myvidplay i doply) zmienil zabezpieczenie. Nasza notatka mowila, ze
to niewidzialny Turnstile przechodzacy automatycznie. To juz NIEPRAWDA: ich strona wola
turnstile.render z size flexible, czyli WIDOCZNY widget, i to dopiero po kliknieciu w
przycisk play, a po weryfikacji przeladowuje strone i dopiero wtedy pojawia sie pass_md5.

Nasz wstrzykiwany skrypt psul dokladnie ten przeplyw. Widget siedzi w kontenerze o klasie
captcha-player z z-index 100000, czyli w tym, co nasz usuwacz nakladek traktuje jak
reklame, a nasze auto-klikniecie w plakat odpalalo brame, zanim widget zdazyl sie
wyrenderowac. Do tego patchujemy prototypy HTMLMediaElement, co Turnstile potrafi uznac
za podejrzane srodowisko (dokladnie ten sam objaw mielismy na vikingfile).

Straz, ktora dotad obejmowala tylko vikingfile, obejmuje teraz cala rodzine bramkowana
Cloudflare. Na stronie pliku i tak nie potrzebujemy ani wyciszania autoplay, ani ad-blocka.

Pulapka po drodze, warta zapamietania: komentarz z backtickami wewnatrz literalu
szablonowego INJECTED_JS przerywa ten literal i wywala parsowanie calego pliku.

Zweryfikowane: regex po rozwinieciu szablonu pomija playmogo/myvidplay/doply/vikingfile/
d0000d/ds2play, a zostawia dzialajacy skrypt na galaxyporn, sxyprn i eporner; podobnie
brzmiacy goodplay.com sie nie lapie. Typecheck wrocil do bazowych 11 bledow.

NIE mam na to dowodu z urzadzenia: przejscie Turnstile trzeba potwierdzic na telefonie.
2026-08-27 09:10:16 +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
646f03d7be test(player): nie wstrzykuj naszego skryptu na stronach z Turnstile
Kolejny podejrzany o negatywna weryfikacje Cloudflare: nasz wlasny INJECTED_JS.
Wstrzykujemy go PRZED zaladowaniem strony, a on podmienia gettery i settery na
prototypie HTMLMediaElement (wyciszanie autoplay) oraz usuwa elementy uznane za
reklamy. Turnstile potrafi uznac tak zmodyfikowane srodowisko za podejrzane.

Na hostach vikingfile konczymy teraz wykonanie zaraz po naszym bloku: zostaje tylko
podswietlenie ramki z zabezpieczeniem, meldunek needs_interaction i podsluch POST-a
z bezposrednim linkiem. Reszta patchy sie nie wykonuje. Na stronie pliku i tak nie
potrzebujemy ani wyciszania autoplay, ani ad-blocka.

To jest TEST HIPOTEZY, nie potwierdzona naprawa. Nie udalo mi sie odtworzyc bledu u
siebie: w Chrome na emulatorze, na tej samej sieci, weryfikacja przechodzi zarowno w
trybie mobilnym, jak i desktopowym. Do apki na emulatorze nie dojde ta scena, bo ma
duration NULL i w glownym feedzie jest ukryta progiem 60 s, a przez strone aktorki
trzeba by przewinac 701 pozycji.

Przy okazji: naprawiony pojedynczy backslash w regexie hosta (szablon go zjadal) i
zaktualizowany komentarz naglowkowy, ktory dalej opisywal chowanie strony, usuniete
dwie zmiany wczesniej.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:35:42 +02:00
goon-foss
2071b36311 fix(player): nie podstawiaj desktopowego UA hosterom z Cloudflare
Dla hosterow z zabezpieczeniem Cloudflare (vikingfile, playmogo, klony DoodStreama)
przestajemy nadpisywac User-Agent i zostawiamy wlasny UA WebView. Dotad podstawialismy
Chrome na Windows, podczas gdy silnikiem jest Android WebView, a Cloudflare porownuje
deklaracje ze srodowiskiem.

UCZCIWE ZASTRZEZENIE: to NIE jest potwierdzona przyczyna. Test A/B w Chrome na
emulatorze (ta sama siec co telefon): tryb mobilny przechodzi weryfikacje, tryb
desktopowy TEZ przechodzi. Czyli sam UA nie wystarcza do odtworzenia bledu. Zmiane
zostawiam, bo zgodnosc UA ze srodowiskiem jest po prostu poprawniejsza, ale przyczyny
szukam dalej. Kolejny podejrzany: nasz INJECTED_JS, ktory patchuje prototypy
HTMLMediaElement przed zaladowaniem strony.

Potwierdzone przy okazji: strona i wyzwanie dzialaja na tej sieci, po klikniecu
checkboxa pojawia sie odtwarzacz i przycisk Download.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:27:24 +02:00
goon-foss
46e7839fb2 fix(galaxyporn): czarny ekran to zablokowane przekierowanie na druga domene
Trzecia proba i tym razem z dowodem z emulatora, a nie ze zgadywania. vikingfile.com
oddaje 302 na INNA domene (dzis vik1ngfile.site). WebView w aplikacji celowo blokuje
przejscie top-frame na inny eTLD+1, zeby popundery nie przejmowaly ekranu, wiec to
przekierowanie bylo odrzucane i zostawal czarny ekran. Z serwera tego nie widac, bo
httpx sledzi przekierowanie po cichu; widac dopiero w przegladarce na urzadzeniu,
gdzie w pasku adresu stoi vik1ngfile.site.

Poprawki:
- ekstraktor oddaje adres DOCELOWY (rozwiazuje 302 przy kazdym resolve, bo domena
  zapasowa rotuje), wiec aplikacja od razu otwiera wlasciwa domene i zadna zmiana
  domeny w ogole nie zachodzi
- wzorzec hosta we wstrzykiwanym skrypcie obejmuje obie pisownie (vik[i1]ngfile.),
  wczesniej dopasowywal tylko vikingfile.com, wiec po przekierowaniu w ogole sie nie
  uruchamial

Przy okazji z emulatora widac, ze zabezpieczenie to CHECKBOX "Verify you are human",
czyli wymaga kliniecia. Dlatego strona musi byc widoczna i uzywalna, a nie schowana.

Opublikowane OTA na 1.2 i 1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 20:03:54 +02:00
goon-foss
a1717e4b5e fix(player): czarny ekran na galaxyporn to byla 15-sekundowa zaslona
Zgloszenie: "galaxyporn dalej czarny ekran po Loading video". Zdiagnozowalem to
wczoraj zle. WebView ma nieprzezroczysta zaslone (coverOverlay z tlem motywu), ktora
znika dopiero po SZTYWNYCH 15 sekundach albo wczesniej, gdy uda sie wyluskac adres
wideo. Dla hostera, ktory wymaga kliknięcia, znaczy to 15 sekund gapienia sie w
spinner, a strony i tak nie widac.

Na to naloilem wczoraj wlasny blad: oswajajac strone vikingfile chowalem CALA jej
oprawe i zostawialem tylko widget na czarnym tle. Gdy widget sie nie wyrenderowal,
po zdjeciu zaslony zostawala czysta czern, czyli gorzej niz przed moja zmiana.

Dwie poprawki:
- strona vikingfile NIE jest juz chowana, tylko podswietlamy ramke z zabezpieczeniem
  i przewijamy do niej; najgorszy przypadek to normalna strona hostera
- gdy widget sie wyrenderuje, strona melduje to aplikacji (needs_interaction), a ta
  zdejmuje zaslone OD RAZU, zamiast czekac 15 sekund

Podsluch POST-a z bezposrednim linkiem zostaje: gdy zabezpieczenie przejdzie samo,
user w ogole nie zobaczy strony, tylko natywny odtwarzacz.

Opublikowane OTA na 1.2 i 1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:52:33 +02:00
goon-foss
1f73dad7d3 feat(vikingfile): przechwytuj bezposredni link zamiast pokazywac strone
Jan slusznie zapytal, czy WebView jest w ogole potrzebny. Rozlozylem protokol do
konca: po przejsciu zabezpieczenia strona robi POST na WLASNY adres z cialem
'cf-turnstile-response=<token>' i dostaje JSON z polem link, czyli gotowy plik.
Endpoint to po prostu adres strony pliku, nie zadne osobne API.

Bez tokenu sie nie da: POST z pustym albo brakujacym cf-turnstile-response oddaje
zwykly HTML (701 kB), a nie JSON. Sprawdzone trzy warianty ciala. Tokenu nie
wyprodukuje klient HTTP, bo wymaga silnika JS. Ale NIE wymaga czlowieka: widget jest
w trybie flexible z callbackiem, wiec na czystym domowym laczu przechodzi sam.

Wykorzystujemy to: WebView zostaje jako silnik JS, tylko podsluchujemy ten jeden POST
i gdy w odpowiedzi pojawi sie link, oddajemy go aplikacji przez istniejacy kanal
video_url. Aplikacja przechodzi wtedy na NATYWNY odtwarzacz, bez reklam i bez
ogladania strony hostera. Oswojony wyglad strony zostaje jako zabezpieczenie na
wypadek, gdyby zabezpieczenie jednak zazadalo kliniecia.

Blok zwalidowany jako realny JavaScript (new Function po zamianie podwojnych
backslashy na pojedyncze, tak jak robi to szablon). Typecheck bez nowych bledow.

Opublikowane OTA na 1.2 i 1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:46:13 +02:00
goon-foss
1154834170 fix(player): oswoj strone vikingfile, zeby nie wygladala na pusta
Zgloszenie 21d6f5af: galaxyporn laduje sie, a potem pusta strona, bez bledu.
Kierowanie bylo juz poprawne, problem byl wizualny. Vikingfile to STRONA PLIKU, nie
goly odtwarzacz: naglowek serwisu, nazwa pliku, rozmiar, przyciski pobierania,
progres i stopka, a wlasciwy widget Cloudflare siedzi w #captcha, czesto pod
zgieciem. W malym oknie odtwarzacza user widzial wiec pustke i nie mial pojecia,
ze ma gdzies kliknac.

Wstrzykujemy teraz dla tego jednego hosta krotki blok, ktory chowa cala oprawe
strony, wysrodkowuje #captcha-download na pelnym ekranie i dokłada jedna linijke
podpowiedzi. Gdy strona zdejmie z <video> klase hidden, chowamy widget i oddajemy
obraz na caly ekran. Dalej dziala zwykly scrape <source>, wiec gdy tylko pojawi sie
adres pliku, i tak przeskakujemy na natywny odtwarzacz.

Blok zwalidowany jako realny JavaScript (new Function na wyciagnietym fragmencie po
zamianie podwojnych backslashy na pojedyncze, tak jak robi to szablon).

Opublikowane OTA na 1.2 i 1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:24:31 +02:00
goon-foss
a62d438500 fix(player): po nieudanym resolverze wchodz od razu w WebView
Zgloszenia 57d6265a ("wszedzie doodstream resolver fail") i 3d3e1b33. Przyczyna nie
jest po naszej stronie: playmogo i klony DoodStreama przeszly z NIEWIDZIALNEGO
Turnstile na RENDEROWANY. Sprawdzone 2026-08-22 przez residential IP: strona ma 59 kB
i zawiera pass_md5, czyli sam protokol zyje, ale w HTML jest turnstile.render i ZERO
znacznikow trybu invisible. Z serwerowni ta sama strona ma 5 kB i pass_md5 w ogole nie
ma, wiec bez residential IP nie da sie tego nawet zdiagnozowac.

Skoro zadne ciche pobranie tego nie przejdzie, ekran "DoodStream resolver fail" z
przyciskiem "Open in WebView" byl juz tylko dodatkowym klikiem przed dzialajacym
odtwarzaniem. Teraz po nieudanym cichym resolverze wchodzimy do WebView od razu, czyli
tam, gdzie user moze kliknac widget. To ta sama sciezka, ktora dziala dla vikingfile.

Opublikowane OTA na 1.2 i 1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:17:33 +02:00
goon-foss
b4c1216133 fix(player): nie twórz playera, gdy apka jest w tle
expo-video wola w init konstruktora VideoPlayer bezwarunkowy startService dla
androidx.media3 MediaSessionService (VideoPlayer.kt:233), a Android od 8.0
zabrania startu zwyklego serwisu z tla. Gdy ekran playera montowal sie juz w tle
(user wyszedl w trakcie resolve albo system wznowil stos ekranow), konstruktor
rzucal IllegalStateException i zamiast wideo pokazywal sie ekran bledu.
GOON-12: 63 wystapienia, 28 osob, wszystkie z in_foreground=false.

Konfiguracja tego nie wylacza, wiec bramkujemy montowanie: hooka nie da sie
warunkowac, stad wlasciwy ekran wyjechal do PlayerScreenActive, a eksportowany
PlayerScreen czeka na AppState 'active'. Bramka dziala tylko przy montowaniu,
wiec zejscie w tlo z juz dzialajacym playerem nie przerywa odtwarzania.

Opublikowane OTA na 1.2 i 1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:16:33 +02:00
goon-foss
20c04698b1 fix(player): scrubber seekuje takze gdy dlugosc zna tylko scena, nie player
SPROSTOWANIE: paska postepu NIE trzeba bylo budowac, on juz istnial (track + fill +
thumb + gest + czasy, 48px hit-box). Moja wczesniejsza diagnoza "player nie ma czym
przewijac" byla bledna: szukalem po nazwach Slider/progressBar/seekBar, a implementacja
nazywa sie scrub*. Zamiast dublowac funkcje, zostal realny blad, ktory przy okazji
wyszedl.

Blad: UI paska liczy sie z `dur = knownDuration || durationSec || 0`, czyli z fallbackiem
na dlugosc z metadanych sceny, ale seek w `onEnd` byl strzezony warunkiem na samym
`knownDuration` (to, co zglosil player). Dla zrodla, ktore nie poda dlugosci playerowi,
a ma ja w metadanych, uchwyt i czas jechaly za palcem, a po puszczeniu nie dzialo sie
nic. Teraz seek uzywa tej samej wartosci co rysowanie, przez `durRef` (gest powstaje raz
w useMemo, wiec domykalby stara wartosc).

Zweryfikowane na emulatorze na realnym odtwarzaniu: przeciagniecie paska przenioslo
pozycje z 1:36 na 18:03, wypelnienie i uchwyt zgodne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 14:55:32 +02:00
goon-foss
085c0c1dd6 fix(playback): perverzija na nowy hoster, naughtymachinima re-resolve na reset
Dwa zgloszenia z apki, dwa rozne pierwotne powody.

perverzija (zgloszenie af9be63a, 520 bledow "Input does not start with #EXTM3U",
ZERO sukcesow): strona porzucila player xtremestream/xs1.php i osadza teraz mixdrop.
Stare URL-e xs1.php oddaja HTML zamiast manifestu HLS, stad kazdy playback padal.
Rejestr przelaczony z natywnego perverzija.extract na _embed_iframe.extract, ktory
wyluskuje mixdrop i oddaje type='hoster' -> telefon resolwuje w WebView. Natywny
ekstraktor zostaje w drzewie, gdyby xtremestream wrocil.

UWAGA co do weryfikacji: mixdrop gejtuje odtwarzanie za adsco.re (antybot). Sprawdzone
w prawdziwym Chrome na IP residential - MDCore.wurl zostaje null, zero requestu wideo,
bo brama celuje w AUTOMATYZACJE. Dla realnego usera w WebView player mixdrop gra
normalnie (to caly biznes mixdropa), ale nie dalo sie tego zautomatyzowac end-to-end.
To i tak scisle lepsze niz obecny stan 100% martwy.

naughtymachinima (zgloszenie ef728604 "od razu fallbackuje do strony, 502/429"):
ekstraktor SPRAWNY, direct mp4 bez tokenu, IP-bound do residential (403 z datacenter,
telefon gra). Telemetria 64 sukcesy / 19 bledow, blad to przejsciowy Connection reset
z CDN na dzialajacym URL-u. Bez re-resolve pojedynczy reset od razu spychal na WebView,
ktory ladowal zdlawiona strone tube'a - stad 502/429 w zgloszeniu. Dopisany do
BACKEND_RERESOLVE_ORIGINS: przy bledzie odswieza polaczenie zamiast uciekac do WebView.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 10:23:05 +02:00
goon-foss
47547fe694 fix(playback): galaxyporn re-resolwuje sie po bledzie zamiast poddawac
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.
2026-08-14 10:22:08 +02:00
goon-foss
7deda639bf fix(theme): rozdziel role akcentu i dodaj ramke, ktora cokolwiek oddziela
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.
2026-08-14 09:50:08 +02:00
goon-foss
a4486980a4 style: myslniki em/en z komentarzy i docstringow (calosc repo)
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>
2026-08-11 11:51:57 +02:00
goon-foss
017927793a style(mobile): myslniki em/en poza tekstow widocznych dla uzytkownika
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>
2026-08-11 11:29:21 +02:00
goon-foss
c1ba536607 feat(player): zmiana jakosci w trakcie odtwarzania
Some checks are pending
Backend tests / test (push) Waiting to run
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.
2026-07-28 11:56:59 +02:00
goon-foss
8841327b58 fix(perverzija): blokuj reklamowy CDN xtremestream (preroll w petli)
Some checks are pending
Backend tests / test (push) Waiting to run
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.
2026-07-28 11:52:42 +02:00
goon-foss
140764bfc5 fix(hqfap): Cloudflare JS-challenge -> tryb WebView zamiast phone-fetch
Some checks are pending
Backend tests / test (push) Waiting to run
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.
2026-07-28 09:42:05 +02:00
goon-foss
90a63b1e77 feat: wylaczalny auto-rotate w playerze + '+N' liczy takze filmy
Some checks are pending
Backend tests / test (push) Waiting to run
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.
2026-07-28 09:34:37 +02:00
goon-foss
55da508f9c fix: keep-screen-on podczas odtwarzania + on-demand miniaturki youporn
Some checks failed
Backend tests / test (push) Has been cancelled
1) Ekran gasl w trakcie ogladania (bug-reports fcbaa933 2026-07-18, c40fb79f
2026-07-23, dwoch userow). Android wygasza po timeoucie, bo dotyk nie pada, a samo
granie wideo nie trzyma wake-locka. expo-keep-awake NIE jest w top-level
node_modules (siedzi w node_modules/expo/node_modules), wiec metro nie rozwiaze
importu, ale natywny modul ExpoKeepAwake JEST w APK (expo go autolinkuje) -
siegamy po niego przez requireNativeModule z expo-modules-core (top-level).
Dzieki temu leci OTA, bez nowego APK. Wake-lock tylko gdy realnie gra (przy pauzie
ekran gasnie normalnie); WebView-player trzyma przez caly czas zycia ekranu, bo
tam nie ma sygnalu play/pause.

2) Miniaturki youporn (bug-report bebf8c92): youporn przeszedl dla czesci katalogu
na imgproxy z PODPISANYM URL-em (?hash=...&validto=<ts>), ktory WYGASA - zapisany
w bazie po czasie zwraca 410 (8666 z 62930 zrodel). Statyczne .../original/N.jpg
dzialaja bezterminowo. Nowy endpoint /proxy/youporn-thumb/<video_id> resolwuje
swiezy poster przy serwowaniu (jak sxyprn-thumb), z html.unescape bo og:image ma
&amp; i psulo to podpis (403). Podmiana TYLKO dla podpisanych - statycznych nie
ruszamy, zero dodatkowych fetchy.

Zweryfikowane: 8/8 wczesniej-410 teraz 200 (57-142KB), statyczne bez regresji.
2026-07-26 17:00:31 +02:00
goon-foss
7afb332fc8 fix(playback+ingest): realny proxy fallback gdy CDN nieosiagalny + porntrex duration
Some checks are pending
Backend tests / test (push) Waiting to run
1) eporner/phone-resolve: gdy strona parsuje sie OK, ale CDN jest nieosiagalny z
sieci usera (audit: siec zglaszajacego nulluje vid-*.eporner.com -> 0.0.0.0, a
www.eporner.com dziala), phone re-resolve zwracal TEN SAM URL, a lancuch fallback
nie ratowal: dla phone-resolved linkow fallbackProxyUrl === url (resolver ustawia
stream_url = direct_url), wiec krok proxy byl no-opem i szlo prosto do WebView =
strona hostera z reklamami ('zaladowala sie reklama zamiast wideo'). Teraz po
nieudanym phone-resolve bierzemy PRAWDZIWE proxy z backendu (VPS pobiera swoim
DNS-em). Tylko na sciezce bledu. Eporner globalnie zdrowy (89-100%, ~100 urzadzen
dziennie), wiec to fix dla userow z blokowanym CDN, nie regresja globalna.

2) porntrex zmienil markup kafelka: class="duration">MM:SS< ->
<div class="durations"><i class="fa fa-clock-o"></i> MM:SS</div>. Stary wzorzec
przestal matchowac -> duration_sec=NULL dla ~95% swiezych scen (6479/6815 w 7 dni),
a mobile domyslnie filtruje min_duration_sec=60, wiec te sceny byly NIEWIDOCZNE
('nie widze nowych scen z porntrex'). Wzorzec obsluguje oba warianty + H:MM:SS.
Zweryfikowane na zywym listingu: 84/85 kafelkow, 20:45 -> 1245s.
2026-07-26 16:34:24 +02:00
goon-foss
2d1800a461 fix(scenes): sxyprn detail thumbnail + stronger WebView pre-play mute
Some checks are pending
Backend tests / test (push) Waiting to run
1) _build_scene_out (detal) nie stosował _sxyprn_thumb_url jak lista → detal
pokazywał martwy trafficdeposit URL, refresh nie pomagał (sxyprn IP-bound). Teraz
detal też podmienia na żywy /proxy/sxyprn-thumb/<id>. Backend-only.

2) Mute WebView-scrape: attribute-autoplay (<video autoplay>) omijał override play()
i grał unmuted. Dokładam proaktywne ciszenie na play/loadeddata/volumechange +
poll 40ms do gestu (property-lock trzyma między tickami). Web Audio i tak gated
autoplay-policy. Raport usera: dalej głos przed ExoPlayerem.
2026-07-22 11:16:44 +02:00
goon-foss
f55f87410a fix(player): lock WebView muted/volume until gesture (kill audio-during-scrape)
Some checks are pending
Backend tests / test (push) Waiting to run
Przy scrape ścieżce (WebView otwiera stronę hostera żeby przechwycić stream)
player hostera po autostarcie ustawiał video.muted=false / volume=1 i dźwięk
buchał zanim ExoPlayer przejął (raport usera). Sam override play() łapał za
wcześnie. Teraz LOCKujemy muted/volume na HTMLMediaElement.prototype: próba
odciszenia przed gestem usera jest ignorowana. Po tapie (watch-in-WebView dla
CF-blocked hosterów) odblokowanie + odciszenie istniejących <video>/<audio>.
Patch leci injectedJavaScriptBeforeContentLoaded, więc przed page JS.
2026-07-21 15:17:30 +02:00
goon-foss
e2cb8df670 fix(telemetry): thread origin/title through WebView auto-extract re-nav
Some checks are pending
Backend tests / test (push) Waiting to run
Źródła które grają przez WebView (embed) → INJECTED_JS wyłuskuje direct mp4 →
nav.replace('Player', {mode:'video'}) gubiły origin i title. Player bez origin
→ success-effect (!playOrigin) SKIP → udane odtworzenia NIE raportowały się.
freshporno (KVS ale VPS resolve spada na embed → phone WebView-extract) miało
przez to 0 success / same błędy → health=0 → fałszywe offline.

3 nav.replace w EmbedWebViewPlayer (hoster-resolve, extractedUrl effect, banner)
teraz przekazują origin/title/playbackId/entityKind z params. Zweryfikowane na
realnym telefonie: origin=tube:freshpornoorg, success-effect FIRE, backend
zapisał 2× success.
2026-07-20 21:45:26 +02:00
goon-foss
21500837ab feat(bugreport): auto-attach device + last-playback context
Some checks failed
Backend tests / test (push) Has been cancelled
Playback reports ("doesn't start", "audio lags") came in with no way to know the
device or which source/server was used, forcing a follow-up question. Now the bug
report auto-context also carries:
- device = phone model / Android version (Platform.constants, zero-dep)
- play = last-played origin/host, mode, position, and last player error

New in-memory lastPlayback store written by PlayerScreen on source/status change, read
by BugReportFAB when composing a report. Reset on app restart (current session only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:53:30 +03:00
goon-foss
b62d22370b feat(player): copy video link button
Some checks failed
Backend tests / test (push) Has been cancelled
User request (07-10): a quick way to grab the direct video URL to share or open
elsewhere. Added a link icon in the player top bar that copies the current playing
URL to the clipboard (direct CDN URL for most sources, so it pastes into VLC/MX/a
browser; proxy-wrapped/referer-bound sources are best-effort).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 22:48:16 +03:00
goon-foss
92adaccf1b fix(hqfap): resolve on the device (site blocks the server IP)
Some checks are pending
Backend tests / test (push) Waiting to run
hqfap.com's Cloudflare blocks the VPS (Hetzner) IP — the server times out fetching
the page (0 bytes), so backend resolve returns None (503) or a stale/IP-bound URL that
fails on the phone (35 player_errors / 3 days, the top error source). But the page loads
fine from residential IPs (200, 0.7s) and its okcdn/vstor/cdnde mp4 is portable cross-IP
(srcIp not enforced, verified 206 from residential).

Fix: phone-side resolve, same pattern as sxyprn/eporner/fpoxxx. New hqfapResolver.ts
(fetch page on device -> JSON-LD contentUrl -> direct mp4, mirror of hqfap.py) wired into
the proactive phone-resolve chain in SceneDetail and the on-error re-resolve in
PlayerScreen; hqfapcom added to PHONE_RESOLVE_ORIGINS. Backend hqfap.extract stays as a
last-resort fallback.

Note: sxyprn/eporner were checked and are NOT broken (95-96% play success; their "gone"
events are real deletions), so no change there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 22:20:43 +03:00
goon-foss
7e2807b42e feat(supjav): resolve voe hoster to direct stream instead of WebView
Some checks failed
Backend tests / test (push) Has been cancelled
supjav is an embed-aggregator (voe/streamtape/turbovid/fc2stream). It was playing
through the WebView fallback because none of its hosters had a native phone-side
resolver wired into the scene player. voe.sx does have one (voeResolver.ts, already
used for movies) — it just was not wired for scenes.

- PlayerScreen: wire isVoeUrl/resolveVoePage into the hoster routing (like
  dood/filemoon), so a voe embed resolves on the phone to a direct m3u8
  (token bound to the phone /16, plays direct, no WebView, no proxy).
- supjav extractor: return voe first (sorted by URL), and stop putting the raw
  hostname in `quality` (the digit in "fc2stream" was parsed as quality 2 and won
  _pick_best) — use a clean digit-free server label instead.
- SceneDetailScreen: for hoster-only scenes, open the first embed (the extractor
  puts the natively-resolvable one first) rather than _pick_best's choice.

Verified: supjav's voe embed resolves to a real HLS manifest (200,
application/vnd.apple.mpegurl, #EXTM3U). WebView stays only as last-resort fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 19:52:26 +02:00
goon-foss
2d3831bd53 fix(player): audio no longer cuts out on tap/scroll (2x-mute regression)
Regression from the 2x-hold mute (commit e30f683). Gesture.LongPress fires
onFinalize for FAILED/CANCELLED gestures too (a plain tap, or a scroll stealing the
finger), not just after a real 2x hold. onFinalize unconditionally restored
player.muted from preSpeedMutedRef, whose initial value is true, so any ordinary
screen interaction muted the audio while the UI still showed the unmuted icon
(report fad4b317 "Audio cuts out on screen interactions").

Track whether 2x actually started (speedStartedRef, set in onStart) and only touch
player.muted in onEnd/onFinalize when it did. A failed or cancelled long-press now
leaves the user's mute preference alone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 09:38:03 +02:00
goon-foss
e30f6830f4 fix(mobile): stop Scenes feed repeating on scroll + mute audio during 2x hold
- Scenes feed repeated the same videos on scroll (report 304c9258): OFFSET
  pagination + continuous ingest means new scenes shift the offset, so later pages
  re-include earlier rows. Backend now appends Scene.id as a unique final tiebreaker
  to every sort (deterministic order), and the mobile Scenes list dedups by scene id
  when concatenating pages so a drifted overlap can never show a duplicate.
- Player: holding to fast-forward at 2x now mutes the sped-up (chipmunk) audio for
  the duration of the hold and restores the user's real mute preference on release
  (report 35bbf428).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:59:28 +02:00
goon-foss
e215b48255 fix(watchporn): re-resolve stale CDN URL in-player, drop WebView page fallback
The zload CDN URL (remote_control.php) is a valid faststart progressive mp4 that
ExoPlayer plays fine when fresh: 206, no IP/referer binding, ~2h token TTL,
verified from a residential IP. Real-device failures (player_error/gone
telemetry) come from the static URL going stale: a rotated or dead CDN node, or
an expired token.

Instead of falling back to the tube page in a WebView (removed, it papered over
the real issue), PlayerScreen now re-resolves the scene fresh via the backend on
initial-load error for backend-native KVS tubes (watchporn). That yields a live
node plus a fresh token and stays on the native direct stream (0 VPS bandwidth).
For these origins a CDN 'gone' (404) means stale URL, not deleted, so we
re-resolve on gone too; a genuinely deleted post raises HosterDead (410) and
falls through to the normal fallback chain.

Also: add playback_events.error_detail (raw ExoPlayer message) to pin down the
exact failure of tubes we cannot reproduce on the emulator. Keep FLAG_SECURE on
release builds only (!__DEV__) so debug builds stay screenshottable for local UI
verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 01:18:08 +02:00
goon-foss
15e7c1646d fix(review): player recovery deadlocks, quick-play re-fire, backfill gaps, em-dashes
Addresses the ultra-review findings on this branch:

Player (PlayerScreen.tsx): the new recoveryPending mirrored the fallback-chain guards
by hand and could deadlock into a permanent "Reconnecting" spinner with no way to Mark
broken — for gone (410) sources on IP-bound tubes (re-resolve bails before setting
reResolveDone) and for any post-load error on those tubes (re-resolve is initial-load
only). Derive one reResolveApplicable flag (IP-bound AND initial-load AND not-gone) and
use it for both the chain gate and the spinner, so gone/post-load errors fall through to
proxy/WebView or the terminal error card. Seek-recovery now falls through to the chain
when player.replace() throws instead of returning.

Quick-play (SceneDetail): the autoplay route param persisted and autoPlay={i===0} re-fired
when the source list reordered (e.g. after Mark broken drops the dead source), bouncing the
user into the player. Consume it once via onAutoPlayConsumed -> nav.setParams({autoplay:false}).

Backfill semantics: performer-driven direct-scraper "backward fill" now tags scenes
backfill=True (search-by-name pulls the whole old catalog); merge coalesces backfill
(keep AND drop) so a fresh scene merged into a dead dup keeps NEW; deep-crawl only tags
backfill on a tube's FIRST sweep (swept_once) so re-sweep catalog growth stays genuine;
pilot script tags backfill.

Perf/migration: migration 0026 is now idempotent (IF NOT EXISTS; prod got the column via
manual ALTER) and adds ix_scene_performers_performer_id (favorites count filtered
performer_id with no index); index also created on prod.

Cleanup: deleted dead FavoriteSceneRow (unused import in two screens, stale isNew without
the backfill guard); removed em-dashes from all lines this branch added (user CLAUDE.md
rule), including the user-facing changelog / Settings / player-overlay strings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 09:20:40 +02:00
goon-foss
7cf338f812 fix(mobile): no false "Mark broken" while a video is still recovering
eporner/sxyprn/fpoxxx resolve phone-side; the native player errors on initial load, then
re-resolve swaps in a fresh URL ~1-3s later and plays fine — but the terminal error
overlay with "Mark broken" rendered during that gap (report dafa8cdb). Added a
recoveryPending flag (mirrors the telemetry's fallback-aware logic: re-resolve / in-place
seek recovery / proxy / webview still in flight) that shows a "Reconnecting…" spinner
instead, and only surfaces the terminal error + Mark broken when nothing is left to try.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:37:19 +02:00
goon-foss
c073acff03 fix(mobile): no center pause button while seeking + incognito diagnostic browser
Player (report dccc05e4): swipe-seek no longer force-opens full controls (it has its own
±time bubble), and the center play/pause button is hidden while actively seeking (pan or
scrub-bar drag) — kills the big pause that popped up mid-seek and lingered ~3.5s.

Diagnostics "open in browser" now routes to an in-app WebView with incognito=true instead
of Linking.openURL: fresh sessionless view of the host page + no NSFW URL dumped into the
user's real browser history (fits the app's privacy stance). New DiagnosticBrowser route.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 11:21:41 +02:00
goon-foss
ac17350a67 fix(sources): require 25 telemetry attempts before a source can show OFFLINE
freshporno (5★ fresh+rich, verified working — 206/507MB) was labeled OFFLINE off 10
playback attempts that all failed in one unlucky window (a CDN-node blip; it resolves
fine now). 10 was too thin a sample to zero out a known-good source's stars. Raised
the telemetry-trust threshold 10→25; below it we fall back to the proxy/heuristic
health instead of declaring offline (user-report cb526949).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 10:23:29 +02:00
goon-foss
2a0e46e17d fix(mobile): re-resolve IP-bound tubes on playback error (sxyprn/eporner/fpoxxx)
sxyprn's video token is bound to the IP that fetched the post page; on mobile the
phone resolver works ~74% but ~26% fail when the egress IP shifts (CGNAT / network
switch) or the token goes stale → native player hung on a dead URL (18 reports, 26%
error rate in telemetry). Now on an initial-load error for these phone-resolved
tubes, the player re-fetches the page fresh (new token bound to the current IP) and
swaps the source before falling through to the proxy/WebView chain. Zero VPS
bandwidth. Gated by resolvePageUrl so other tubes are completely unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:11:21 +02:00
goon-foss
ce85d7d92e chore(ingest): hard-remove hqfap + 4k69 (entire CDN library gone)
Re-check 2026-06-25 across the full id range confirmed both PlayTube tubes
serve only the fixed `/upload/videos/video_down.mp4` "server down" stub, never
a real file: hqfap 0/80 real (79 stub, 1 none), 4k69 0/40 real (38 stub, 2
none). Both were disabled 2026-06-22; CDN never came back, so removing entirely
(mirrors the pornhub/redtube/0dayxx/pornditt/pornhat removals).

Removed the extractor registry entries (hqfapcom, 4k69com) + module files and
the browse scrapers + imports. Prod DB data deleted separately (28,398
solo-orphan scenes + 46,196 playback_sources). `_playtube.py` kept: superporn
and neporn still use its JSON-LD helpers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:07:47 +02:00