From 644a4bc78bd493e27fab82dc9f93611038f88612 Mon Sep 17 00:00:00 2001 From: Cedric Date: Fri, 19 Jun 2026 09:56:11 +0200 Subject: [PATCH] Actualiser api.php --- api.php | 221 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 179 insertions(+), 42 deletions(-) diff --git a/api.php b/api.php index 275ec0c..dc2dc05 100644 --- a/api.php +++ b/api.php @@ -3,7 +3,6 @@ header("Content-Type: application/json; charset=UTF-8"); header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS"); header("Access-Control-Allow-Headers: Content-Type, Authorization"); - header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Pragma: no-cache"); @@ -19,11 +18,23 @@ try { PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]); - - $pdo->exec("CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL)"); - $pdo->exec("CREATE TABLE IF NOT EXISTS critiques (id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), poster TEXT, rating INT DEFAULT 3, review TEXT, streaming VARCHAR(255))"); - $pdo->exec("CREATE TABLE IF NOT EXISTS videotheque (id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), poster TEXT, format VARCHAR(50), length VARCHAR(50), publisher VARCHAR(255), ean_isbn13 VARCHAR(50), number_of_discs INT DEFAULT 1, aspect_ratio VARCHAR(50), description TEXT)"); - + + // Création des tables si elles n'existent pas + $pdo->exec("CREATE TABLE IF NOT EXISTS users ( + id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL + )"); + $pdo->exec("CREATE TABLE IF NOT EXISTS config ( + key_name VARCHAR(50) PRIMARY KEY, key_value TEXT NOT NULL + )"); + $pdo->exec("CREATE TABLE IF NOT EXISTS critiques ( + id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), + poster TEXT, rating INT DEFAULT 3, review TEXT, streaming VARCHAR(255) + )"); + $pdo->exec("CREATE TABLE IF NOT EXISTS videotheque ( + id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), + poster TEXT, format VARCHAR(50), length VARCHAR(50), publisher VARCHAR(255), ean_isbn13 VARCHAR(50), + number_of_discs INT DEFAULT 1, aspect_ratio VARCHAR(50), description TEXT + )"); } catch (\PDOException $e) { echo json_encode(["error" => "Erreur BDD : " . $e->getMessage()]); exit; @@ -36,13 +47,14 @@ function makeStableId($title, $year) { function checkAuth($pdo) { $stmtCheck = $pdo->query("SELECT COUNT(*) FROM users"); - if ($stmtCheck->fetchColumn() == 0) return true; - + if ($stmtCheck->fetchColumn() == 0) return true; + $token = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; if (empty($token) && function_exists('apache_request_headers')) { $headers = apache_request_headers(); $token = $headers['Authorization'] ?? $headers['authorization'] ?? ''; } + if ($token !== md5(ENCRYPTION_KEY . 'session')) { http_response_code(403); echo json_encode(["error" => "Accès interdit."]); @@ -50,6 +62,84 @@ function checkAuth($pdo) { } } +// ── FONCTIONS TMDB & CHIFFREMENT ── + +function tmdbHttpGet($url) { + if (function_exists('curl_init')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + $res = curl_exec($ch); + curl_close($ch); + return $res; + } + return @file_get_contents($url); +} + +function getTmdbApiKey($pdo) { + $stmt = $pdo->prepare("SELECT key_value FROM config WHERE key_name = 'tmdb_api_key'"); + $stmt->execute(); + $row = $stmt->fetch(); + if (!$row) return null; + + $encrypted = $row['key_value']; + $decoded = base64_decode($encrypted); + + // Séparation des données et du IV (format base64(data::iv)) + if (strpos($decoded, '::') !== false) { + list($encData, $iv) = explode('::', $decoded, 2); + } else { + $encData = $decoded; + $iv = str_repeat("\0", 16); + } + + // ⚠️ ADAPTEZ CETTE PARTIE SI VOTRE MÉTHODE DE CHIFFREMENT CÔTÉ FRONT EST DIFFÉRENTE + $key = hash('sha256', ENCRYPTION_KEY, true); + $iv = substr($iv, 0, 16); + + $decrypted = openssl_decrypt($encData, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); + return $decrypted ?: null; +} + +function fetchTmdbData($title, $year, $apiKey) { + if (empty($apiKey) || empty($title)) return null; + + $searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($title) . "&year={$year}&language=fr-FR"; + $searchRes = tmdbHttpGet($searchUrl); + if (!$searchRes) return null; + + $searchData = json_decode($searchRes, true); + if (empty($searchData['results'])) return null; + + $movie = $searchData['results'][0]; + $movieId = $movie['id']; + $poster = !empty($movie['poster_path']) ? "https://image.tmdb.org/t/p/w500" . $movie['poster_path'] : ''; + + // Récupération du réalisateur + $creditsUrl = "https://api.themoviedb.org/3/movie/{$movieId}/credits?api_key={$apiKey}&language=fr-FR"; + $creditsRes = tmdbHttpGet($creditsUrl); + $director = ''; + if ($creditsRes) { + $creditsData = json_decode($creditsRes, true); + if (!empty($creditsData['crew'])) { + foreach ($creditsData['crew'] as $crew) { + if ($crew['job'] === 'Director' || $crew['job'] === 'Directing') { + $director = $crew['name']; + break; + } + } + } + } + + return [ + 'director' => $director, + 'poster' => $poster + ]; +} + +// ── ROUTEUR PRINCIPAL ── + $action = $_GET['action'] ?? ''; $data = json_decode(file_get_contents('php://input'), true) ?? []; @@ -96,14 +186,36 @@ switch ($action) { $type = $data['type'] ?? 'critique'; $id = !empty($data['id']) ? $data['id'] : makeStableId($data['title'] ?? '', $data['year'] ?? '0000'); + // 🔍 RÉCUPÉRATION AUTO TMDB SI CHAMPS VIDES + if (empty($data['director']) || empty($data['poster'])) { + $apiKey = getTmdbApiKey($pdo); + $tmdbData = fetchTmdbData($data['title'] ?? '', $data['year'] ?? '', $apiKey); + if ($tmdbData) { + if (empty($data['director'])) $data['director'] = $tmdbData['director']; + if (empty($data['poster'])) $data['poster'] = $tmdbData['poster']; + } + } + if ($type === 'critique') { - $sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), poster=VALUES(poster), rating=VALUES(rating), review=VALUES(review), streaming=VALUES(streaming)"; + $sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), poster=VALUES(poster), rating=VALUES(rating), review=VALUES(review), streaming=VALUES(streaming)"; $stmt = $pdo->prepare($sql); - $stmt->execute([$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $data['poster'] ?? '', $data['rating'] ?? 3, $data['review'] ?? '', $data['streaming'] ?? '']); + $stmt->execute([ + $id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', + $data['poster'] ?? '', $data['rating'] ?? 3, $data['review'] ?? '', $data['streaming'] ?? '' + ]); } else { - $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), poster=VALUES(poster), format=VALUES(format), length=VALUES(length), publisher=VALUES(publisher), ean_isbn13=VALUES(ean_isbn13), number_of_discs=VALUES(number_of_discs), aspect_ratio=VALUES(aspect_ratio), description=VALUES(description)"; + $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), poster=VALUES(poster), format=VALUES(format), length=VALUES(length), publisher=VALUES(publisher), ean_isbn13=VALUES(ean_isbn13), number_of_discs=VALUES(number_of_discs), aspect_ratio=VALUES(aspect_ratio), description=VALUES(description)"; $stmt = $pdo->prepare($sql); - $stmt->execute([$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $data['poster'] ?? '', $data['format'] ?? '', $data['length'] ?? '', $data['publisher'] ?? '', $data['ean_isbn13'] ?? '', $data['number_of_discs'] ?? 1, $data['aspect_ratio'] ?? '', $data['description'] ?? '']); + $stmt->execute([ + $id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', + $data['poster'] ?? '', $data['format'] ?? '', $data['length'] ?? '', + $data['publisher'] ?? '', $data['ean_isbn13'] ?? '', $data['number_of_discs'] ?? 1, + $data['aspect_ratio'] ?? '', $data['description'] ?? '' + ]); } echo json_encode(["success" => true]); break; @@ -113,7 +225,7 @@ switch ($action) { $type = $_GET['type'] ?? 'critique'; $table = ($type === 'videotheque') ? 'videotheque' : 'critiques'; $id = $_GET['id'] ?? null; - if (!$id) break; + if (!$id) { http_response_code(400); echo json_encode(["error" => "ID manquant."]); break; } $stmt = $pdo->prepare("DELETE FROM $table WHERE id = ?"); $stmt->execute([$id]); echo json_encode(["success" => true]); @@ -122,13 +234,16 @@ switch ($action) { case 'bulk_delete': checkAuth($pdo); $ids = $data['ids'] ?? []; - $type = $data['type'] ?? 'critique'; + $type = $data['type'] ?? 'critique'; $table = ($type === 'videotheque') ? 'videotheque' : 'critiques'; if (!empty($ids)) { $placeholders = implode(',', array_fill(0, count($ids), '?')); $stmt = $pdo->prepare("DELETE FROM $table WHERE id IN ($placeholders)"); $stmt->execute($ids); echo json_encode(["success" => true]); + } else { + http_response_code(400); + echo json_encode(["success" => false, "error" => "Aucun élément sélectionné."]); } break; @@ -138,55 +253,77 @@ switch ($action) { $file = $_FILES['csv_file']['tmp_name']; $type = $_POST['type'] ?? 'critique'; + // On récupère la clé une seule fois pour tout l'import + $tmdbApiKey = getTmdbApiKey($pdo); + if (($handle = fopen($file, "r")) !== FALSE) { - // Suppression du BOM si présent (fréquent sur Excel) - $bom = fread($handle, 3); - if ($bom !== "\xEF\xBB\xBF") rewind($handle); - $header = fgetcsv($handle, 0, ","); $header = array_map('trim', $header); - + while (($row = fgetcsv($handle, 0, ",")) !== FALSE) { - while (count($row) < count($header)) $row[] = ''; - if (count($row) > count($header)) $row = array_slice($row, 0, count($header)); - + if (count($row) !== count($header)) continue; $rowData = array_combine($header, $row); - // Noms de colonnes flexibles pour s'adapter à Letterboxd - $title = $rowData['Name'] ?? $rowData['title'] ?? $rowData['Title'] ?? ''; - if (empty($title)) continue; - + $title = $rowData['Name'] ?? $rowData['title'] ?? 'Sans titre'; $year = $rowData['Year'] ?? $rowData['year'] ?? '0000'; - $director = $rowData['Director'] ?? ''; - $poster = $rowData['Poster'] ?? ''; + $director = $rowData['Director'] ?? $rowData['director'] ?? ''; + $poster = $rowData['Poster'] ?? $rowData['poster'] ?? $rowData['image'] ?? ''; + // 🔍 RÉCUPÉRATION AUTO TMDB SI CHAMPS VIDES DANS LE CSV + if (empty($director) || empty($poster)) { + $tmdbData = fetchTmdbData($title, $year, $tmdbApiKey); + if ($tmdbData) { + if (empty($director)) $director = $tmdbData['director']; + if (empty($poster)) $poster = $tmdbData['poster']; + } + } + $id = makeStableId($title, $year); if ($type === 'critique') { - $ratingStr = $rowData['Rating'] ?? '3'; - $rating = (int)round((float)$ratingStr); - $review = $rowData['Review'] ?? ''; - - $sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review) - VALUES (?, ?, ?, ?, ?, ?, ?) - ON DUPLICATE KEY UPDATE - rating = VALUES(rating), + $rating = isset($rowData['Rating']) ? (int)round($rowData['Rating'] * 1) : 3; + $review = $rowData['Review'] ?? $rowData['review'] ?? ''; + $streaming = $rowData['Streaming'] ?? $rowData['streaming'] ?? ''; + $sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + rating = VALUES(rating), review = IF(VALUES(review) != '', VALUES(review), review), director = IF(VALUES(director) != '', VALUES(director), director), - poster = IF(VALUES(poster) != '', VALUES(poster), poster)"; + poster = IF(VALUES(poster) != '', VALUES(poster), poster), + streaming = IF(VALUES(streaming) != '', VALUES(streaming), streaming)"; $stmt = $pdo->prepare($sql); - $stmt->execute([$id, $title, $year, $director, $poster, $rating, $review]); + $stmt->execute([$id, $title, $year, $director, $poster, $rating, $review, $streaming]); } else { - $sql = "INSERT INTO videotheque (id, title, year, director, poster) - VALUES (?, ?, ?, ?, ?) - ON DUPLICATE KEY UPDATE title=VALUES(title)"; + $format = $rowData['format'] ?? $rowData['Format'] ?? ''; + $length = $rowData['length'] ?? $rowData['Length'] ?? ''; + $publisher = $rowData['publisher'] ?? $rowData['Publisher'] ?? ''; + $ean = $rowData['ean_isbn13'] ?? $rowData['EAN'] ?? ''; + $discs = $rowData['number_of_discs'] ?? 1; + $aspect = $rowData['aspect_ratio'] ?? ''; + $desc = $rowData['description'] ?? $rowData['Description'] ?? ''; + $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + director = IF(VALUES(director) != '', VALUES(director), director), + poster = IF(VALUES(poster) != '', VALUES(poster), poster), + format = IF(VALUES(format) != '', VALUES(format), format), + length = IF(VALUES(length) != '', VALUES(length), length), + publisher = IF(VALUES(publisher) != '', VALUES(publisher), publisher), + ean_isbn13 = IF(VALUES(ean_isbn13) != '', VALUES(ean_isbn13), ean_isbn13), + number_of_discs = IF(VALUES(number_of_discs) != 1, VALUES(number_of_discs), number_of_discs), + aspect_ratio = IF(VALUES(aspect_ratio) != '', VALUES(aspect_ratio), aspect_ratio), + description = IF(VALUES(description) != '', VALUES(description), description)"; $stmt = $pdo->prepare($sql); - $stmt->execute([$id, $title, $year, $director, $poster]); + $stmt->execute([$id, $title, $year, $director, $poster, $format, $length, $publisher, $ean, $discs, $aspect, $desc]); } } fclose($handle); } echo json_encode(["success" => true]); + } else { + http_response_code(400); + echo json_encode(["error" => "Aucun fichier reçu."]); } break; } \ No newline at end of file