docs(claude): add resolve/playback findings + local debugging guide
Capture the durable Goon facts (phone-side resolve for IP-bound/Turnstile hosters, DoodStream/playmogo pass_md5, _embed_iframe vs _vps_blocked_fallback, stable image proxy tokens, paradisehill multipart, dedup/merge) and a local-debugging section (prod psql/worker patterns, Windows real-Python gotcha, Android emulator AVD `goon` + FLAG_SECURE-off screencap + 2x OTA apply, Chrome DevTools port 9223 + CDP-blanking + hoster network signatures). No secrets/IPs/usernames — env-var forms only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
904f8984c8
commit
953068f0db
1 changed files with 32 additions and 0 deletions
32
CLAUDE.md
32
CLAUDE.md
|
|
@ -30,6 +30,38 @@ Reguły:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Resolve / playback (kluczowe ustalenia)
|
||||||
|
|
||||||
|
Stream resolve jest **on-demand, per-source**. Nic nie jest pre-resolvowane do DB poza miniaturkami i metadanymi.
|
||||||
|
|
||||||
|
- **Registry ekstraktorów**: `app/extractors/__init__.py` `_REGISTRY` mapuje `sitetag` na funkcję. Natywny ekstraktor zwraca `list[StreamSource]`. `_vps_blocked_fallback.extract` = sygnał "resolve tylko w WebView na telefonie" (sprawdzaj `is_vps_blocked_fallback(sitetag)`).
|
||||||
|
- **IP-bound / CAPTCHA hosterzy resolwują się PO STRONIE TELEFONU**, nie na VPS. CDN tokeny i Cloudflare Turnstile wiążą się z IP requestera, więc VPS (Hetzner) dostaje 403 albo Turnstile gate, a residential IP telefonu przechodzi. Resolvery phone-side: `mobile/src/lib/{doodstream,packerHoster,filemoonHoster,getfileResolver,pornxpResolver}.ts`. `PlayerScreen.tsx` routuje URL `type='hoster'`: `isDoodStream`→`resolveDoodStream`, `isPackerHoster`→`resolvePackerHoster`, `isFilemoonHoster`→`resolveFilemoonHoster`.
|
||||||
|
- **DoodStream i klony** (playmogo, doply, dood.*): protokół `pass_md5` + infra `doodcdn.io` + **niewidzialny** Cloudflare Turnstile (przechodzi automatycznie w WebView z residential IP, to NIE interaktywny CAPTCHA). Tube który embeduje playmogo (sxyland, xmoviesforyou, siska) ma iść przez `_embed_iframe.extract` (wyłuskuje iframe, oddaje `type='hoster'`, telefon dood-resolwuje), NIE przez `_vps_blocked_fallback`.
|
||||||
|
- **Image proxy**: WSZYSTKIE miniaturki idą przez `/proxy/img/{token}/...` (backend dokłada Referer, którego expo-image nie wysyła → CDN by zwracał 403). Token MUSI być stabilny (`make_token(..., stable_bucket_sec=...)`), inaczej URL zmienia się co request → expo-image cache miss → re-download co fetch/launch.
|
||||||
|
- **Movies multipart** (paradisehill): backend parsuje `var videoList` i zwraca wszystkie części jako osobne `StreamLink`; mobile pokazuje je w **scrollowalnym Modalu** (nie `Alert.alert` — Androidowy AlertDialog renderuje max 3 buttony, stąd dawne "max 3 z 35").
|
||||||
|
- **Dedup**: `app/scheduler/bulk_dedup.py` (cross-source performer-shared + `phash_exact`). `merge_scenes` (`app/resolve/scene_merge.py`) przenosi refs/performers/tags/fingerprints/**playback_sources** i kasuje drop. Missing-merge bez phash: `scripts/merge_exact_title_duration.py` (ten sam performer + identyczny znormalizowany tytuł + długość co do sekundy). Over-attribution performerów bierze się z luźnego tube-searcha (hqporner wymaga WSZYSTKICH tokenów query w slug).
|
||||||
|
- **Bug reports z apki**: tabela `bug_reports` na prodzie (`screen_name`, `scene_id`, `movie_id`, `message`, `screenshot_b64`, `resolved`). To główne źródło triage'u. Screenshot dekodujesz z base64 i oglądasz.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lokalny debugging
|
||||||
|
|
||||||
|
Hosta VPS, klucze API i wartości env trzymaj w prywatnej pamięci / `.env.local`. NIE commituj ich tu (repo jest publiczne).
|
||||||
|
|
||||||
|
- **DB / worker na prodzie** (przez ssh na VPS): `docker compose exec -T db psql -U goon -d goon -c "..."` (pamiętaj `-U goon`, bez tego "role root does not exist"). Python w workerze: `docker compose exec -T worker python3 -c "..."` albo heredoc. `from app.db import session_scope` (NIE `app.db.session`).
|
||||||
|
- **Deploy backendu**: `scp app/...` na VPS + `docker compose restart worker api`. Wolumeny `./app` i `./scripts` → restart wystarcza, bez rebuildu.
|
||||||
|
- **Windows: prawdziwy Python**. `python`/`python3` na PATH to STUB ze Sklepu Microsoft (wypisuje "Python was not found" i wychodzi). Użyj realnego interpretera: `%LOCALAPPDATA%\Programs\Python\Python3XX\python.exe` (uruchamiaj przez PowerShell). `publish_update.py` po sukcesie kończy się czysto (UTF-8 stdout wymuszony 2026-06-08, koniec mylącego exit-1 na polskich znakach).
|
||||||
|
- **Emulator Android** (podgląd odtwarzania scen i UI):
|
||||||
|
- adb: `%ANDROID_HOME%\platform-tools\adb.exe` (`ANDROID_HOME` ustawiony; SDK NIE w domyślnym `%LOCALAPPDATA%\Android\Sdk`). AVD: **`goon`**.
|
||||||
|
- Start: `emulator -avd goon -no-snapshot-load -no-boot-anim -gpu swiftshader_indirect` (w tle). Czekaj na boot: `adb wait-for-device` + poll `adb shell getprop sys.boot_completed` == `1`.
|
||||||
|
- Pakiet apki: `com.goon.mobile`. Launch: `adb shell monkey -p com.goon.mobile -c android.intent.category.LAUNCHER 1`.
|
||||||
|
- **Screencap działa bo dev/emulator build ma `FLAG_SECURE` WYŁĄCZONE.** Release build ustawia `FLAG_SECURE` (blokuje screenshoty/nagrywanie ekranu treści NSFW) — w buildzie emulatora zostawiamy off, żeby AI mógł `adb exec-out screencap -p > out.png` i zweryfikować odtwarzanie/UI.
|
||||||
|
- **OTA na emulatorze**: po publish force-stop + launch **2×** (1. pobiera bundle w tle, 2. aplikuje).
|
||||||
|
- Gesty przez adb: tap `adb shell input tap X Y` (współrzędne device, sprawdź `wm size`, zwykle 1080x2400). Long-press: `adb shell input swipe X Y X Y 700` (ten sam punkt, >300ms = `delayLongPress`). Bounds elementów: `adb shell uiautomator dump` (RN czasem nie eksponuje tekstu, natywne Alert/dialogi tak).
|
||||||
|
- **Chrome DevTools (diagnoza hosterów/playbacku — sprawdzaj, nie zgaduj)**: odpal Chrome `--remote-debugging-port=9223 --user-data-dir=<temp>`; podłącza się `chrome-devtools` MCP. KVS/dood tubes **blankują się na wykrycie CDP** (strona → about:blank) → używaj `list_network_requests(includePreservedRequests=true)` zamiast DOM. Sygnatury w trace: `pass_md5` + `doodcdn.io` = DoodStream; `kt_player(` + `license_code` = KVS; `cdn-cgi/challenge-platform` + `turnstile` = Cloudflare (sprawdź czy invisible).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Kanban (auto-aggregation)
|
## Kanban (auto-aggregation)
|
||||||
|
|
||||||
Ten workspace ma własny Kanban (custom tracker type `kanban` w `.nimbalyst/trackers/kanban.yaml`) z kolumnami:
|
Ten workspace ma własny Kanban (custom tracker type `kanban` w `.nimbalyst/trackers/kanban.yaml`) z kolumnami:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue