- /api/v2/* : login SID (mot de passe = clé Torznab), app/version, torrents/info (progression temps réel), properties (content_path), add (rejoue le grab encodé dans le .torrent de service, dédupliqué par infohash SHA-1), delete (± fichiers), pause/resume - Les grabs Sonarr sont marqués « sonarr:<hash>| » dans source_key → suivis de bout en bout : Sonarr importe, renomme et range les épisodes dans sa bibliothèque, puis retire le torrent de la file Ohm - L'indexeur Torznab embarque les paramètres du grab dans l'announce - README : nouveau mode « client de téléchargement » recommandé (Remote Path Mapping documenté), blackhole en variante minimale - 3 nouveaux tests (flux complet add → suivi → import → delete)
215 lines
9.2 KiB
Markdown
215 lines
9.2 KiB
Markdown
# ⛩ Ohm Stream Downloader
|
|
|
|
Application web **auto-hébergée** (homelab) : centre de contrôle unique pour découvrir,
|
|
regarder et télécharger des animes et séries VOSTFR/VF.
|
|
|
|
## Déploiement (Docker) — recommandé
|
|
|
|
Le déploiement officiel passe par Docker Compose : l'image (ffmpeg inclus) est
|
|
hébergée sur le **registre privé du Gitea** — rien n'est publié publiquement.
|
|
|
|
### Installation guidée (recommandée)
|
|
|
|
```bash
|
|
git clone https://git.lanro.eu/Roman/ohm_streaming.git && cd ohm_streaming
|
|
./scripts/install.sh
|
|
```
|
|
|
|
Le script vérifie Docker, demande la **destination des épisodes** (dossier dédié
|
|
recommandé — voir « Bibliothèque Plex/Sonarr » ci-dessous), le port, génère les
|
|
secrets, branche le montage et démarre. Non interactif aussi :
|
|
`./scripts/install.sh --dir /srv/animes --port 8777 --skip-login`.
|
|
|
|
### À la main
|
|
|
|
```bash
|
|
# 1. Récupérer le projet puis se connecter au registre privé (compte Gitea avec accès lecture)
|
|
git clone https://git.lanro.eu/Roman/ohm_streaming.git && cd ohm_streaming
|
|
docker login git.lanro.eu
|
|
|
|
# 2. Configuration locale
|
|
cp .env.example .env
|
|
# → OHM_SECRET_KEY (openssl rand -hex 32) et WATCHTOWER_TOKEN (openssl rand -hex 24) obligatoires
|
|
|
|
# 3. Démarrage
|
|
docker compose up -d
|
|
```
|
|
|
|
Puis ouvrir http://localhost:8777 — le **premier compte créé est administrateur**.
|
|
Les données (`data/`, `downloads/`) sont montées en volumes : elles survivent aux
|
|
|
|
|
|
### Bibliothèque Plex / Sonarr existante
|
|
|
|
Ohm peut déposer ses épisodes directement dans ton serveur de média :
|
|
|
|
1. **Crée un dossier dédié** (recommandé : hors de la racine Sonarr, ex.
|
|
`/plex_videos/ohm`) et monte-le à la place de `./downloads` :
|
|
`- /plex_videos/ohm:/downloads` — c'est ce que fait `scripts/install.sh`.
|
|
2. **Ajoute ce dossier à Plex** comme dossier d'une bibliothèque (ou comme
|
|
dossier supplémentaire de ta bibliothèque animes). Les épisodes arrivent
|
|
rangés par animé : `One Piece/One Piece - E1010 (VOSTFR).mp4` — le nom du
|
|
dossier sert de série, le fichier d'épisode.
|
|
3. **Sonarr n'est pas touché** : l'entrypoint du conteneur ne prend possession
|
|
(`chown`) que d'un dossier de téléchargements **vide** ; une bibliothèque
|
|
existante et ses droits restent intacts. Pour piloter Ohm depuis Sonarr ou
|
|
Prowlarr, voir l'API Torznab plus bas.
|
|
|
|
Si tu pointes `/downloads` sur un dossier **non vide**, Ohm adopte les fichiers
|
|
présents (ils apparaissent dans sa bibliothèque interne) et conserve les droits
|
|
existants — assure-toi juste que l'uid 1000 du conteneur peut y écrire.
|
|
|
|
### Mettre à jour
|
|
|
|
**Depuis l'interface** (déploiement Docker) : page **Admin → Mise à jour** —
|
|
configurer une fois le dépôt Gitea + un jeton d'accès (droit lecture), puis
|
|
« Vérifier » et « ⬆ Mettre à jour maintenant ». Watchtower tire la nouvelle
|
|
image et recrée le conteneur : quelques secondes d'indisponibilité, les pages
|
|
ouvertes se reconnectent et rechargent automatiquement.
|
|
|
|
**En ligne de commande** (toujours possible) :
|
|
|
|
```bash
|
|
docker compose pull && docker compose up -d
|
|
```
|
|
|
|
### Publier une version (mainteneur)
|
|
|
|
```bash
|
|
./scripts/release.sh 0.2.0
|
|
```
|
|
|
|
Bump de version, commit + tag git, build de l'image et push vers
|
|
`git.lanro.eu/roman/ohm_streaming` (tags `0.2.0` et `latest`).
|
|
|
|
## Démarrage rapide (développement)
|
|
|
|
```bash
|
|
uv sync
|
|
# ffmpeg requis pour les flux HLS (binaire statique dans ~/.local/bin, ou apt install ffmpeg)
|
|
uv run uvicorn app.main:app --host 0.0.0.0 --port 8777
|
|
```
|
|
|
|
Serveur persistant en dev : préférer Docker (voir plus haut) ; sinon
|
|
`tmux new-session -d -s ohm 'uv run uvicorn app.main:app --host 0.0.0.0 --port 8777'`.
|
|
|
|
Puis ouvrir http://localhost:8777 — le **premier compte créé est administrateur**.
|
|
|
|
## Configuration
|
|
|
|
Variables d'environnement (préfixe `OHM_`, voir `.env.example`) :
|
|
|
|
| Variable | Défaut | Rôle |
|
|
|---|---|---|
|
|
| `OHM_SECRET_KEY` | `change-me-in-production` | **À changer** — signature des tokens |
|
|
| `OHM_DOWNLOAD_DIR` | `./downloads` | Dossier des fichiers téléchargés |
|
|
| `OHM_DATABASE_PATH` | `./data/ohm.db` | Base SQLite |
|
|
| `OHM_MAX_PARALLEL_DOWNLOADS` | `3` | Téléchargements simultanés |
|
|
| `OHM_WATCHTOWER_URL` | *(vide)* | URL Watchtower pour la mise à jour (réglé par docker-compose) |
|
|
| `OHM_WATCHTOWER_TOKEN` | *(vide)* | Jeton partagé Watchtower (réglé par docker-compose) |
|
|
| `OHM_VERSION` | *(pyproject)* | Version affichée — cuite dans l'image Docker au build |
|
|
|
|
## Fonctionnalités
|
|
|
|
- **Recherche unifiée** sur plusieurs sources (Vostfree, French-Manga) — chaque source
|
|
est un module interchangeable activable/désactivable à chaud (page Admin), dont l'URL
|
|
est modifiable à la volée (utile si un site change de domaine).
|
|
- **Extraction en 2 niveaux** : page d'épisode → lecteurs embarqués → URL directe
|
|
(Sibnet, SendVid, VidMoly, Uqload, Vidzy, Luluvdo).
|
|
- **Proxy vidéo intégré** (`/api/proxy`) : contourne les protections (tokens liés à l'IP, Referer/UA obligatoires), réécrit les playlists HLS.
|
|
- **Streaming HLS** via hls.js ; **téléchargement HLS** via ffmpeg (remux mp4, progression temps réel).
|
|
- **Métadonnées enrichies** via Kitsu (synopsis, genres, note, images) avec cache 72 h.
|
|
- **Téléchargements** : file parallèle, pause/reprise (HTTP Range), retry, anti-doublons,
|
|
progression en temps réel (SSE), persistance au redémarrage.
|
|
- **Bibliothèque locale** : streaming avec range requests, reprise de lecture,
|
|
navigation épisode suivant/précédent.
|
|
- **Comptes** : JWT court + refresh token (rotation), rôles admin/utilisateur,
|
|
administration des comptes.
|
|
- **Découverte** (`/discover`) : 🆕 nouveautés fusionnées de toutes les sources, triées
|
|
par date de sortie réelle (enrichissement Kitsu, badge « en cours de diffusion »),
|
|
🔥 incontournables (top popularité Kitsu) et ✨ recommandations par genres déduites
|
|
des téléchargements et favoris, titres déjà possédés exclus (cache mémoire).
|
|
|
|
|
|
## Intégration Sonarr / Prowlarr (*arr)
|
|
|
|
OhmStreaming expose une **API Torznab** (indexeur) **et une API compatible
|
|
qBittorrent** (client de téléchargement) : Sonarr peut lui déléguer toute la
|
|
chaîne — recherche, téléchargement, puis **import et renommage automatiques**
|
|
dans la bibliothèque Sonarr.
|
|
|
|
### 1. OhmStreaming comme indexeur
|
|
|
|
Dans **Admin → Intégrations Sonarr / Prowlarr**, copier :
|
|
|
|
| Champ | Valeur |
|
|
|---|---|
|
|
| URL | `http://<hote-ohm>:8777/torznab/api` |
|
|
| Clé API | générée automatiquement (bouton Régénérer pour la changer) |
|
|
|
|
- **Prowlarr** : Indexers → Add Indexer → *Generic Torznab* → coller URL + clé,
|
|
puis synchroniser vers Sonarr.
|
|
- **Sonarr** (direct) : Settings → Indexers → Add → *Torznab* → coller URL + clé.
|
|
Catégories : TV (5000) / Anime (5070).
|
|
|
|
Endpoints : `t=caps`, `t=tvsearch` (q, season, ep), `t=search` — auth par
|
|
`?apikey=` ou en-tête `X-Api-Key`.
|
|
|
|
### 2. OhmStreaming comme client de téléchargement (recommandé)
|
|
|
|
Dans Sonarr : **Settings → Download Clients → Add → qBittorrent** :
|
|
|
|
| Champ | Valeur |
|
|
|---|---|
|
|
| Host | `http://<hote-ohm>:8777` |
|
|
| Username | `ohm` |
|
|
| Password | la clé API Torznab (Admin → Intégrations) |
|
|
|
|
Le flux complet devient : Sonarr grab → Ohm télécharge (progression visible
|
|
dans la file Sonarr) → Sonarr **importe, renomme et range** l'épisode dans sa
|
|
bibliothèque selon ses propres règles → le « torrent » est retiré de la file
|
|
Ohm (fichier inclu si « Remove Completed » est coché).
|
|
|
|
**Chemin d'accès** : Ohm annonce les fichiers sous `/downloads/<Animé>/…`
|
|
(chemin conteneur). Si Sonarr tourne dans Docker sans ce montage, ajouter un
|
|
*Remote Path Mapping* : hôte = `<hote-ohm>`, distant = `/downloads`, local =
|
|
le dossier hôte monté (ex. `/plex_videos/ohm`).
|
|
|
|
Variante minimale sans import : client « Torrent Blackhole » — Sonarr pose le
|
|
`.torrent` de service et l'épisode reste dans la bibliothèque OhmStreaming
|
|
seulement (pas d'import/renommage Sonarr).
|
|
|
|
### 2. « Pour toi » personnalisé par Sonarr
|
|
|
|
Toujours dans **Admin → Intégrations**, renseigner l'URL Sonarr
|
|
(`http://sonarr:8989`) et sa clé API (*Settings → General → API Key*), puis
|
|
« Enregistrer » et « Tester ». Les genres des séries téléchargées/grabées sur
|
|
Sonarr alimentent la section ✨ **Pour toi** (et ce qui y est possédé n'est pas
|
|
re-recommandé). Sonarr absent ou KO → dégradation gracieuse, rien ne casse.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
app/
|
|
├── main.py # FastAPI + lifespan (DB, download manager)
|
|
├── config.py # pydantic-settings (OHM_*)
|
|
├── db.py # SQLite (aiosqlite) — source de vérité unique
|
|
├── routers/ # auth, search, discover, downloads, library, admin, torznab, pages
|
|
├── scrapers/
|
|
│ ├── base.py # contrats SourceScraper/HosterExtractor + registres
|
|
│ ├── configs/ # sélecteurs YAML externalisés (réparer sans coder)
|
|
│ ├── sources/ # vostfree, french_manga
|
|
├── services/ # downloads, kitsu, discover, sonarr, torznab, settings
|
|
└── templates/ + static/ # UI htmx + Alpine.js, thème sombre
|
|
```
|
|
|
|
**Ajouter une source** : créer `app/scrapers/sources/ma_source.py` qui implémente
|
|
`SourceScraper`, la décorer `@register_source` — c'est tout (registre auto-découvert).
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
uv run pytest # 86 tests
|
|
uv run ruff check . # lint
|
|
```
|