14 KiB
Plan : Refonte du Système Watchlist
TL;DR
Objectif : Refaire le système de watchlist avec auto-téléchargement, notifications et stockage SQLite
Deliverables :
- Base de données SQLite pour la watchlist
- API REST pour gérer les animes suivis
- Système d'auto-téléchargement (vérification automatique des nouveaux épisodes)
- Système de notifications (in-app)
- Interface frontend (page séparée, même style que le reste)
Effort : XL Exécution : En waves parallèles
Contexte
Système Actuel
- Stockage JSON (
config/watchlist.json) - Pas de SQLite
- Auto-download basique via scheduler
- Pas de système de notifications
- Interface intégrée à la page principale
Besoins Utilisateur
- Auto-téléchargement des nouveaux épisodes ✅
- Notifications quand un nouvel épisode est dispo ✅
- Stockage SQLite ✅
- Même style que le reste du site ✅
- Page séparée ✅
Work Objectives
Objectif Principal
Créer un système de watchlist complet permettant de :
- Suivre des animes (ajout via recherche)
- Détecter automatiquement les nouveaux épisodes
- Télécharger automatiquement les nouveaux épisodes
- Notifier l'utilisateur quand un nouvel épisode est disponible
Deliverables Concrets
- Base de données SQLite (
config/watchlist.db) - Modèles Pydantic pour la watchlist
- API endpoints (CRUD + actions)
- Service d'auto-check (scheduler)
- Service de notifications
- Page frontend dédiée
- Intégration avec le système de download existant
Définition de Terminé
- Un anime peut être ajouté à la watchlist
- La watchlist affiche tous les animes suivis
- Les épisodes peuvent être téléchargés manuellement
- Le scheduler vérifie automatiquement les nouveaux épisodes
- Les nouveaux épisodes sont téléchargés automatiquement
- Une notification apparaît quand un nouvel épisode est dispo
Architecture
Structure des Fichiers
app/
├── watchlist/
│ ├── __init__.py
│ ├── models.py # Modèles Pydantic
│ ├── database.py # Connexion SQLite
│ ├── service.py # Logique métier
│ ├── scheduler.py # Auto-check
│ └── notifications.py # Notifications
├── routes/
│ └── watchlist.py # API endpoints
static/
└── js/
└── watchlist/ # Frontend
├── index.js
├── components/
└── style.css
Schéma Base de Données (SQLite)
-- Table principale : watchlist items
CREATE TABLE watchlist_items (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
anime_title TEXT NOT NULL,
anime_url TEXT NOT NULL,
provider_id TEXT NOT NULL,
lang TEXT DEFAULT 'vostfr',
poster_image TEXT,
cover_image TEXT,
synopsis TEXT,
genres TEXT, -- JSON array
-- Tracking
status TEXT DEFAULT 'active', -- active, paused, completed
auto_download INTEGER DEFAULT 1,
quality_preference TEXT DEFAULT 'auto',
last_episode_downloaded INTEGER DEFAULT 0,
total_episodes INTEGER,
last_checked_at TEXT,
-- Metadata
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
-- Table : Episodes téléchargés
CREATE TABLE downloaded_episodes (
id TEXT PRIMARY KEY,
watchlist_item_id TEXT NOT NULL,
episode_number INTEGER NOT NULL,
filename TEXT NOT NULL,
file_path TEXT,
file_size INTEGER,
downloaded_at TEXT NOT NULL,
FOREIGN KEY (watchlist_item_id) REFERENCES watchlist_items(id)
);
-- Table : Notifications
CREATE TABLE notifications (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
watchlist_item_id TEXT,
type TEXT NOT NULL, -- new_episode, download_complete, error
title TEXT NOT NULL,
message TEXT,
read INTEGER DEFAULT 0,
created_at TEXT NOT NULL,
FOREIGN KEY (watchlist_item_id) REFERENCES watchlist_items(id)
);
-- Table : Settings
CREATE TABLE watchlist_settings (
id INTEGER PRIMARY KEY CHECK (id = 1),
check_interval_hours INTEGER DEFAULT 6,
auto_download_enabled INTEGER DEFAULT 1,
max_concurrent_downloads INTEGER DEFAULT 2,
notifications_enabled INTEGER DEFAULT 1
);
Execution Strategy
Wave 1 (Fondations)
Tâches :
├── 1. Créer structure du module watchlist/
├── 2. Créer database.py (connexion SQLite, migrations)
├── 3. Créer models.py (Pydantic models)
├── 4. Créer service.py (CRUD operations)
└── 5. Mettre à jour models/__init__.py
Dépendances :Aucune (start immediate)
Wave 2 (API + Scheduler)
Tâches (dépendent de Wave 1) :
├── 6. Créer routes/watchlist.py (API endpoints)
├── 7. Créer scheduler.py (auto-check)
├── 8. Intégrer scheduler dans main.py
└── 9. Créer notifications.py
Bloqué par : 1-5
Wave 3 (Frontend)
Tâches (dépendent de Wave 2) :
├── 10. Créer page HTML watchlist.html
├── 11. Créer watchlist-ui.js (logique)
├── 12. Ajouter CSS pour la page
└── 13. Ajouter routes pour servir la page
Bloqué par : 6-9
Wave 4 (Intégration + Tests)
Tâches :
├── 14. Tester l'ajout d'un anime
├── 15. Tester le téléchargement manuel
├── 16. Tester l'auto-download
├── 17. Tester les notifications
└── 18. Nettoyer l'ancien code
Bloqué par : 10-13
TODOs
-
1. Créer la structure du module watchlist/
Quoi faire :
- Créer le répertoire
app/watchlist/ - Créer
__init__.pyavec exports
Pas faire :
- Toucher aux autres modules
Agent recommandé :
quickQA Scenarios :
Scenario: Le répertoire existe Tool: Bash Command: ls -la app/watchlist/ Expected: Le répertoire existe avec __init__.py - Créer le répertoire
-
2. Créer database.py (connexion SQLite)
Quoi faire :
- Créer
app/watchlist/database.py - Implémenter connexion SQLite avec
sqlite3 - Implémenter fonctions :
init_db(),get_connection(),migrate() - Créer les tables définies dans le schéma
Pas faire :
- Toucher aux autres fichiers
Agent recommandé :
quickQA Scenarios :
Scenario: La base de données est créée Tool: Bash Command: python3 -c "from app.watchlist.database import init_db; init_db(); import os; print(os.path.exists('config/watchlist.db'))" Expected: True Scenario: Les tables existent Tool: Bash Command: sqlite3 config/watchlist.db ".tables" Expected: watchlist_items downloaded_episodes notifications watchlist_settings - Créer
-
3. Créer models.py
Quoi faire :
- Créer
app/watchlist/models.py - Définir les modèles Pydantic :
- WatchlistItem, WatchlistItemCreate, WatchlistItemUpdate
- DownloadedEpisode
- Notification, NotificationCreate
- WatchlistSettings
- Utiliser les types existants de
app/models/
Pas faire :
- Dupliquer les types existants
Agent recommandé :
quickQA Scenarios :
Scenario: Les modèles peuvent être importés Tool: Bash Command: python3 -c "from app.watchlist.models import WatchlistItem, Notification; print('OK')" Expected: OK (no error) - Créer
-
4. Créer service.py
Quoi faire :
- Créer
app/watchlist/service.py - Implémenter
WatchlistServiceavec :add_item(),get_items(),get_item(),update_item(),delete_item()mark_episode_downloaded(),get_downloaded_episodes()create_notification(),get_notifications(),mark_notification_read()get_settings(),update_settings()get_items_due_for_check()
- Utiliser SQLite directement (pas d'ORM)
Pas faire :
- Toucher au frontend
Agent recommandé :
unspecified-highQA Scenarios :
Scenario: Ajouter un item à la watchlist Tool: Bash Command: python3 -c " - Créer
from app.watchlist.service import WatchlistService svc = WatchlistService() item = svc.add_item(user_id='test', anime_title='Test Anime', anime_url='https://example.com', provider_id='anime-sama') print(f'Created: {item.id}') " Expected: Un UUID est retourné
Scenario: Récupérer les items Tool: Bash Command: python3 -c " from app.watchlist.service import WatchlistService svc = WatchlistService() items = svc.get_items() print(f'Count: {len(items)}') " Expected: Count: 1
- [ ] 5. **Mettre à jour models/__init__.py**
**Quoi faire** :
- Ajouter export des nouveaux modèles si besoin
**Agent recommandé** : `quick`
- [ ] 6. **Créer routes/watchlist.py**
**Quoi faire** :
- Créer `app/routes/watchlist.py`
- Définir les endpoints :
- `GET /api/watchlist` - Liste des items
- `POST /api/watchlist` - Ajouter un item
- `GET /api/watchlist/{id}` - Détail d'un item
- `PUT /api/watchlist/{id}` - Modifier un item
- `DELETE /api/watchlist/{id}` - Supprimer un item
- `POST /api/watchlist/{id}/download/{episode}` - Télécharger un épisode
- `GET /api/watchlist/{id}/episodes` - Épisodes téléchargés
- `GET /api/watchlist/notifications` - Liste des notifications
- `PUT /api/watchlist/notifications/{id}/read` - Marquer comme lu
- `GET /api/watchlist/settings` - Settings
- `PUT /api/watchlist/settings` - Mettre à jour settings
- Ajouter auth (Bearer token)
- Intégrer avec `download_manager` pour les téléchargements
**Agent recommandé** : `unspecified-high`
**QA Scenarios** :
Scenario: L'API répond Tool: Bash Command: curl -s http://127.0.0.1:3000/api/watchlist Expected: {"items": [...], "count": N}
- [ ] 7. **Créer scheduler.py**
**Quoi faire** :
- Créer `app/watchlist/scheduler.py`
- Implémenter `WatchlistScheduler` :
- `start()`, `stop()`
- `_check_loop()` - Boucle principale
- `check_item(item)` - Vérifier un anime
- `download_new_episodes(item, new_episodes)` - Télécharger
- Utiliser `APScheduler` (déjà dans requirements)
- Intervalle configurable (défaut: 6h)
**Agent recommandé** : `unspecified-high`
- [ ] 8. **Intégrer scheduler dans main.py**
**Quoi faire** :
- Importer et initialiser le scheduler
- Ajouter au startup event
- Ajouter au shutdown event
**Agent recommandé** : `quick`
- [ ] 9. **Créer notifications.py**
**Quoi faire** :
- Créer `app/watchlist/notifications.py`
- Implémenter `NotificationService`
- Types de notifications :
- `new_episode` - Nouvel épisode détecté
- `download_started` - Téléchargement commencé
- `download_complete` - Téléchargement terminé
- `download_error` - Erreur de téléchargement
- Stocker dans SQLite
- Retourner via API pour affichage
**Agent recommandé** : `quick`
- [ ] 10. **Créer page HTML watchlist.html**
**Quoi faire** :
- Créer `templates/watchlist.html`
- Même structure que `index.html`
- Sections :
- Header avec stats
- Liste des animes (cards)
- Zone de notifications
- Modal pour les détails
**Agent recommandé** : `visual-engineering`
**QA Scenarios** :
Scenario: La page se charge Tool: playwright Navigate: http://127.0.0.1:3000/watchlist Expected: Titre "Ma Watchlist" affiché
- [ ] 11. **Créer watchlist-ui.js**
**Quoi faire** :
- Créer `static/js/watchlist/main.js`
- Fonctions :
- `loadWatchlist()` - Charger la liste
- `renderWatchlist(items)` - Afficher les cards
- `addAnime(animeData)` - Ajouter un anime
- `removeAnime(id)` - Retirer
- `downloadEpisode(itemId, episode)` - Télécharger
- `loadNotifications()` - Charger les notifs
- `renderNotifications(notifs)` - Afficher
- `markAsRead(id)` - Marquer lu
- Appels API vers les endpoints créés
**Agent recommandé** : `visual-engineering`
- [ ] 12. **Ajouter CSS**
**Quoi faire** :
- Créer `static/css/watchlist.css`
- Style cohérent avec `style.css` existant
- Cards, badges, buttons, notifications
**Agent recommandé** : `visual-engineering`
- [ ] 13. **Ajouter routes pour servir la page**
**Quoi faire** :
- Ajouter route `GET /watchlist` dans main.py
- Servir le template
**Agent recommandé** : `quick`
- [ ] 14-17. **Tests d'intégration**
**Quoi faire** :
- Tester le flux complet :
1. Ajouter un anime via API
2. Voir dans la liste
3. Télécharger un épisode manuellement
4. Recevoir une notification
- Tester l'auto-download (simuler un nouvel épisode)
**Agent recommandé** : `unspecified-high`
- [ ] 18. **Nettoyer l'ancien code**
**Quoi faire** :
- Supprimer `app/watchlist.py` (l'ancien)
- Supprimer les fichiers JSON `config/watchlist*.json`
- Mettre à jour les imports
**Agent recommandé** : `quick`
---
## Stratégie de Vérification
### Test Manual (Agent QA)
**Scenario: Ajout d'un anime**
- Ouvrir /watchlist
- Cliquer "Ajouter un anime"
- Rechercher "Frieren"
- Sélectionner un résultat
- Cliquer "Suivre" Expected: L'anime apparaît dans la liste
**Scenario: Téléchargement manuel**
- Dans la watchlist, cliquer sur un anime
- Voir la liste des épisodes
- Cliquer "Télécharger" sur épisode 1
- Vérifier dans /downloads Expected: Le téléchargement commence
**Scenario: Auto-download**
- Ajouter un anime avec auto-download activé
- Simuler l'apparition d'un nouvel épisode (via scheduler)
- Vérifier dans les downloads Expected: L'épisode est téléchargé automatiquement
**Scenario: Notification**
- Un nouvel épisode est détecté
- Une notification apparaît
- Cliquer sur la notification Expected: Redirection vers l'épisode
---
## Critères de Succès
- [ ] La base SQLite est créée et fonctionnelle
- [ ] Les animes peuvent être ajoutés/retirés de la watchlist
- [ ] Les épisodes peuvent être téléchargés manuellement
- [ ] Le scheduler vérifie automatiquement les nouveaux épisodes
- [ ] L'auto-téléchargement fonctionne
- [ ] Les notifications sont créées et affichées
- [ ] L'interface est cohérente avec le reste du site
- [ ] L'ancien code est nettoyé
---
## Commit Strategy
- Wave 1: `feat(watchlist): add SQLite database and models`
- Wave 2: `feat(watchlist): add API routes and scheduler`
- Wave 3: `feat(watchlist): add frontend UI`
- Wave 4: `feat(watchlist): integrate and test`
---
## Notes
- Le système de download existant (`download_manager`) est réutilisé
- Les providers existants (anime-sama, vostfree, etc.) sont réutilisés
- Le système de notification est simple (in-app) pour éviter les dépendances supplémentaires
- Le scheduler utilise APScheduler déjà présent dans le projet