# Ombrora YTDLP

Interface web de téléchargement de vidéos via [yt-dlp](https://github.com/yt-dlp/yt-dlp), avec file d'attente persistante, suivi en base de données et liens de téléchargement sécurisés.

## Fonctionnement

1. L'utilisateur soumet une URL depuis l'interface web.
2. La demande est enregistrée en base (statut `PENDING`).
3. Le worker Passenger (Node.js, arrière-plan) dépile les jobs et exécute `yt-dlp` en parallèle (concurrence configurable).
4. Le fichier téléchargé est stocké localement ; un token signé (24h) est généré.
5. L'utilisateur est redirigé vers une page de statut qui se rafraîchit jusqu'à ce que le fichier soit prêt.
6. Un cron quotidien supprime les fichiers expirés et marque les entrées `FILE_DELETED` — la DB conserve l'historique complet.

## Stack technique

| Couche | Technologie |
|--------|-------------|
| Framework | Next.js 16 (App Router) |
| Base de données | MariaDB 11 via Prisma 7 |
| Frontend | React 19, TypeScript |
| Worker | Node.js (ts-node) |
| Conteneur (dev) | Docker Compose |

## Prérequis

- Node.js 20+
- Docker & Docker Compose (pour MariaDB en développement)
- `yt-dlp` et `ffmpeg` (binaires précompilés dans `./bin/` ou dans le `PATH`)

## Démarrage rapide

```bash
# 1. Cloner le dépôt
git clone <url> ombrora-ytdlp && cd ombrora-ytdlp

# 2. Copier et remplir les variables d'environnement
cp .env.example .env

# 3. Démarrer MariaDB
docker-compose up -d

# 4. Installer les dépendances
npm install

# 5. Appliquer les migrations Prisma
npm run db:migrate

# 6. Lancer le serveur Next.js
npm run dev

# 7. Dans un autre terminal, lancer le worker
npm run worker
```

L'interface est accessible sur [http://localhost:3000](http://localhost:3000).

## Variables d'environnement

| Variable | Requis | Exemple | Description |
|----------|--------|---------|-------------|
| `DATABASE_URL` | oui | `mysql://ombrora:ombrora@localhost:3306/ombrora` | Connexion MariaDB |
| `STORAGE_PATH` | oui | `/var/www/ombrora/storage` | Répertoire de stockage des fichiers téléchargés |
| `BIN_DIR` | non | `./bin` | Répertoire contenant `yt-dlp` et `ffmpeg` (défaut : `./bin`) |

## Scripts npm

| Script | Description |
|--------|-------------|
| `npm run dev` | Serveur de développement Next.js |
| `npm run build` | Build de production |
| `npm start` | Serveur de production |
| `npm test` | Tests Jest |
| `npm run worker` | Worker de téléchargement (boucle de polling) |
| `npm run worker:check` | Vérifie si le worker tourne, le démarre sinon (usage cron) |
| `npm run worker:cleanup` | Expire et supprime les fichiers anciens (usage cron) |
| `npm run db:migrate` | Crée et applique les migrations Prisma |
| `npm run db:generate` | Régénère le client Prisma |

## Configuration

Les paramètres applicatifs sont centralisés dans `config/app.config.ts` :

```typescript
DOWNLOAD_LINK_TTL_HOURS: 24     // Durée de validité du token de téléchargement
WORKER_CONCURRENCY:       3     // Téléchargements parallèles maximum
WORKER_POLL_INTERVAL_MS:  10000 // Intervalle de polling du worker (ms)
RATE_LIMIT_MAX:           5     // Soumissions max par IP par fenêtre
RATE_LIMIT_WINDOW_MS:     3600000 // Fenêtre de rate-limit (1h)
```

## API

| Méthode | Endpoint | Description |
|---------|----------|-------------|
| `POST` | `/api/downloads` | Soumet une URL. Corps JSON : `{ url, format?, quality?, subtitles?, extraArgs? }`. Retourne `{ uuid }`. |
| `GET` | `/api/downloads/:uuid` | Statut d'un téléchargement. Retourne `{ status, fileName, fileSize, downloadToken?, tokenExpiresAt?, errorMsg? }`. |
| `GET` | `/api/download/:token` | Téléchargement du fichier (token à usage unique, 24h). |

## Architecture

```
src/
├── app/
│   ├── page.tsx                  # Page d'accueil (formulaire de soumission)
│   ├── status/[uuid]/page.tsx    # Page de suivi
│   └── api/
│       ├── downloads/route.ts    # POST — création
│       ├── downloads/[uuid]/route.ts  # GET — statut
│       └── download/[token]/route.ts  # GET — téléchargement
├── components/
│   ├── SubmitForm.tsx            # Formulaire de soumission
│   └── StatusView.tsx            # Vue de suivi (polling)
└── lib/
    ├── prisma.ts                 # Client Prisma (singleton)
    ├── rate-limit.ts             # Rate limiting par IP
    ├── token.ts                  # Génération/validation de tokens
    └── ytdlp.ts                  # Construction des arguments yt-dlp

worker/
├── index.ts                      # Boucle de polling principale
├── processor.ts                  # Exécution de yt-dlp, mise à jour DB
├── cron-cleanup.ts               # Nettoyage des fichiers expirés
└── cron-check.ts                 # Supervision du worker (cron)

prisma/
└── schema.prisma                 # Modèles : Download, DownloadToken
```

## Déploiement (o2switch / Passenger)

### Contraintes spécifiques à l'hébergement mutualisé

- **Pas de compilation sur le serveur** : `yt-dlp` et `ffmpeg` doivent être des binaires précompilés pour la plateforme cible, placés dans `BIN_DIR`.
- **`node_modules` unique** : Passenger ne crée qu'un seul `node_modules` à la racine. Toute dépendance runtime importée par le frontend doit figurer dans le `dependencies` du `package.json` racine (en plus de `frontend/package.json`).
- **Worker** : lancer `npm run worker:check` depuis un cron cPanel pour maintenir le worker actif.

### Étapes de déploiement

1. Uploader les sources (hors `node_modules`, `.env`, `storage/`).
2. Déposer `yt-dlp` et `ffmpeg` dans `BIN_DIR`.
3. Créer `.env` avec les valeurs de production.
4. Via cPanel > "Setup Node.js App" : pointer sur le dépôt, lancer `npm install` puis `npm run build`.
5. Appliquer les migrations : `npm run db:migrate`.
6. Configurer deux crons cPanel :
   - `npm run worker:check` toutes les 5 minutes (redémarre le worker si arrêté).
   - `npm run worker:cleanup` une fois par jour (suppression des fichiers expirés).

## Tests

```bash
npm test
```

Tests Jest (environnement Node, transpilation SWC). Les fichiers de test sont dans `**/__tests__/**/*.test.ts`.

## Licence

Usage interne — non distribué.
