Actualiser api.php

This commit is contained in:
2026-06-19 14:17:51 +02:00
parent 22aabe7d49
commit a97ece2e0a
+22 -27
View File
@@ -5,21 +5,18 @@ header("Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization"); header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache"); header("Pragma: no-cache");
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200); http_response_code(200);
exit; exit;
} }
define('ENCRYPTION_KEY', 'MaCleSecreteSuperRobuste123!'); define('ENCRYPTION_KEY', 'MaCleSecreteSuperRobuste123!');
try { try {
$pdo = new PDO("mysql:host=localhost;dbname=mon_cinema;charset=utf8mb4", "root", "", [ $pdo = new PDO("mysql:host=localhost;dbname=mon_cinema;charset=utf8mb4", "root", "", [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]); ]);
// Création des tables (ajout de la table config) // Création des tables (rating changé en DECIMAL(3,1) pour accepter les notes Letterboxd comme 2.5, 3.5)
$pdo->exec("CREATE TABLE IF NOT EXISTS users ( $pdo->exec("CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL
)"); )");
@@ -28,7 +25,7 @@ try {
)"); )");
$pdo->exec("CREATE TABLE IF NOT EXISTS critiques ( $pdo->exec("CREATE TABLE IF NOT EXISTS critiques (
id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), 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) poster TEXT, rating DECIMAL(3,1) DEFAULT 3.0, review TEXT, streaming VARCHAR(255)
)"); )");
$pdo->exec("CREATE TABLE IF NOT EXISTS videotheque ( $pdo->exec("CREATE TABLE IF NOT EXISTS videotheque (
id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255),
@@ -48,13 +45,11 @@ function makeStableId($title, $year) {
function checkAuth($pdo) { function checkAuth($pdo) {
$stmtCheck = $pdo->query("SELECT COUNT(*) FROM users"); $stmtCheck = $pdo->query("SELECT COUNT(*) FROM users");
if ($stmtCheck->fetchColumn() == 0) return true; if ($stmtCheck->fetchColumn() == 0) return true;
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; $token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (empty($token) && function_exists('apache_request_headers')) { if (empty($token) && function_exists('apache_request_headers')) {
$headers = apache_request_headers(); $headers = apache_request_headers();
$token = $headers['Authorization'] ?? $headers['authorization'] ?? ''; $token = $headers['Authorization'] ?? $headers['authorization'] ?? '';
} }
if ($token !== md5(ENCRYPTION_KEY . 'session')) { if ($token !== md5(ENCRYPTION_KEY . 'session')) {
http_response_code(403); http_response_code(403);
echo json_encode(["error" => "Accès interdit."]); echo json_encode(["error" => "Accès interdit."]);
@@ -62,8 +57,6 @@ function checkAuth($pdo) {
} }
} }
// ── FONCTIONS TMDB & CHIFFREMENT ──
function encryptData($data) { function encryptData($data) {
$iv = openssl_random_pseudo_bytes(16); $iv = openssl_random_pseudo_bytes(16);
$key = hash('sha256', ENCRYPTION_KEY, true); $key = hash('sha256', ENCRYPTION_KEY, true);
@@ -93,7 +86,6 @@ function getTmdbApiKey($pdo) {
function fetchTmdbData($title, $year, $apiKey) { function fetchTmdbData($title, $year, $apiKey) {
if (empty($apiKey) || empty($title)) return null; 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"; $searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($title) . "&year={$year}&language=fr-FR";
$searchRes = @file_get_contents($searchUrl); $searchRes = @file_get_contents($searchUrl);
if (!$searchRes && function_exists('curl_init')) { if (!$searchRes && function_exists('curl_init')) {
@@ -104,14 +96,11 @@ function fetchTmdbData($title, $year, $apiKey) {
curl_close($ch); curl_close($ch);
} }
if (!$searchRes) return null; if (!$searchRes) return null;
$searchData = json_decode($searchRes, true); $searchData = json_decode($searchRes, true);
if (empty($searchData['results'])) return null; if (empty($searchData['results'])) return null;
$movie = $searchData['results'][0]; $movie = $searchData['results'][0];
$movieId = $movie['id']; $movieId = $movie['id'];
$poster = !empty($movie['poster_path']) ? "https://image.tmdb.org/t/p/w500" . $movie['poster_path'] : ''; $poster = !empty($movie['poster_path']) ? "https://image.tmdb.org/t/p/w500" . $movie['poster_path'] : '';
$creditsUrl = "https://api.themoviedb.org/3/movie/{$movieId}/credits?api_key={$apiKey}&language=fr-FR"; $creditsUrl = "https://api.themoviedb.org/3/movie/{$movieId}/credits?api_key={$apiKey}&language=fr-FR";
$creditsRes = @file_get_contents($creditsUrl); $creditsRes = @file_get_contents($creditsUrl);
if (!$creditsRes && function_exists('curl_init')) { if (!$creditsRes && function_exists('curl_init')) {
@@ -121,7 +110,6 @@ function fetchTmdbData($title, $year, $apiKey) {
$creditsRes = curl_exec($ch); $creditsRes = curl_exec($ch);
curl_close($ch); curl_close($ch);
} }
$director = ''; $director = '';
if ($creditsRes) { if ($creditsRes) {
$creditsData = json_decode($creditsRes, true); $creditsData = json_decode($creditsRes, true);
@@ -134,15 +122,12 @@ function fetchTmdbData($title, $year, $apiKey) {
} }
} }
} }
return ['director' => $director, 'poster' => $poster]; return ['director' => $director, 'poster' => $poster];
} }
// ── ROUTEUR PRINCIPAL ── // ── ROUTEUR PRINCIPAL ──
$action = $_GET['action'] ?? ''; $action = $_GET['action'] ?? '';
$data = json_decode(file_get_contents('php://input'), true) ?? []; $data = json_decode(file_get_contents('php://input'), true) ?? [];
switch ($action) { switch ($action) {
case 'check_security_status': case 'check_security_status':
$stmt = $pdo->query("SELECT COUNT(*) FROM users"); $stmt = $pdo->query("SELECT COUNT(*) FROM users");
@@ -175,7 +160,6 @@ switch ($action) {
echo json_encode(["success" => true]); echo json_encode(["success" => true]);
break; break;
// ── NOUVELLE ACTION : SAUVEGARDE DE LA CLÉ EN BASE ──
case 'save_config': case 'save_config':
checkAuth($pdo); checkAuth($pdo);
$keyName = $data['key_name'] ?? ''; $keyName = $data['key_name'] ?? '';
@@ -202,7 +186,6 @@ switch ($action) {
$type = $data['type'] ?? 'critique'; $type = $data['type'] ?? 'critique';
$id = !empty($data['id']) ? $data['id'] : makeStableId($data['title'] ?? '', $data['year'] ?? '0000'); $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'])) { if (empty($data['director']) || empty($data['poster'])) {
$apiKey = getTmdbApiKey($pdo); $apiKey = getTmdbApiKey($pdo);
$tmdbData = fetchTmdbData($data['title'] ?? '', $data['year'] ?? '', $apiKey); $tmdbData = fetchTmdbData($data['title'] ?? '', $data['year'] ?? '', $apiKey);
@@ -219,7 +202,7 @@ switch ($action) {
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$stmt->execute([ $stmt->execute([
$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '',
$data['poster'] ?? '', $data['rating'] ?? 3, $data['review'] ?? '', $data['streaming'] ?? '' $data['poster'] ?? '', $data['rating'] ?? 3.0, $data['review'] ?? '', $data['streaming'] ?? ''
]); ]);
} else { } else {
$sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description) $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description)
@@ -268,24 +251,27 @@ switch ($action) {
if (isset($_FILES['csv_file'])) { if (isset($_FILES['csv_file'])) {
$file = $_FILES['csv_file']['tmp_name']; $file = $_FILES['csv_file']['tmp_name'];
$type = $_POST['type'] ?? 'critique'; $type = $_POST['type'] ?? 'critique';
// On récupère la clé une seule fois pour tout l'import
$tmdbApiKey = getTmdbApiKey($pdo); $tmdbApiKey = getTmdbApiKey($pdo);
try {
if (($handle = fopen($file, "r")) !== FALSE) { if (($handle = fopen($file, "r")) !== FALSE) {
$header = fgetcsv($handle, 0, ","); $header = fgetcsv($handle, 0, ",");
if (!$header) throw new Exception("Impossible de lire l'en-tête du CSV.");
// 🧹 Nettoyage du BOM UTF-8 (très fréquent sur les exports Letterboxd/Excel)
$header[0] = str_replace("\xEF\xBB\xBF", '', $header[0]);
$header = array_map('trim', $header); $header = array_map('trim', $header);
$imported = 0;
while (($row = fgetcsv($handle, 0, ",")) !== FALSE) { while (($row = fgetcsv($handle, 0, ",")) !== FALSE) {
if (count($row) !== count($header)) continue; if (count($row) !== count($header)) continue; // Ignore les lignes vides ou mal formées
$rowData = array_combine($header, $row);
$rowData = array_combine($header, $row);
$title = $rowData['Name'] ?? $rowData['title'] ?? 'Sans titre'; $title = $rowData['Name'] ?? $rowData['title'] ?? 'Sans titre';
$year = $rowData['Year'] ?? $rowData['year'] ?? '0000'; $year = $rowData['Year'] ?? $rowData['year'] ?? '0000';
$director = $rowData['Director'] ?? $rowData['director'] ?? ''; $director = $rowData['Director'] ?? $rowData['director'] ?? '';
$poster = $rowData['Poster'] ?? $rowData['poster'] ?? $rowData['image'] ?? ''; $poster = $rowData['Poster'] ?? $rowData['poster'] ?? $rowData['image'] ?? '';
// 🔍 RÉCUPÉRATION AUTO TMDB SI CHAMPS VIDES DANS LE CSV
if (empty($director) || empty($poster)) { if (empty($director) || empty($poster)) {
$tmdbData = fetchTmdbData($title, $year, $tmdbApiKey); $tmdbData = fetchTmdbData($title, $year, $tmdbApiKey);
if ($tmdbData) { if ($tmdbData) {
@@ -297,9 +283,11 @@ switch ($action) {
$id = makeStableId($title, $year); $id = makeStableId($title, $year);
if ($type === 'critique') { if ($type === 'critique') {
$rating = isset($rowData['Rating']) ? (int)round($rowData['Rating'] * 1) : 3; // 🌟 Conservation de la précision Letterboxd (2.5, 3.5, etc.)
$rating = isset($rowData['Rating']) && $rowData['Rating'] !== '' ? (float)$rowData['Rating'] : 3.0;
$review = $rowData['Review'] ?? $rowData['review'] ?? ''; $review = $rowData['Review'] ?? $rowData['review'] ?? '';
$streaming = $rowData['Streaming'] ?? $rowData['streaming'] ?? ''; $streaming = $rowData['Streaming'] ?? $rowData['streaming'] ?? '';
$sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) $sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE
@@ -333,10 +321,17 @@ switch ($action) {
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$stmt->execute([$id, $title, $year, $director, $poster, $format, $length, $publisher, $ean, $discs, $aspect, $desc]); $stmt->execute([$id, $title, $year, $director, $poster, $format, $length, $publisher, $ean, $discs, $aspect, $desc]);
} }
$imported++;
} }
fclose($handle); fclose($handle);
echo json_encode(["success" => true, "imported" => $imported]);
} else {
throw new Exception("Impossible d'ouvrir le fichier.");
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode(["error" => "Erreur lors de l'import : " . $e->getMessage()]);
} }
echo json_encode(["success" => true]);
} else { } else {
http_response_code(400); http_response_code(400);
echo json_encode(["error" => "Aucun fichier reçu."]); echo json_encode(["error" => "Aucun fichier reçu."]);