false, 'error' => $message]); exit; } if ($_SERVER['REQUEST_METHOD'] !== 'POST') { peertubeRelinkError(405, 'Méthode non autorisée.'); } $csrfHeader = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''; if (!isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $csrfHeader)) { peertubeRelinkError(403, 'Token CSRF invalide.'); } $body = json_decode(file_get_contents('php://input'), true); if (!is_array($body)) { peertubeRelinkError(400, 'JSON invalide.'); } $thesisId = filter_var($body['thesis_id'] ?? '', FILTER_VALIDATE_INT); $uuid = trim($body['uuid'] ?? ''); if (!$thesisId || $uuid === '') { peertubeRelinkError(400, 'Paramètres invalides (thesis_id + uuid requis).'); } // Validate UUID format (shortUUID or full UUID) if (!preg_match('/^[a-zA-Z0-9\-_]+$/', $uuid)) { peertubeRelinkError(400, 'UUID invalide.'); } require_once APP_ROOT . '/src/Database.php'; require_once APP_ROOT . '/src/PeerTubeService.php'; $db = new Database(); if (!PeerTubeService::isConfigured($db)) { peertubeRelinkError(503, 'PeerTube non configuré.'); } // Check thesis exists $thesis = $db->getThesis($thesisId); if (!$thesis) { peertubeRelinkError(404, 'TFE introuvable.'); } // Check this UUID is not already linked to this thesis $pdo = $db->getConnection(); $stmt = $pdo->prepare( "SELECT id FROM thesis_files WHERE thesis_id = ? AND file_path = ?" ); $stmt->execute([$thesisId, 'peertube_ids:' . $uuid]); if ($stmt->fetch()) { peertubeRelinkError(409, 'Cette vidéo est déjà liée à ce TFE.'); } // Verify the video exists on the channel $info = PeerTubeService::fetchVideoInfo($db, $uuid); if ($info === null) { peertubeRelinkError(404, 'Vidéo introuvable sur PeerTube.'); } // Verify it's not already linked to another TFE $stmt = $pdo->prepare( "SELECT t.identifier FROM thesis_files tf JOIN theses t ON t.id = tf.thesis_id WHERE tf.file_path = ? AND t.deleted_at IS NULL" ); $stmt->execute(['peertube_ids:' . $uuid]); $existing = $stmt->fetch(); if ($existing) { peertubeRelinkError(409, 'Cette vidéo est déjà liée au TFE ' . htmlspecialchars($existing['identifier'] ?? '?') . '. Dé-liez-la d\'abord avant de la relier à un autre.' ); } // Determine file type from PeerTube info $videoName = $info['name'] ?? $uuid; $fileType = 'video'; // default $catId = (int)($info['category']['id'] ?? 0); if ($catId === 16) { $fileType = 'audio'; } $db->insertThesisFile( $thesisId, $fileType, 'peertube_ids:' . $uuid, $videoName, 0, // size unknown (not on disk) 'video/mp4', // PeerTube streams HLS, mime is nominal null, null ); $newId = $pdo->lastInsertId(); error_log("[peertube-relink] thesis_id=$thesisId uuid=$uuid file_type=$fileType new_id=$newId"); header('Content-Type: application/json'); echo json_encode([ 'ok' => true, 'id' => (int)$newId, 'message' => 'Vidéo PeerTube reliée avec succès.', ]); exit;