# Recipe: descarga automática castellano gnula → Jellyfin Flujo completo validado 2026-05-30. Para promover a pipeline del registry (`download_gnula_movie_py_pipelines` o similar). Humano solo hace captcha si sale. ## 0. Infra previa (una vez) - Bridge NordVPN: `start_nordvpn_socks_bridge_bash_infra --port 8889` (creds env NORDVPN_SOCKS_USER/PASS de `pass datardos-vps/nordvpn`). gost SOCKS5→HTTP local. - Jellyfin realtime monitor ON en libs `media/movies`,`media/tv` (ya). - systemd-user timer `popelis-import.timer` (3min) → `popelis_import_media_drop` (manual→media+metadata). - Extensiones unpacked en Windows: `C:\Users\lucas\hls-dl-ext` (HLS+AES decrypt), `C:\Users\lucas\ubol` (uBlock Origin Lite MV3, mata ads/popunders). ## 1. Lanzar Chrome (Windows, visible) por NordVPN + CDP + extensiones ``` chrome.exe --remote-debugging-port=9222 --remote-debugging-address=0.0.0.0 \ --remote-allow-origins='*' \ --user-data-dir='C:\Users\lucas\AppData\Local\fn-chrome-cdp-profile' \ --proxy-server=http://127.0.0.1:8889 \ --disable-extensions-except='C:\Users\lucas\hls-dl-ext,C:\Users\lucas\ubol' \ --load-extension='C:\Users\lucas\hls-dl-ext,C:\Users\lucas\ubol' \ --no-first-run --no-default-browser-check --new-window "https://www.gnularetro.cc/release/2025/" ``` NOTA Chrome 148: `--load-extension` SOLO no carga las extensiones; hay que añadir `--disable-extensions-except` con los mismos paths. Verificar con browser-ws Target.getTargets (SW chrome-extension://) o chrome://extensions. gnula está ISP-bloqueado (Allot) + Cloudflare → NordVPN salta ISP, navegador real pasa CF. ## 2. Listado: detectar pelis con bandera España + dedup CDP eval en la página release: por cada `a[href*="/ver-pelicula/"]`, mirar imgs `/flags/`. - `es.png` = **España (Español/castellano)** — la que queremos. (En el LISTADO el alt-text está invertido: es.png alt="Latino". IGNORAR alt, usar el nombre de imagen es.png. Confirmado en la página de peli: el grupo es.png se etiqueta literalmente "Español".) - `mx.png` = México/Latino. `jp.png` = Subtitulado/VOSE. - Dedup: cruzar título vs `GET /api/v3/movie` de Radarr (key 63fb51c8...) — saltar los ya presentes. ## 3. Página de la peli: elegir server Español CDP: navegar al href. Las opciones de player son `li[data-nume]` (DooPlay): - Grupo "Español" (es.png) = dnume bajos; "Subtitulado" (jp.png) = dnume altos. - Servers: streamplay, **luluvid(=luluvdo)**, bigwarp, filemoon, dsvplay, powvideo, streamtape, vidmoly, voe. - PREFERIR luluvid/luluvdo (sabemos descifrar su HLS AES-128). Clic: `li[data-nume="2"].click()` (luluvid Español). - Carga iframe `lulustream.com/e/` → resuelve a `luluvdo.com/e/`. ## 4. Play (CDP) — método que FUNCIONA (sin depender de uBlock) luluvdo pone un **overlay ad click-catcher** `div` con `z-index>=1000` encima del player: el `.click()` JS no es gesto válido y un clic normal abre popunder. Solución validada (en el target del iframe luluvdo): 1. **Quitar overlays**: `document.querySelectorAll('div,iframe')` con `zIndex>=1000` → `.remove()` (quita ~4). 2. **Trusted click** en `.jw-icon-display`/video via `Input.dispatchMouseEvent` (coords del rect). 3. `jwplayer().play(true)`. → video.paused=false + master.m3u8 pedido. Captcha real (si sale) = humano. - Cerrar popunders: `GET /json/list` → cerrar targets que no sean gnula/luluvdo (`/json/close/`). - uBlock: `--load-extension` SOLO falló en Chrome 148 (ver gotcha); NO es necesario para play (el overlay se quita in-page). Útil solo para reducir popunders generales. ## 5. Descarga streaming + descifrado (NO blob → no peta Chrome) `temp/grab_stream.py `: - Conecta CDP al iframe player. - Lee master.m3u8 (de performance entries) → variante → media playlist. - AES-128: `#EXT-X-KEY` (key url + IV; sin IV → IV=media-sequence en 16B BE). - Por segmento: in-page `fetch(seg)→arrayBuffer→base64` (sesión browser=pasa 522 CF) → CDP → LOCAL: base64decode + `AES.new(key,CBC,iv).decrypt` + unpad PKCS7 + append a `/tmp/grab/.ts`. (1 segmento en RAM a la vez → aguanta pelis grandes.) - Remux `ffmpeg -c copy` .ts→.mkv directo a `F:\POPELIS\manual\movies\.mkv`. Borra .ts. ## 6. Import + Jellyfin (automático) - systemd timer (3min) corre `popelis_import_media_drop` → identifica (Radarr/TMDb) + mueve manual/movies → media/movies con ficha → Jellyfin realtime monitor → aparece. - (o lanzar import on-demand: `RADARR_KEY=.. SONARR_KEY=.. python popelis_import_media_drop.py --apply`) ## Gotchas - blob-en-memoria petaba Chrome con peli 3.4GB → usar grab_stream.py (streaming). - Token master.m3u8 caduca ~8h + ligado a IP de salida → descargar por el MISMO proxy/sesión. - 522 CF sólo afecta clientes externos (curl/ffmpeg/yt-dlp); la sesión viva del navegador = 200. - Multi-audio urlset: el variant elegido trae 1 audio (el del grupo Español = castellano). - chrome.downloads / a.click() blob cae en Downloads, NO respeta setDownloadBehavior → por eso grab_stream.py escribe directo a disco vía CDP+local, evitando el download del navegador. - **`--load-extension` falla en Chrome 148**: las extensiones unpacked (hls-dl-ext, ubol) NO cargaron (Target.getTargets no lista sus SW + overlay ad seguía). Fix a probar: añadir `--disable-extensions-except=''` junto a `--load-extension`. Pero NO es necesario para el flujo: el overlay se neutraliza in-page (paso 4). uBOL Lite (MV3 DNR) además NO mata bien el click-catcher inyectado por JS (limitado vs uBO full, que es MV2 y Chrome 148 ya no admite). Conclusión: depender del paso-4 in-page, no de uBlock.