Uso › Web UI¶
La Web UI è una SPA React servita da FastAPI. Copre l'intero workflow di pre-flight Unit3D dal browser: scansione libreria, upload guidato, coda torrent, storico, configurazione, log in tempo reale, integrazione live con Unit3DWebUp. Disponibile in italiano e inglese (selettore nella TopBar).
Avvio:
Apri l'URL risultante (http://<U3DP_HOST>:<U3DP_PORT><U3DP_ROOT_PATH>, default http://127.0.0.1:8765). Assicurati che Unit3DWebUp sia in ascolto su WEBUP_URL (default 127.0.0.1:8000).
Login¶
Schermata iniziale: campo password. Credenziali validate contro U3DP_PASSWORD_HASH (bcrypt). La sessione è firmata con U3DP_SECRET (itsdangerous) e dura finché il browser mantiene il cookie.
Middleware order
Dietro le quinte: SessionMiddleware deve essere aggiunto dopo il middleware auth (LIFO = l'ultimo è l'outermost). Se vedi AssertionError: SessionMiddleware must be installed, è un bug — apri un issue.
Media Library¶

Lista le categorie (sottocartelle di U3DP_MEDIA_ROOT) e gli item al loro interno.
Funzionalità:
- Dropdown categoria — auto-scoperte (
GET /api/library/categories). Non hardcoded. - Lista item — ogni riga mostra titolo, anno (se da TMDB), dimensione totale, lingue audio rilevate.
- Ordinamento — nome, anno, dimensione.
- Ricerca — filtro live sul nome.
- Nascondi uploadati — toggle controllato da
W_HIDE_UPLOADED. - Filtro lingua — dropdown con le lingue trovate nella categoria corrente, separate fra audio e sottotitoli e con il numero di elementi per ciascuna; mostra solo i media che contengono la lingua scelta. Si azzera con la × e al cambio categoria.
- Solo da controllare — toggle che mostra solo i media marcati "da controllare" (vedi sotto).
- Detail panel — click su un item apre un panel laterale (mobile: overlay a tutto schermo) con file list, match TMDB, azioni.
- Rescan lingue audio — bottone che stream-a via SSE la scansione
pymediainfoaggiornando la cache. - Match TMDB manuale — campo per inserire un ID, bottone cerca con preview risultati.
- Selezione multipla — checkbox su ogni item; action bar con "Seleziona tutto", "Deseleziona", "Marca come caricato" per operazioni in blocco.
- Filtro tipo — toggle per mostrare solo film (
kind === 'movie'), nascondendo serie e stagioni. - Mark uploaded a tutti i livelli — per le serie: intera serie, singola stagione, singolo episodio.
- Da controllare (⚑) — bottone per marcare un media da ricontrollare (es. manca la traccia audio italiana). Persistente e removibile con un click; disponibile a tutti i livelli (film, episodio, stagione, serie intera). I media segnati mostrano un badge giallo "da controllare" ed è possibile filtrarli con il toggle Solo da controllare. Endpoint:
POST /api/library/{category}/{item}/to-check.
Endpoint coinvolti: GET /api/library/categories, GET /api/library/{category}, GET /api/library/{category}/{item}, POST /api/library/{category}/{item}/langs, POST /api/tmdb/search, POST /api/tmdb/fetch.
Upload Wizard¶

Flusso guidato in step. Alternativa alla CLI con storico persistente, progress bar grafica e log live SSE.
Step tipici:
- Seleziona sorgente — file o cartella sotto
U3DP_MEDIA_ROOT. - Check audio — se
W_AUDIO_CHECK, scansiona le tracce. - TMDB — ricerca o inserimento ID. Se
W_AUTO_TMDB, auto-fetch da ID esistente. - Preview nome — editabile; se
W_CONFIRM_NAMESè OFF, salta la conferma. - Controllo duplicati — se
W_DUPLICATE_CHECK(default ON), interroga l'API ITT prima dell'hardlink. Se trova un torrent con la stessa dimensione esatta, mostra un pannello giallo (vedi sotto). Saltato per i season pack. - Hardlink — in
U3DP_SEEDINGS_DIR/.unit3dprep/<jobid>/...(sandbox per-upload, vedi Integrazione Unit3DWebUp). SeW_HARDLINK_ONLY, termina qui e registra exit code0. - Upload — il bridge HTTP esegue
setenv → scan → maketorrent → upload → seedsu Unit3DWebUp e stream-a log + progress al frontend via SSE (GET /api/wizard/{tok}/upload). Phase weights mostrati in barra: setenv 3% / scan 27% / maketorrent 45% / upload 15% / seed 10%. - Registrazione storico —
update_exit_code(seeding_path, code)scrive inU3DP_DB_PATH(anche suwizard_finishquandoW_HARDLINK_ONLY=1, exit code 0).
Controllo duplicati pre-upload¶
Replica il comportamento del vecchio unit3dup CLI: prima di creare il .torrent, il bridge chiama GET <ITT_URL>/api/torrents/filter?tmdbId=<id>&api_token=<key> e confronta data[].attributes.size byte-per-byte con la dimensione del file locale. Match esatto → pannello giallo con:
- Nome, dimensione, tipo/risoluzione, uploader, seeders/leechers, data creazione;
- Link "Apri sul tracker" alla pagina dei dettagli;
- "Carica comunque" → procede con hardlink + upload (utile se si tratta di una re-release legittima o di un'altra fonte);
- "Annulla" → registra una entry nello storico con status
⏭ duplicato skippato, nasconde l'item dalla Media Library (source_pathfinisce inuploaded_paths), e termina il wizard senza creare l'hardlink.
Webup 0.0.25 NON implementa duplicate detection (DUPLICATE_ON/SKIP_DUPLICATE sono # Todo Not yet implemented upstream): il check è eseguito dal bridge unit3dprep e funziona solo su kind=movie e kind=episode. Per i season pack la somma totale dei byte non corrisponde a nessun singolo torrent sul tracker, quindi il check viene saltato.
Best-effort: se l'API ITT è irraggiungibile o ritorna un errore, il check viene saltato silenziosamente e l'upload prosegue normalmente. Disabilitabile globalmente da Settings → Default wizard → Controllo duplicati sul tracker.
Quick upload¶
POST /api/upload/quick salta gran parte del wizard per utenti esperti: ricevi direttamente un job ID e consumi GET /api/upload/{job}/stream. Usalo se hai già file rinominati in ~/seedings/. Il flow chiama stream_webup direttamente, senza pre-flight di unit3dprep.
Dry-run¶
Se U3DP_DRY_RUN_TRACKER=1, il wizard salta /upload ma esegue tutto il resto. Utile in dev/WSL.
Upload Queue¶

Mostra i torrent attivi nel client configurato (TORRENT_CLIENT nel .env: qbittorrent, transmission, rtorrent).
- Filtro per nome e per stato (downloading, seeding, paused, error).
- Refresh automatico.
- Link ai file locali.
Endpoint: GET /api/queue. Credenziali client lette dalle chiavi QBIT_* / TRASM_* / RTORR_* del .env condiviso.
Uploaded (storico)¶
Tabella degli upload completati (GET /api/uploaded). Campi:
- Path locale in
~/seedings/. - Stato del record:
✓ exit 0— upload completato regolarmente.✗ exit N— fallito col codice indicato.pending— exit code mai registrato (vedi nota qui sotto).manual—W_HARDLINK_ONLY=1(solo hardlink, niente upload).⏭ duplicato skippato— l'utente ha annullato dopo che il controllo duplicati ha trovato un torrent con la stessa dimensione esatta. Ilduplicate_info(id, nome, link tracker, ecc.) è persistito nel DB per audit.
- Tracker di destinazione.
- Timestamp.
- Dimensione.
- Ricerca e filtro.
Stat card in cima: Totale, Completati, Falliti, Hardlink only, Duplicati skippati.
Su mobile la tabella ha overflow-x:auto con min-width:820px per garantire leggibilità su schermi stretti.
Record pending che non si chiudono
Se un record rimane pending dopo un upload riuscito, significa che l'endpoint non ha chiamato update_exit_code. È un bug noto in caso di modifiche a quickupload.py o wizard.py — vedi Troubleshooting.
Search Tracker¶

Ricerca un torrent su ITT (sempre) e su PTT/SIS (se configurati con URL + API key valide nel .env).
- Tab per tracker.
- Mostra link, dimensione, seeders, freeleech, data upload.
- Utile per duplicate-check prima di caricare.
Endpoint: GET /api/trackers (status) + GET /api/search?q=.... Sotto il cofano POST /api/webup/filter proxia Unit3DWebUp /filter.
Stato tracker
Un tracker appare "Online" solo se URL e API key sono entrambi settati e la API key non è il placeholder "no_key". I tracker nella sidebar sono tutti elencati, anche quelli non configurati (badge grigio "Not set").
Settings¶

Editor completo del .env condiviso direttamente dal browser. Ogni Save:
- scrive atomico in
$ENVPATH/.env(nomenclatura canonicaTRACKER__* / TORRENT__* / PREFS__*su disco); - propaga le chiavi modificate a Unit3DWebUp via
POST /setenv(no restart richiesto).
Sezioni:
- Tracker — URL, API key, PID per ITT / PTT / SIS; lista
MULTI_TRACKER. - Metadata — TMDB, TVDB, IGDB, YouTube.
- Torrent client — tipo + credenziali (qBit / Transmission / rTorrent).
- Image host — ordine preferenza + API key per PTSCREENS, PASSIMA, IMGBB, IMGFI, ecc. L'ordine nella lista è proiettato in
PREFS__<HOST>_PRIORITY(1, 2, …, 99 per host non in lista). - Opzioni upload —
ANON,PERSONAL_RELEASE,NUMBER_OF_SCREENSHOTS,COMPRESS_SCSHOT,TAG_ORDER_*, ecc. - Seeding Flow —
U3DP_*con valori effettivi (env vs file) viaenv_runtime(). Read-only perUNIT3DUP_CONFIG. - Radarr / Sonarr — URL e API key delle due istanze, con test di connessione. Vedi sezione dedicata.
- Versione — vedi sezione dedicata.
- App Auto-Update —
U3DP_SYSTEMD_UNIT, nome systemd user unit usata dal bottone "Update app" per il restart post-aggiornamento. Defaultunit3dprep-web.service; override solo se la tua unit ha un nome diverso. - Wizard Defaults — tutte le
W_*. - Interface — selettore lingua (IT / EN); preferenza salvata in
localStoragee sincronizzata conU3DP_LANGviaPUT /api/settings.
Secret mascherati come __SET__ — il campo appare riempito. Modificare altre chiavi non cancella i secret.
Endpoint: GET /api/settings, PUT /api/settings, GET /api/settings/fs-check.
Mobile: la nav a sinistra diventa una riga orizzontale scrollabile; le griglie 2-col collassano in 1-col.
Versione e auto-update¶
In Settings › Versione trovi due card affiancate:
- App — versione corrente (
importlib.metadataopyproject.tomlin modalità git) vs ultima release GitHub. - Unit3DWebUp — versione installata nel venv di webup vs ultima su PyPI.
Ogni card espone:
- Pulsante Controlla aggiornamenti (force
POST /api/version/refresh— bypassa cache 10 min). - Pulsante Installa aggiornamento (visibile solo se
newer == true). - Accordion Changelog con il body della release GitHub (per app) o link a PyPI (per webup).
Click su Installa:
- Modal
UpdateProgressModalcon logpip/gitlive-streamed via SSE (GET /api/version/update/{app|webup}/stream). - Backend invalida
_cachedi/api/version/infosudone, riavvia systemd in scope transient (systemd-run --user --on-active=3s). - Countdown 5s + reload del browser; popup post-reload con il changelog (chiave
unit3dprep.pendingChangelogin localStorage).
EventSource auto-riconnette
Se un endpoint SSE chiude la connessione (es. dopo systemctl restart), il browser ripete la richiesta → re-esecuzione dell'endpoint. Il modal chiama closeSSE() su done/error per evitare il loop. Se modifichi il modal, mantieni questo invariante.
Endpoint: GET /api/version/info, GET /api/version/changelog?v=X, GET /api/version/update/{app|webup}/stream (SSE), POST /api/version/refresh.
Health Unit3DWebUp¶
In Settings › Tracker (o sezione Integrazioni a seconda del rendering) compare la card Unit3DWebUp:
- Stato
online/offline(cache 5s, ping aWEBUP_URL/setting). - Versione installata.
- Latenza ping in ms.
- Indicatore WebSocket (connessione attiva al canale eventi del bot).
- Pulsante "Spingi config" — esegue
POST /api/webup/sync(push di tutto il payload.envmappato a webup, utile dopo ripristino backup o se sospetti drift). - Pulsante "Aggiorna" — link rapido alla card Versione.
Endpoint: GET /api/webup/health, POST /api/webup/sync, GET /api/webup/setting.
Logs¶
Stream log in tempo reale via SSE. Tutto ciò che uvicorn / l'app scrive su logbuf (unit3dprep/web/logbuf.py) arriva qui, classificato per:
- source —
app,wizard,quickupload,webup(rimpiazzaunit3duplegacy),system. - kind —
info/ok/warn/error/progress.
Filtri persistiti in localStorage (chiavi unit3dprep.logs.{hiddenSources,hiddenKinds,autoScroll}).
Utile per debugging senza aprire una shell sul VPS.
Note mobile (≤768px)¶
La UI è responsive:
- Sidebar — si chiude in
translateX(-100%), scrim overlay quando aperta. - Modal — full-bleed con padding 14px.
- Library detail — overlay
position:fixed; inset:0invece del panel laterale da 360px. - Settings nav — riga orizzontale scrollabile.
- Tabelle —
overflow-x:auto.
Breakpoint gestito da isMobile (App.tsx → Sidebar / TopBar / Library / Settings via props).
Bisogni accesso programmatico?¶
Tutte le view della UI consumano l'API JSON sotto {U3DP_ROOT_PATH}/api/*. Puoi chiamarla direttamente con cookie di sessione valido. Vedi unit3dprep/web/api/*.py per la lista completa dei router (settings, version, webup, library, queue, uploaded, search, tmdb, fs).
Radarr e Sonarr¶
Configura URL e API key in Impostazioni → Radarr / Sonarr e usa Test connessione per verificarli. Il test interroga le credenziali salvate, quindi resta disabilitato finché ci sono modifiche non salvate. Radarr e Sonarr devono vedere lo stesso filesystem di unit3dprep: l'accoppiamento fra libreria e monitoraggio avviene per path.
Quando l'integrazione è attiva la libreria mostra un badge monitorato su ciò che Radarr o Sonarr stanno ancora cercando. Il pulsante di rimozione compare solo lì:
- Film — nel pannello dettaglio.
- Serie — nel pannello dettaglio; spegne anche tutte le stagioni e tutti gli episodi.
- Stagione — icona nell'intestazione della stagione; spegne anche i suoi episodi.
- Episodio — icona sulla riga dell'episodio.
Il monitoraggio si può solo rimuovere, non riattivare.
La card della serie resta monitorata dopo aver spento tutte le stagioni
Sonarr mantiene il flag series.monitored indipendente da quello delle singole
stagioni: se rimuovi il monitoraggio stagione per stagione, la serie può restare
marcata come monitorata anche a zero stagioni attive. È il comportamento corretto
di Sonarr, non un bug — usa il pulsante di rimozione a livello di serie per
spegnere anche quel flag.
Per lavorare in blocco: filtra per Lingua, entra in selezione multipla, seleziona e usa Rimuovi monitoraggio. Gli elementi che Radarr e Sonarr non conoscono, o che sono già senza monitoraggio, vengono esclusi automaticamente; i film vengono spenti in un colpo solo, le serie a cascata (più cascate in parallelo, con un limite di concorrenza per non sovraccaricare Radarr/Sonarr), e alla fine un avviso riporta quanti sono riusciti e quanti no.
Se Radarr o Sonarr non rispondono, la libreria funziona come sempre e in cima compare un avviso: badge e pulsanti restano nascosti finché il servizio non torna.