diff --git a/bin/api/recordings_api.dart b/bin/api/recordings_api.dart index f080014..129d52e 100644 --- a/bin/api/recordings_api.dart +++ b/bin/api/recordings_api.dart @@ -47,85 +47,58 @@ class RecordingsApi { ); } - Router get router { - final router = Router(); + /// GET /api/recordings — Liste tous les enregistrements + Response handleGetAll(Request request) { + final recordings = _db.getAllRecordings(); + return Response.ok( + json.encode(recordings.map((r) => r.toMap()).toList()), + headers: {'Content-Type': 'application/json'}, + ); + } - // Récupérer tous les enregistrements (admin) ou les enregistrements de l'utilisateur courant (si filtré plus tard via les middlewares) - router.get('/', (Request request) { - // Dans une implémentation complète, nous récupérerions l'ID utilisateur - // final session = request.context['session'] as Session?; - // final userId = session?.userId; - - final recordings = _db.getAllRecordings(); - return Response.ok( - json.encode(recordings.map((r) => r.toMap()).toList()), - headers: {'Content-Type': 'application/json'}, - ); - }); - - // Planifier un nouvel enregistrement - router.post('/', (Request request) async { - // final session = request.context['session'] as Session; - // final userId = session.userId; + /// POST /api/recordings — Planifie un nouvel enregistrement + Future handlePost(Request request) async { + try { final payload = await request.readAsString(); final data = json.decode(payload); - try { - final recording = _db.createRecording( - userId: 'dev_user_id', // Remplacer par `userId` dans l'implèm réelle avec Auth - channelId: data['channel_id'], - streamUrl: data['stream_url'], - title: data['title'] ?? 'Sans Titre', - startTime: DateTime.parse(data['start_time']), - endTime: DateTime.parse(data['end_time']), - ); - - return Response.ok( - recording.toJson(), - headers: {'Content-Type': 'application/json'}, - ); - } catch (e) { - return Response.internalServerError( - body: json.encode({'error': 'Erreur lors de la programmation de l\'enregistrement : $e'}), - headers: {'Content-Type': 'application/json'}, - ); - } - }); - - // Supprimer (annuler) un enregistrement - router.delete('/', (Request request, String id) { - final recording = _db.getRecordingById(id); - - if (recording == null) { - return Response.notFound(json.encode({'error': 'Enregistrement non trouvé'})); - } - - // 1. Si l'enregistrement est en cours, il faut potentiellement l'arrêter - // _scheduler.cancelRecording(id); // Ceci pourrait être une nouvelle méthode de l'ordonnanceur - - // 2. Supprimer la donnée en BDD - _db.deleteRecording(id); - - // 3. Supprimer le fichier vidéo physiquement si existant - /* - if (recording.filePath != null) { - final file = File(recording.filePath!); - if (file.existsSync()) { - file.deleteSync(); - } - } - */ + final recording = _db.createRecording( + userId: 'dev_user_id', + channelId: data['channel_id'], + streamUrl: data['stream_url'], + title: data['title'] ?? 'Sans Titre', + startTime: DateTime.parse(data['start_time']), + endTime: DateTime.parse(data['end_time']), + ); return Response.ok( - json.encode({'message': 'Enregistrement supprimé avec succès'}), + recording.toJson(), headers: {'Content-Type': 'application/json'}, ); - }); + } catch (e) { + return Response.internalServerError( + body: json.encode({'error': 'Erreur lors de la programmation: $e'}), + headers: {'Content-Type': 'application/json'}, + ); + } + } - // Note: La route GET /logs/ est déclarée directement dans server.dart - // car shelf_router a un conflit interne entre DELETE / et GET /logs/ - // dans le même routeur. + /// DELETE /api/recordings/ — Annule ou supprime un enregistrement + Response handleDelete(Request request, String id) { + final recording = _db.getRecordingById(id); + + if (recording == null) { + return Response.notFound( + json.encode({'error': 'Enregistrement non trouvé'}), + headers: {'Content-Type': 'application/json'}, + ); + } - return router; + _db.deleteRecording(id); + + return Response.ok( + json.encode({'message': 'Enregistrement supprimé avec succès'}), + headers: {'Content-Type': 'application/json'}, + ); } } diff --git a/bin/server.dart b/bin/server.dart index 562974d..34d9704 100644 --- a/bin/server.dart +++ b/bin/server.dart @@ -116,15 +116,13 @@ void main(List args) async { .addMiddleware(authMiddleware(db)) .addHandler(settingsHandler.router.call), ) - // TV Recordings - Route des logs AVANT le mount general (évite collision shelf_router avec /) - ..get('/api/recordings/logs/', recordingsApi.getLogHandler) - // TV Recordings endpoints (GET /, POST /, DELETE /) - ..mount( - '/api/recordings', - const Pipeline() - //.addMiddleware(authMiddleware(db)) // TODO: Activer quand UI aura l'Auth header - .addHandler(recordingsApi.router.call), - ); + // TV Recordings - Chaque route déclarée EXPLICITEMENT pour éviter les conflits shelf_router + // NE PAS utiliser mount() ici car mount('/api/recordings', ...) intercepte TOUT + // ce qui commence par /api/recordings (y compris /api/recordings/logs/) + ..get('/api/recordings', recordingsApi.handleGetAll) + ..post('/api/recordings', recordingsApi.handlePost) + ..delete('/api/recordings/', recordingsApi.handleDelete) + ..get('/api/recordings/logs/', recordingsApi.getLogHandler); // NOTE: /api/xtream is handled by proxyHandler in the Cascade below // Do NOT mount here as it would intercept and block the actual proxy