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.
This commit is contained in:
goon-foss 2026-07-26 16:34:24 +02:00
parent 4e8acd21b0
commit 7afb332fc8
3 changed files with 36 additions and 1 deletions

View file

@ -32,7 +32,15 @@ _A_RE = re.compile(
)
_ALT_RE = re.compile(r'alt="([^"]*)"')
_THUMB_RE = re.compile(r'data-src="(//[^"]+\.(?:jpg|jpeg|webp|png)[^"]*)"', re.IGNORECASE)
_DUR_RE = re.compile(r'class="duration">\s*([\d]{1,2}(?:\s*:\s*[\d]{2}){1,2})\s*<')
# porntrex zmienił markup kafelka (audit 2026-07-26): `class="duration">MM:SS<` →
# `<div class="durations"><i class="fa fa-clock-o"></i> MM:SS</div>`. Stary wzorzec
# przestał matchować → duration_sec=NULL dla ~95% świeżych scen, a mobile domyślnie
# filtruje `min_duration_sec=60`, więc te sceny BYŁY NIEWIDOCZNE w apce (6479 scen w
# 7 dni; user: "nie widzę nowych scen z porntrex"). Wzorzec obsługuje oba warianty:
# liczbę mnogą, opcjonalną ikonę <i> przed wartością i H:MM:SS.
_DUR_RE = re.compile(
r'class="durations?"[^>]*>(?:\s*<i[^>]*>\s*</i>)?\s*([\d]{1,2}(?:\s*:\s*[\d]{2}){1,2})'
)
def _parse_duration(text: str | None) -> int | None:

View file

@ -16,6 +16,14 @@ export type ChangelogEntry = {
};
export const CHANGELOG: ChangelogEntry[] = [
{
id: '2026-07-26',
date: 'July 2026',
items: [
'If your network or DNS blocks a site\'s video servers (some providers do), the app now falls back to streaming through the server instead of dropping you on the site\'s page full of ads.',
'porntrex: new videos show up again. Their site changed, so we were saving new scenes without a length, and the "minimum length" filter was hiding them.',
],
},
{
id: '2026-07-22b',
date: 'July 2026',

View file

@ -316,6 +316,25 @@ function NativeVideoPlayer({ params }: { params: RouteParams }) {
player.play();
return; // sukces → status zmieni się z 'error', łańcuch fallback nie ruszy
}
// Phone-resolve zadziałał, ale dał TEN SAM URL — czyli strona parsuje się dobrze,
// a pada samo pobranie z CDN. Typowo: DNS/ISP usera blokuje hosta CDN (audit
// 2026-07-26: sieć zgłaszającego nulluje `vid-*.eporner.com` → 0.0.0.0, podczas gdy
// `www.eporner.com` działa). Wtedy łańcuch fallback NIE ratuje: dla phone-resolved
// linków `fallbackProxyUrl === url` (resolver ustawia stream_url = direct_url), więc
// krok proxy jest no-opem i lecimy prosto do WebView = strona hostera z reklamami
// ("załadowała się reklama zamiast wideo"). Bierzemy więc PRAWDZIWE proxy z backendu
// (VPS pobiera swoim DNS-em i streamuje do nas). Tylko na ścieżce błędu.
if (!cancelled && !!resolvePageUrl && sceneId && params.playbackId) {
const res = await client.resolvePlayback(sceneId, params.playbackId);
const viaProxy = (res.links || [])
.map((l) => l.stream_url)
.find((u): u is string => !!u && u !== url);
if (!cancelled && viaProxy) {
player.replace(viaProxy);
player.play();
return;
}
}
} catch {
// ignore → łańcuch fallback przejmie (proxy/embed/error)
} finally {