From 140764bfc5b0edd2eb96cc38da4eddc24b7a37d1 Mon Sep 17 00:00:00 2001 From: goon-foss Date: Tue, 28 Jul 2026 09:42:05 +0200 Subject: [PATCH] fix(hqfap): Cloudflare JS-challenge -> tryb WebView zamiast phone-fetch 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. --- app/extractors/__init__.py | 10 +++++++++- mobile/src/screens/PlayerScreen.tsx | 2 -- mobile/src/screens/SceneDetailScreen.tsx | 11 ++++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/extractors/__init__.py b/app/extractors/__init__.py index 5dd0fdc..74b0098 100644 --- a/app/extractors/__init__.py +++ b/app/extractors/__init__.py @@ -210,7 +210,15 @@ _REGISTRY: dict[str, Callable[[str], list[StreamSource] | None]] = { # biblioteka serwowała `/upload/videos/video_down.mp4` stub), PRZYWRÓCONY 2026-07-07: # strona wróciła na CDN vstor.top z realnymi plikami (portable cross-IP, zweryfikowane), # user request. 4k69 zostaje usunięty (nie sprawdzany ponownie). - "hqfapcom": hqfap.extract, + # 2026-07-28: hqfap wdrożył Cloudflare z JS-challenge na strony /watch/ — 403 zarówno + # z VPS, jak i z residential IP, także przy pełnym komplecie nagłówków przeglądarki + # (strona główna dalej 200, więc blokada jest celowana w strony wideo). Phone-side + # `resolveHqfapPage` (zwykły fetch) nie ma jak przejść challenge, więc padał i user + # lądował na stronie zamiast na wideo (bug-report 92e9133e "Hqfap przekierowuje na + # stronę"; telemetria to PRZEMILCZAŁA — zero eventów od 27.07, bo błąd jest przed + # playerem). WebView (Chrome engine + JS + cookie) challenge przechodzi, więc + # przełączamy na tryb WebView; INJECTED_JS i tak wyłuska mp4 i wróci na native player. + "hqfapcom": _vps_blocked_fallback.extract, # javflix (JAV, WordPress) — przyciski serwerów to `` # (streamtape/voe/doodstream/emturbovid). Generyczny _embed_iframe łapie je anchor-hoster # patternem → type='hoster', telefon resolwuje (voe backend, dood/filemoon phone-side). diff --git a/mobile/src/screens/PlayerScreen.tsx b/mobile/src/screens/PlayerScreen.tsx index 98340df..ba09692 100644 --- a/mobile/src/screens/PlayerScreen.tsx +++ b/mobile/src/screens/PlayerScreen.tsx @@ -321,8 +321,6 @@ function NativeVideoPlayer({ params }: { params: RouteParams }) { links = await (await import('../lib/epornerResolver')).resolveEpornerPage(resolvePageUrl); } else if (resolvePageUrl && playOrigin === 'tube:fpoxxx') { links = await (await import('../lib/fpoxxxResolver')).resolveFpoxxxPage(resolvePageUrl); - } else if (resolvePageUrl && playOrigin === 'tube:hqfapcom') { - links = await (await import('../lib/hqfapResolver')).resolveHqfapPage(resolvePageUrl); } else if (canBackendReresolve && sceneId && params.playbackId) { // Świeży resolve przez backend (VPS re-runuje extractor KVS → nowy nod + token). const res = await client.resolvePlayback(sceneId, params.playbackId); diff --git a/mobile/src/screens/SceneDetailScreen.tsx b/mobile/src/screens/SceneDetailScreen.tsx index 162bf95..c48c980 100644 --- a/mobile/src/screens/SceneDetailScreen.tsx +++ b/mobile/src/screens/SceneDetailScreen.tsx @@ -25,7 +25,6 @@ import { resolvePornxpPage } from '../lib/pornxpResolver'; import { resolveSxyprnPage } from '../lib/sxyprnResolver'; import { resolveEpornerPage } from '../lib/epornerResolver'; import { resolveFpoxxxPage } from '../lib/fpoxxxResolver'; -import { resolveHqfapPage } from '../lib/hqfapResolver'; import type { RootStackParamList } from '../navigation'; import { theme } from '../theme'; import type { PlaybackSource, SceneOut, StreamLink } from '../types'; @@ -626,7 +625,7 @@ function PlaybackButton({ // IP-bound tuby resolwowane phone-side: przekaż page_url, by Player mógł // re-resolve'ować świeży token gdy native padnie na initial-load (zmiana IP / TTL). - const PHONE_RESOLVE_ORIGINS = ['tube:sxyprncom', 'tube:epornercom', 'tube:fpoxxx', 'tube:hqfapcom']; + const PHONE_RESOLVE_ORIGINS = ['tube:sxyprncom', 'tube:epornercom', 'tube:fpoxxx']; nav.navigate('Player', { url: initialUrl, sceneId, @@ -669,9 +668,11 @@ function PlaybackButton({ ? resolveFpoxxxPage : source.origin === 'tube:pornxpph' ? resolvePornxpPage - : source.origin === 'tube:hqfapcom' - ? resolveHqfapPage - : null; + : // hqfap zdjęty 2026-07-28: strona wdrożyła Cloudflare z JS-challenge na + // /watch/ (403 dla każdego zwykłego fetcha, także z pełnym kompletem + // nagłówków przeglądarki), więc phone-resolve tylko padał i zrzucał usera + // na stronę hostera. Backend oznacza go teraz jako WebView-only. + null; if (phoneResolver) { setResolving(true); try {