---
name: popelis_import_media_drop
kind: function
lang: py
domain: infra
version: 1.0.0
purity: impure
description: "Importa drops de Popelis (manual/movies, manual/tv) via Radarr/Sonarr: identifica contra TMDb/TVDB, da de alta peli/serie con metadata y mueve+renombra a la libreria limpia que ve Jellyfin."
signature: "def popelis_import_media_drop(radarr_url: str, radarr_key: str, sonarr_url: str, sonarr_key: str, movies_drop: str = '/data/manual/movies', tv_drop: str = '/data/manual/tv', movie_root: str = '/data/media/movies', tv_root: str = '/data/media/tv', quality_profile_id: int = 4, import_mode: str = 'move', dry_run: bool = False, series_refresh_wait: float = 6.0, timeout: float = 60.0) -> dict"
error_type: error_go_core
returns_optional: false
tags: [popelis, radarr, sonarr, jellyfin, media, import, mediastack, http, infra]
uses_functions: []
uses_types: []
imports: [json, re, time, urllib]
tested: false
file_path: python/functions/infra/popelis_import_media_drop.py
params:
  - name: radarr_url
    desc: "URL base de Radarr sin trailing slash. Ej http://localhost:7878"
  - name: radarr_key
    desc: "API key de Radarr (Settings > General > Security). Secreto."
  - name: sonarr_url
    desc: "URL base de Sonarr. Ej http://localhost:8989"
  - name: sonarr_key
    desc: "API key de Sonarr. Secreto."
  - name: movies_drop
    desc: "Carpeta drop de pelis EN EL NAMESPACE de Radarr (/data/manual/movies)."
  - name: tv_drop
    desc: "Carpeta drop de series EN EL NAMESPACE de Sonarr (/data/manual/tv)."
  - name: movie_root
    desc: "Root folder de Radarr donde se mueven las pelis (/data/media/movies)."
  - name: tv_root
    desc: "Root folder de Sonarr donde se mueven las series (/data/media/tv)."
  - name: quality_profile_id
    desc: "Quality profile id para altas nuevas. 4 = HD-1080p en el stack Popelis."
  - name: import_mode
    desc: "'move' (default, borra el origen) o 'copy'."
  - name: dry_run
    desc: "Si True no escribe nada: solo reporta que haria. Default False."
  - name: series_refresh_wait
    desc: "Segundos a esperar tras dar de alta una serie antes de re-listar el drop (Sonarr refresca episodios async). Default 6.0."
  - name: timeout
    desc: "Timeout HTTP por peticion en segundos. Default 60.0."
output: "Dict {movies: [...], tv: [...], summary: {...}}: una entrada por fichero/serie con su status (import_queued | added | no_match | still_unmatched | would_*) y contadores agregados en summary."
---

Importa una carpeta drop del stack Popelis (Radarr/Sonarr/Jellyfin) anadiendo
metadata. El usuario suelta ficheros sueltos en `manual/movies` o `manual/tv`;
esta funcion los identifica contra TMDb/TVDB, da de alta la pelicula/serie con
su ficha (poster, fanart, sinopsis) y dispara un ManualImport que mueve+renombra
el fichero a la libreria limpia (`media/movies`, `media/tv`). Radarr/Sonarr son
la unica fuente de verdad de metadata; Jellyfin solo escanea `media/` y nunca
mete fichas fantasma de descargas a medias.

## Ejemplo

```python
from infra.popelis_import_media_drop import popelis_import_media_drop

# Dry-run primero (no escribe nada)
res = popelis_import_media_drop(
    radarr_url="http://localhost:7878",
    radarr_key="63fb51c8c95746e2a327740baac02f5e",
    sonarr_url="http://localhost:8989",
    sonarr_key="1c6f380b1cca49b8b1223570e80f0071",
    dry_run=True,
)
print(res["summary"])
# {'movies_queued': 1, 'movies_unmatched': 0, 'tv_queued': 0,
#  'tv_added_series': 1, 'tv_unmatched': 0, 'dry_run': True}

# Aplicar de verdad (mueve ficheros + descarga metadata)
res = popelis_import_media_drop(
    radarr_url="http://localhost:7878", radarr_key="...",
    sonarr_url="http://localhost:8989", sonarr_key="...",
    dry_run=False,
)
```

CLI directo (lee keys de env):

```bash
RADARR_KEY=... SONARR_KEY=... \
  python/.venv/bin/python3 python/functions/infra/popelis_import_media_drop.py --apply
```

## Cuando usarla

- Cuando sueltas pelis/series sueltas en `F:/POPELIS/manual/{movies,tv}` y quieres
  que Radarr/Sonarr las identifiquen, descarguen ficha y las muevan limpias a la
  libreria que ve Jellyfin.
- Antes de mirar Jellyfin: pasa esta funcion para que la libreria solo contenga
  media identificada (sin fichas fantasma).
- Lanzala on-demand tras cada drop. Para automatizar, envuelvela en un watcher/cron.

## Gotchas

- **Paths en namespace de contenedor**: `movies_drop`/`tv_drop`/`movie_root`/`tv_root`
  son paths DENTRO de Radarr/Sonarr (`/data/...`), NO del host. Radarr y Sonarr
  montan `F:/POPELIS` en `/data`.
- **Permisos del drop (Windows bind)**: las carpetas drop deben ser escribibles
  por el usuario del contenedor (PUID, abc/1000 en linuxserver). Si las creas como
  root, `import_mode=move` falla con `UnauthorizedAccessException`. Fix:
  `docker exec -u 0 radarr chown -R 1000:1000 /data/manual`.
- **Numeracion DVD vs aired**: releases en orden DVD (ej. Futurama S01 con 13 eps)
  chocan con TVDB en orden emision (S01 = 9 eps). Los episodios fuera de rango
  quedan `still_unmatched` con reason `Invalid season or episode` y permanecen en
  el drop. No es un bug: requiere resolucion manual o cambiar el series type a
  'DVD' en Sonarr.
- **Lookup coge el primer resultado**: titulos ambiguos pueden matchear mal.
  Revisa el report antes de confiar; usa `dry_run=True` primero.
- **No renombra si la *arr no lo tiene activado**: el fichero se mueve a la carpeta
  correcta pero conserva su nombre original salvo que actives "Rename" en la config
  de naming de Radarr/Sonarr.
- **import_mode='move' borra el origen**: usa 'copy' si quieres conservar el drop.
- **Secretos**: `radarr_key`/`sonarr_key` son API keys. No logear ni interpolar en URLs.
- **Solo stdlib**: usa `urllib`, sin `requests`.

## Capability growth log

(sin cambios desde v1.0.0)
