feat(diag): sxyprn resolve reason in bug-report auto-context
Some checks failed
Backend tests / test (push) Has been cancelled
Some checks failed
Backend tests / test (push) Has been cancelled
'sxyprn ładuje reklamy' jest niereprodukowalny z naszych IP (strona zwraca data-vnfo → resolver OK) → podejrzenie region/IP-gate u usera. resolveSxyprnPage zapamiętuje powód ostatniego resolve (http_<status> / challenge_<len> / no_vnfo_<len> / post_not_found / vnfo_parse_err / ok_N) i BugReportFAB dokleja go jako sxyprn=<reason> do auto-contextu. Przy kolejnym zgłoszeniu zobaczymy CO sxyprn realnie zwrócił temu userowi, bez pytania. Non-behavioral (nie rusza resolve).
This commit is contained in:
parent
2d1800a461
commit
33553729f8
2 changed files with 45 additions and 3 deletions
|
|
@ -35,6 +35,7 @@ import { captureScreen } from 'react-native-view-shot';
|
|||
import { GoonClient } from '../api';
|
||||
import { theme } from '../theme';
|
||||
import { formatLastPlayback } from '../lib/lastPlayback';
|
||||
import { getSxyprnDiag } from '../lib/sxyprnResolver';
|
||||
|
||||
interface Props {
|
||||
client: GoonClient | null;
|
||||
|
|
@ -200,6 +201,10 @@ export function BugReportFAB({ client, appVersion, navRef }: Props) {
|
|||
// się rozjeżdża", bo mówi KTÓRE źródło i gdzie, niezależnie od ekranu zgłoszenia.
|
||||
const play = formatLastPlayback();
|
||||
if (play) extraContext.push(`play=${play}`);
|
||||
// Diagnostyka sxyprn "ładuje reklamy" (niereprodukowalny z naszych IP → region-gate?).
|
||||
// Powód ostatniego phone-resolve sxyprn (http status / challenge / brak vnfo / ok_N).
|
||||
const sxy = getSxyprnDiag();
|
||||
if (sxy) extraContext.push(`sxyprn=${sxy}`);
|
||||
const sceneId =
|
||||
rawSceneId && /^[0-9a-f-]{36}$/.test(rawSceneId) ? rawSceneId : null;
|
||||
const finalMessage = extraContext.length > 0
|
||||
|
|
|
|||
|
|
@ -24,6 +24,22 @@ export function isSxyprnUrl(url: string | null | undefined): boolean {
|
|||
return !!url && /(?:^|\/\/|\.)sxyprn\.com\//i.test(url);
|
||||
}
|
||||
|
||||
// Diagnostyka: bug-report "sxyprn ładuje reklamy zamiast wideo" jest NIEreprodukowalny
|
||||
// z naszych IP (strona zwraca data-vnfo → resolver działa), więc podejrzenie na
|
||||
// region/IP-gate po stronie usera. Zapamiętujemy powód OSTATNIEGO resolve i doklejamy go
|
||||
// do auto-contextu zgłoszenia (BugReportFAB) — przy kolejnym raporcie zobaczymy CO sxyprn
|
||||
// realnie zwrócił temu userowi (http status / challenge / brak vnfo / ok_N), bez pytania.
|
||||
let _lastDiag: { at: number; reason: string } | null = null;
|
||||
function _diag(reason: string): void {
|
||||
_lastDiag = { at: Date.now(), reason };
|
||||
}
|
||||
/** Powód ostatniego resolve sxyprn + wiek w sekundach (null gdy nic jeszcze). */
|
||||
export function getSxyprnDiag(): string | null {
|
||||
if (!_lastDiag) return null;
|
||||
const ageS = Math.round((Date.now() - _lastDiag.at) / 1000);
|
||||
return `${_lastDiag.reason} ${ageS}s ago`;
|
||||
}
|
||||
|
||||
/** Suma cyfr w stringu (ssut51 z main2.js). */
|
||||
function ssut51(s: string): number {
|
||||
let sum = 0;
|
||||
|
|
@ -66,18 +82,38 @@ export async function resolveSxyprnPage(pageUrl: string): Promise<StreamLink[]>
|
|||
let html: string;
|
||||
try {
|
||||
const r = await fetch(pageUrl, { headers: { 'User-Agent': UA, Accept: 'text/html' } });
|
||||
if (!r.ok) return [];
|
||||
if (!r.ok) {
|
||||
_diag(`http_${r.status}`);
|
||||
return [];
|
||||
}
|
||||
html = await r.text();
|
||||
} catch {
|
||||
_diag('fetch_error');
|
||||
return [];
|
||||
}
|
||||
// Challenge / ad-gate: gdy user dostaje CF/turnstile albo interstitial zamiast strony
|
||||
// z playerem, resolve pada i coś w fallbacku pokazuje reklamę. To najbardziej
|
||||
// podejrzana ścieżka dla "ładuje reklamy" (region/IP-specific).
|
||||
if (/cf-challenge|challenge-platform|turnstile|Just a moment|Attention Required|Checking your browser/i.test(html)) {
|
||||
_diag(`challenge_${html.length}b`);
|
||||
return [];
|
||||
}
|
||||
if (html.includes('Post Not Found')) {
|
||||
_diag('post_not_found'); // usunięty post
|
||||
return [];
|
||||
}
|
||||
if (html.includes('Post Not Found')) return []; // usunięty post
|
||||
const m = _VNFO_RE.exec(html);
|
||||
if (!m) return [];
|
||||
if (!m) {
|
||||
// Brak data-vnfo: albo zmiana struktury, albo user dostał inną stronę (ad-gate).
|
||||
// Długość HTML rozróżnia "pełna strona bez vnfo" od "krótki interstitial".
|
||||
_diag(`no_vnfo_${html.length}b`);
|
||||
return [];
|
||||
}
|
||||
let vnfo: Record<string, unknown>;
|
||||
try {
|
||||
vnfo = JSON.parse(m[1]);
|
||||
} catch {
|
||||
_diag('vnfo_parse_err');
|
||||
return [];
|
||||
}
|
||||
const links: StreamLink[] = [];
|
||||
|
|
@ -100,5 +136,6 @@ export async function resolveSxyprnPage(pageUrl: string): Promise<StreamLink[]>
|
|||
type: 'mp4',
|
||||
});
|
||||
}
|
||||
_diag(links.length > 0 ? `ok_${links.length}` : 'vnfo_empty');
|
||||
return links;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue